java-retry(重试)-spring-retry--guava-retrying-详解

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

1javaretry(重试)springretry,guavaretrying详解系列说明情景导⼊简单的需求代码谈话重试重试作⽤V.⽀持重试版本思考实现V.代理模式版本易于维护代理模式实现V.动态代理模式⽅便拓展代码实现V.动态代理模式增强对话字节码技术实现V.AOP实现对话设计思路实现⽅法的使⽤V.spring-retry版本对话2思考spring-retry注解式使⽤缺陷注解介绍@EnableRetry@Retryable@Backoff@Recover⽅法式使⽤spring-retry结构概览重试策略重试回退策略guava-retrying谈话guava-retrying代码例⼦⼊⻔案例重试策略guava-retrying简介RetryerBuilder主要接⼝总结优雅重试共性和原理优雅重试适⽤场景谈话javaretry的⼀步步实现机制。系列说明3产品经理:实现⼀个按条件,查询⽤户信息的服务。⼩明:好的。没问题。UserService.java1publicinterfaceUserService{23/**4*根据条件查询⽤户信息5*@paramcondition条件6*@returnUser信息7*/8UserqueryUser(QueryUserConditioncondition);910}UserServiceImpl.java1publicclassUserServiceImplimplementsUserService{23privateOutServiceoutService;45publicUserServiceImpl(OutServiceoutService){6this.outService=outService;java-retry源码地址情景导⼊简单的需求代码47}89@Override10publicUserqueryUser(QueryUserConditioncondition){11outService.remoteCall();12returnnewUser();13}1415}项⽬经理:这个服务有时候会失败,你看下。⼩明:OutService在是⼀个RPC的外部服务,但是有时候不稳定。项⽬经理:如果调⽤失败了,你可以调⽤的时候重试⼏次。你去看下重试相关的东⻄对于重试是有场景限制的,不是什么场景都适合重试,⽐如参数校验不合法、写操作等(要考虑写是否幂等)都不适合重试。远程调⽤超时、⽹络突然中断可以重试。在微服务治理框架中,通常都有⾃⼰的重试与超时配置,⽐如dubbo可以设置retries=1,timeout=500调⽤失败只重试1次,超过500ms调⽤仍未返回则调⽤失败。⽐如外部RPC调⽤,或者数据⼊库等操作,如果⼀次操作失败,可以进⾏多次重试,提⾼调⽤成功的可能性。谈话重试重试作⽤V1.0⽀持重试版本思考5⼩明:我⼿头还有其他任务,这个也挺简单的。5分钟时间搞定他。UserServiceRetryImpl.java1publicclassUserServiceRetryImplimplementsUserService{23@Override4publicUserqueryUser(QueryUserConditioncondition){5inttimes=0;6OutServiceoutService=newAlwaysFailOutServiceImpl();78while(timesRetryConstant.MAX_TIMES){9try{10outService.remoteCall();11returnnewUser();12}catch(Exceptione){13times++;1415if(times=RetryConstant.MAX_TIMES){16thrownewRuntimeException(e);17}18}19}2021returnnull;22}2324}实现V1.1代理模式版本易于维护6项⽬经理:你的代码我看了,功能虽然实现了,但是尽量写的易于维护⼀点。⼩明:好的。(⼼想,是说要写点注释什么的?)为其他对象提供⼀种代理以控制对这个对象的访问。在某些情况下,⼀个对象不适合或者不能直接引⽤另⼀个对象,⽽代理对象可以在客户端和⽬标对象之间起到中介作⽤。其特征是代理与委托类有同样的接⼝。⼩明想到以前看过的代理模式,⼼想⽤这种⽅式,原来的代码改动量较少,以后想改起来也⽅便些。UserServiceProxyImpl.java1publicclassUserServiceProxyImplimplementsUserService{23privateUserServiceuserService=newUserServiceImpl();45@Override6publicUserqueryUser(QueryUserConditioncondition){7inttimes=0;89while(timesRetryConstant.MAX_TIMES){10try{11returnuserService.queryUser(condition);12}catch(Exceptione){13times++;1415if(times=RetryConstant.MAX_TIMES){16thrownewRuntimeException(e);17}代理模式实现718}19}20returnnull;21}2223}项⽬经理:⼩明啊,这⾥还有个⽅法也是同样的问题。你也给加上重试吧。⼩明:好的。⼩明⼼想,我在写⼀个代理,但是转念冷静了下来,如果还有个服务也要重试怎么办呢?RoleService.java1publicinterfaceRoleService{23/**4*查询5*@paramuser⽤户信息6*@return是否拥有权限7*/8booleanhasPrivilege(Useruser);910}DynamicProxy.javaV1.2动态代理模式⽅便拓展代码实现81publicclassDynamicProxyimplementsInvocationHandler{23privatefinalObjectsubject;45publicDynamicProxy(Objectsubject){6this.subject=subject;7}89@Override10publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{11inttimes=0;1213while(timesRetryConstant.MAX_TIMES){14try{15//当代理对象调⽤真实对象的⽅法时,其会⾃动的跳转到代理对象关联的handler对象的invoke⽅法来进⾏调⽤16returnmethod.invoke(subject,args);17}catch(Exceptione){18times++;1920if(times=RetryConstant.MAX_TIMES){21thrownewRuntimeException(e);22}23}24}2526returnnull;27}2829/**30*获取动态代理31*32*@paramrealSubject代理对象33*/34publicstaticObjectgetProxy(ObjectrealSubject){35//我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调⽤其⽅法的36InvocationHandlerhandler=newDynamicProxy(realSubject);37returnProxy.newProxyInstance(handler.getClass().getClassLoa9der(),38realSubject.getClass().getInterfaces(),handler);39}4041}测试代码1@Test2publicvoidfailUserServiceTest(){3UserServicerealService=newUserServiceImpl();4UserServiceproxyService=(UserService)DynamicProxy.getProxy(realService);56Useruser=proxyService.queryUser(newQueryUserCondition());7LOGGER.info(failUserServiceTest:+user);8}91011@Test12publicvoidroleServiceTest(){13RoleServicerealService=newRoleServiceImpl();14RoleServiceproxyService=(RoleService)DynamicProxy.getProxy(realService);1516booleanhasPrivilege=proxyService.hasPrivilege(newUser());17LOGGER.info(roleServiceTest:+hasPrivilege);18}V1.3动态代理模式增强对话10项⽬经理:⼩明,你动态代理的⽅式是挺会偷懒的,可是我们有的类没有接⼝。这个问题你要解决⼀下。⼩明:好的。(谁?写服务竟然不定义接⼝)ResourceServiceImpl.java1publicclassResourceServiceImpl{23/**4*校验资源信息5*@paramuser⼊参6*@return是否校验通过7*/8publicbooleancheckResource(Useruser){9OutServiceoutService=newAlwaysFailOutServiceImpl();10outService.remoteCall();11returntrue;12}1314}⼩明看了下⽹上的资料,解决的办法还是有的。CGLIBCGLIB是⼀个功能强⼤、⾼性能和⾼质量的代码⽣成库,⽤于扩展JAVA类并在运⾏时实现接⼝。javassistjavassist(Java编程助⼿)使Java字节码操作变得简单。它是Java中编辑字节码的类库;它允许Java程序在运⾏时定义新类,并在JVM加载类⽂件时修改类⽂件。与其他类似的字节码编辑器不同,Javassist提供了两个级别的API:源级和字节码级。字节码技术11如果⽤户使⽤源代码级API,他们可以编辑类⽂件,⽽不需要了解Java字节码的规范。整个API只使⽤Java语⾔的词汇表进⾏设计。您甚⾄可以以源⽂本的形式指定插⼊的字节码;Javassist动态编译它。另⼀⽅⾯,字节码级API允许⽤户直接编辑类⽂件作为其他编辑器。ASMASM是⼀个通⽤的Java字节码操作和分析框架。它可以⽤来修改现有的类或动态地⽣成类,直接以⼆进制形式。ASM提供了⼀些通⽤的字节码转换和分析算法,可以从这些算法中构建⾃定义复杂的转换和代码分析⼯具。ASM提供与其他Java字节码框架类似的功能,但主要关注性能。因为它的设计和实现都尽可能地⼩和快,所以⾮常适合在动态系统中使⽤(当然也可以以静态的⽅式使⽤,例如在编译器中)。⼩明看了下,就选择使⽤CGLIB。CglibProxy.java1publicclassCglibProxyimplementsMethodInterceptor{23@Override4publicObjectintercept(Objecto,Methodmethod,Object[]objects,MethodProxymethodProxy)throwsThrowable{5inttimes=0;67while(timesRetryConstant.MAX_TIMES){8try{

1 / 33
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功