目录
前言
Dubbo服务通过整合Sentinel,实现服务限流以及服务熔断。用Jemter工具进行压力测试,以及Sentinel的Dashboard控制台查看数据。
一、Dubbo服务限流
1,jar包依赖
Sentinel 提供 Dubbo 的相关适配 Sentinel Dubbo Adapter,主要包括针对 Service Provider 和 Service Consumer 实现的 Filter。相关模块:
sentinel-apache-dubbo-adapter
(兼容 Apache Dubbo 2.7.x 及以上版本,自 Sentinel 1.5.1 开始支持)sentinel-dubbo-adapter
(兼容 Dubbo 2.6.x 版本)
对于 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 的服务接口和方法(包括调用端和服务端)就会成为 Sentinel 中的资源,在配置了规则后就可以自动享受到 Sentinel 的防护能力。
官方提示:Dubbo Service 服务的jar包依赖,注意dubbo和sentinel相关jar包,不同版本有所不同。下面是经过验证测试过的两种版本号。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-dubbo-adapter</artifactId>
<version>1.6.1</version>
</dependency>
<!--通信控制台-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.3</version>
</dependency>
<!-- dubbo正式使用 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-apache-dubbo-adapter</artifactId>
<version>1.7.0</version>
</dependency>
<!-- 接入dashboard控制台使用 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.6.1</version>
</dependency>
<!--连接zookeeper-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>
2,项目代码
创建dubbo服务sentinel-service和SpringBoot接口系统sentinel-web,分别为provider和consumer。Springboot+Dubbo+Zookeeper系统搭建
sentinel-service:aplication.properties
dubbo.scan.base-packages=com.wzf.study.sentinelprovider
dubbo.application.name=sentinel-service
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.registry.address=zookeeper://192.168.1.109:2181?192.168.1.106:2181
sentinel-service:SentinelServiceImpl代码
package com.wzf.study.sentinelprovider.service;
import com.wzf.study.ISentinelService;
import org.apache.dubbo.config.annotation.Service;
import java.time.LocalDateTime;
@Service
public class SentinelServiceImpl implements ISentinelService {
@Override
public String sayHello() {
return "HELLO "+LocalDateTime.now();
}
}
sentinel-web:aplication.properties
server.port=8080
dubbo.scan.base-packages=com.wzf.study.sentinelprovider
dubbo.application.name=sentinel-web
dubbo.registry.address=zookeeper://192.168.1.109:2181?192.168.1.106:2181
sentinel-web:HelloController代码
package com.wzf.study.sentinelweb;
import com.wzf.study.ISentinelService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Reference
private ISentinelService sentinelService;
@GetMapping("hello")
public String hello(){
return sentinelService.sayHello();
}
}
3,流量规则
流量控制主要有两种统计类型,一种是统计并发线程数,另外一种则是统计 QPS。
controllerBehavior:当 QPS 超过某个阈值的时候,则采取措施进行流量控制。流量控制的效果包括以下几种:直接拒绝、Warm Up、匀速排队。对应 FlowRule
中的 controlBehavior
字段。
直接拒绝:默认的流量控制方式,当QPS超过任意规则的阈值后,新的请求就会被立即拒绝;
匀速排队:方式会严格控制请求通过的间隔时间,也即是让请求以均匀的速度通过,对应的是漏桶算法;
Warm Up:即预热/冷启动方式。通过"冷启动",让通过的流量缓慢增加,避免流量突然增加直接把系统瞬间压垮。
4,定义规则:服务限流
将限流定义在sentinel-service的SentinelProviderApplication中,如下:
@SpringBootApplication
public class SentinelProviderApplication {
public static void main(String[] args) {
initFlowRule();//启动之前设置限制规则
SpringApplication.run(SentinelProviderApplication.class, args);
}
private static void initFlowRule(){
FlowRule flowRule = new FlowRule();
//注意:这里是 service接口:方法()
flowRule.setResource("com.wzf.study.ISentinelService:sayHello()");
flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
flowRule.setCount(20);
// flowRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
//指定限流来源,不是通过dubbo.application.name里的值拦截的,
//而是在consumer方法中通过dubbo的隐式传参,如:RpcContext.getContext().setAttachment("dubboApplication","sentinel-web");
//flowRule.setLimitApp("sentinel-web");
FlowRuleManager.loadRules(Collections.singletonList(flowRule));
}
}
5,启动访问
在idea中启动sentinel-service项目时,在JvmOpthion中配置以下参数,然后使用jemeter请求。
-Dcsp.sentinel.dashboard.server=localhost:7777 //连接dashboard控制台。启动时加入 JVM 参数
-Dcsp.sentinel.dashboard.server=consoleIp:port
指定控制台地址和端口。-Dcsp.sentinel.log.use.pid=true //多个项目,根据pid记录统计。若在本地启动多个 Demo 示例,需要加上
-Dcsp.sentinel.log.use.pid=true
参数,否则控制台显示监控会不准确。-Ddubbo.protocol.port=20881 //指定dubb服务端口。可以在idea的jvm配置不同的端口,启动多个sentinel-service以便测试。
-Dproject.name=App-Wzf //指定项目名
6,Sentinel控制台
根据控制台可以看到,成功限流为每秒20QPS。
二、Dubbo服务熔断降级
1,项目准备
和上面服务限流一样,提前准备:jar包依赖;项目代码;
2,熔断规则
3,定义规则:熔断降级
定义规则的加载有两种方式,这次换个和上面不一样的,当然两种都可以:
在sentinel-service的resources下创建文件 META-INF\services\com.alibaba.csp.sentinel.init.InitFunc (此处为sentinel的SPI机制),
内容为 com.wzf.study.sentinelprovider.DataSourceInitFunc。
创建DataSourceInitFunc类(名字随便起),继承InitFunc,代码如下。
package com.wzf.study.sentinelprovider;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import java.util.Collections;
public class NacosDataSourceInitFunc implements InitFunc {
@Override
public void init() {
initFlowRules();
}
public static void initFlowRules(){
DegradeRule rule = new DegradeRule();
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);//
rule.setCount(20);//平均响应时间阈值,单位毫秒
rule.setTimeWindow(5); //单位秒
//这里的时service接口,不能指定到方法粒度
rule.setResource("com.wzf.study.ISentinelService");
DegradeRuleManager.loadRules(Collections.singletonList(rule));
}
}
4,访问测试
在服务方法中添加 Thread.sleep(100); 以达到延迟响应的效果,根据Jemeter显示可知测试熔断降级成功。因为minRequestAmount默认为5,所以请求成功了5个。