大家之前有没有听过或遇到过以下类似场景:
-
某些流量明星在微博发布官宣消息时,导致微博朋友圈崩溃;
-
自身的系统由于依赖了某些故障节点,导致自身系统出现堵塞,直至系统雪崩,处于不可用状态。
针对以上场景,相信很多小伙伴很快就能想到对系统设置限流和熔断机制,以保证系统的稳定性。是的,今天要和大家介绍的大咖就是用来保障系统稳定性的sentinel。Sentinel它是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、熔断降级、系统过载保护、热点防护等多个维度来保护系统稳定性。github地址:https://github.com/alibaba/Sentinel。
Sentinel技术专题将分为四篇文章来分享
-
Sentinel服务端和客户端通讯原理和Sentinel控制台介绍
-
Sentinel限流和熔断等核心链路源码分析
-
Sentinel中限流算法和指标统计源码分析
-
Sentinel数据持久化改造方案
Sentinel服务端和客户端通讯原理
Sentinel源码中有几个核心模块:sentinel-dashboard、sentinel-core、sentinel-transport。其中sentinel-dashboard是Sentinel控制台,用以配置规则等;sentinel-core是处理限流等操作的核心代码块,用以客户端依赖;sentinel-transport是用于dashboard中规则和core通信的桥梁,通讯协议包含http、netty或springmvc等方式。
在介绍Sentinel服务端(dashboard)和客户端(微服务)通讯原理之前,请大家思考以下几个问题
-
客户端是如何感知服务端,服务端又是如何感知客户端的存在?
-
客户端是如何拿到服务端配置的规则,服务端又是如何拿到客户端实时的指标数据?
-
客户端宕机了,服务端如何感知,服务端宕机了,客户端又会如何感知?
接下来,通过上面图来详细回答以上三个问题来了解服务端和客户端的通讯原理
-
在客户端启动之前,需要配置csp.sentinel.dashboard.Server=ip:port指定服务端地址,客户端通过指定的地址定时发送心跳,向服务端注册客户端基本信息,如app名称、app类型、版本信息、IP和端口。另外,客户端本地会启动一个发送的IP和端口的Server监听;后续服务端有推送新消息或实时拉取指标数据时,均可通过上传的IP和端口进行消息推送。客户端类HeartbeatSenderInitFunc,服务端类MachineRegistryController。(Sentinel采用心跳机制注册的好处:告知服务端基本信息和通讯IP以及端口,后续服务端可以使用这个地址进行消息推送;二是用于保活,既可以节省系统资源,又可保证服务端和客户端通讯时能够正常通讯);
-
在步骤1中,客户端通过心跳机制向服务端注册后,服务端可以拿到客户端发送的IP和端口信息,服务端会有一个定时任务实时拉取指标数据,可参考服务端类MetricFetcher;另外,当有新的规则配置时,服务端通过API推送方式至客户端,以提供使用
-
步骤2中的说到类MetricFetcher会定时拉取实时指标数据,如passQps、blockQps、successQps、exceptionQps、rt,但是在拉取之前,会进行客户端健康状态检查工作,判断客户端是否已dead,已dead,则自动移除客户端机器信息。计算公式:当前时间-最近一次心跳时间,是否超过阈值,若超过则移除此机器。
//如果机器挂了if(machine.isDead()) {latch.countDown(); //移除机器 appManagement.getDetailApp(app).removeMachine(machine.getIp(),machine.getPort());continue;}
那么服务端宕机了,客户端是否能自动切换到其它服务端呢?通过查看代码发现sentinel这块容错机制并未实现,如下代码。
privateEndpointgetAvailableAddress(){ if(addressList==null||addressList.isEmpty()){ returnnull; } if(currentAddressIdx<0){ currentAddressIdx=0; } intindex=currentAddressIdx%addressList.size(); returnaddressList.get(index); }
Sentinel控制台介绍
Sentinel控制台配置有两个核心概念:资源 Rule。如对什么资源配置什么规则,规则包括统计类型、阈值,超过阈值后的效果等等。
资源:只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源;Rule:围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
Sentinel控制台具备功能点:实时指标监控、流控规则配置、授权配置、熔断配置等等。那么这些数据展示和规则配置是来源哪里以及如何让客户端生效新规则?这里拿流控规则设置原理解读。
-
读层面:每次页面调用接口时,会实时去对应客户端获取。数据填充的手段是先清理服务端内存中数据,再存入内存,且返回前端(Sentinel并未做持久化操作,需要使用者自身做扩展,后续将分享)
-
写层面:先将规则按机器维度添加至内存,随后再按照机器维度获取对应规则的全量数据推送至客户端。具体有哪些规则大家可以访问sentinel dashboard查看,大家思考这些规则推送到客户端又是怎么生效的,将在下节分享。
@PostMapping("/rule") @AuthAction(PrivilegeType.WRITE_RULE) publicResult<FlowRuleEntity>apiAddFlowRule(@RequestBodyFlowRuleEntityentity){ //参数校验 Result<FlowRuleEntity>checkResult=checkEntityInternal(entity); if(checkResult!=null){ returncheckResult; } //初始化流控实体 entity.setId(null); Datedate=newDate(); entity.setGmtCreate(date); entity.setGmtModified(date); entity.setLimitApp(entity.getLimitApp().trim()); entity.setResource(entity.getResource().trim()); try{ //保存数据 entity=repository.save(entity); //按照机器和规则维度一次性将全量流控规则推送到客户端 publishRules(entity.getApp(),entity.getIp(),entity.getPort()).get(5000,TimeUnit.MILLISECONDS); returnResult.ofSuccess(entity); }catch(Throwablet){ Throwablee=tinstanceofExecutionException ?t.getCause():t; logger.error("Failedtoaddnewflowrule,app={},ip={}",entity.getApp(),entity.getIp(),e); returnResult.ofFail(-1,e.getMessage()); } }
下一篇:Sentinel限流和熔断等核心链路源码分析
,