Sentinel 整合Apollo,生产环境搭建指南

/ 0评 / 19

Sentinel 整合Apollo,生产环境搭建指南

第一次接触这个是19年团队微服务化重构的时候,最初版本我们是使用了官方全家桶的Hystrix(但是很遗憾,并没有配置规则,只是匆忙的看了下那头熊..)但是也很快将其替换成了Sentinel。关于其实现原理其实挺庞大也挺复杂的,至于更换的原因(那期Nacos干掉Eureka也说了一些,其实是领导选型的侧重,其实他们都满足我们的“需求”,但是那个时候的QPS,其实从未出现过比较离谱的情况...一直比较低)

而那次的使用其实只是从官网下载dashboard源码,按照官网指示启动了下(甚至有两台机器的高可用方案)。但是其实那个时候Sentinel没有解决我们的问题,也没有在生产中真正帮到我们。在我离职的时候甚至连当初部署他的运维大神都忘记了其的存在...因为真的很没存在感。

好了吐槽就说这么多,今天重新认识这中间件。

背景

目前我们线上的服务器超过百台且大部分机器半数接口QPS稳居20以上,每台机器均值QPS在95上下。而运营方告知接下来几月流量可以能会翻几倍,也就是95会乘以N。面对这种情况一般思路我们肯定要保护核心流程的永远畅通,追求服务的稳定性,以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。为啥不选Hystrix(原因和之前一样[因为我领导没换..开玩笑]),其实有考虑到Sentinel相较于Hystrix的优点:

Sentinel Hystrix
隔离策略 基于并发数 线程池隔离/信号量隔离
熔断降级策略 基于响应时间或失败比率 基于失败比率
实时指标实现 滑动窗口 滑动窗口(基于 RxJava)
规则配置 支持多种数据源 支持多种数据源
扩展性 多个扩展点 插件的形式
基于注解的支持 支持 支持
调用链路信息 支持同步调用 不支持
限流 基于 QPS / 并发数,支持基于调用关系的限流 不支持
流量整形 支持慢启动、匀速器模式 不支持
系统负载保护 支持 不支持
实时监控 API 各式各样 较为简单
控制台 开箱即用,可配置规则、查看秒级监控、机器发现等 不完善
常见框架的适配 Spring Cloud、Dubbo、gRPC Servlet、Spring Cloud Netflix

说简单一点就是你有的我都有,而我做的都比你好,我也更适合。确定选型之后我们开始接入Sentinel。
sentinel有以下特点:
UTOOLS1585664091414.png

工程接入

Sentinel 分为两个部分:
- 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo /Spring Cloud 等框架也有较好的支持。
- 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器

控制台Dashbord

我们使用开源版本的Sentinel控制台,如果有需要,可以通过切换依赖即可快速接入AHAS Sentinel(商用版本,功能比开源版少点但是持久化和admin都改的挺好看,唯一缺点就是收费,注解支持不是很好)控制台,反之亦可。

控制台包含了以下功能:
- 查看机器列表以及健康情况:收集 Sentinel 客户端发送的心跳包,用于判断机器是否在线。
- 监控 (单机和集群聚合):通过 Sentinel 客户端暴露的监控 API,定期拉取并且聚合应用监控信息,最终可以实现秒级的实时监控。
- 规则管理和推送:统一管理推送规则。
- 鉴权:生产环境中鉴权非常重要。这里每个开发者需要根据自己的实际情况进行定制。

规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。
UTOOLS1585664095643.png
(几百台机器一致性很好保证了,重启也不担心了)
为了持久化我Fork了人的代码,然后稍微改了改:
sentinel本身就在源码中提供了各种数据源持久化的方案,我选择的是Apollo,将
test package com.alibaba.csp.sentinel.dashboard.rule.apollo 下的代码复制到
main中,修改pom(将scope>test<去掉):

<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-openapi</artifactId>
    <version>1.2.0</version>
</dependency>

然后在上述代码填上你目标源的配置,如果你有接入过携程Apollo 的openapi的话这段建议跳过。
然后修改发布和推送的类 FlowControllerV2:

@Autowired
@Qualifier("flowRuleApolloProvider")
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
@Qualifier("flowRuleApolloPublisher")
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;

将dashBoard 内v1版本的内存推送改为v2版本(由于前端是AngularJS,和java有点像,勉强改几句 ):

sentinel-dashboard\src\main\webapp\resources\app\scripts\controllers\identity.js:
FlowServiceV1 ----> FlowServiceV2

sentinel-dashboard\src\main\webapp\resources\app\scripts\directives\sidebar\sidebar.html:
add++:
<li ui-sref-active="active" ng-if="entry.appType==0">
    <a ui-sref="dashboard.flow({app: entry.app})">
    <i class="glyphicon glyphicon-filter"></i>流控规则(Apollo)</a>
</li>

然后在根目录:

mvn clean package -Dmaven.test.skip=true

将dashboard的包上传到服务器(可以自动化部署...)
以Springboot Main 的方式启动:

java  -server -Xmx2g -Xms2g  -Dserver.port=8085 -Dproject.name=sentinel-dashboard  -jar sentinel-dashboard-test.jar &

关于启动参数和控制台的使用我觉得官方文档特别靠谱:
https://github.com/alibaba/Sentinel/wiki/

客户端

客户端的接入就很无脑了:

<dependency>
     <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>1.5.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-parameter-flow-control</artifactId>
    <version>1.5.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>0.1.2.RELEASE</version>
</dependency>

其中Transport 是为了与控制台连接,而parameter是为了热词限流功能,核心都在spring-cloud-starter-alibaba-sentinel 中。
加入以下配置:

#sentinel
spring.cloud.sentinel.transport.port = 12000
project.name = project-name
csp.sentinel.statistic.max.rt = 4900
feign.sentinel.enabled = true
spring.cloud.sentinel.transport.dashboard = dashboardip:8085

其中 spring.cloud.sentinel.transport.port 是dashboard连接客户端的port,注意别和其他端口冲突
通过feign.sentinel.enabled 打开对feign的支持
通过project.name来指定项目在dashboard的名字
csp.sentinel.statistic.max.rt 最大有效响应时长(ms),超出此值则按照此值记录

启动项目,可以在控制台看到服务列表中,多了客户端的机器,可以对有请求记录的接口进行配置,为了使配置不在加载到内存,使用push模式,集成Apollo:

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-apollo</artifactId>
    <version>1.5.2</version>
</dependency>

然后在能被扫描到的service包中添加同步代码:

@Component
public class SentinelApolloKeyRefresh implements InitializingBean {

    public static final String FLOW_DATA_ID_POSTFIX = "-flow-rules";

    @Value("${project.name}")
    private String projectName;

    @Override
    public void afterPropertiesSet() throws Exception {
        // Apollo 的命名空间
        String namespaceName = "space.apollo.sentinel.rule";
        // 限流规则的Key, 在Apollo中用此Key
        String flowRuleKey = String.format("%s%s", projectName, FLOW_DATA_ID_POSTFIX);
        // 限流规则的默认值
        String defaultFlowRules = "[]";
        // 注册数据源
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ApolloDataSource<>(namespaceName,
                flowRuleKey, defaultFlowRules, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
        }));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    }
}

ApolloDataSource 中集成了监听Apollo配置更新和reload,至此接入结束。

关于生产环境的使用注意事项

最后,感谢Github sentinel非常详细的文档:https://github.com/alibaba/Sentinel/wiki

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注