精华内容
下载资源
问答
  • Java 实现重试机制

    千次阅读 2019-11-06 18:29:56
    2)循环重试(包括:重试次数,重试间隔) 3、代码 package com.retry; /** * @author liuxd * @version 1.0 * @date 2019-11-06 17:36 */ import java.util.Random; import java.util.conc...

    1、场景

    批量给第三方回写数据,失败情况重发

    2、设计

    1)异常捕获

    2)循环重试(包括:重试次数,重试间隔)

    3、代码

    package com.retry;
    /**
     * @author liuxd
     * @version 1.0
     * @date 2019-11-06 17:36
     */
    import java.util.Random;
    import java.util.concurrent.TimeUnit;
    
    public class TestRetry {
        //最大重试次数
        private static final Integer tryTimes = 6;
        //重试间隔时间单位秒
        private static final Integer intervalTime = 2;
    
        public static void main(String[] args) throws InterruptedException {
            boolean flag = TestRetry.retryBuss();
            System.out.println("最终执行结果:" + (flag ? "成功" : "失败"));
        }
    
        public static boolean retryBuss() throws InterruptedException {
            Integer retryNum = 1;
            boolean flag = false;
            while (retryNum <= tryTimes) {
                try {
                    flag = execute(retryNum);
                    if (flag) {
                        System.out.println("第" + retryNum + "次执行成功!!!");
                        break;
                    }
                    System.err.println("第" + retryNum + "次执行失败...");
                    retryNum++;
                } catch (Exception e) {
                    retryNum++;
                    TimeUnit.SECONDS.sleep(intervalTime);
                    continue;
                }
            }
    
            return flag;
        }
    
        /**
         * 具体业务
         * @param retryNum
         * @return
         */
        private static boolean execute(int retryNum) {
            Random random = new Random();
            int a = random.nextInt(10);
            boolean flag = true;
            try {
                if (a != 6) {
                    flag = false;
                    throw new RuntimeException();
                }
            } catch (Exception e) {
            }
            return flag;
        }
    }

    4、结果

    4.1)失败情况

    第1次执行失败...
    第2次执行失败...
    第3次执行失败...
    第4次执行失败...
    第5次执行失败...
    第6次执行失败...
    最终执行结果:失败

    4.2)成功情况

    第1次执行失败...
    第2次执行成功!!!
    最终执行结果:成功

     

    展开全文
  • Java编写的显示器显示模式检测程序 2个目标文件 内容索引:JAVA源码,系统相关,系统信息检测 用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作...
  • 在应用程序中,由于一些网络等不可预知的问题,我们的程序或者接口会失败,比如调用一个第三方的接口获取数据失败了,这时就需要重试机制,比如延时3S后重试、间隔不断增加重试等,而这些机制完全不需要你自己去实现...

    楔子

    在应用程序中,由于一些网络等不可预知的问题,我们的程序或者接口会失败,比如调用一个第三方的接口获取数据失败了,这时就需要重试机制,比如延时3S后重试、间隔不断增加重试等,而这些机制完全不需要你自己去实现,全部交给Spring Retry吧。

    使用

    1.在pom文件中添加相应的依赖
    <dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
        <version>1.2.2.RELEASE</version>
    </dependency>
    

    最新版本可以在Maven Central找到
    Spring Retry使用AOP实现,所以必须要有spring-aspects依赖,

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
    </dependency>
    
    2.在启动类或者配置类上添加注解@EnableRetry

    配置类

    @Configuration
    @EnableRetry
    public class AppConfig { ... }
    

    启动类

    @SpringBootApplication
    @EnableRetry
    public class Application
    
    3. 在需要重试的方法上添加注解@Retryable
    @Service
    public class DemoService {
    @Retryable(value= {Exception.class},maxAttempts = 3)
        public void call() throws Exception {
                System.out.println("do something...");
                throw new Exception("RPC调用异常");
        }
        @Recover
        public void recover(RemoteAccessException e) {
                System.out.println(e.getMessage());
        }
    }
    
    @Retryable(maxAttempts = 3, backoff = @Backoff(value = 3000, multiplier = 1.5))
    public Customer getCustomer(String customerId) {
    		if (true) {
    			JSONArray data = retObj.getJSONArray("data");
    			if (data != null && !data.isEmpty()) {
    				return data.toJavaList(Customer.class).get(0);
    			}
    		} else {
    			log.error("异常,{}", customerId);
    			throw new RuntimeException("获数据失败");
    		}
    		return null;
    }
    

    @Retryable被注解的方法发生异常时会重试

    @Retryable注解中的参数说明:
    maxAttempts :最大重试次数,默认为3,如果要设置的重试次数为3,可以不写;
    value:抛出指定异常才会重试
    include:和value一样,默认为空,当exclude也为空时,所有异常都重试
    exclude:指定不处理的异常,默认空,当include也为空时,所有异常都重试
    backoff:重试等待策略,默认使用@Backoff@Backoff的value默认为1000L,我们设置为2000L。

    @Backoff重试补偿机制,默认没有

    @Backoff注解中的参数说明:
    value:隔多少毫秒后重试,默认为1000L,我们设置为3000L;
    delay:和value一样,但是默认为0;
    multiplier(指定延迟倍数)默认为0,表示固定暂停1秒后进行重试,如果把multiplier设置为1.5,则第一次重试为2秒,第二次为3秒,第三次为4.5秒。

    4. 可以在指定方法上标记@Recover来开启重试失败后调用的方法(注意,需跟重处理方法在同一个类中)

    @Recover
    当重试到达指定次数时,被注解的方法将被回调,可以在该方法中进行日志处理。需要注意的是发生的异常和入参类型一致时才会回调。

    5. 采坑提示
    • 1、由于retry用到了aspect增强,所有会有aspect的坑,就是方法内部调用,会使aspect增强失效,那么retry当然也会失效。参考改链接
    public class demo {
        public void A() {
            B();
        }
    
        //这里B不会执行
        @Retryable(Exception.class)
        public void B() {
            throw new RuntimeException("retry...");
        }
    }
    
    • 2、重试机制,不能在接口实现类里面写。所以要做重试,必须单独写个service。
    • 3、maxAttemps参数解释的是说重试次数,但是我再打断点的时候发现这个=1时,方法一共只执行了一次。

    参考文献

    展开全文
  • Java 实现间隔重试(一)

    千次阅读 2018-05-31 14:37:07
    实现类似于支付宝或微信在回调第三方接口时,出错间隔重试的功能。例如:25小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h);思前想后提出了一下几个方案:1.推送信息记录到表中,定时器触发...

    实现类似于支付宝或微信在回调第三方接口时,出错间隔重试的功能。

    例如:25小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h);

    思前想后提出了一下几个方案:

    1.推送信息记录到表中,定时器触发重推推送失败的数据

        优点:实现简单

        缺点:实现不了单条数据间隔重推,批量推送服务器IO在短时间内压力大

    2.使用多线程,将推送失败的数据放入queue中,线程轮询判断触发重推

        难以实现。

    3.使用redis和mq,将推送失败的数据放入redis中,设置超时时间,监听redis key超时事件触发重推

        优点:能够实现单条数据间隔重推,分担服务器推送压力

        缺点:需要搭建redis,并开发事件监听

    4.采用rocketmq,消息推送

    展开全文
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...
  • 异步重试模式

    2020-05-13 05:55:39
    当您有一段经常失败且必须重试的代码时,此Java 7/8库提供了丰富且不引人注目的API,并提供了针对此问题的快速且可扩展的解决方案: ScheduledExecutorService scheduler = Executors....

    当您有一段经常失败且必须重试的代码时,此Java 7/8库提供了丰富且不引人注目的API,并提供了针对此问题的快速且可扩展的解决方案:

    ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    RetryExecutor executor = new AsyncRetryExecutor(scheduler).
        retryOn(SocketException.class).
        withExponentialBackoff(500, 2).     //500ms times 2 after each retry
        withMaxDelay(10_000).               //10 seconds
        withUniformJitter().                //add between +/- 100 ms randomly
        withMaxRetries(20);

    现在,您可以运行任意代码块,并且库将为您重试该代码块,以防它抛出SocketException

    final CompletableFuture<Socket> future = executor.getWithRetry(() ->
            new Socket("localhost", 8080)
    );
    
    future.thenAccept(socket ->
            System.out.println("Connected! " + socket)
    );

    请仔细看! getWithRetry()不会阻止。 它立即返回CompletableFuture并异步调用给定的函数。 您可以一次收听该Future甚至是多个Future ,并同时进行其他工作。 因此,这段代码的作用是:尝试连接到localhost:8080 ,如果由于SocketException而失败,它将在500毫秒后重试(带有一些随机抖动),每次重试后的延迟加倍,但不超过10秒。

    等效但更简洁的语法:

    executor.
            getWithRetry(() -> new Socket("localhost", 8080)).
            thenAccept(socket -> System.out.println("Connected! " + socket));

    这是您可能期望的示例输出:

    TRACE | Retry 0 failed after 3ms, scheduled next retry in 508ms (Sun Jul 21 21:01:12 CEST 2013)
    java.net.ConnectException: Connection refused
        at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0-ea]
        //...
    
    TRACE | Retry 1 failed after 0ms, scheduled next retry in 934ms (Sun Jul 21 21:01:13 CEST 2013)
    java.net.ConnectException: Connection refused
        at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0-ea]
        //...
    
    TRACE | Retry 2 failed after 0ms, scheduled next retry in 1919ms (Sun Jul 21 21:01:15 CEST 2013)
    java.net.ConnectException: Connection refused
        at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0-ea]
        //...
    
    TRACE | Successful after 2 retries, took 0ms and returned: Socket[addr=localhost/127.0.0.1,port=8080,localport=46332]
    
    Connected! Socket[addr=localhost/127.0.0.1,port=8080,localport=46332]

    想象一下,您连接到两个不同的系统,一个系统速度 ,第二个系统不可靠并且经常失败:

    CompletableFuture<String> stringFuture = executor.getWithRetry(ctx -> unreliable());
    CompletableFuture<Integer> intFuture = executor.getWithRetry(ctx -> slow());
    
    stringFuture.thenAcceptBoth(intFuture, (String s, Integer i) -> {
        //both done after some retries
    });

    当缓慢且不可靠的系统最终都无任何故障地答复时,异步异步执行thenAcceptBoth()回调。 类似地(使用CompletableFuture.acceptEither() ),您可以同时异步调用两个或多个不可靠的服务器,并在重试几次后第一个成功时会收到通知。

    我对此不够强调–重试是异步执行的,并且有效地使用了线程池,而不是盲目入睡。

    基本原理

    通常我们被迫重试给定的代码段,因为它失败了,我们必须再次尝试,通常会稍有延迟以节省CPU。 这项要求非常普遍,并且在Spring Batch中通过RetryTemplate类提供重试支持的现成通用实现很少RetryTemplate 。 但是几乎没有其他类似的方法( [1][2] )。 所有这些尝试(我敢打赌,你们中的许多人自己都实现了类似的工具!)遇到了相同的问题-它们正在阻塞,从而浪费了大量资源,并且扩展性不好。

    本身并不坏因为它使编程模型更加简单-库负责重试,而您只需要等待比平常更长的返回值即可。 但是,这不仅会造成泄漏的抽象(由于重试和延迟,通常非常快的方法通常会突然变慢),而且还会浪费宝贵的线程,因为这种工具将在重试之间花费大部分时间。 因此
    创建了Async-Retry实用程序,该实用程序针对Java 8 (现有Java 7 backport )并解决了上述问题。

    主要的抽象是RetryExecutor ,它提供了简单的API:

    public interface RetryExecutor {
    
        CompletableFuture<Void> doWithRetry(RetryRunnable action);
    
        <V> CompletableFuture<V> getWithRetry(Callable<V> task);
    
        <V> CompletableFuture<V> getWithRetry(RetryCallable<V> task);
    
        <V> CompletableFuture<V> getFutureWithRetry(RetryCallable<CompletableFuture<V>> task);
    }

    不必担心RetryRunnableRetryCallable –为方便起见,它们允许使用已检查的异常,并且在大多数情况下,我们还是会使用lambda表达式。

    请注意,它返回CompletableFuture 。 我们不再假装调用错误方法很快。 如果库遇到异常,它将使用预先配置的退避延迟重试我们的代码块。 调用时间将从几毫秒飞涨到几秒钟。 CompletableFuture清楚地表明了这一点。 而且,它不是一个愚蠢的java.util.concurrent.Future我们都知道– Java 8中的CompletableFuture非常强大 ,最重要的是–默认情况下是非阻塞的。

    如果您毕竟需要阻止结果,只需在Future对象上调用.get()

    基本API

    该API非常简单。 您提供了一个代码块,该库将多次运行它,直到它正常返回为止,而不是引发异常。 它也可能在重试之间设置可配置的延迟:

    RetryExecutor executor = //...
    
    executor.getWithRetry(() -> new Socket("localhost", 8080));

    一旦成功连接到localhost:8080将解析返回的CompletableFuture<Socket> localhost:8080 。 (可选)我们可以使用RetryContext来获取额外的上下文,例如当前正在执行的重试:

    executor.
        getWithRetry(ctx -> new Socket("localhost", 8080 + ctx.getRetryCount())).
        thenAccept(System.out::println);

    该代码比看起来更聪明。 在第一次执行时, ctx.getRetryCount()返回0 ,因此我们尝试连接到localhost:8080 。 如果失败,则下一个重试将尝试localhost:80818080 + 1 ),依此类推。 而且,如果您意识到所有这些操作都是异步发生的,则可以扫描多台计算机的端口,并收到有关每个主机上第一个响应端口的通知:

    Arrays.asList("host-one", "host-two", "host-three").
        stream().
        forEach(host ->
            executor.
                getWithRetry(ctx -> new Socket(host, 8080 + ctx.getRetryCount())).
                thenAccept(System.out::println)
        );

    对于每个主机, RetryExecutor将尝试连接到端口8080,并尝试使用更高的端口。

    getFutureWithRetry()需要特别注意。 我想重试已经返回CompletableFuture<V> :例如异步HTTP调用的结果:

    private CompletableFuture<String> asyncHttp(URL url) { /*...*/}
    
    //...
    
    final CompletableFuture<CompletableFuture<String>> response = 
        executor.getWithRetry(ctx -> 
            asyncHttp(new URL("http://example.com")));

    asyncHttp()传递给getWithRetry()将产生CompletableFuture<CompletableFuture<V>> 。 与它一起工作不仅很尴尬,而且还很麻烦。 该库将仅调用asyncHttp()并仅在失败时重试,但在返回时不重试
    CompletableFuture<String>失败。 解决方案很简单:

    final CompletableFuture<String> response =
        executor.getFutureWithRetry(ctx ->
            asyncHttp(new URL("http://example.com")));

    在这种情况下, RetryExecutor将理解从asyncHttp()返回的内容实际上只是一个Future并且将(异步)等待结果或失败。 该库功能更强大,因此让我们深入了解:

    配置选项

    通常,您可以配置两个重要因素: RetryPolicy ,用于控制是否应进行下一次重试;以及Backoff (可以有选择地增加后续重试之间的延迟)。

    默认情况下, RetryExecutor在每个Throwable上无限地重复用户任务,并在RetryExecutor重试之间增加1秒的延迟。

    创建

    RetryExecutor默认实现是AsyncRetryExecutor ,您可以直接创建:

    ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    
    RetryExecutor executor = new AsyncRetryExecutor(scheduler);
    
    //...
    
    scheduler.shutdownNow();

    唯一需要的依赖关系是JDK的标准ScheduledExecutorService 。 在许多情况下,一个线程就足够了,但是如果您要同时处理数百个或更多任务的重试,请考虑增加池大小。

    请注意, AsyncRetryExecutor不会关闭ScheduledExecutorService 。 这是一个有意识的设计决策,将在后面进行解释。

    AsyncRetryExecutor几乎没有其他构造函数,但是在大多数情况下,更改类的行为对于with*()方法链接的调用最为方便。 您将看到大量以此方式编写的示例。 稍后,我们将仅使用executor引用而不定义它。 假设它是RetryExecutor类型。

    重试政策

    例外情况

    默认情况下,从用户任务抛出的每个Throwable (特殊AbortRetryException除外)都会导致重试。 显然,这是可配置的。 例如,在JPA中,您可能想重试由于OptimisticLockException而失败的事务-但其他所有异常都应立即失败:

    executor.
        retryOn(OptimisticLockException.class).
        withNoDelay().
        getWithRetry(ctx -> dao.optimistic());

    其中dao.optimistic()可能会引发OptimisticLockException 。 在这种情况下,您可能不希望重试之间有任何延迟,以后再说。 如果您不喜欢在每个Throwable上重试的默认设置,只需使用retryOn()来限制它:

    executor.retryOn(Exception.class)

    当然,也可能需要相反的操作–中止重试并在抛出某些异常的情况下立即失败而不是重试。 就这么简单:

    executor.
            abortOn(NullPointerException.class).
            abortOn(IllegalArgumentException.class).
            getWithRetry(ctx -> dao.optimistic());

    显然,您不想重试NullPointerExceptionIllegalArgumentException因为它们指示编程错误,而不是瞬时失败。 最后,您可以结合使用重试和中止策略。 如果出现任何retryOn()异常(或子类),则用户代码将重试,除非它应该abortOn()指定的异常。 例如,我们想重试每个IOExceptionSQLException但是如果遇到FileNotFoundExceptionjava.sql.DataTruncation则中止(顺序无关):

    executor.
        retryOn(IOException.class).
        abortIf(FileNotFoundException.class).
        retryOn(SQLException.class).
        abortIf(DataTruncation.class).
        getWithRetry(ctx -> dao.load(42));

    如果这还不够,您可以提供将在每次失败时调用的自定义谓词:

    executor.
        abortIf(throwable ->
            throwable instanceof SQLException &&
                    throwable.getMessage().contains("ORA-00911")
        );

    最大重试次数

    中断重试“循环”的另一种方法(请记住此过程是异步的,没有阻塞循环 )是通过指定最大重试次数:

    executor.withMaxRetries(5)

    在极少数情况下,您可能希望禁用重试,并且几乎不利用异步执行。 在这种情况下,请尝试:

    executor.dontRetry()

    重试之间的延迟(退避)

    有时需要在失败后立即重试(请参阅OptimisticLockException示例),但是在大多数情况下,这是一个坏主意。 如果您无法连接到外部系统,请稍等片刻,然后再尝试下一次尝试。 您可以节省CPU,带宽和其他服务器的资源。 但是有很多选择要考虑:

    • 我们应该以固定的间隔重试还是增加每次失败后的延迟
    • 轮候时间是否应该有上限和下限?
    • 我们是否应该添加随机“抖动”来延迟时间以及时分散许多任务的重试?

    该库回答了所有这些问题。

    重试间隔固定

    默认情况下,每次重试之前都有1秒的等待时间。 因此,如果初始尝试失败,则将在1秒后执行第一次重试。 当然,我们可以将默认值更改为200毫秒:

    executor.withFixedBackoff(200)

    如果我们已经在此处,则默认情况下,执行用户任务后将应用退避。 如果用户任务本身消耗一些时间,则重试的频率将降低。 例如,重试延迟为RetryExecutor毫秒,用户任务失败所需的平均时间约为50毫秒, RetryExecutor将每秒重试约4次(50毫秒+ RetryExecutor毫秒)。 但是,如果要将重试频率保持在更可预测的水平,则可以使用fixedRate标志:

    executor.
            withFixedBackoff(200).
            withFixedRate()

    这类似于ScheduledExecutorService “固定速率”与“固定延迟”方法。 顺便说一句,不要期望RetryExecutor非常精确,这是最好的,但是在很大程度上取决于前面提到的ScheduledExecutorService准确性。

    重试之间的间隔呈指数增长

    它可能是一个活跃的研究主题,但总的来说,您可能希望随着时间的推移扩展重试延迟,假设如果用户任务多次失败,我们应该减少尝试次数。 例如,假设我们从100ms延迟开始,直到进行第​​一次重试为止,但是如果该尝试也失败了,我们应该再等待两次(200ms)。 再过400毫秒,800毫秒……您就会明白:

    executor.withExponentialBackoff(100, 2)

    这是一个指数函数,可以快速增长。 因此,将最大退避时间设置在某个合理的水平(例如10秒)非常有用:

    executor.
        withExponentialBackoff(100, 2).
        withMaxDelay(10_000)      //10 seconds

    随机抖动

    在严重停机期间经常观察到的一种现象是系统趋于同步。 想象一下一个繁忙的系统突然停止响应。 成百上千的请求失败并被重试。 这取决于您的退避,但是默认情况下,所有这些请求都会在一秒钟后精确重试,从而在某个时间点产生大量流量。 最后,此类故障会传播到其他系统,这些系统又会进行同步。

    为避免此问题,随着时间的推移扩展重试,使负载平坦化是很有用的。 一个简单的解决方案是添加随机抖动来延迟时间,以便并非所有请求都计划在完全相同的时间重试。 您可以在均匀抖动(随机值从-100ms到100ms)之间进行选择:

    executor.withUniformJitter(100)     //ms

    …和成比例的抖动,将延迟时间乘以随机因子,默认情况下为0.9到1.1(10%):

    executor.withProportionalJitter(0.1)        //10%

    您还可以对延迟时间设置严格的下限,以避免安排较短的重试时间:

    executor.withMinDelay(50)   //ms

    实施细节

    该库是在考虑Java 8的情况下构建的,以利用lambda和新的CompletableFuture抽象(但是存在具有Guava依赖项的Java 7 port )。 它在下面使用ScheduledExecutorService来运行任务并计划将来的重试-这样可以最大程度地利用线程。

    但是真正有趣的是整个库是完全不变的,根本没有单个可变字段。 起初这可能是违反直觉的,例如以以下简单代码示例为例:

    ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    
    AsyncRetryExecutor first = new AsyncRetryExecutor(scheduler).
        retryOn(Exception.class).
        withExponentialBackoff(500, 2);
    
    AsyncRetryExecutor second = first.abortOn(FileNotFoundException.class);
    
    AsyncRetryExecutor third = second.withMaxRetries(10);

    似乎所有with*()方法或retryOn() / abortOn()方法retryOn()现有的执行程序变异。 但是事实并非如此,每次配置更改都会创建一个新实例 ,而旧实例则保持不变。 因此,例如,当first执行者将重试FileNotFoundExceptionsecondthird执行者则不会。 但是它们都共享同一个scheduler 。 这就是AsyncRetryExecutor不关闭ScheduledExecutorService (甚至没有任何close()方法)的原因。 由于我们不知道有多少个AsyncRetryExecutor副本指向同一调度程序,因此我们甚至不尝试管理其生命周期。 但是,这通常不是问题(请参见下面的Spring集成 )。

    您可能想知道,为什么这么笨拙的设计决定? 有以下三个原因:

    • 在编写并发代码时,不变性可以大大降低多线程错误的风险。 例如, RetryContext保存重试次数。 但是,我们无需更改变量,而只需创建具有递增但final计数器的新实例(副本)即可。 没有比赛条件或可见性。
    • 如果给您现有的RetryExecutor几乎完全是您想要的,但是您需要进行一些细微调整,则只需调用executor.with...()并获取一个新副本。 您不必担心使用同一执行程序的其他地方(请参阅: Spring集成以获取更多示例)
    • 如今,函数式编程和不变的数据结构非常流行

    注意: AsyncRetryExecutor 标记为final ,您可以通过将其子类化并添加可变状态来打破不变性。 请不要这样做,子类只允许更改行为。

    依存关系

    该库需要Java 8和SLF4J进行记录。 Java 7端口还取决于Guava

    Spring整合

    如果您即将在Spring中使用RetryExecutor ,请放心,但是配置API可能对您不起作用。 Spring通过大量的设置来促进(或用于促进)可变服务的约定。 在XML中,您可以定义bean并在其上调用setter(通过<property name="..."/> )。 该约定假定存在变异设置器。 但是我发现这种方法在某些情况下容易出错并且违反直觉。

    假设我们全局定义了org.springframework.transaction.support.TransactionTemplate bean并将其注入到多个位置。 大。 现在有一个请求,它的超时要求略有不同:

    @Autowired
    private TransactionTemplate template;

    后来在同一个班级:

    final int oldTimeout = template.getTimeout();
    template.setTimeout(10_000);
    //do the work
    template.setTimeout(oldTimeout);

    此代码在许多级别上都是错误的! 首先,如果发生故障,我们将永远不会恢复oldTimeout 。 好了, finally救了。 但还要注意我们如何更改全局共享的TransactionTemplate实例。 谁知道不知道更改配置的其他几个bean和线程将要使用它?

    即使您确实想全局更改事务超时,也足够公平,但是这样做仍然是错误的方法。 private timeout字段不是volatile ,因此对其进行的更改可能对其他线程可见或不可见。 真是一团糟! 同样的问题在许多其他类(如JmsTemplate

    你知道我要去哪里吗? 只需创建一个不变的服务类,并在需要时通过创建副本来安全地对其进行调整。 现在,使用此类服务​​同样简单:

    @Configuration
    class Beans {
    
        @Bean
        public RetryExecutor retryExecutor() {
            return new AsyncRetryExecutor(scheduler()).
                retryOn(SocketException.class).
                withExponentialBackoff(500, 2);
        }
    
        @Bean(destroyMethod = "shutdownNow")
        public ScheduledExecutorService scheduler() {
            return Executors.newSingleThreadScheduledExecutor();
        }
    
    }

    嘿! 进入21世纪,我们在Spring不再需要XML。 Bootstrap也很简单:

    final ApplicationContext context = new AnnotationConfigApplicationContext(Beans.class);
    final RetryExecutor executor = context.getBean(RetryExecutor.class);
    //...
    context.close();

    如您所见,将现代的,不可变的服务与Spring集成非常简单。 顺便说一句,如果您在设计自己的服务时没有准备好进行如此大的更改,请至少考虑使用构造函数注入

    到期

    该库包含大量的单元测试。 但是,尚未在任何生产代码中使用它,并且该API可能会更改。 当然,我们鼓励您提交错误,功能请求提取请求 。 它是在考虑到Java 8的情况下开发的,但是Java 7 backport存在一些更详细的API和强制性Guava依赖关系( ListenableFuture而不是
    Java 8的CompletableFuture )。

    GitHub上的完整源代码。

    参考:来自Java和社区博客的JCG合作伙伴 Tomasz Nurkiewicz的异步重试模式

    翻译自: https://www.javacodegeeks.com/2013/08/asynchronous-retry-pattern.html

    展开全文
  • Google Guava Retry 优雅的重试方案前言使用场景什么场景不适合重试了解幂等性一、Guava Retry是什么?与Spring retry比较二、使用步骤1.引入库2.码代码总结导读 前言 使用场景 当需要两个或者多个组件协同工作而...
  • 将一个字符串中字符按出现频率的高到低排序返回,如果两个字符出现的频率一样,则将最先出现的字符排在前面 例如: orderChar(“abcdefg”)返回 “abcdefg” orderChar(“abcdefgg”)返回 “gabcdef” orderChar(...
  • 本篇博文我将继续通过源码对请求之后结果的封装解码及失败重试进行介绍和学习。 正文 在上篇博文中提到,OpenFeign通过SynchronousMethodHandler进行同步方法请求处理,在介绍executeAndDecode方法源码时,...
  • 使用RabbitMQ,会有知晓消息是否成功、如果消费失败重试的需求,这篇文章主要讲的是消息确认机制(ACK)和消息重试机制。 二、消息确认机制 RabbitMQ的消费者确认机制用来确认消费者是否成功消费了队列中的消息...
  • java源码包---java 源码 大量 实例

    千次下载 热门讨论 2013-04-18 23:15:26
     用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作方法及源代码 1个目标文件 摘要:Java源码,初学实例,波浪文字  Java波浪文字,一个利用...
  • 限制网站访客访问频率,超过限制24小时后重试 redis中键的生存时间(expire) package cn.redis.demo; import static org.junit.Assert.*; import java.util.List; import org.apache.commons.pool2.impl....
  • Java虚拟机 - JVM是什么?

    千次阅读 2018-05-08 14:54:36
    JVM是帮助Java程序开发者在开发过程中无需考虑无用的资源需要进行回收,避免内存溢出等问题且实现在不同平台上运行Java程序。 如: 开餐馆,你每天要把店铺的垃圾拉到垃圾厂去,如果你不拉或忘记拉,越积...
  • java websocket断开

    千次阅读 2018-11-04 11:29:09
    #java websocket断开重连,java客户端websocket断开重连 最近一个需求。需要用java客户端的方式...首先需要注意的是为了防止重试给远端的websocket 站点带来过大的压力,我们需要设计一个规则,重试间隔随着重试次...
  • 源码分析RocketMQ之消息消费重试机制

    千次阅读 2018-01-07 23:19:14
    本文主要关注业务方在消息消费失败后,返回ConsumeConcurrentlyStatus.RECONSUME_LATER,专业术语:业务方每条消息消费后要告诉MQ消费者一个结果(ack,message back),触发MQ消息消费重试机制,然后MQ消费者需要反馈给...
  • Feign实现远程调用,超时时间以及重试次数 继上次学习我们接着上次的代码改造通过Feign的方式实现远程调用首先在product-api中引入jar,但是当粘贴进去发现依赖并没有下载下来,我们还需要把parent,properties,...
  • 测试开发笔记

    万次阅读 多人点赞 2019-11-14 17:11:58
    测试开发笔记 第一章 测试基础 7 1.什么是软件测试: 7 2.软件测试的目的、意义:(怎么做好软件测试) 7 3....需求规格说明书 系统测试计划书 系统测试方案书 系统测试用例 预测项 系统测试用例、预测项通过评审...
  • 消息中间件MQ与RabbitMQ面试题(2020最新版)

    万次阅读 多人点赞 2020-03-01 11:11:21
    除此之外,RabbitMQ的开源社区很活跃,较高频率的迭代版本,来修复发现的bug以及进行各种优化,因此综合考虑过后,公司采取了RabbitMQ。 但是RabbitMQ也有一点缺陷,就是他自身是基于erlang语言开发的,所以导致...
  • 基于JAVA的购物网站(毕业论文)

    万次阅读 多人点赞 2010-12-20 14:25:00
    XX 大 学   毕业设计(论文)         题目: 基于Java技术的网上交易系统的开发         学 院: 专 业: 班 级: ...
  • Redis面试题集

    千次阅读 多人点赞 2019-09-16 10:19:31
    (7)重新从消息队列中获得该数据,重试操作。 参考资料: Redis缓存和数据库一致性问题 6.Redis的分布式锁如何实现,有什么优缺点? 分布式锁需要解决的问题 互斥性:任意时刻只能有一个客户端拥有锁,...
  • C#基础教程-c#实例教程,适合初学者

    万次阅读 多人点赞 2016-08-22 11:13:24
    C#语法和C++和JAVA语法非常相似,如果读者用过C++和JAVA,学习C#语言应是比较轻松的。 用C#语言编写的源程序,必须用C#语言编译器将C#源程序编译为中间语言(MicroSoft Intermediate Language,MSIL)代码,形成扩展名...
  • 任务失败重试机制某些场景下业务失败需要重试,比如说状态通知第三方,发奖品,发短信等等。总体的思路是将任任务现场记录下来,然后稍后重试。方案有多种 任务现场存储在db中,使用分布式任务调度统一去执行。 任务...
  • 场景模拟工程 itstack-demo-design-4-00 └── src └── main └── java └── org.itstack.demo.design ├── AnswerQuestion.java └── ChoiceQuestion.java 在这里模拟了两个试卷题目的类;...
  • Java的前景如何,好不好自学?

    千次阅读 多人点赞 2020-06-15 20:09:37
    首先来回答,Java 的前景如何? 在我眼里,Java 绝对是世界第一编程语言啊,PHP 表示不服,那也没办法啊,来看 TIOBE 这个编程语言排行榜吧。 上面这幅图是几个热门编程语言(Java、C、Python、JavaScript 等等)近...
  • // 重试次数   HttpClient httpClient = httpClientBuilder.build();   HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =  new   HttpComponentsClientHttpRequestFactory( ...
  • 1.4 手工测试的局限性与自动化测试的优势 手工测试的局限性: 手工测试无法覆盖所有的代码路径 简单的功能性测试用例在每一轮的测试中都不能少,而且具有一定的机械性、 复性,工作量较大,影响效率。 举例:如果...
  • web测试知识详解

    千次阅读 多人点赞 2018-11-21 17:09:19
    页面的访问频率占比如何?因为测试的精力和侧重点也要根据这个数据而定 3.10.2. 网站部署时是否会影响到用户使用,如何避免? 3.10.3. 不要直接显示不友好的错误提示,是否有友好的提示信息? 3.10.4. web应用不能...
  • Redis应用之限制访问频率

    万次阅读 2019-03-17 10:22:03
      我们知道当网站的访问量突然很大的时候肯定会对服务器造成影响,甚至无法...Redis实现限制访问频率 1.实现访问一   限制每个用户每分钟最多只能访问100个页面。实现思路:key使用有&quot;rate.limiting...
  • 实际编程过程中,第二种用的是最多的, ## 九、消息中间件目前使用频率最大是RabbitMQ吗? 技术选型是从技术的使用场景,优缺点等方面综合评估的。很多企业用RocketMQ和kafka,大数据基本100%选kafka. ##十、为什么...
  • Java编写的显示器显示模式检测程序 2个目标文件 内容索引:JAVA源码,系统相关,系统信息检测 用JAVA编写了一个小工具,用于检测当前显示器也就是显卡的显示模式,比如分辨率,色彩以及刷新频率等。 Java波浪文字制作...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 28,742
精华内容 11,496
关键字:

频率重试java

java 订阅