目录
一、Sentinel下载并运行
二、创建8401微服务整合Sentinel
三、流控规则
3.1、直接模式
3.2、关联模式
3.3、链路模式
3.3.1、修改8401代码
3.3.2、创建流控模式
3.4、Warm UP(预热) 编辑
3.5、排队等待
四、熔断规则
4.1、慢调用比例
4.2、异常比例
4.3、异常数
五、@SentinelResource注解
5.1、按照rest地址限流+默认限流返回 编辑
5.2、按SentinelResource资源名称限流+自定义限流返回
5.3、按SentinelResource资源名称限流+自定义限流返回+服务降级处理
六、热点规则
6.1、参数例外项
七、授权规则 编辑
八、规则持久化
九、整合Openfeign
十、整合Gateway
一、Sentinel下载并运行
运行命令:java -jar sentinel-dashboard-1.8.7.jar
访问界面:
二、创建8401微服务整合Sentinel
导入相关pom及yml文件配置
<dependencies><!--SpringCloud alibaba sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><!--nacos-discovery--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- 引入自己定义的api通用包 --><dependency><groupId>com.cjc.cloud</groupId><artifactId>cloud-api-commons</artifactId><version>1.0-SNAPSHOT</version></dependency><!--SpringBoot通用依赖模块--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--hutool--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version><scope>provided</scope></dependency><!--test--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
server:port: 8401spring:application:name: cloudalibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848 #Nacos服务注册中心地址sentinel:transport:dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
测试代码:
@SpringBootApplication
@EnableDiscoveryClient
public class Main8401 {public static void main(String[] args) {SpringApplication.run(Main8401.class,args);}
}
@RestController
public class FlowLimitController {@GetMapping("/testA")public String testA(){return "------testA";}@GetMapping("/testB")public String testB(){return "------testB";}
}
三、流控规则
3.1、直接模式
默认使用
3.2、关联模式
3.3、链路模式
3.3.1、修改8401代码
sentinel:transport:dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路
@Service
public class FlowLimitService {@SentinelResource(value = "common")public void common(){System.out.println("------FlowLimitService come in");}
}
@Autowiredprivate FlowLimitService flowLimitService;@GetMapping("/testC")public String testC(){flowLimitService.common();return "------testC";}@GetMapping("/testD")public String testD(){flowLimitService.common();return "------testD";}
3.3.2、创建流控模式
3.4、Warm UP(预热)
3.5、排队等待
四、熔断规则
4.1、慢调用比例
进行压测:
4.2、异常比例
4.3、异常数
五、@SentinelResource注解
SentinelResource是一个流量防卫防护组件注解, 哨兵资源是一个流量防卫防护组件注解,用于指定防护资源,对配置的资源进行流量控制、熔断降级等功能。
5.1、按照rest地址限流+默认限流返回
测试访问:
5.2、按SentinelResource资源名称限流+自定义限流返回
测试代码:
@GetMapping("/rateLimit/byResource")@SentinelResource(value = "byResourceSentinelResource",blockHandler = "handleException")public String byResource(){return "按资源名称SentinelResource限流测试OK";}public String handleException(BlockException exception){return "服务不可用@SentinelResource启动"+"\t"+"o(╥﹏╥)o";}
测试访问:
5.3、按SentinelResource资源名称限流+自定义限流返回+服务降级处理
@GetMapping("/rateLimit/doAction/{p1}")@SentinelResource(value = "doActionSentinelResource",blockHandler = "doActionBlockHandler", fallback = "doActionFallback")public String doAction(@PathVariable("p1") Integer p1) {if (p1 == 0){throw new RuntimeException("p1等于零直接异常");}return "doAction";}public String doActionBlockHandler(@PathVariable("p1") Integer p1,BlockException e){log.error("sentinel配置自定义限流了:{}", e);return "sentinel配置自定义限流了";}public String doActionFallback(@PathVariable("p1") Integer p1,Throwable e){log.error("程序逻辑异常了:{}", e);return "程序逻辑异常了"+"\t"+e.getMessage();}
测试结果:
六、热点规则
@GetMapping("/testHotKey")@SentinelResource(value = "testHotKey",blockHandler = "dealHandler_testHotKey")public String testHotKey(@RequestParam(value = "p1",required = false) String p1,@RequestParam(value = "p2",required = false) String p2){return "------testHotKey";}public String dealHandler_testHotKey(String p1,String p2,BlockException exception){return "-----dealHandler_testHotKey";}
测试结果:
6.1、参数例外项
七、授权规则
测试访问:
八、规则持久化
添加pom依赖
<!--SpringCloud ailibaba sentinel-datasource-nacos --><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId></dependency>
修改yml
spring:application:name: cloudalibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848 #Nacos服务注册中心地址sentinel:transport:dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口web-context-unify: false # controller层的方法对service层调用不认为是同一个根链路datasource:ds1:nacos:server-addr: localhost:8848dataId: ${spring.application.name}groupId: DEFAULT_GROUPdata-type: jsonrule-type: flow # com.alibaba.cloud.sentinel.datasource.RuleType
在nacos服务配置中进行配置
测试:
九、整合Openfeign
修该9001服务提供者pom及yml
<!--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>
spring:application:name: nacos-payment-providercloud:nacos:discovery:server-addr: localhost:8848 #配置Nacos地址sentinel:transport:dashboard: localhost:8080 #配置Sentinel dashboard控制台服务地址port: 8719 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
测试代码:
@GetMapping("/pay/nacos/get/{orderNo}")@SentinelResource(value = "getPayByOrderNo",blockHandler = "handlerBlockHandler")public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo){//模拟从数据库查询出数据并赋值给DTOPayDTO payDTO = new PayDTO();payDTO.setId(1024);payDTO.setOrderNo(orderNo);payDTO.setAmount(BigDecimal.valueOf(9.9));payDTO.setPayNo("pay:"+ IdUtil.fastUUID());payDTO.setUserId(1);return ResultData.success("查询返回值:"+payDTO);}public ResultData handlerBlockHandler(@PathVariable("orderNo") String orderNo, BlockException exception){return ResultData.fail(ReturnCodeEnum.RC500.getCode(),"getPayByOrderNo服务不可用," +"触发sentinel流控配置规则"+"\t"+"o(╥﹏╥)o");}
远程调用测试代码:
@FeignClient(value = "nacos-payment-provider",fallback = PayFeignSentinelApiFallBack.class)
public interface PayFeignSentinelApi {@GetMapping("/pay/nacos/get/{orderNo}")public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo);
}
@Component
public class PayFeignSentinelApiFallBack implements PayFeignSentinelApi{@Overridepublic ResultData getPayByOrderNo(String orderNo) {return ResultData.fail(ReturnCodeEnum.RC500.getCode(),"对方服务宕机或不可用,FallBack服务降级o(╥﹏╥)o");}
}
修改80消费者yml
# 激活Sentinel对Feign的支持
feign:sentinel:enabled: true
@Resourceprivate PayFeignSentinelApi payFeignSentinelApi;@GetMapping(value = "/consumer/pay/nacos/get/{orderNo}")public ResultData getPayByOrderNo(@PathVariable("orderNo") String orderNo){return payFeignSentinelApi.getPayByOrderNo(orderNo);}
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class NFMain80 {public static void main(String[] args) {SpringApplication.run(NFMain80.class,args);}
}
启动80服务报错
修改springcloud版本,也可以下调springboot版本
测试结果:
十、整合Gateway
新建9528微服务并导入相关pom与yml
<dependencies><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.6</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></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
server:port: 9528spring:application:name: cloudalibaba-sentinel-gateway # sentinel+gataway整合Casecloud:nacos:discovery:server-addr: localhost:8848gateway:routes:- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名uri: http://localhost:9001 #匹配后提供服务的路由地址predicates:- Path=/pay/** # 断言,路径相匹配的进行路由
测试代码:
@SpringBootApplication
@EnableDiscoveryClient
public class Main9528 {public static void main(String[] args) {SpringApplication.run(Main9528.class,args);}
}
@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(-1)public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();}@PostConstruct //javax.annotation.PostConstructpublic void doInit() {initBlockHandler();}//处理/自定义返回的例外信息private void initBlockHandler() {Set<GatewayFlowRule> rules = new HashSet<>();rules.add(new GatewayFlowRule("pay_routh1").setCount(2).setIntervalSec(1));GatewayRuleManager.loadRules(rules);BlockRequestHandler handler = new BlockRequestHandler() {@Overridepublic Mono<ServerResponse> handleRequest(ServerWebExchange exchange, Throwable t) {Map<String,String> map = new HashMap<>();map.put("errorCode", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());map.put("errorMessage", "请求太过频繁,系统忙不过来,触发限流(sentinel+gataway整合Case)");return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(map));}};GatewayCallbackManager.setBlockHandler(handler);}
}