在Spring Cloud微服务体系中,由于限流熔断组件Hystrix开源版本不在维护,因此国内不少有类似需求的公司已经将眼光转向阿里开源的Sentinel框架。而以下要介绍的正是作者最近两个月的真实项目实践过程,这中间被不少网络Demo示例级别水文误导过,为了以正视听特将实践过程加以总结,希望能够帮到有类似需要的朋友!
一、Sentinel概述
在基于Spring Cloud构建的微服务体系中,服务之间的调用链路会随着系统的演进变得越来越长,这无疑会增加了整个系统的不可靠因素。在并发流量比较高的情况下,由于网络调用之间存在一定的超时时间,链路中的某个服务出现宕机都会大大增加整个调用链路的响应时间,而瞬间的流量洪峰则会导致这条链路上所有服务的可用线程资源被打满,从而造成整体服务的不可用,这也就是我们常说的“雪崩效应”。
而在微服务系统设计的过程中,为了应对这样的糟糕情况,最常用的手段就是进行”流量控制“以及对网络服务的调用实现“熔断降级”。所谓流量控制就是根据服务的承载能力指定一个策略,对一定时间窗口内的网络调用次数进行限制,例如1s内某个服务最多只能处理10个请求,那么1s内的第11+的请求会被被限制丢弃;而熔断降级的概念则是说在A服务→B服务调用过程中,按照一定的规则A服务发现调用B服务经常失败或响应时间过长,如果触发了A服务对B服务调用的熔断降级规则,那么在一定时间窗口内,A服务在处理请求的过程中对于B服务的调用将会直接在A服务的逻辑中被熔断降级,请求则不会通过网络打到B服务,从而避免A服务由于过长的超时时间导致自身资源被耗尽的情况发生。
虽然我们知道以上两种手段非常有用,但若没有合适的技术来支持,就好像一句话说的“虽然明白很多道理,但是依然过不好这一生”一样。而Sentinel就是这样一种技术,它是阿里巴巴开源的一款客户端限流组件,可以与Spring Cloud微服务体系无缝地集成;而与之对应的是另外一款Netflix公司推出的知名度也比较高的Hystrix组件,Hystrix也是Spring Cloud官方集成熔断限流组件,只不过相对于Sentinel来说,Hystrix所提供的功能和灵活度比较低,并且它目前已经处于开源版本暂停维护的状态,因此目前国内很多基于Spring Cloud搞微服务的公司都转向了Sentinel。关于二者的对比由于不是本文的重点,这里就不再赘述,大家搜索下就好(ps:可能网上也没几篇能说明白的文章,关键还在于大家实际使用对比)。
二、Sentinel+Apollo架构说明
Sentinel开源版本架构
在Github Sentinel官方Wiki说明以及网上一大堆的水文中,关于Sentinel的资料已经很多了,但是大多数属于Demo级别,所以本文不想过多的耗费大家的精力(因为在学习过程中,作者也被误导过)。以下将从实际生产的使用方式上来阐述如何构建Sentinel的使用架构。
从本质上说Sentinel与Hystrix是一类性质的熔断限流组件,之所以说它们只是组件就在于它们都需要内嵌于微服务应用本身的主进程之中,所有的限流、熔断策略及指标信息的收集等逻辑都是基于客户端的(这里不要对客户端有所误会,它指的是处于调用端上游的微服务本身)。而这一点是明显区别于Service Mesh(服务网格)架构中将熔断、限流等逻辑抽象在SideCar(边车)而不是微服务应用本身的。
因此从这种意义上说,Sentinel的使用应该是并不复杂的,它应该与Hystrix一样,在Spring Cloud微服务应用中引入相关依赖即可。事实上从某种程度来说的确如此,只不过Sentinel提供了比Hystrix要强一点的规则配置能力,提供了可以进行限流、熔断降级以及热点、授权等其他规则统一配置和管理的控制台服务->sentinel-dashboard。
虽然如此,但这也并没有改变Sentinel作为客户端限流组件性质,通过控制台配置的规则依然要推送到微服务应用Sentinel客户端本身才能生效,而微服务之间的调用链路等指标信息也需要推送给Sentinel控制台,才能比较方便地使用Sentinel提供的一些能力,因此在开源的架构版本中需要微服务应用本身开启独立端口与sentinel-dashboard进行通信,从而获取配置规则以及上送微服务应用各类指标信息。而这一点,显然也会占用微服务额外的资源,并且由于sentinel-dashboard在此条件下并不具备集群部署能力,因此也会形成一个单节点问题,但是有一套控制台总好过于没有,如果希望比较方便快速地应用Sentinel这也是一种代价。此时的Sentinel架构如下图所示:
在开源版本架构中,通过sentinel-dashboard控制台配置的限流、熔断降级等规则都是存储于Sentinel控制台服务内存之中的,如果控制台服务重启或者微服务应用重启都会导致规则丢失。而这在生产环境下是不可接受的,因此Sentinel在官方的生产架构指导中也是推荐使用第三方数据源(如本文的Apollo)作为永久存储中心,这样各个微服务的限流、降级规则都可以永久存储。虽然Sentinel官方推荐使用第三方数据源作为规则存储中心,目前也提供了针对Apollo、Nacos、Zookeeper、Redis、Consul、Spring Cloud Config等多种存储源的依赖集成Jar,但是却并没有针对这些数据源提供一个可以实际使用的sentinel-dashboard第三方数据源存储版本,所以当你选择了一种数据源那么就需要你自己对sentinel-dashboard项目进行改造,这里作者针对Sentinel 1.7.0(成文时最新版本)使用Apollo数据源改造了一个版本,所有规则基本可用,但可能会有细节的Bug需要自行Fix。具体代码改造点见Github链接:
https://github.com/manongwudi/Sentinel/commit/f3a27adb6fdbf13d9eaa4510e317c1b55c206e89
关于以上sentinel-dashboard接入Apollo数据源的代码改造情况,大家可以详细参考上述链接,这里作者只说以下几个重点:
目前官方推荐的方式是通过Apollo的开放平台授权的方式进行写入,因此我们需要在sentinel-dashboard项目pom.xml文件引入以下依赖:
<!-- Apollo配置依赖 -->
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-openapi</artifactId>
<version>1.5.0</version>
</dependency>
之后我们需要在Apollo Portal创建一个针对sentinel-dashboard的应用,具体创建方法如下图所示:
以上我们创建了一个针对Sentinel控制台的应用(这里的应用是Apollo配置中心的基本概念,具体微服务接入Apollo的方法,大家可以自行搜索)。
创建应用后,未来Sentinel控制台在启动是需要指定Apollo应用ID才能接入Apollo,而接入Apollo之后Sentinel的规则需要写入该应用下的namespace空间,因此还需要创建针对该应用的namespace空间,具体创建方式如下图所示&#