Spring Boot/Cloud集成Sentinel实现流量控制 (二) | Spring Cloud 24
创始人
2025-05-29 21:17:23
0

一、前言

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

在前面我们通过以下章节对Sentinel有了基础的了解:

Sentinel:分布式系统的流量防卫兵 | Spring Cloud 19

Sentinel:资源与规则定义 | Spring Cloud 20

Sentinel:原理深入浅出解读 | Spring Cloud 21

Sentinel:流量控制规则定义详解 | Spring Cloud 22

Spring Boot/Cloud集成Sentinel实现流量控制 | Spring Cloud 23

现在开始我们正式学习SentinelSpring Boot/Cloud中的集成使用。

书接上回:Spring Boot/Cloud集成Sentinel实现流量控制 | Spring Cloud 23 ,本节进行对以下部分进行集成演示:

  • SentinelFeign 集成
  • SentinelRestTemplate 集成
  • Spring Boot/Cloud集成 Sentinel 开启链路流控模式

二、项目集成 Sentinel

2.1 项目总体结构

在这里插入图片描述

  • 模块sentinel-nacos-provider

    用于演示自定义限流处理逻辑

  • 模块sentinel-nacos-consumer

    用于演示SentinelFeign 集成

    用于演示SentinelRestTemplate集成

    用于演示Sentinel 链路流控模式

2.2 sentinel-nacos-provider模块

请见:Spring Boot/Cloud集成Sentinel实现流量控制 | Spring Cloud 23

2.3 sentinel-nacos-consumer模块

2.3.1 引入依赖

com.alibaba.cloudspring-cloud-starter-alibaba-sentinel

完整sentinel/sentinel-nacos-consumer/pom.xml


com.gmsentinel0.0.1-SNAPSHOT4.0.0jarsentinel-nacos-consumerorg.springframework.cloudspring-cloud-starter-bootstraporg.springframework.cloudspring-cloud-starter-loadbalancerorg.springframework.cloudspring-cloud-starter-openfeigncom.alibaba.cloudspring-cloud-starter-alibaba-nacos-discoveryorg.springframework.bootspring-boot-starter-testtestorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-actuatorcom.alibaba.cloudspring-cloud-starter-alibaba-sentinelcom.alibaba.cspsentinel-web-servletorg.springframework.bootspring-boot-maven-pluginio.fabric8docker-maven-pluginsrc/main/resourcestrue**/*.xlsx**/*.xlssrc/main/resourcesfalse**/*.xlsx**/*.xls

2.3.2 配置文件信息

完整版src/main/resources/bootstrap.yml

server:port: 3000spring:application:name: @artifactId@cloud:nacos:username: @nacos.username@password: @nacos.password@discovery:server-addr: ${NACOS_HOST:nacos1.kc}:${NACOS_PORT:8848},${NACOS_HOST:nacos2kc}:${NACOS_PORT:8848},${NACOS_HOST:nacos3.kc}:${NACOS_PORT:8848}sentinel:transport:port: 8720dashboard: 127.0.0.1:8080web-context-unify: falsefeign:sentinel:enabled: true # 开启feign对sentinel的支持

2.3.3 服务测试类

完整版 com/gm/sentinel_nacos_consumer/controller/ConsumerController.java

import com.gm.sentinel_nacos_consumer.service.ChainService;
import com.gm.sentinel_nacos_consumer.service.ProviderServiceFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;@RestController
public class ConsumerController {@AutowiredProviderServiceFeign providerServiceFeign;@AutowiredChainService chainService;@AutowiredRestTemplate restTemplate;/*** 用于测试Feign支持** @return*/@RequestMapping(value = "sayHello", method = RequestMethod.GET)public String sayHello() {return providerServiceFeign.sayHello("hello world");}/*** 用于测试STRATEGY_DIRECT模式,根据调用方进行限流。** @return*/@RequestMapping(value = "sayHelloDirect", method = RequestMethod.GET)public String sayHelloDirect() {return chainService.message();}/*** 用于测试STRATEGY_CHAIN模式,根据调用链路入口限流。** @return*/@RequestMapping(value = "sayHelloChain", method = RequestMethod.GET)public String sayHelloChain() {return chainService.message();}/*** 用于restTemplate限流测试** @return*/@RequestMapping(value = "sayHelloRest", method = RequestMethod.GET)public String sayHelloRestTemplate() {String url = String.format("http://sentinel-nacos-provider/sayHello?world=hello world");String result = restTemplate.getForObject(url, String.class);return result;}
}

此类中的所需的依赖类,在下文中均有体现。

2.3.4 Sentinel 与 Feign 集成

加入 spring-cloud-starter-openfeign 依赖使 Sentinel starter 中的自动化配置类生效:

org.springframework.cloudspring-cloud-starter-openfeign

在配置文件中加入 SentinelFeign 的支持:

feign:sentinel:enabled: true # 开启feign对sentinel的支持

新建简单使用示例com/gm/sentinel_nacos_consumer/service/ProviderServiceFeign.java

import com.gm.sentinel_nacos_consumer.config.FeignConfiguration;
import com.gm.sentinel_nacos_consumer.service.impl.ProviserServiceFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;@FeignClient(value = "sentinel-nacos-provider", fallback = ProviserServiceFallback.class, configuration = FeignConfiguration.class)
public interface ProviderServiceFeign {@RequestMapping(value = "sayHello", method = RequestMethod.GET)String sayHello(@RequestParam("world") String world);}

Feign 对应的接口中的资源名策略定义:httpmethod:protocol://requesturl @FeignClient 注解中的所有属性,Sentinel 都做了兼容。

ProviderServiceFeign接口中方法 sayHello对应的资源名为:GET:http://sentinel-nacos-provider/sayHello

新建FeignClient的配置类com/gm/sentinel_nacos_consumer/config/FeignConfiguration.java

import com.gm.sentinel_nacos_consumer.service.impl.ProviserServiceFallback;
import org.springframework.context.annotation.Bean;public class FeignConfiguration {@Beanpublic ProviserServiceFallback proviserServiceFallback() {return new ProviserServiceFallback();}
}

新建熔断器的处理类com/gm/sentinel_nacos_consumer/service/impl/ProviserServiceFallback.java

import com.gm.sentinel_nacos_consumer.service.ProviderServiceFeign;public class ProviserServiceFallback implements ProviderServiceFeign {@Overridepublic String sayHello(String world) {return "fallback";}
}

先访问:http://127.0.0.1:3000/sayHello 测试功能是否正常访问:

在这里插入图片描述
新建流控规则:

在这里插入图片描述

高频刷新:http://127.0.0.1:3000/sayHello ,验证Feign集成效果:

在这里插入图片描述

2.3.5 Sentinel 与 RestTemplate 集成

Spring Cloud Alibaba Sentinel 支持对 RestTemplate 的服务调用使用 Sentinel 进行保护,在构造 RestTemplate bean的时候需要加上 @SentinelRestTemplate 注解。

com/gm/sentinel_nacos_consumer/config/RestTemplateConfig.java

import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
import com.gm.sentinel_nacos_consumer.component.ExceptionUtil;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class RestTemplateConfig {@Bean@LoadBalanced@SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class)public RestTemplate restTemplate() {return new RestTemplate();}
}

@SentinelRestTemplate 注解的属性支持限流(blockHandler, blockHandlerClass)和降级(fallback, fallbackClass)的处理。

其中 blockHandlerfallback 属性对应的方法必须是对应 blockHandlerClassfallbackClass 属性中的静态方法。

该方法的参数跟返回值跟 org.springframework.http.client.ClientHttpRequestInterceptor#interceptor 方法一致,其中参数多出了一个 BlockException 参数用于获取 Sentinel 捕获的异常。

比如上述 @SentinelRestTemplate 注解中 ExceptionUtilhandleException 属性对应的方法声明如下,com/gm/sentinel_nacos_consumer/component/ExceptionUtil.java

import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpResponse;public class ExceptionUtil {public static ClientHttpResponse handleException(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException exception) throws Exception {ClientHttpResponse response = new SentinelClientHttpResponse("请求被限流!");return response;}}

@SentinelRestTemplate 注解的限流(blockHandler, blockHandlerClass)和降级(fallback, fallbackClass)属性不强制填写

当使用 RestTemplate 调用被 Sentinel 熔断后,会返回 RestTemplate request block by sentinel 信息,或者也可以编写对应的方法自行处理返回信息。这里提供了 SentinelClientHttpResponse 用于构造返回信息

Sentinel RestTemplate 限流的资源规则提供两种粒度:

  • httpmethod:schema://host:port/path:协议、主机、端口和路径

  • httpmethod:schema://host:port:协议、主机和端口

http://sentinel-nacos-provider/sayHello对应的资源名有两种粒度,分别是:GET:http://sentinel-nacos-provider、GET:http://sentinel-nacos-provider/sayHello

因上节与Feign 集成测试过程中已对资源GET:http://sentinel-nacos-provider/sayHello创建流控规则:

在这里插入图片描述

高频刷新:http://127.0.0.1:3000/sayHelloRest,验证RestTemplate集成效果:

在这里插入图片描述

2.3.6 开启链路流控模式

Sentinel 1.6.3 版本开始,Sentinel Web filter 默认收敛所有 URL 的入口 context,因此链路流控不生效。1.7.0 版本开始通过配置开启链路流控。

引入依赖:

com.alibaba.cspsentinel-web-servlet

配置开启链路流控:

  • 方式一:

    在配置文件新增spring.cloud.sentinel.web-context-unify=false

  • 方式二:

    添加一个配置类,自己构建CommonFilter实例:

    import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;@Configuration
    public class FilterContextConfig {/*** @NOTE 在spring-cloud-alibaba v2.1.1.RELEASE及前,sentinel1.7.0及后,关闭URL PATH聚合需要通过该方式,spring-cloud-alibaba v2.1.1.RELEASE后,可以通过配置关闭:spring.cloud.sentinel.web-context-unify=false* 手动注入Sentinel的过滤器,关闭Sentinel注入CommonFilter实例,修改配置文件中的 spring.cloud.sentinel.filter.enabled=false* 入口资源聚合问题:https://github.com/alibaba/Sentinel/issues/1024 或 https://github.com/alibaba/Sentinel/issues/1213* 入口资源聚合问题解决:https://github.com/alibaba/Sentinel/pull/1111*/@Beanpublic FilterRegistrationBean sentinelFilterRegistration() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new CommonFilter());registration.addUrlPatterns("/*");// 入口资源关闭聚合registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");registration.setName("sentinelFilter");registration.setOrder(1);return registration;}}
    

新建com/gm/sentinel_nacos_consumer/service/ChainService.java

public interface ChainService {String message();
}

新建com/gm/sentinel_nacos_consumer/service/impl/ProviserServiceFallback.java

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.gm.sentinel_nacos_consumer.service.ChainService;
import org.springframework.stereotype.Service;@Service
public class ChainServiceImpl implements ChainService {@SentinelResource(value = "message")public String message() {return "hello world";}
}

调用树如下图所示:

 	                 machine-root/               \/                 \/sayHelloDirect              /sayHelloChain/                       \/                         \
DefaultNode(message)         DefaultNode(message)

新建流控规则:

在这里插入图片描述

使用@SentinelResource注解,将方法message()定义为资源

高频访问: http://127.0.0.1:3000/sayHelloChain,发现流控规则生效:

在这里插入图片描述

在后续章节补充基于@SentinelResource注解的异常处理

控制台输出:

在这里插入图片描述

高频访问:http://127.0.0.1:3000/sayHelloDirect,一切正常:

在这里插入图片描述

开启链路流控模式后,针对资源message调用,链路入口/sayHelloChain的流控规则生效,对来自 /sayHelloDirect的调用漠不关心。

三、源码地址

源码地址:https://gitee.com/gm19900510/springboot-cloud-example

相关内容

热门资讯

安卓只恢复系统应用,重拾系统流... 你有没有遇到过这种情况?手机突然卡顿,或者某个应用突然罢工,你一气之下,直接开启了“恢复出厂设置”大...
安卓系统出现支付漏洞,揭秘潜在... 你知道吗?最近安卓系统可是闹出了不小的风波呢!没错,就是那个我们每天离不开的安卓系统,竟然出现了支付...
苹果换了安卓系统恢复,体验变革... 你有没有遇到过这种情况?手机里的苹果突然变成了安卓系统,而且还是那种让你摸不着头脑的恢复模式。别急,...
安卓怎么卸载系统app,轻松告... 手机里的系统应用越来越多,有时候真的让人眼花缭乱。有些应用虽然看起来很实用,但用起来却发现并不适合自...
安卓系统查看步数,揭秘日常运动... 你有没有发现,每天手机里的小秘密越来越多?今天,咱们就来聊聊安卓系统里那个悄悄记录你每一步的小家伙—...
安卓系统未来会不会,未知。 你有没有想过,那个陪伴我们手机生活的安卓系统,它的未来会怎样呢?想象每天早上醒来,手机屏幕上跳出的信...
安卓系统怎么设置截图,轻松捕捉... 亲爱的手机控们,你是不是也和我一样,有时候想记录下手机屏幕上的精彩瞬间呢?别急,今天就来手把手教你如...
安卓系统下载软件安装,安卓系统... 你有没有发现,手机里的安卓系统就像一个巨大的宝藏库,里面藏着各种各样的软件,让人眼花缭乱。今天,就让...
安卓10系统转移程序,轻松实现... 你有没有想过,当你从一台安卓手机升级到安卓10系统后,那些珍贵的照片、联系人、应用和数据怎么才能无缝...
安卓电脑强制重启系统,原因解析... 你有没有遇到过这种情况?你的安卓电脑突然间就强制重启了,屏幕上闪过一行行代码,你还没来得及保存文件,...
安卓怎么降低系统耗电,深度解析... 手机电量总是不够用,是不是你也和我一样,每天都要担心手机没电呢?别急,今天就来教你怎么给安卓手机降耗...
安卓系统的总体框架,架构与核心... 你有没有想过,你的手机里那个神奇的安卓系统,它到底是怎么运作的呢?今天,就让我带你一探究竟,揭开安卓...
谁的安卓系统好,谁家的安卓系统... 说到安卓系统,这可是个热门话题呢!你有没有想过,这么多安卓手机品牌,哪个的操作系统最让你心动?今天,...
安卓系统信付通,安全无忧的移动... 你知道吗?在安卓手机的世界里,有一个超级好用的支付工具,它就是信付通。今天,就让我带你来全方位了解一...
小米官方系统安卓包,深度解析与... 亲爱的数码爱好者们,你是否曾为手机系统而烦恼?市面上那么多手机品牌,各种操作系统让人眼花缭乱。今天,...
自制安卓手机双系统,自制安卓手... 你有没有想过,自己的手机可以同时运行两个操作系统呢?没错,就是那种安卓手机双系统!听起来是不是很酷?...
小米安卓系统怎么设置,科技前沿... 小米手机的用户们,是不是觉得安卓系统有点复杂,设置起来有点头疼呢?别担心,今天就来手把手教你如何轻松...
点歌系统支持安卓系统么,安卓用... 你有没有想过,在手机上点歌听歌,是不是也能像在KTV里那样随心所欲呢?现在,就让我来告诉你一个超级酷...
原版安卓系统刷机,解锁无限可能 你有没有想过,你的安卓手机其实可以焕然一新?没错,就是那种原汁原味的安卓系统,让你的手机重新找回当初...
欧尚改装安卓系统,打造智能驾驶... 你有没有想过,你的欧尚汽车其实也可以变身成为智能座驾呢?没错,就是那个你每天上下班的伙伴——欧尚,现...