前言:此篇文章系本人学习过程中记录下来的笔记,里面难免会有不少欠缺的地方,诚心期待大家多多给予指教。
往期目录回顾:
- SpringCloud微服务(一)
- SpringCloud微服务(二)
- SpringCloud微服务(三)
- SpringCloud微服务(四)
- SpringCloud微服务(五)
- SpringCloud微服务(六)
- SpringCloud微服务(七)
- SpringCloud微服务(八)
- SpringCloud微服务(九)
- SpringCloud微服务(十)
接上期内容:上期完成Sentinel组件的学习,接下来用两个小案例来加深Sentinel的理解,话不多说,直接发车!
一、Sentinel集成OpenFeign实现服务降级
1、需求说明
order9001服务通过OpenFeign调用payment9002服务,主要分两种情况:
1、正常:9001 ===》OpenFeign ===》9002 正常🆗,正常返回。
2、异常:9001 ===》OpenFeign ===》9002 错误❌,如果9002出现异常,需要进行服务降级处理,避免出现9001服务宕机的可能。
3、9001服务自身也需要增加流控配置,防止服务不可用。
2、实操
1、修改cloud-provider-payment9002
1.1、修改pom.xml文件
引入相关依赖,(记得刷新maven)
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
1.2、修改application.yml文件
server:
port: 9002
spring:
application:
name: alibaba-nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置naCos地址
sentinel:
transport:
dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址
port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
1.3、新增测试接口
1.4、测试接口
测试9002服务是否正常,访问http://localhost:9002/pay/nacos/get/1024
2、修改cloud-api-commons
2.1、修改pom.xml文件
导入相关依赖,(记得刷新maven)
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2.2、新增测试接口
2.3、新增统一的fallback类
/**
* 统一的 fallback 类实现所有方法的回退逻辑
*/
@Component
public class PayFeignSentinelApiFallBack implements PayFeignSentinelApi {
@Override
public ResultResponse<Object> getPayByOrderNo(String orderNo) {
return ResultResponse.fail(ReturnCodeEnum.RC201.getCode(), "对方服务宕机或不可用,FallBack服务降级o(╥﹏╥)o");
}
// 其他接口方法的回退逻辑实现...
}
3、修改cloud-consume-order9001
3.1、修改pom.xml文件
导入相关依赖,(记得刷新maven)
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--alibaba-sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
3.2、修改application.yml文件
# 激活Sentinel对Feign的支持
feign:
sentinel:
enabled: true
3.3、修改主启动类
开启Feign功能
3.4、新增测试接口
3.5、新增自定义Sentinel限流提示。
9001服务使用自定义限流提示,9002服务使用的是@SentinelResource注解实现自定义限流提示
/**
* 自定义sentinel限制提示
*/
@Component
public class CustomSentinelException implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpStatus.OK.value());
// 通过判断异常的类型 来判断到底是限流还是熔断降级还是授权限制
if (e instanceof FlowException) {
response.getWriter().println("{\"code\":"
+ HttpStatus.OK.value() + ",\"msg\":\"success\",\"data\":\"请求被限流了\",\"timestamp\":" + System.currentTimeMillis() + "}");
} else if (e instanceof ParamFlowException) {
response.getWriter().println("{\"code\":"
+ HttpStatus.OK.value() + ",\"msg\":\"success\",\"data\":\"请求被热点参数限流\",\"timestamp\":" + System.currentTimeMillis() + "}");
} else if (e instanceof DegradeException) {
response.getWriter().println("{\"code\":"
+ HttpStatus.OK.value() + ",\"msg\":\"success\",\"data\":\"请求被降级了\",\"timestamp\":" + System.currentTimeMillis() + "}");
} else if (e instanceof AuthorityException) {
response.getWriter().println("{\"code\":"
+ HttpStatus.OK.value() + ",\"msg\":\"success\",\"data\":\"禁止访问\",\"timestamp\":" + System.currentTimeMillis() + "}");
}
}
}
3、测试
3.1、启动服务
分别启动Nacos、Sentinel、9001、9002服务,成功启动图省略。
3.2、Sentinel后台配置
1、先访问9001、9002的服务各一次
2、9001服务,Sentinel后台配置:
3、9002服务,Sentinel后台配置:
4、快速多次访问http://localhost:9001/alibaba/consumer/order/nacos/get/1024,会触发9001服务本身的限流规则。
正常访问9001,正常返回结果。
5、快速多次访问http://localhost:9002/pay/nacos/get/1024,触发9002服务本身的限流规则。
正常访问就不会。
6、停掉9002服务,看看9001服务是否正常。
9002服务宕机,9001正常访问,只是触发了服务降级功能,避免了9001服务也发生宕机。
4、总结
通过小案例的学习,加深了对Sentinel组件的了解,方便后续在开发中更加熟练的对流量把控,避免服务不可用。
二、Sentinel集成Gateway实现服务限流
1、需求说明
Spring Cloud Gateway 本身是构建微服务架构中网关层的得力工具,有着出色的路由转发、请求过滤等功能。它与 Spring Cloud 生态体系无缝集成,借助服务注册与发现机制,可以高效地将请求准确路由到对应的后端微服务上。当与 Sentinel 集成后,更是如虎添翼,能在网关这个关键节点上,利用 Sentinel 的强大限流能力,从入口处把控进入系统的流量,避免大量请求冲击后端服务,保障了整个微服务架构的稳定性和健壮性。
目的:网关保护9002服务,避免大流量将9002服务冲垮。
2、实操
1、新建cloud-sentinel-gateway9528模块
1.1、新建详细步骤省略。
1.2、修改pom.xml文件
导入相关依赖,(记得刷新maven)
<!--loadbalancer-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--nacos-discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.8.8</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
<scope>compile</scope>
</dependency>
1.3、新增application.yml文件
server:
port: 9528
spring:
application:
name: cloud-sentinel-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
routes:
- id: cloud-sentinel-gateway #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
uri: lb://alibaba-nacos-payment-provider
predicates:
- Path=/alibaba/pay/** # 断言,路径相匹配的进行路由
1.4、修改主启动类
1.5、新增gateway相关配置
1、根据官方文档,依葫芦画瓢,官方地址:网关限流 · alibaba/Sentinel Wiki · GitHub
2、新增GatewayConfiguration,设置触发限流提示语
@Configuration
public class GatewayConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// Register the block exception handler for Spring Cloud Gateway.
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
@Bean
//@Order(Ordered.HIGHEST_PRECEDENCE)
@Order(-1) //数值越低,优先级越高
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
@PostConstruct //javax.annotation.PostConstruct
public void doInit() {
initBlockHandler();
}
//处理/自定义返回的sentinel限流规则的提示语
private void initBlockHandler() {
// 定义限流规则
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("cloud-sentinel-gateway").setCount(2) //单位时间内允许通过的请求数量
.setIntervalSec(1) // 设置统计的时间间隔,单位是秒
);
// 加载规则
GatewayRuleManager.loadRules(rules);
// 设置返回提示语
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map<String, Object> map = new HashMap<>();
map.put("code", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());
map.put("msg", "请求太过频繁,系统忙不过来,触发限流(sentinel+gateway整合Case)");
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)// 设置返回的 HTTP 状态码
.contentType(MediaType.APPLICATION_JSON)//设置返回的响应内容类型为 JSON 格式
.body(BodyInserters.fromValue(map)); //将构建好的包含响应数据的 map 通过 BodyInserters 插入到响应体中
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
2、修改cloud-api-commons模块
2.1、新增接口
2.2、实现接口
PayFeignSentinelApiFallBack需要实现PayFeignSentinelGatewayApi接口
3、修改cloud-consume-order9001模块
3.1、新增测试接口
3.2、测试功能
1、启动Nacos、sentinel、9001、9002、9528服务
2、正常访问http://localhost:9001/alibaba/consumer/order/nacos/byGateway/get/1024
3、快速多次访问http://localhost:9001/alibaba/consumer/order/nacos/byGateway/get/1024
????,为啥提示会是这个??,不应该是网关那边配置的提示语么?
原因:因为OpenFeign在通过gateway调用9002的时候,触发了gateway的限流配置,返回错误信息,9001发现9002服务无法正常处理,直接走了服务降级处理。如果想验证gateway的限流配置是否真的有效,那么直接干掉cloud-api-commons包中统一处理的降级处理逻辑即可。
4、重启9001、9002服务,在快速多次访问http://localhost:9001/alibaba/consumer/order/nacos/byGateway/get/1024
确实会得到gateway网关那边配置的限流提示,如此看来,gateway整合Sentinel成功了。
三、总结
通过两个小案例加深对Sentinel组件的了解和运用,也让我们对SpringCloud微服务架构下的网关层流量控制机制有了更透彻的认识。同时,也为我们在未来面对更加多样化、复杂化的业务场景时,如何灵活运用 Sentinel 进行流量控制提供了丰富的实践经验。
ps:努力到底,让持续学习成为贯穿一生的坚守。学习笔记持续更新中。。。。