原理地址:原理讲解地址
服务熔断和限流
一、熔断降级
说明:熔断降级组件目前流行的有hystrix和sentinel,如下是功能比较图:
服务熔断步骤:
sentinel单独的熔断降级不再赘述,这里是openfeign和sentinel集成的熔断实现。
Sentinel Feign Example可参考文档:https://github.com/alibaba/spring-cloud-alibaba/blob/2.2.x/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example/readme-zh.md
1、引入包
<!-- openfeign依赖,服务间的调用,集成了spring-cloud-starter-loadbalancer包,默认使用loadbalancer负载均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 依赖sentinel,做熔断和限流,hystrix开源社区已关停,所以选sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2、开启熔断
feign:
sentinel:
enabled: true #开启sentinel熔断
client: #建议设置下feign调用的超时时间,避免默认的时间太长导致请求时间太长
config:
default: # 针对所有的服务
loggerLevel: BASIC # 日志级别 NONE:不打印 BASIC:打印简单信息 HEADERS:打印头信息 FULL:打印全部信息 (默认 NONE)
connectTimeout: 5000 # Feign的连接建立超时时间,默认为10秒
readTimeout: 5000 # Feign的请求处理超时时间,默认为60秒
3、客户端编写feign接口,指定熔断callback类
// 这里一定要被spring扫描到加载到容器,单是Openfeign可以手动设置FeignClientBuilder构建,但是集成sentinel后,sentinel源码会从spring容器找到这个bean,找不到会报错
// 第一种写法
@FeignClient(value = "server-auth", path = "/auth", fallbackFactory = AuthDemoClientFallbackFactory.class)
public interface AuthDemoClient {
@GetMapping("/demo/auth_test1")
JsonResult test1() throws Exception;
}
// 第二种写法
@FeignClient(value = "server-auth", path = "/auth", fallback = AuthDemoClientFallbackFactory.class)
public interface AuthDemoClient {
@GetMapping("/demo/auth_test1")
JsonResult test1() throws Exception;
}
4、编写熔断callback类
// 对应第一种写法
@Component // 这个一定要加,要交给spring容器管理
public class AuthDemoClientFallbackFactory implements FallbackFactory<AuthDemoClient> {
@Override
public AuthDemoClient create(Throwable cause) {
return new AuthDemoClient() {
@Override
public JsonResult test1() throws Exception {
return JsonResult.getInstant(-1, "auth-client server available");
}
};
}
}
// 对应第二种写法
@Component // 这个一定要加,要交给spring容器管理
public class AuthDemoClientFallbackFactory implements AuthDemoClient {
@Override
public JsonResult test1() throws Exception {
return JsonResult.getInstant(-1, "auth-client server available");
}
}
5、启动类开启feignClient
// scanBasePackages要扫描到fallback类
@SpringBootApplication(scanBasePackages = {"cn.zlf.auth"})
// 开启feign调用,要扫描到feign定义的接口类
@EnableFeignClients(basePackages = {"cn.zlf.auth"})
public class DemoServerApplication {
public static void main(String[] args) {
SpringApplication.run(DemoServerApplication.class,args);
}
}
6、调用
// facade封装
@Component
public class AuthDemoClientFacade {
@Autowired
private AuthDemoClient authDemoClient;
public String test1() {
JsonResult<String> jsonResult = null;
try {
jsonResult = authDemoClient.test1();
} catch (Exception e) {
throw new BusinessException(e.getMessage());
}
if (!jsonResult.isSuccess()) {
throw new BusinessException(jsonResult.getMsg(), jsonResult.getCode());
}
return jsonResult.getData();
}
}
// 测试类
@SpringBootTest(classes = DemoServerApplication.class)
@RunWith(SpringRunner.class)
public class DemoSentinelTest {
@Autowired
private AuthDemoClientFacade authDemoClientFacade;
@Test
public void test1() {
System.out.println(authDemoClientFacade.test1());
}
}
二、限流
在上一步熔断的基础上增加。
简介
下载sentinel dashboard:https://edas-public.oss-cn-hangzhou.aliyuncs.com/install_package/demo/sentinel-dashboard.jar
在服务器安装并启动:
java -Dcsp.sentinel.log.dir=D:\sentinel\logs \
-Dserver.port=8859 \
-Dproject.name=sentinel-dashboard \
-Dsentinel.dashboard.auth.username=sentinel \
-Dsentinel.dashboard.auth.password=123456 \
-Dserver.servlet.session.timeout=7200 \
-jar .\sentinel-dashboard-1.8.6.jar
说明:sentinel限流有编码方式,注解方式,控制台方式。这里只说明控制台限流+Nacos持久化方式。
Sentinel Example可参考文档:https://github.com/alibaba/spring-cloud-alibaba/blob/2.2.x/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md
限流操作步骤:
1、引入包
<!-- openfeign依赖,服务间的调用,集成了spring-cloud-starter-loadbalancer包,默认使用loadbalancer负载均衡 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 依赖sentinel,做熔断和限流,hystrix开源社区已关停,所以选sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- 依赖actuator,sentinel依赖他实现监控 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2、指定dashboard控制台
spring:
cloud:
sentinel:
eager: true #开启心跳
transport:
dashboard: 127.0.0.1:8859 #指定控制台地址和端口号
clientIp: 127.0.0.1 #这里如果服务和dashboard控制台在一个机器上,则不需要配置;如果不在一个机器上,则需要配置服务的地址,dashboard会请求这个ip服务上的健康数据信息
datasource: #ds1表示ReadableDataSource的名称,可随意编写。ds1后面的nacos表示ReadableDataSource的类型。目前支持file, nacos, zk, apollo,redis 这5种类型
ds1:
nacos:
namespace: basic
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
data-id: demo_sentinel
group-id: DEFAULT_GROUP
data-type: json
rule-type: flow
# 开启健康数据
management:
endpoints:
web:
exposure:
include: '*'
3、在Nacos上配置限流信息,命名为demo_sentinel,配置格式为JSON
[
{
"resource": "/test",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"clusterMode": false
}
]
- resource:资源名,资源名是限流规则的作用对象;
- count:限流阈值
- grade:限流阈值类型,QPS 模式(1)或并发线程数模式(0),默认QPS 模式
- limitApp:流控针对的调用来源
- strategy:调用关系限流策略:直接(0)、链路(1)、关联(2),默认根据资源本身(直接)
- controlBehavior:流控效果(直接拒绝(0);WarmUp(1);匀速+排队等待(2)),不支持按调用关系限流,默认直接拒绝
- clusterMode:是否集群限流,默认否
4、自定义限流返回值
/**
* 自定义Sentinel的限流返回值
*/
@Component
@Slf4j
public class SentinelFlowBlockHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
httpServletResponse.setHeader("Content-Type", "application/json;charset=UTF-8");
try (Writer writer = httpServletResponse.getWriter()) {
JsonResult<String> instant = JsonResult.getInstant(-1, "达到限流限制,请稍后再试");
writer.write(JSON.toJSONString(instant));
writer.flush();
} catch (Exception e1) {
log.error("response error, case:" + e1, e1);
}
}
}
4、启动服务开始请求即可,在http://127.0.0.1:8859/#/dashboard 控制台可以看到实时监控图。