Alibaba Sentinel 使用ZooKeeper集中管理和推送规则

如果不做任何修改,Sentinel Dashboard 的推送规则方式是通过 API 将规则推送至客户端并直接更新到内存中,这种方式规则保存在内存中,重启即消失不建议在线上使用,架构图如下:

image.png

Sentinel官方是建议使用推模式,这种方式规则是持久化的,服务重启不会消失;通过配置中心来保证规则的一致性;规则实时下发,响应速度快,架构图如下:

image.png

Sentinel 目前提供了ZooKeeper, Apollo, Nacos 等的动态数据源实现,但是为了使用第二种架构方式我们需要对原来的Dashboard进行一定的改造。

搭建ZooKeeper环境

ZooKeeper常用命令

1. 启动ZK服务:       sh bin/zkServer.sh start
2. 查看ZK服务状态: sh bin/zkServer.sh status
3. 停止ZK服务:       sh bin/zkServer.sh stop
4. 重启ZK服务:       sh bin/zkServer.sh restart

ZooInspector 图形化工具

ZooInspector是ZooKeeper的图形化工具,ZooInspector下载地址:

https://issues.apache.org/jira/secure/attachment/12436620/ZooInspector.zip

解压,进入ZooInspector\build目录,通过如下命令执行jar包:

java -jar zookeeper-dev-ZooInspector.jar  & //执行成功后,会弹出java ui client
image.png

获取源码

https://github.com/alibaba/Sentinel

改造Dashboard工程

引入Zookeeper包

<!--for Zookeeper rule publisher sample-->
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>${curator.version}</version>
    <scope>test</scope>
</dependency>

去掉<scope>test</scope>

通过Zookeeper来同步

在test目录中,sentinel提供了使用Zookeeper来同步流控规则的实现,我们直接复制到com.alibaba.csp.sentinel.dashboard.rule包中,并根据样例写出降级规则的实现,目录如图:

image.png
image.png

这里需要注意的一点是,流控规则和降级规则的zkpath:

// 流控规则
final String flowPath = "/sentinel_rule_config/" + appName + "/flow";

// 降级规则
final String degradePath = "/sentinel_rule_config/" + appName + "/degrade";

// 应用启动时指定的-Dproject.name=sentinel-demo参数
String appName = System.getProperty("project.name");

修改Controller,当规则变动时给Zookeeper发消息

FlowControllerV1 流控规则Controller

流控规则Controller可以参考FlowControllerV2类来修改,主要有两点修改:

  1. apiQueryMachineRules方法,当获取规则时,直接通过zk获取:
image.png
  1. publishRules方法,当规则变更时,通过zk做通知:
image.png

DegradeController 降级规则Controller

DegradeController的修改和FlowControllerV1修改的地方时一样的。

修改规则ID的ID生成器

这里算是有个小bug把,规则的ID生成器如InMemDegradeRuleStore使用的是private static AtomicLong ids = new AtomicLong(0);,这样如果Dashboard重新部署的话,就会导致生成规则的id又从0开始了,这样有可能会导致新创建规则的时候,会将老规则给覆盖掉,做如下修改:

image.png

InMemoryRuleRepositoryAdapter这个类的子类都有这个问题,可以一起修改。

然后打成jar包,通过如下命令启动:

-Dserver.port=8900 -Dcsp.sentinel.dashboard.server=localhost:8900 -Dproject.name=sentinel-dashboard -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456789
  • -Dserver.port=8900:用于指定 Sentinel 控制台端口为 8900
  • -Dsentinel.dashboard.auth.username=sentinel:指定登录 Sentinel 控制台的用户名。
  • -Dsentinel.dashboard.auth.password=123456789:指定登录 Sentinel 控制台的密码。

客户端的修改

适配框架

Sentinel 支持主流框架的适配。这里我适配的是Web Servlet

引入jar包的支持

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>${sentinel.version}</version>
</dependency>

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>${sentinel.version}</version>
</dependency>

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-web-servlet</artifactId>
    <version>${sentinel.version}</version>
</dependency>

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-zookeeper</artifactId>
    <version>${sentinel.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.14</version>
    <exclusions>
        <exclusion>
            <artifactId>slf4j-log4j12</artifactId>
            <groupId>org.slf4j</groupId>
        </exclusion>
    </exclusions>
</dependency>

通过Spring 配置过滤器

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean sentinelFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new CommonFilter());
        registration.addUrlPatterns("/*");
        registration.setName("sentinelFilter");
        registration.setOrder(1);

        return registration;
    }
}

接入 CommonFilter 之后,所有访问的 Web URL 就会被自动统计为 Sentinel 的资源,可以针对单个 URL 维度进行流控。若希望区分不同 HTTP Method,可以将 HTTP_METHOD_SPECIFY 这个 init parameter 设为 true,给每个 URL 资源加上前缀,比如 GET:/foo。更多资料说明请查看文档

适配 Sentinel 动态数据源,支持规则的持久化

我这里主要适配了流控和降级的规则通知和持久化。

@Configuration
public class SentinelDataSourceInitFuncConfig {

    @Value("${spring.application.name}")
    private String applicationName;

    @PostConstruct
    public void initSentinelDataSourceInitFuncConfig() {

        String appName = StringUtils.isNotBlank(System.getProperty("project.name")) ? System.getProperty("project.name") : applicationName;

        final String remoteAddress = "127.0.0.1:2181";

        // 流控规则
        final String flowPath = "/sentinel_rule_config/" + appName + "/flow";
        ReadableDataSource<String, List<FlowRule>> redisFlowDataSource = new ZookeeperDataSource<>(remoteAddress, flowPath,
                source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
                }));
        FlowRuleManager.register2Property(redisFlowDataSource.getProperty());

        // 降级规则
        final String degradePath = "/sentinel_rule_config/" + appName + "/degrade";
        ReadableDataSource<String, List<DegradeRule>> redisDegradeDataSource = new ZookeeperDataSource<>(remoteAddress, degradePath,
                source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {
                }));
        DegradeRuleManager.register2Property(redisDegradeDataSource.getProperty());
    }
}

这里ZooKeeper的地址可以改成配置项。

业务系统埋点

Sentinel支持多种埋点方式,这里我只列举了对一段特定代码块进行埋点的方式,其他方式可以参考文档,源码如下:

@Override
public Result thread(String arg) {
    String resourceName = "testSentinel";
    int time = random.nextInt(700);
    ContextUtil.enter("entrance1", "appA");
    Entry entry = null;
    String retVal;
    try {
        entry = SphU.entry(resourceName, EntryType.IN);
        Thread.sleep(time);
        if (time > 690) {
            throw new RuntimeException("耗时太长啦");
        }

        retVal = "passed";
    } catch (BlockException e) {
        retVal = "blocked";
    } catch (Exception e) {
        // 异常数统计埋点
        Tracer.trace(e);
        throw new RuntimeException(e);
    } finally {
        if (entry != null) {
            entry.exit();
        }
    }
    return Result.success(retVal + "::" + time);
}

这里需求特别说明的是 EntryType,共有两种类型:INOUT

  • IN:是指进入我们系统的入口流量,比如 http 请求或者是其他的 rpc 之类的请求,设置为IN主要是为了保护自己系统。
  • OUT:是指我们系统调用其他第三方服务的出口流量,设置为OUT是为了保护第三方系统。

启动应用

应用启动时需要通过JVM启动参数指定Sentinel Dashboard的地址和端口,并且需要指定项目名称。

-Dcsp.sentinel.dashboard.server=127.0.0.1:8900 -Dproject.name=sentinel-demo
image.png

应用被注册到Dashboard上的效果

客户端配置好了与控制台的连接参数之后,并不会主动连接上控制台,需要触发一次客户端的规则才会开始进行初始化,并向控制台发送心跳和客户端规则等信息。

image.png

参考

在生产环境中使用-Sentinel

源码

https://github.com/wyh-spring-ecosystem-student/spring-boot-student/tree/releases

spring-boot-student-sentinel 工程和spring-boot-student-sentinel-dashboard工程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352