在工作中,经常会遇到与其他业务系统进行通讯交互,无非是通过调用对方的http接口进行数据的交互,少则一个,多则几十个。
随着Oauth2.0协议在各个业务系统的应用,调用其他业务系统的方式也是千篇一律:首先通过对方颁发的客户端信息进行客户端认证,认证通过之后获取accessToken,随后所有业务接口携带accessToken调用接口。一些安全性较高的系统,还会增加一些加解密、验签、完整性、证书的验证。
当前大部分思路是通过开发各个接口调用逻辑功能,然后通过统一封装http调用工具进行接口调用,整个代码会显得特别臃肿,同时最近在读feign源码,因此仿照feign客户端进行代码改造,旨在优化业务代码,同时也加深对feign的理解。
只需要按照接口出入参拼接实体类,再接口中维护接口信息即可。一些公共的接口调用逻辑,在动态代理的InvocationHandler中统一进行处理(序列化、反序列化、远程接口调用、异常处理等等)。
同时该部分代码单独打包成jar包,易于维护及管理。
@InvokeClient(value="/v1/api", name="requestClient", configuration={RemoteCallConfig.class})publicinterfaceRequestClient{@InvokeRequest(value="/queryUser",method=HttpMethod.POST)@BreakerCommand(fallback=RequestClientFallback.class)publicResponseDto<User>queryUser(User user);}
项目地址:https://github.com/beardlessCat/simple-remote-call,喜欢的烦请star
该版本一些远程客户端的声明都必须在client包内,这样设计的初始目的主要是想规范将客户端的声明与客户端的调用区分开,使得代码更加的整洁已于管理。有需要改动时仅仅调整client包即可,
无需调整引入该包的相关代码。但是此种方式生成的依赖包仅仅能够供某一特定系统进行使用,系统兼容性较差。
该版本建议将客户端的声明存放到引入该包的模块或系统中,这样的话,client包仅仅作为远程调用的工具,客户端的声明需在引入该包的模块或者系统中自行声明,
优劣势与1.0.x相反,同时这种方式也是openfeign的模式。后续的一些维护及升级也是主要基于此版本。
整个功能要实现最主要需要完成两点:远程调用client自动注入及动态代理生成生成客户端实现类进行远程调用处理。当这两个点完成后,其他的就剩下一下
代理逻辑的处理了。
通过接口熔断管理器管理接口状态,对接口进行熔断保护
(1)接口状态说明
接口基于断路器状态分为三种:OPEN,HAlf-OPEN,CLOSE
(2)接口状态变更转换图
(3)接口状态流程图
(4)熔断器测试日志
: 【断路器变为CLOSE】 : BreakerStateManager(failCount=0, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@43b23436) : 接口调用失败! : BreakerStateManager(failCount=1, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@43b23436) : 接口调用失败! : BreakerStateManager(failCount=2, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@43b23436) : 接口调用失败! : BreakerStateManager(failCount=3, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@43b23436) : 接口调用失败! : BreakerStateManager(failCount=4, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@43b23436) : 接口调用失败! =============================================================================================== : 【断路器变为OPEN】 : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@189436cd) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@189436cd) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@189436cd) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@189436cd) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@189436cd) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : 【断路器变为HALF-OPEN】 : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@4cef79fb) : 接口调用失败! : BreakerStateManager(failCount=6, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=1, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@4cef79fb) : 接口调用失败! : BreakerStateManager(failCount=7, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=2, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@4cef79fb) : 接口调用失败! : BreakerStateManager(failCount=8, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=3, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@4cef79fb) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=8, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=3, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@4cef79fb) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=8, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=3, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@4cef79fb) : 接口调用失败! : BreakerStateManager(failCount=9, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=4, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@4cef79fb) : 接口调用失败! : 【断路器变为OPEN】 : BreakerStateManager(failCount=10, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@485fb0e8) : 【断路器变为HALF-OPEN】 : BreakerStateManager(failCount=10, successCount=1, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@6bb3d520) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=10, successCount=1, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@6bb3d520) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=10, successCount=1, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@6bb3d520) : BreakerStateManager(failCount=10, successCount=2, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@6bb3d520) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=10, successCount=2, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@6bb3d520) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=10, successCount=2, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@6bb3d520) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=10, successCount=2, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@6bb3d520) : BreakerStateManager(failCount=10, successCount=3, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@6bb3d520) : BreakerStateManager(failCount=10, successCount=4, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@6bb3d520) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=10, successCount=4, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@6bb3d520) =============================================================================================== : 【断路器变为CLOSE】 : BreakerStateManager(failCount=0, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@44348bd0) : BreakerStateManager(failCount=0, successCount=1, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@44348bd0) : BreakerStateManager(failCount=0, successCount=2, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@44348bd0) : BreakerStateManager(failCount=0, successCount=3, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@44348bd0) : BreakerStateManager(failCount=0, successCount=4, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@44348bd0) : 接口调用失败! : BreakerStateManager(failCount=1, successCount=4, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@44348bd0) : 接口调用失败! : BreakerStateManager(failCount=2, successCount=4, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@44348bd0) : 接口调用失败! : BreakerStateManager(failCount=3, successCount=4, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@44348bd0) : 接口调用失败! : BreakerStateManager(failCount=4, successCount=4, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@44348bd0) : 接口调用失败! =============================================================================================== : 【断路器变为OPEN】 : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.OpenState@2e97b6dc) =============================================================================================== : 【断路器变为HALF-OPEN】 : BreakerStateManager(failCount=5, successCount=1, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@5143c073) com.bigyj.exception.MethodNotAvailableException: 服务已熔断,请稍等重试! : BreakerStateManager(failCount=5, successCount=1, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@5143c073) : BreakerStateManager(failCount=5, successCount=2, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@5143c073: BreakerStateManager(failCount=5, successCount=3, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@5143c073) : BreakerStateManager(failCount=5, successCount=4, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.HalfOpenState@5143c073) =============================================================================================== : 【断路器变为CLOSE】 : BreakerStateManager(failCount=0, successCount=0, maxOpenToTryTime=60000, maxFailCount=5, maxSuccessCount=5, openRetryCount=0, maxOpenRetryCount=5, breakerState=com.bigyj.breaker.state.ClosedState@7236669a)
通过ImportBeanDefinitionRegistrar进行依赖注入
publicclassClientBeanDefinitionRegistrarimplementsImportBeanDefinitionRegistrar,ResourceLoaderAware,EnvironmentAware{privateEnvironment environment;privateResourceLoader resourceLoader;/** * 自动注入相关类 * @param importingClassMetadata * @param registry */@OverridepublicvoidregisterBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry){}@OverridepublicvoidsetEnvironment(Environment environment){this.environment= environment;}@OverridepublicvoidsetResourceLoader(ResourceLoader resourceLoader){this.resourceLoader= resourceLoader;}}
通过自定义FactoryBean,在getObject方法中使用代理模式,动态生成相关类
publicclassInvokeClientFactoryBeanimplementsFactoryBean<Object>,ApplicationContextAware{privateApplicationContext applicationContext;@SetterprivateClass<?> type;@SetterprivateString path;/** * 生成代理对象 * @return * @throws Exception */@OverridepublicObjectgetObject(){returnProxy.newProxyInstance(type.getClassLoader(),newClass<?>[]{type}, invocationHandler);}@OverridepublicClass<?>getObjectType(){returnthis.type;}@OverridepublicvoidsetApplicationContext(ApplicationContext applicationContext)throwsBeansException{this.applicationContext= applicationContext;}}