阿里sentinel流控框架初探

netflix的hystrix作为业界使用最广泛的流控框架,sentinel的开发团队自然少不了对其的学习与改进,这里有一篇开发团队写的两者的对比,总结起来就是sentinel的实现更加轻量,进行流控的维度也更多样。

使用sentinel的另一个理由就是其与国内广泛使用的各大微服务框架都做了集成,接入sentinel更加方便。这里是sentinel集成的其它框架的接入文档

下面我们以国内使用最为广泛的微服务框架dubbo为例,探索sentinel的使用。

sentinel dashboard部署

sentinel控制台可以对接入的应用的实际流量进行监控,也可以查看,修改接入应用的流控,降级,热点等规则。开发者文档很详细的介绍了部署和接入步骤,这里不再赘述,需要提醒的是只有当被限流的服务产生实际流量时,控制台才会显示数据。


dubbo provider接入

首先引入sentinel基础依赖
对于 Apache Dubbo 2.7.x 及以上版本,使用时需引入以下模块(以 Maven 为例):

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-apache-dubbo-adapter</artifactId>
    <version>x.y.z</version>
</dependency>

对于 Dubbo 2.6.x 及以下版本,使用时需引入以下模块(以 Maven 为例):

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-dubbo-adapter</artifactId>
    <version>x.y.z</version>
</dependency>

写一个简单的dubbo provider

public interface DemoService {
    public String sayHello(String name);
}
 <dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService"/>

配置限流规则
首先介绍下sentinel的限流规则

一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果:
resource:资源名,即限流规则的作用对象
count: 限流阈值
grade: 限流阈值类型(QPS 或并发线程数)
limitApp: 流控针对的调用来源,若为 default 则不区分调用来源
strategy: 调用关系限流策略
controlBehavior: 流量控制效果(直接拒绝、Warm Up、匀速排队)

这里的resource在不同的情况下配置的规则也不相同,而与dubbo整合的情况下,resource的粒度可以分为两种粒度

限流粒度可以是服务接口和服务方法两种粒度:
服务接口:resourceName 为 接口全限定名,如 com.alibaba.csp.sentinel.demo.dubbo.FooService
服务方法:resourceName 为 接口全限定名:方法签名,如 com.alibaba.csp.sentinel.demo.dubbo.FooService:sayHello(java.lang.String)

比如我想DemoService这个服务接口的QPS进行限流,不限制请求来源,被限流的请求直接拒绝且每秒只接受20的QPS,那么我的限流规则应该如下:

[
  {
    "resource": "org.apache.dubbo.demo.DemoService",
    "controlBehavior": 0,
    "count": 20.0,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  }
]

介绍完如何编写限流规则,下一步就是如何配置这些规则使其起效,sentinel将不同来源的限流规则抽象成一个个数据源且支持动态更新,其基础抽象类为(com.alibaba.csp.sentinel.datasource.AbstractDataSource),还提供了一个抽象接口(com.alibaba.csp.sentinel.datasource.Converter)进行源数据到限流规则(com.alibaba.csp.sentinel.slots.block.flow.FlowRule)的转换。sentinel提供了多种数据源的实现,包括文件,zookeeper,redis等,这里介绍最简单也是最常用的静态文件配置方式,对动态配置感兴趣的可以参考官方文档

静态文件方式配置
首先在工程的resource目录下准备一份json格式的配置文件(其它格式也可以,解析规则是由开发者自行编写的,怎么方便怎么来),内容就是一个json数组:
在这里插入图片描述

[
  {
    "resource": "org.apache.dubbo.demo.DemoService",
    "controlBehavior": 0,
    "count": 20.0,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  }
]

编写代码解析配置文件,然后将配置规则载入内存

private Converter<String, List<FlowRule>> flowRuleListParser = s -> JSON.parseObject(s, new TypeReference<List<FlowRule>>() {});

private void loadRules() throws Exception {
        ClassLoader classLoader = getClass().getClassLoader();
        String flowRulePath = URLDecoder.decode(classLoader.getResource("FlowRule.json").getFile(), "UTF-8");
        log.info(flowRulePath);

        FileRefreshableDataSource<List<FlowRule>> flowRuleDataSource = new FileRefreshableDataSource<>(flowRulePath, flowRuleListParser);
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    }

其它几类规则的载入方式也是相同的这里不再赘述,流控规则载入完成后,我们的dubbo rpc接口就能受到sentinel的保护啦,最后一步启动应用,加入以下参数(接入sentinel dashboard需要)

-Dcsp.sentinel.dashboard.server=127.0.0.1:9999 -Dproject.name=dubbo_provider -Dcsp.sentinel.api.port=8719 -Djava.net.preferIPv4Stack=true

dubbo consumer接入

consumer不需要配置限流规则,配置相对简单
同样需要引入sentinel依赖

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

进行dubbo消费者的配置,为了更加准确的观测结果,需要关闭重试机制(retries=“0”)

<dubbo:reference id="demoService" check="false" retries="0" interface="org.apache.dubbo.demo.DemoService"/>

同时发出50个请求

public class Application {
    private static final Logger log = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml");
        context.start();
        DemoService demoService = context.getBean("demoService", DemoService.class);

        for (int i = 0; i < 50; i++) {
            new Thread(() -> {
                String hello = demoService.sayHello("dubbo");
                log.info("result: " + hello);
            }).start();
        }
    }
}

启动应用,若想在dashboard中进行实时监控,启动参数也需要加入以下参数

-Dcsp.sentinel.dashboard.server=127.0.0.1:9999 -Dproject.name=dubbo_provider -Djava.net.preferIPv4Stack=true

此时可以看到控制台出现大量FlowException异常
观察sentinel的流控日志sentinel-block.log
默认位于~/logs/csp下
在这里插入图片描述
先介绍下日志各个字段的含义

2019-10-12 15:54:11:时间戳;
1:序号;
org.apache.dubbo.demo.DemoService:资源描述符;
XXXException:表示被限制的种类。FlowException 表示被限流,DegradeException 表示被降级,SystemException 表示被系统保护
default:规则上配置的限制应用;
origin:实际被限制的来源应用,可能为空字符串;
30,0:30 代表这一秒内限流降级发生的次数,0 无含义(可忽略)。

观察sentinel dashboard的实时监控数据
在这里插入图片描述
可以看到结果都符合预期,sentitinel确实起到了限流的作用。


结语

以上只是sentinel最简单的一个单机版本的限流例子,接下来的博客中会逐步介绍它的降级规则,熔断恢复,集群流控,网关流控,多维度限流的能力。由于其与dubbo都经由alibaba开发并开源,在众多dubbo构建的微服务体系下,相信会是比hystrix更好的选择。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章