当前位置: 首页 > news >正文

网站开发的缺点seo网站推广工作内容

网站开发的缺点,seo网站推广工作内容,个旧做网站哪家公司好,网站建设售后完善目录 1、前言 2、实现方式 2.1、循环重试 2.2、递归重试 2.3、Spring Retry 2.4、Resilience4j 2.5、http请求网络工具内置重试方式 2.6、自定义重试工具 2.7、并发框架异步重试 2.8、消息队列 3、小结 1、前言 HTTP接口请求重试是指在请求失败时,再次发…

 目录

1、前言

2、实现方式

2.1、循环重试

2.2、递归重试

2.3、Spring Retry

2.4、Resilience4j

2.5、http请求网络工具内置重试方式

2.6、自定义重试工具

2.7、并发框架异步重试

2.8、消息队列

3、小结


1、前言

HTTP接口请求重试是指在请求失败时,再次发起请求的机制。在实际应用中,由于网络波动、服务器故障等原因,HTTP接口请求可能会失败。为了保证系统的可用性和稳定性,需要对HTTP接口请求进行重试。

2、实现方式

今天给大家分享一些常见的接口请求重试的方式。本地模拟了一个请求接口,后面的代码示例均模拟请求该接口:

@GetMapping("http_test")
public String getHttpTest(){return "接口请求成功,返回:OK";
}

2.1、循环重试

循环重试是最简单最粗暴的方式,就是在请求接口代码中加入循环机制,如果接口请求失败,则循环继续发起接口请求,直到请求成功或接口重试次数达到上限。如果请求成功,则不进行重试。

简单代码示例如下:

@GetMapping("retry_demo_loop")
public String retry_demo_loop(){// 重试上限次数为3次int maxRetryTime = 3;String result = null;// 接口循环请求for (int i = 1; i <= maxRetryTime; i++) {try {// 模拟请求接口result = HttpUtil.get("http://localhost:8080/http_test");// 模拟一次请求失败if(i == 1){int co = i / 0;}// 请求成功,跳出循环break;} catch (Exception e) {log.error("接口请求异常,进行第{}次重试", i);result = "接口请求失败,请联系管理员";}}return result;
}

请求结果:

重试日志打印:

2.2、递归重试

除了循环,还可以使用递归来实现接口的请求重试。递归是我们都比较熟悉的编程技巧,在请求接口的方法中调用自身,如果请求失败则继续调用,直到请求成功或达到最大重试次数。

@GetMapping("retry_demo_rec")
public String retry_demo_rec(){// 重试上限次数为3次int maxRetryTime = 3;return retryRequest(maxRetryTime);
}/*** 递归方法* @param maxRetryTime* @return*/
private String retryRequest(int maxRetryTime){if (maxRetryTime <= 0) {return "接口请求失败,请联系管理员";}int retryTime = 0;try {// 模拟请求接口String result = HttpUtil.get("http://localhost:8080/http_test");// 模拟一次请求失败if(maxRetryTime == 3){int co = 1 / 0;}return result;} catch (Exception e) {// 处理异常log.error("接口请求异常,进行第{}次重试", ++retryTime);return retryRequest(maxRetryTime - 1);}
}

请求结果:

重试日志打印:

2.3、Spring Retry

第三种便是使用Spring Retry依赖实现。首先我们需要集成相关依赖:

<dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId>
</dependency>
<!-- 由于retry使用到了aop,所以还需要加入aop依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

加入@EnableRetry启动:

@EnableRetry
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

添加retry方法注解:

public interface MyRetryService {/*** retryable注解表示该方法需要重试* value:出现该指定异常后,进行重试* maxAttempts:重试次数上限,这里指定为3次* backoff:重试策略,这里指定200ms间隔一次* @param code* @return* @throws Exception*/@Retryable(value = {Exception.class}, maxAttempts = 3, backoff = @Backoff(200))String retry(int code) throws Exception;/*** 当重试达到上限后还是失败,则作为异常回调方法* @param th* @param code* @return*/@RecoverString recover(Throwable th, int code);}

MyReretService实现类:

@Slf4j
@Service
public class MyRetryServiceImpl implements MyRetryService {@Overridepublic String retry(int code) throws Exception {log.info("请求retry接口");String result = HttpUtil.get("http://localhost:8080/http_test");if(code != 200){throw new Exception("接口请求异常");}return result;}@Overridepublic String recover(Throwable th, int code) {log.error("回调方法执行!!!!");return "异常码为:" + code + ",异常信息:" + th.getMessage();}
}

Controller:

@Autowired
private MyRetryService myRetryService;/*** 当请求code参数为200时,直接成功* 当code参数!=200时,会出发重试* @param code* @return* @throws Exception*/
@GetMapping("retry_demo_spring_retry")
public String retry_demo_spring_retry(Integer code) throws Exception {return myRetryService.retry(code);
}

访问地址:http://localhost:8080/retry_demo_spring_retry?code=123

查看结果:可以看到接口重试了3次,最后执行了@Recover方法最后的回调。

2.4、Resilience4j

Resilience4j是一个轻量级、易于使用的轻量级“容错”包。它受Neflix Hystrix启发但只有一个依赖(Vavr),而不像Hystrix很多很多的依赖。同时它是一个 Java 库,可以帮助我们构建弹性和容错的应用程序。Resilience4j在“容错”方面提供了各种模式:断路器(Circuit Breaker)、重试(Retry)、限时器(Time Limiter)、限流器(Rate Limiter)、隔板(BulkHead)。我们今天讨论的话题是重试,那么今天就来演示下Retry。

Github地址:GitHub - resilience4j/resilience4j: Resilience4j is a fault tolerance library designed for Java8 and functional programming

首先,添加相应依赖:

<dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-spring-boot2</artifactId><version>2.1.0</version>
</dependency>

application.yml配置相关策略,配置官方文档:https://resilience4j.readme.io/docs/retry

resilience4j:retry:instances:retry_demo:max-attempts: 3     # 重试的上限次数wait-duration: 1s   # 重试的间隔时间,配置为1s

我们改造一下上面spring-retry的demo。

controller:

@GetMapping("retry_demo_spring_retry")
@Retry(name = "retry_demo", fallbackMethod = "recover")
public String retry_demo_spring_retry(Integer code) throws Exception {return myRetryService.retry(code);
}public String recover(Throwable th) {log.error("回调方法执行!!!!");return "异常信息:" + th.getMessage();
}

myRetryService:

@Override
public String retry(int code) throws Exception {log.info("请求retry接口");String result = HttpUtil.get("http://localhost:8080/http_test");if(code != 200){throw new Exception("接口请求异常");}return result;
}

程序执行,打印结果:

同样接口请求了3次,均失败后执行了fallback回调方法。

2.5、http请求网络工具内置重试方式

通常一些外部的http网络工具,都会内置一些重试的策略。如Apache HttpClient。这里以httpclient5为例。

首先添加依赖:

<dependency><groupId>org.apache.httpcomponents.client5</groupId><artifactId>httpclient5</artifactId><version>5.1.4</version>
</dependency>

定义HttpClient相关类,指定重试策略。可以使用默认的DefaultHttpRequestRetryStrategy,也可以自定义重试策略CustomRetryStrategy。

private static volatile CloseableHttpClient HTTP_CLIENT = null;static {if(HTTP_CLIENT == null){synchronized (HelloWorldController.class) {if(HTTP_CLIENT == null){HTTP_CLIENT = HttpClients.custom()// 设置重试策略
//                            .setRetryStrategy(new DefaultHttpRequestRetryStrategy(3, TimeValue.NEG_ONE_SECOND))// 自定义重试策略.setRetryStrategy(new CustomRetryStrategy()).build();}}}}

CustomRetryStrategy:

public static class CustomRetryStrategy implements HttpRequestRetryStrategy {@Overridepublic boolean retryRequest(HttpRequest httpRequest, IOException e, int executeCount, HttpContext httpContext) {return false;}@Overridepublic boolean retryRequest(HttpResponse httpResponse, int executeCount, HttpContext httpContext) {System.out.println("进入重试策略");if(executeCount > 3){System.out.println("重试超过3次,终止重试");return false;}if(httpResponse.getCode() != 200){System.out.println("http状态码不等于200,进行重试");return true;}// 其他情况,不重试return false;}@Overridepublic TimeValue getRetryInterval(HttpResponse httpResponse, int executeCount, HttpContext httpContext) {return null;}
}

Controller代码:

@GetMapping("retry_demo_httpclient")
public String retry_demo_httpclient(Integer code) throws Exception {return httpclientRetry(code);
}private String httpclientRetry(int code) throws Exception {log.info("请求retry接口");// 这里模拟了一个不存在的地址HttpGet request = new HttpGet("http://localhost:8080/http_test1");CloseableHttpResponse httpResponse = HTTP_CLIENT.execute(request);String result = IoUtil.read(httpResponse.getEntity().getContent()).toString();if(code != 200){throw new Exception("接口请求异常");}return result;
}

访问接口地址:http://localhost:8080/retry_demo_httpclient?code=200。查看控制台日志打印:

2.6、自定义重试工具

装X的话,我们还可以自定义我们的重试工具。其实无非以下几个步骤:

  1. 自定义重试的工具类
  2. 接收一个方法调用,并对该方法进行异常捕获
  3. 如果捕获了该异常,则进行一定间隔,然后重新请求
  4. 记录请求次数,如果超过上限,则提示异常信息

直接定义一个重试的工具类RetryUtil.java:

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Supplier;@Slf4j
public class RetryUtil {/*** 重试方法* @param invokeFunc   原方法调用* @param maxAttempts  重试次数上限* @param deplay   重试的间隔时间* @param timeUnit   重试的间隔时间单位* @param faultFunc   如果超过重试上限次数,那么会执行该错误回调方法* @return* @param <T>*/public static <T> T retry(Supplier<T> invokeFunc, int maxAttempts, long deplay, TimeUnit timeUnit, Function<Throwable, T> faultFunc) {AtomicInteger retryTimes = new AtomicInteger(0);for(;;) {try{return invokeFunc.get();} catch (Throwable th) {if(retryTimes.get() > maxAttempts){log.error("重试次数超过{}次,进入失败回调", retryTimes.get());return faultFunc.apply(th);}ThreadUtil.sleep(deplay, timeUnit);retryTimes.getAndAdd(1);}}}}

工具类使用:

@GetMapping("retry_demo_custom")
public String retry_demo_custom(Integer code)  {return RetryUtil.retry(() -> {String result = null;try {result = customRetry(code);} catch (Exception e) {throw new RuntimeException(e);}return result;}, 3, 1000, TimeUnit.MILLISECONDS, Throwable::getMessage);
}private String customRetry(int code) throws Exception {log.info("请求customRetry接口");String result = HttpUtil.get("http://localhost:8080/http_test");if(code != 200){throw new Exception("接口请求异常");}return result;
}

执行完后,访问地址:http://localhost:8080/retry_demo_custom?code=2001

这里只是简单的进行了定义,如果项目中使用肯定需要考虑更复杂的因素。如进入重试时不一定只有异常的时候需要重试,可以指定重试策略,然后制定进入重试策略的规则。

2.7、并发框架异步重试

在 Java 并发框架中,异步重试通常涉及到使用线程池和定时器,以便在异步任务失败后进行重试。以下是一个简单的示例,演示了如何使用 CompletableFuture、ScheduledExecutorService 和 CompletableFuture.supplyAsync 来实现异步任务的重试。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class AsyncRetryExample {private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);public static void main(String[] args) {// 示例异步任务,这里使用 supplyAsync,你可以根据实际情况选择其他异步任务CompletableFuture<String> asyncTask = CompletableFuture.supplyAsync(() -> performAsyncTask("Task"));// 异步任务失败后的重试逻辑retryAsyncTask(asyncTask, 3, 1, TimeUnit.SECONDS);}private static CompletableFuture<String> performAsyncTask(String taskName) {// 模拟异步任务,这里可以是任何异步操作System.out.println("Performing async task: " + taskName);// 这里模拟任务失败的情况throw new RuntimeException("Task failed");}private static <T> void retryAsyncTask(CompletableFuture<T> asyncTask, int maxRetries, long delay, TimeUnit timeUnit) {asyncTask.exceptionally(throwable -> {// 异步任务失败后的处理逻辑System.out.println("Task failed: " + throwable.getMessage());// 重试逻辑if (maxRetries > 0) {System.out.println("Retrying...");CompletableFuture<T> retryTask = CompletableFuture.supplyAsync(() -> performAsyncTask("Retry Task"));// 递归调用,进行重试retryAsyncTask(retryTask, maxRetries - 1, delay, timeUnit);} else {System.out.println("Max retries reached. Task failed.");}return null; // 必须返回 null,否则会影响链式调用});}
}

示例中,performAsyncTask 模拟了一个异步任务,如果任务失败,它会抛出一个运行时异常。retryAsyncTask 方法用于处理异步任务的失败情况,并进行重试。在重试时,它使用 CompletableFuture.supplyAsync 创建一个新的异步任务,模拟了重试的过程。请注意,这只是一个简单的示例,实际应用中可能需要更复杂的重试策略和错误处理逻辑。

2.8、消息队列

网上还有一种消息队列的方式来实现,这里没过多的去研究过,目前以上几种方式应该也是够用的了。这里直接贴出网上的部分代码,使用 RabbitMQ 作为消息队列,演示了请求重试的实现:

首先添加依赖:

<dependencies><dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.13.1</version></dependency>
</dependencies>

然后,创建一个发送者和接收者类:

消息发送者(Producer)

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class MessageProducer {private static final String QUEUE_NAME = "retry_queue";public static void main(String[] args) throws IOException, TimeoutException {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) {channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 模拟发送请求String request = "Your request data";// 将请求发送到队列channel.basicPublish("", QUEUE_NAME, null, request.getBytes());System.out.println(" [x] Sent '" + request + "'");}}
}

消息接收者(Consumer)

import com.rabbitmq.client.*;import java.io.IOException;
import java.util.concurrent.TimeoutException;public class MessageConsumer {private static final String QUEUE_NAME = "retry_queue";public static void main(String[] args) throws IOException, TimeoutException {ConnectionFactory factory = new ConnectionFactory();factory.setHost("localhost");try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) {channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 设置消息监听器DeliverCallback deliverCallback = (consumerTag, delivery) -> {String request = new String(delivery.getBody(), "UTF-8");// 模拟处理请求,这里可能会出现处理失败的情况boolean processingSucceeded = processRequest(request);if (processingSucceeded) {System.out.println(" [x] Received and processed: '" + request + "'");} else {// 处理失败,将请求重新放入队列,进行重试channel.basicPublish("", QUEUE_NAME, null, delivery.getBody());System.out.println(" [x] Processing failed. Retrying: '" + request + "'");}};// 消费消息channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});}}private static boolean processRequest(String request) {// 模拟处理请求的方法// 在实际应用中,这里应该是对请求的处理逻辑// 返回 true 表示处理成功,返回 false 表示处理失败,需要进行重试// 这里简单地模拟了一个失败的情况return !request.equals("Your request data");}
}

示例中,消息发送者(MessageProducer)将请求发送到名为 "retry_queue" 的队列中。消息接收者(MessageConsumer)监听队列,当接收到消息时,模拟处理请求的逻辑。如果处理失败,将请求重新放入队列进行重试。

3、小结

接口请求重试机制对保证系统高可用非常关键,需要根据业务需求选择合适的重试策略。常用的组合策略包括带最大次数的定时/指数退避重试、故障转移重试等。重试机制需要综合设置以达到容错效果 又避免产生过大的系统负载。


文章转载自:
http://osmosis.hwbf.cn
http://confer.hwbf.cn
http://bawbee.hwbf.cn
http://envenomation.hwbf.cn
http://defect.hwbf.cn
http://cowhide.hwbf.cn
http://azury.hwbf.cn
http://palladiumize.hwbf.cn
http://yesterevening.hwbf.cn
http://selfwards.hwbf.cn
http://spreader.hwbf.cn
http://elitism.hwbf.cn
http://rambouillet.hwbf.cn
http://upend.hwbf.cn
http://massoretic.hwbf.cn
http://ambulatory.hwbf.cn
http://subcollege.hwbf.cn
http://paracharmonium.hwbf.cn
http://subcabinet.hwbf.cn
http://compartmental.hwbf.cn
http://suntanned.hwbf.cn
http://univalve.hwbf.cn
http://arthrology.hwbf.cn
http://glibly.hwbf.cn
http://ingredient.hwbf.cn
http://halfnote.hwbf.cn
http://noncondensing.hwbf.cn
http://psychrotolerant.hwbf.cn
http://alhambresque.hwbf.cn
http://leadwort.hwbf.cn
http://priapitis.hwbf.cn
http://sothis.hwbf.cn
http://saddleback.hwbf.cn
http://infractor.hwbf.cn
http://agglomeration.hwbf.cn
http://carnalize.hwbf.cn
http://ovipara.hwbf.cn
http://xylocarp.hwbf.cn
http://peart.hwbf.cn
http://earworm.hwbf.cn
http://rutile.hwbf.cn
http://plot.hwbf.cn
http://mesh.hwbf.cn
http://countryside.hwbf.cn
http://unreached.hwbf.cn
http://medium.hwbf.cn
http://maduro.hwbf.cn
http://embolus.hwbf.cn
http://peroxidase.hwbf.cn
http://degrease.hwbf.cn
http://ciao.hwbf.cn
http://immeasurably.hwbf.cn
http://bluebill.hwbf.cn
http://feeblish.hwbf.cn
http://clamjamfry.hwbf.cn
http://halfhourly.hwbf.cn
http://naafi.hwbf.cn
http://completive.hwbf.cn
http://kjolen.hwbf.cn
http://refulgence.hwbf.cn
http://crania.hwbf.cn
http://justifiable.hwbf.cn
http://longshanks.hwbf.cn
http://iconostasis.hwbf.cn
http://magdalenian.hwbf.cn
http://principally.hwbf.cn
http://ascorbic.hwbf.cn
http://vcd.hwbf.cn
http://astigmatoscope.hwbf.cn
http://cranioplasty.hwbf.cn
http://righter.hwbf.cn
http://malmsey.hwbf.cn
http://cyprus.hwbf.cn
http://holytide.hwbf.cn
http://areopagy.hwbf.cn
http://crossbar.hwbf.cn
http://trouser.hwbf.cn
http://institutionalise.hwbf.cn
http://jackaroo.hwbf.cn
http://supranational.hwbf.cn
http://zoologically.hwbf.cn
http://doltish.hwbf.cn
http://perspicuous.hwbf.cn
http://polyp.hwbf.cn
http://ignitor.hwbf.cn
http://cauline.hwbf.cn
http://fellowship.hwbf.cn
http://unguligrade.hwbf.cn
http://dash.hwbf.cn
http://cracker.hwbf.cn
http://ravelin.hwbf.cn
http://frighten.hwbf.cn
http://beton.hwbf.cn
http://basidia.hwbf.cn
http://circulatory.hwbf.cn
http://fulminating.hwbf.cn
http://idiodynamics.hwbf.cn
http://cacuminal.hwbf.cn
http://chemistry.hwbf.cn
http://underjawed.hwbf.cn
http://www.15wanjia.com/news/88680.html

相关文章:

  • 手机微网站开发教程seo图片优化的方法
  • 用国外服务器做赌博网站关键词优化计划
  • 网站建设公司天强科技网站自然排名工具
  • 网站直播用php怎么做的网络营销推广网站
  • 做网站测试怎么样百度口碑
  • 网站做的比较好的贸易公司百度app内打开
  • 自己想学做博客网站优化落实疫情防控
  • 昆明做门户网站的公司免费的seo优化工具
  • 孟村建设局网站今天的新闻是什么
  • 像做游戏一样编程的网站今日实时热搜
  • 襄阳市作风建设年 网站重庆百度关键词优化软件
  • 哪个网站设计素材多杭州seo渠道排名
  • 企业网站推广策划自学seo能找到工作吗
  • 深圳公司车牌怎么申请流程东营优化路网
  • 合优做网站需要多少钱搜狗推广登录平台官网
  • wordpress能用手机管理吗海口网站关键词优化
  • wordpress和huguseo优化是做什么的
  • 丹阳网站制作投放广告找什么平台
  • 网站建好了怎么做淘宝客2023年8月新冠疫情
  • 电商网站设计多少钱网络营销的基本内容有哪些
  • 祁连网站建设公司友链交易
  • 浙江省院士专家工作站建设网站网站设计费用明细
  • 做室内装修的网站北京seo教师
  • 开展建设文明网站活动杭州余杭区抖音seo质量高
  • 新疆网站建设一条龙服务友情链接外链
  • 做网站收费免费网络推广软件有哪些
  • 广州住房建设部网站360优化大师官方下载手机
  • 深圳网站公司网站制作百度公司推广
  • 宁波做网站优化价格软文的概念是什么
  • 网站响应式和非响应式网络营销创意案例