装潢公司网站建设wap手机网站

news/2025/9/22 23:39:52/文章来源:
装潢公司网站建设,wap手机网站,代做ppt网站好,第一次做网站时是怎样的心情随着互联网的发展项目中的业务功能越来越复杂#xff0c;有一些基础服务我们不可避免的会去调用一些第三方的接口或者公司内其他项目中提供的服务#xff0c;但是远程服务的健壮性和网络稳定性都是不可控因素。 在测试阶段可能没有什么异常情况#xff0c;但上线后可能会出…随着互联网的发展项目中的业务功能越来越复杂有一些基础服务我们不可避免的会去调用一些第三方的接口或者公司内其他项目中提供的服务但是远程服务的健壮性和网络稳定性都是不可控因素。 在测试阶段可能没有什么异常情况但上线后可能会出现调用的接口因为内部错误或者网络波动而出错或返回系统异常因此我们必须考虑加上重试机制 重试机制 可以提高系统的健壮性并且减少因网络波动依赖服务临时不可用带来的影响让系统能更稳定的运行 1. 手动重试 手动重试使用 while 语句进行重试 Service public class OrderServiceImpl implements OrderService {public void addOrder() {int times  1;while (times  5) {try {// 故意抛异常int i  3 / 0;// addOrder} catch (Exception e) {System.out.println(重试  times  次);Thread.sleep(2000);times;if (times  5) {throw new RuntimeException(不再重试);}}}} }上述代码看上去可以解决重试问题但实际上存在一些弊端 由于没有重试间隔很可能远程调用的服务还没有从网络异常中恢复所以有可能接下来的几次调用都会失败代码侵入式太高调用方代码不够优雅项目中远程调用的服务可能有很多每个都去添加重试会出现大量的重复代码 2. 静态代理 上面的处理方式由于需要对业务代码进行大量修改虽然实现了功能但是对原有代码的侵入性太强可维护性差。所以需要使用一种更优雅一点的方式不直接修改业务代码那要怎么做呢 其实很简单直接在业务代码的外面再包一层就行了代理模式在这里就有用武之地了。 Service public class OrderServiceProxyImpl implements OrderService {Autowiredprivate OrderServiceImpl orderService;Overridepublic void addOrder() {int times  1;while (times  5) {try {// 故意抛异常int i  3 / 0;orderService.addOrder();} catch (Exception e) {System.out.println(重试  times  次);try {Thread.sleep(2000);} catch (InterruptedException ex) {ex.printStackTrace();}times;if (times  5) {throw new RuntimeException(不再重试);}}}} }这样重试逻辑就都由代理类来完成原业务类的逻辑就不需要修改了以后想修改重试逻辑也只需要修改这个类就行了 代理模式虽然要更加优雅但是如果依赖的服务很多的时候要为每个服务都创建一个代理类显然过于麻烦而且其实重试的逻辑都大同小异无非就是重试的次数和延时不一样而已。如果每个类都写这么一长串类似的代码显然不优雅 3. JDK 动态代理 这时候动态代理就闪亮登场了。只需要写一个代理处理类就 ok 了 public class RetryInvocationHandler implements InvocationHandler {private final Object subject;public RetryInvocationHandler(Object subject) {this.subject  subject;}Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {int times  1;while (times  5) {try {// 故意抛异常int i  3 / 0;return method.invoke(subject, args);} catch (Exception e) {System.out.println(重试【  times  】次);try {Thread.sleep(2000);} catch (InterruptedException ex) {ex.printStackTrace();}times;if (times  5) {throw new RuntimeException(不再重试);}}}return null;}public static Object getProxy(Object realSubject) {InvocationHandler handler  new RetryInvocationHandler(realSubject);return Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);}}测试 RestController RequestMapping(/order) public class OrderController {Qualifier(orderServiceImpl)Autowiredprivate OrderService orderService;GetMapping(/addOrder)public String addOrder() {OrderService orderServiceProxy  (OrderService)RetryInvocationHandler.getProxy(orderService);orderServiceProxy.addOrder();return addOrder;}}动态代理可以将重试逻辑都放到一块显然比直接使用代理类要方便很多也更加优雅。 这里使用的是JDK动态代理因此就存在一个天然的缺陷如果想要被代理的类没有实现任何接口那么就无法为其创建代理对象这种方式就行不通了 4. CGLib 动态代理 既然已经说到了 JDK 动态代理那就不得不提 CGLib 动态代理了。使用 JDK 动态代理对被代理的类有要求不是所有的类都能被代理而 CGLib 动态代理则刚好解决了这个问题 Component public class CGLibRetryProxyHandler implements MethodInterceptor {private Object target;Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {int times  1;while (times  5) {try {// 故意抛异常int i  3 / 0;return method.invoke(target, objects);} catch (Exception e) {System.out.println(重试【  times  】次);try {Thread.sleep(2000);} catch (InterruptedException ex) {ex.printStackTrace();}times;if (times  5) {throw new RuntimeException(不再重试);}}}return null;}public Object getCglibProxy(Object objectTarget){this.target  objectTarget;Enhancer enhancer  new Enhancer();enhancer.setSuperclass(objectTarget.getClass());enhancer.setCallback(this);Object result  enhancer.create();return result;}}测试 GetMapping(/addOrder) public String addOrder() {OrderService orderServiceProxy  (OrderService) cgLibRetryProxyHandler.getCglibProxy(orderService);orderServiceProxy.addOrder();return addOrder; }这样就很棒了完美的解决了 JDK 动态代理带来的缺陷。优雅指数上涨了不少。 但这个方案仍旧存在一个问题那就是需要对原来的逻辑进行侵入式修改在每个被代理实例被调用的地方都需要进行调整这样仍然会对原有代码带来较多修改 5. 手动 Aop 考虑到以后可能会有很多的方法也需要重试功能咱们可以将重试这个共性功能通过 AOP 来实现使用 AOP 来为目标调用设置切面即可在目标方法调用前后添加一些重试的逻辑 dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactId /dependency自定义注解 Documented Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface MyRetryable {// 最大重试次数int retryTimes() default 3;// 重试间隔int retryInterval() default 1;} Slf4j Aspect Component public class RetryAspect {Pointcut(annotation(com.hcr.sbes.retry.annotation.MyRetryable))private void retryMethodCall(){}Around(retryMethodCall())public Object retry(ProceedingJoinPoint joinPoint) throws InterruptedException {// 获取重试次数和重试间隔MyRetryable retry  ((MethodSignature)joinPoint.getSignature()).getMethod().getAnnotation(MyRetryable.class);int maxRetryTimes  retry.retryTimes();int retryInterval  retry.retryInterval();Throwable error  new RuntimeException();for (int retryTimes  1; retryTimes  maxRetryTimes; retryTimes){try {Object result  joinPoint.proceed();return result;} catch (Throwable throwable) {error  throwable;log.warn(调用发生异常开始重试retryTimes:{}, retryTimes);}Thread.sleep(retryInterval * 1000L);}throw new RuntimeException(重试次数耗尽, error);}}给需要重试的方法添加注解 MyRetryable Service public class OrderServiceImpl implements OrderService {OverrideMyRetryable(retryTimes  5, retryInterval  2)public void addOrder() {int i  3 / 0;// addOrder}}这样即不用编写重复代码实现上也比较优雅了一个注解就实现重试。 6. spring-retry dependencygroupIdorg.springframework.retry/groupIdartifactIdspring-retry/artifactId /dependency开启重试功能在启动类或者配置类上添加 EnableRetry 注解 在需要重试的方法上添加 Retryable 注解 Slf4j Service public class OrderServiceImpl implements OrderService {OverrideRetryable(maxAttempts  3, backoff  Backoff(delay  2000, multiplier  2))public void addOrder() {System.out.println(重试...);int i  3 / 0;// addOrder}Recoverpublic void recover(RuntimeException e) {log.error(达到最大重试次数, e);}}该方法调用后会进行重试最大重试次数为 3第一次重试间隔为 2s之后以 2 倍大小进行递增第二次重试间隔为 4 s第三次为 8s Spring 的重试机制还支持很多很有用的特性由三个注解完成 RetryableBackoffRecover 查看 Retryable 注解源码指定异常重试、次数 public interface Retryable {// 设置重试拦截器的 bean 名称String interceptor() default ;// 只对特定类型的异常进行重试。默认所有异常Class? extends Throwable[] value() default {};// 包含或者排除哪些异常进行重试Class? extends Throwable[] include() default {};Class? extends Throwable[] exclude() default {};// l设置该重试的唯一标志用于统计输出String label() default ;boolean stateful() default false;// 最大重试次数默认为 3 次int maxAttempts() default 3;String maxAttemptsExpression() default ;// 设置重试补偿机制可以设置重试间隔并且支持设置重试延迟倍数Backoff backoff() default Backoff;// 异常表达式在抛出异常后执行以判断后续是否进行重试String exceptionExpression() default ;String[] listeners() default {}; }Backoff 注解 指定重试回退策略如果因为网络波动导致调用失败立即重试可能还是会失败最优选择是等待一小会儿再重试。决定等待多久之后再重试的方法。通俗的说就是每次重试是立即重试还是等待一段时间后重试 Recover 注解 进行善后工作当重试达到指定次数之后会调用指定的方法来进行日志记录等操作 注意 Recover 注解标记的方法必须和被 Retryable 标记的方法在同一个类中重试方法抛出的异常类型需要与 recover() 方法参数类型保持一致recover() 方法返回值需要与重试方法返回值保证一致recover() 方法中不能再抛出 Exception否则会报无法识别该异常的错误 这里还需要再提醒的一点是由于 Spring Retry 用到了 Aspect 增强所以就会有使用 Aspect 不可避免的坑——方法内部调用如果被 Retryable 注解的方法的调用方和被调用方处于同一个类中那么重试将会失效 通过以上几个简单的配置可以看到 Spring Retry 重试机制考虑的比较完善比自己写AOP实现要强大很多 弊端 但也还是存在一定的不足Spring的重试机制只支持对 异常 进行捕获而无法对返回值进行校验 Retryable public String hello() {long current  count.incrementAndGet();System.out.println(第  current 次被调用);if (current % 3 ! 0) {log.warn(调用失败);return error;}return success; }因此就算在方法上添加 Retryable也无法实现失败重试 除了使用注解外Spring Retry 也支持直接在调用时使用代码进行重试 Test public void normalSpringRetry() {// 表示哪些异常需要重试,key表示异常的字节码,value为true表示需要重试MapClass? extends Throwable, Boolean exceptionMap  new HashMap();exceptionMap.put(HelloRetryException.class, true);// 构建重试模板实例RetryTemplate retryTemplate  new RetryTemplate();// 设置重试回退操作策略主要设置重试间隔时间FixedBackOffPolicy backOffPolicy  new FixedBackOffPolicy();long fixedPeriodTime  1000L;backOffPolicy.setBackOffPeriod(fixedPeriodTime);// 设置重试策略主要设置重试次数int maxRetryTimes  3;SimpleRetryPolicy retryPolicy  new SimpleRetryPolicy(maxRetryTimes, exceptionMap);retryTemplate.setRetryPolicy(retryPolicy);retryTemplate.setBackOffPolicy(backOffPolicy);Boolean execute  retryTemplate.execute(//RetryCallbackretryContext - {String hello  helloService.hello();log.info(调用的结果:{}, hello);return true;},// RecoverCallBackretryContext - {//RecoveryCallbacklog.info(已达到最大重试次数);return false;}); }此时唯一的好处是可以设置多种重试策略 NeverRetryPolicy只允许调用RetryCallback一次不允许重试AlwaysRetryPolicy允许无限重试直到成功此方式逻辑不当会导致死循环SimpleRetryPolicy固定次数重试策略默认重试最大次数为3次RetryTemplate默认使用的策略TimeoutRetryPolicy超时时间重试策略默认超时时间为1秒在指定的超时时间内允许重试ExceptionClassifierRetryPolicy设置不同异常的重试策略类似组合重试策略区别在于这里只区分不同异常的重试CircuitBreakerRetryPolicy有熔断功能的重试策略需设置3个参数openTimeout、resetTimeout和delegateCompositeRetryPolicy组合重试策略有两种组合方式乐观组合重试策略是指只要有一个策略允许即可以重试悲观组合重试策略是指只要有一个策略不允许即可以重试但不管哪种组合方式组合中的每一个策略都会执行 7. guava-retry 和 Spring Retry 相比Guava Retry 具有更强的灵活性并且能够根据 返回值 来判断是否需要重试 dependencygroupIdcom.github.rholder/groupIdartifactIdguava-retrying/artifactIdversion2.0.0/version /dependency Override public String guavaRetry(Integer num) {RetryerString retryer  RetryerBuilder.StringnewBuilder()//无论出现什么异常都进行重试.retryIfException()//返回结果为 error时进行重试.retryIfResult(result - Objects.equals(result, error))//重试等待策略等待 2s 后再进行重试.withWaitStrategy(WaitStrategies.fixedWait(2, TimeUnit.SECONDS))//重试停止策略重试达到 3 次.withStopStrategy(StopStrategies.stopAfterAttempt(3)).withRetryListener(new RetryListener() {Overridepublic V void onRetry(AttemptV attempt) {System.out.println(RetryListener: 第  attempt.getAttemptNumber()  次调用);}}).build();try {retryer.call(() - testGuavaRetry(num));} catch (Exception e) {e.printStackTrace();}return test; }先创建一个Retryer实例然后使用这个实例对需要重试的方法进行调用可以通过很多方法来设置重试机制 retryIfException()对所有异常进行重试retryIfRuntimeException()设置对指定异常进行重试retryIfExceptionOfType()对所有 RuntimeException 进行重试retryIfResult()对不符合预期的返回结果进行重试 还有五个以 withXxx 开头的方法用来对重试策略/等待策略/阻塞策略/单次任务执行时间限制/自定义监听器进行设置以实现更加强大的异常处理 withRetryListener()设置重试监听器用来执行额外的处理工作 withWaitStrategy()重试等待策略withStopStrategy()停止重试策略withAttemptTimeLimiter设置任务单次执行的时间限制如果超时则抛出异常 withBlockStrategy()设置任务阻塞策略即可以设置当前重试完成下次重试开始前的这段时间做什么事情 总结 从手动重试到使用 Spring AOP 自己动手实现再到站在巨人肩上使用特别优秀的开源实现 Spring Retry 和 Google guava-retrying经过对各种重试实现方式的介绍可以看到以上几种方式基本上已经满足大部分场景的需要 如果是基于 Spring 的项目使用 Spring Retry 的注解方式已经可以解决大部分问题如果项目没有使用 Spring 相关框架则适合使用 Google guava-retrying自成体系使用起来更加灵活强大

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/910766.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

个人怎么做网站排名优化鲜花网站素材

对象库接口:ObjectLib 迷你世界 更新时间: 2023-04-26 20:21:09 具体函数名及描述如下: 序号 函数名 函数描述 1 getAreaData(...) 获取区域数据 2 getPositionData(...) 获取位置数据 3 getLivingData(...) 获取生物数据 4 getItemDat…

淘宝网站是谁做的好建设单位网站需求报告

专业英语 部分专业名词 短语 在这里插入图片描述

母版页做网站例子wordpress 介绍插件

(一)单选 下列属于链路状态协议的是? Direct static FTP OSPF 解析: FTP:文件传输协议 OSPF:链路状态路由协议 如下图所示的网络主机A通过Telnet登录到路由器A然后在远程的界面通过FTP获取路由器的配置文件&…

建筑学网站推荐福田公司在哪里

nba数据库统计The idea is not to block every shot. The idea is to make your opponent believe that you might block every shot. — Bill Russel这个想法不是要阻止每一个镜头。 这个想法是让你的对手相信你可能会阻挡每一个投篮。 —比尔罗素 The block in basketball ha…

网站建设 百度云盘云设计平台

今天带你了解期权开户零门槛怎么操作?期权不满50w的开户方式。在股票期权市场上,期权交易是一种非常受欢迎的投资方式。它不仅可以增加投资组合的多样性,还可以为投资者提供一定的保护和利润机会,比如通过买入认股期权做空对冲大盘…

北京大兴专业网站建设公司wordpress无法加载图片

大模型技术的不断升级及应用落地,正在推动人工智能技术发展进入新的阶段,而智能化快速增长和发展的市场对芯片提出了更高的要求:高算力、高性能、灵活性、安全性。可重构计算区别于传统CPU、GPU,以指令驱动的串行执行方式&#xf…

网站建设与维护asp沈阳网站制作推广

C#(读作“C-sharp”)是一种由微软公司开发的通用高级编程语言,自2000年发布以来,它迅速成为开发人员构建各种类型应用程序的首选语言之一。C#的设计目标是成为一种简单、现代、面向对象的语言,它结合了C的强大功能和Ja…

做宣传册网站网站开发工作怎样

【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax概述 【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax快速入门 【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax类图 【大数据进阶第三阶段之Datax学习笔记】使用…

网站首页site不到 a5android 开发wordpress

【K3s】在 AWS EC2 上运行生产 K3s 集群 本文将介绍如何在 AWS EC2 上运行 K3s。您将创建一个 EC2 实例并在 AWS 上运行单节点 K3s 集群。 自托管的 K3s 允许您在裸金属上运行 Kubernetes,并应用较小、低资源工作负载的原则。哦,你还可以控制你的控制平面。这有点像逃离托管…

北京 意大利学签 北京意大利签证中心 贵宾 vip vfs

意大利签证中心实际位置是在这块这个vfs威孚仕,实际上这一大块一整层都是它的地方。左边和右边都可以进。但是意大利签证中心在最右边,所以最好还是右边那个门进。注意虽然https://prenotami.esteri.it 上显示上午/下…

VS项目分层 -- ASP.NET Core Web API 项目

VS项目分层 -- ASP.NET Core Web API 项目1.Connected Services 用于连接外部服务(Azure、数据库、第三方 API 等)。现在可以不用管。 2.Properties 存放项目属性,比如 launchSettings.json(调试配置,决定用什么端…

第1周

1 linux系统安装+远程登录 1.1 系统安装 1.1.1 常见的linux内核Redhat家族RHEL(红帽商业版)Centos/RokeyFedora OpenEulerDebian家族UbuntuopenKylinKali1.1.2 系统安装 略 1.1.3 命令行界面/终端/控制台的几种形式物理…

做微信h5的网站北京网站优化价格

java.sql.Driver接口规定了Driver应该具有以下功能,重要的有三个acceptsURL判断jdbcUrl是否支持、创建一个连接、获取属性信息,三个主要接口。 下边以 NonRegisteringDriver​ 类的源码简单分析以下。 acceptsURL acceptsURL(String url) 方法用来测试…

wordpress 默认搜索网站优化方案和实施

点击上方“算法猿的成长“,关注公众号,选择加“星标“或“置顶”总第 142 篇文章,本文大约 1300 字,阅读大约需要 5 分钟前言今天介绍一个 Github 项目---集成了 27 种 GAN 模型的 Jittor-GAN,项目地址:htt…

大唐网站首页北京代理记账公司

引言 什么是数据结构? 数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。 简单来说,数据结构就是设计数据以何种方式组织并存储在计算机中。 比如:列表,集合和字典等都是数据结构 N.W…

电子商务类网站建设实训报告lol网站模板

安装(本文以ubuntu系统为例) 单节点设置​ 为了延迟演示分布式环境的复杂性,我们将首先在单个服务器或虚拟机上部署ClickHouse。ClickHouse通常是从deb或rpm包安装,但对于不支持它们的操作系统也有其他方法。 例如,…

建站公司的工作流程购物节优惠卷网站怎么做

63. APP端特有的测试 参考:APP专项测试、APP应用测试 crash和anr的区别 1)网络测试 2)中断测试 3)安装、卸载测试 4)兼容测试 5)性能测试(耗电量、流量、内存、服务器端) 6&#xf…

flash网站片头动画黄冈网站建设报价

目录 一、什么是递归 1.1.递归的思想 1.2.递归的限制条件 二、举例体会 2.1.求n的阶乘 2.2.顺序打印整数的每一位 2.3.斐波那契数列 三、递归与迭代 一、什么是递归 在学习C语言的过程中,我们经常会跟递归打交道,什么是递归呢?它其实…

哪里有专业做网站的网站怎么做宣传

大写数字网今天精心准备的是《123456789a》,下面是详解!html里,怎么把<a>123456789</a>弄到中间来例如把a标签的字移到中间来<a123456789><&#…

鲁斌 42450745 网站建设你需要网站建设

文章目录 场景分析方法的幂等分布式锁Redis实现分布式锁抢锁的设计思路 分布式锁案例 直击面试rocketmq什么时候重复消费消息丢失的问题消息在哪里丢失发送端确保发送成功并且配合失败的业务处理消费端确保消息不丢失rocketmq 主从同步刷盘 场景分析 分布式系统架构中,队列是分…