架构
概述
ServiceKeeper总体设计遵循简单易用的原则,整体架构也比较简洁,如下图所示:
其中:箭头所示方法表示请求正常的执行流程,特别重要地是:
- 通常来说,只有熔断后的请求才会走降级方法,但对
ServiceKeeper而言,并发数超过限制、流量超过限制、重试后仍然失败的请求同样会执行降级逻辑 - 箭头所示的方向为同一个资源各个服务治理功能的执行顺序,对于同时使用参数级和方法级服务治理功能的接口,参数级的整体优先级更高,且多个参数根据参数值下标优先级依次递减。
执行原理
Spring AOP代理(适应于Spring、Spring Boot、Restlight)
对于上述应用,ServiceKeeper通过Spring AOP完成对原始方法的代理,并织入服务治理的功能。更具体地讲,ServiceKeeper会代理有指定注解的方法,包括:
-
@ConcurrentLimiter用于并发数限制 -
@RateLimiter用于流量限制 -
@CircuitBreaker声明熔断配置 -
@Retryable方法重试配置 -
@EnableServiceKeeper一个空注解,仅用于标识该方法可被ServiceKeeper代理
只要原始方法拥有以上注解中的任何一个,该方法就可以被ServiceKeeper拦截到,后续就可以通过配置文件等实时配置需要的功能。需要说明地是:
- 除了
ServiceKeeper内置的上述注解外,对于Spring Boot和Restlight应用而言,默认还会代理对外提供服务的Controller方法(即带@RequestMapping、@GetMapping、@PostMapping、@PutMapping、@PatchMapping、@DeleteMapping注解的方法),由于前述注解在两种应用中包名不同因此提供了不同的接入适配模块,详情参见快速接入 - 默认情况下,
ServiceKeeper提供的AOP的优先级最低,如果需要更改该优先级,可以参考下文自定义AOP顺序
Filter扩展(适用于Dubbo Extension、ESA RPC)
上述两种应用通过各自的Filter扩展完成Consumer和Provider接入。
自定义AOP
ServiceKeeper支持用户代理任意指定的方法,并完成对该方法的服务治理,自定义的AOP需要继承AbstractServiceKeeperAop,具体示例如下:
@Aspect
@Component
public class CustomizeServiceKeeperAop extends AbstractServiceKeeperAop {
@Pointcut("execution(public * io.esastack.servicekeeper.test.service.*.*(..))")
private void serviceKeeper() {
}
@Around("io.esastack.servicekeeper.test.CustomizeServiceKeeperAop.serviceKeeper() ")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
return super.doInvoke(pjp);
}
}
如上所示AOP表示,代理io.esastack.servicekeeper.test.service包下的所有方法并织入服务治理的功能。使用过程中需要注意地是,ServiceKeeper已经完成了对带有指定注解方法的代理功能,自定义AOP时需要避免重复代理的情况,否则一个方法执行可能会多次执行服务治理逻辑。
自定义AOP顺序
示例如下:
@Bean(DEFAULT_SERVICE_KEEPER)
public DefaultServiceKeeperAop myAop() {
return new DefaultServiceKeeperAop() {
@Override
public int getOrder() {
return Integer.MAX_VALUE;
}
};
}
如上所示,更改DefaultServiceKeeperAop的优先级为最低。