Dubbo集成Sentinel实现限流

Sentinel提供了与Dubbo整合的模块Sentinel Apache Dubbo Adapter,可以针对服务提供方和服务消费方进行流控,在使用的时候只需要添加下面依赖:

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

添加好依赖后,Dubbo服务中的接口和方法就会成为Sentinel中的资源,只需要针对指定资源配置流控规则就可以实现Sentinel流控功能。

Sentinel Apache Dubbo Adapter实现限流的核心原理是基于Dubbo的SPI机制实现Filter扩展,Dubbo的Filter机制是专门为服务提供方和服务消费方调用过程进行拦截设计得到,每次执行远程方法,该拦截都会被执行。

同时,Sentinel Apache Dubbo Adapter还可以自定义开启或者关闭某个过滤器的功能,下面这段代码表示关闭消费端的过滤器。

@Bean
public ConsumerConfig consumerConfig() {
    ConsumerConfig consumerConfig = new ConsumerConfig();
    consumerConfig.setFilter("-sentinel.dubbo.filter");
    return consumerConfig;
}

Dubbo服务接入Sentinel Dashboard

spring-cloud-starter-alibaba-sentinel目前无法支持Dubbo服务的限流,所以针对Dubbo服务的限流只能使用sentinel-apache-dubbo-adapter。这个适配组件并没有自动接入sentinel dashboard,所以需要通过以下步骤来进行接入。

  • 引入sentinel-transport-simple-http依赖,这个依赖可以上报应用相关信息到控制台
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-transport-simple-http</artifactId>
    <version>1.7.1</version>
</dependency>
  • 添加启动参数
-Djava.net.perferIPv4Stack=true -Dcsp.sentinel.api.port=8720 -Dcsp.sentinel.dashboard.server=localhost:7777 -Dproject.name=spring-cloud-sentinel-dubbo-provider

参数配置说明:

  • -Djava.net.preferIPv4Stack:表示只支持IPv4。

  • -Dcsp.sentinel.api.port:客户端的port,用于上报应用的信息。

  • -Dcsp.sentinel.dashboard.server:Sentinel Dashboard地址

  • -Dproject.name:应用名称,会在Sentinel Dashboard右侧展示。

  • 登陆Sentinel Dashboard之后,进入"簇点链路",就可以看到资源信息


    在这里插入图片描述

    这里的限流可以通过服务接口或者服务方法设置

  • 服务接口:resourceName为接口的全限定名,如com.xxx.sentinel.dubbo.IHelloService.

  • 服务方法:resourceName为接口全限定名:方法名,如com.xxx.sentinel.dubbo.IHelloService:sayHello()。

Dubbo服务限流规则配置

Dubbo的限流规则同样可以通过以下方式来实现

  • Sentinel Dashboard
  • FlowRuleManager.loadRules(rules)。

在Sentinel Dashboard中配置流控规则,最终可以持久化到Nacos中,然而规则的持久化机制在Spring Cloud Sentinel中是自动实现的。在Sentinel Apache Dubbo Adapter的组件中并没有实现这个功能,需要我们自己按照下面步骤去实现规则的持久化。

  1. 添加sentinel-datasource-nacos的依赖
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <version>1.7.1</version>
</dependency>
  1. 通过Sentinel提供的InitFunc扩展点,实现Nacos数据源的配置
public class NacosDataSourceInitFunc implements InitFunc{
    private String serverAddr="localhost:8848";
    private String groupId="DEFAULT_GROUP";
    private String dataId="spring-cloud.sentinel-dubbo.provider-sentinel-flow";

    @Override
    public void init() throws Exception {
        loadNacosData();
    }
    private void loadNacosData(){
        ReadableDataSource<String,List<FlowRule>> flowRuleDataSource=
                new NacosDataSource<>(serverAddr, groupId, dataId, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
                }));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    }
}

NacosDataSourceInitFunc要实现自动加载,需要在resource目录下的META-INF/services中创建一个名称为com.alibaba.csp.sentinel.init.InitFunc的文件,文件内容为com.sentinel.dubbo.NacosDataSourceInitFunc

  1. 访问Sentinel Dashboard,在针对资源创建流控规则的时候,这个规则会同步保存到Nacos配置中心。而当Nacos配置中心发生变化的时候,也会触发事件机制通知Dubbo应用重新加载流控规则。

Sentinel热点限流

Sentinel提供了热点参数限流的策略,它是一种特殊的限流,在普通限流的基础上对同一个受保护的资源根据请求中的参数分别处理,该策略只对包含热点参数的资源调用生效。

热点限流在下面的场景中使用较多:

  1. 服务网关层:例如防止网络爬虫和恶意攻击,一种常用的方法就是限制爬虫的IP地址,客户端IP地址就是一种热点参数。
  2. 写数据的服务:例如业务系统提供写数据的服务,数据会写入数据库之类得到存储系统。存储系统的底层会加锁写磁盘上的文件,部分存储系统会将某一类数据写入同一个文件。如果底层写同一个文件,会出现抢占锁的情况,导致出现大量超时和失败。出现这种情况时一般有两种解决办法:修改存储设计、对热点参数限流。

Sentinel通过LRU策略结合滑动窗口机制来实现热点参数的设计,其中LRU策略可以统计单位时间内最常访问的热点数据,滑动窗口机制可以协助统计每个参数的QPS。

热点参数限流的使用

引入热点参数限流依赖包sentinel-parameter-flow-control

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-parameter-flow-control</artifactId>
    <version>1.7.1</version>
</dependency>

接下来创建一个Rest接口,并定义限流点

@RestController
public class ParamRuleController {
    
    private String resourceName = "hello";
    
    @GetMapping("/hello")
    public String sayHello(@PathParam("id") String id, @PathParam("name") String name) {
        Entry entry = null;
        try {
            entry = SphU.entry(resourceName, EntryType.IN, 1, id);
            return "success";
        } catch (BlockException e) {
            e.printStackTrace();
            return "block";
        } finally {
            if (entry != null) {
                entry.exit();
            }
        }
    }
}

针对不同的热点参数,需要通过SphU.entry(resourceName, EntryType.IN, 1, id)方法设置。最后一个参数是数组,有多个参数时就按照顺序依次传入。

同时,针对hello资源设置热点参数限流规则,通过ParamFlowRuleManager.loadRules()方法加载热点参数规则

@PostConstruct
public void initParamRule() {
    ParamFlowRule rule = new ParamFlowRule(resourceName);
    rule.setParamIdx(0);
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule.setCount(1);
    ParamFlowRuleManager.loadRules(Collections.singletonList(rule));
}

@SentinelResource热点参数限流

如果通过@SentinelResource注解来定义资源的,当注解所配置的方法上有参数的时候,Sentinel会把这些参数传入SphU.entry(res, args),比如下面这段代码,会把id这个参数作为热点参数进行限流。

@SentinelResource
@GetMapping("/hello")
public String sayHello(@PathParam("id") String id) {
    return "hello";
}

默认情况下,当用户访问这个接口时就会触发热点限流规则的验证。

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