1.流量控制
系统处理能力有限,需要根据系统的处理能力对流量进行控制,他的实质上就是调整网络包的发送。那么sentinel框架就作为一个调配器或者整形器,可以根据规则把随机的请求调整成系统能承受的合适的形状,如下图所示:
sentinel流量控制方式:
•资源的调用关系,如:接口间的调用链路,服务调用来源的关联控制,API分组限流管理等•运行指标,如:QPS,线程数,异常比率,系统负载等•控制效果,如:直接失败,warm up,排队等
2.熔断降级
熔断降级其实是分开的两个概念,控制效果有所不同。所谓熔断就是类似家庭所用的保险丝,当某个服务出现不可用或者响应超时时,为了防止系统出现雪崩现象,对暂时不可用的服务进行调用屏蔽,快速返回。而对于降级来说,控制效果就相对温柔一些,当系统出现负载较高时,在其内部定义降级规则,暂时舍弃一些非核心功能的处理,释放资源保证系统整体的稳定性。sentinel熔断策略:
•慢调用比例•异常比例•异常数:异常数降级只会针对业务异常,限流异常不会统计在其中
3. 资源
资源是sentinel是一个很关键的抽象概念。他可以是一段代码,可以是一个接口,也可以是交易链路,甚至是一整个微服务。只要是能被Sentinel API能保护起来,这就是资源。
一般来说sentinel中提供SphU和SphO中的entry方法获取限流资源,示例如下:
private void fetchSync() { Entry entry = null; try { entry = SphU.entry("test-sync"); } catch (BlockException ex) { ex.printStackTrace(); } finally { if (entry != null) { entry.exit(); } }}
那么对于使用SentinelResource
注解又是怎么定义资源的呢?其实sentinel使用了AOP,简单代码如下:
@Aspectpublic class SentinelResourceAspect extends AbstractSentinelAspectSupport { //切入点就是`SentinelResource` @Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)") public void sentinelResourceAnnotationPointcut() { } //切面执行方法 @Around("sentinelResourceAnnotationPointcut()") public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable { ...... //此处开始其实就和使用普通sentinel定义资源的方式一致了 Entry entry = null; try { entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs()); Object result = pjp.proceed(); return result; } catch (BlockException ex) { return handleBlockException(pjp, annotation, ex); } catch (Throwable ex) { ...... throw ex; } finally { if (entry != null) { entry.exit(1, pjp.getArgs()); } } }}
4.规则
在定义好了资源之后,我们就需要告诉sentinel每个资源以什么方式方法去做限制,在什么情况下限制,限制到什么程度,通过种种特殊场景的不同设定最终抽象到规则。在sentinel中对接了如nacos、zk等规则数据源之后,所有可以动态实时调整。详细对接方式可查看之前文章(动态规则)。
5.context
Context
是对资源操作时的上下文环境,每个资源操作必须属于同一个Context
,当一个请求横跨多个资源时,都是在同一个Context
下面,这样也就可以实现跨资源的链路访问统计。Context
是基于ThreadLocal
的,在entry创建时会新建Context
,在entry退出时会被清掉,主要属性如下:
public class Context { /** * 上下文名称 */ private final String name; /** * 调用链入口节点信息 */ private DefaultNode entranceNode; /** * 当前entry,一个context生命周期内可能对多个资源操作 */ private Entry curEntry; /** * The origin of this context (usually indicate different invokers, e.g. service consumer name or origin IP). */ private String origin = ""; private final boolean async; ...}
6.Entry
Entry
表示一次资源操作,内部会保存当前的调用信息。那么在一个Context
中会存在多次资源的操作,每次SphU.entry()
和SphO.entry()
都会返回一个Entry
,也就会对应多个Entry
。
理解以上基础概念之后,会对sentinel的流量统计以及规则配置有一定指导意义,持续更新中....