欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > SpringCloudAlibaba-Sentinel-熔断与限流

SpringCloudAlibaba-Sentinel-熔断与限流

2025/3/17 23:37:43 来源:https://blog.csdn.net/qq_39007838/article/details/143293066  浏览:    关键词:SpringCloudAlibaba-Sentinel-熔断与限流

版本说明

<spring.boot.version>3.2.0</spring.boot.version>
<spring.cloud.version>2023.0.0</spring.cloud.version>
<spring.cloud.alibaba.version>2023.0.1.2</spring.cloud.alibaba.version>

是什么

能干嘛

面试题

服务雪崩

安装使用

后台 8719,前端 8080,用户名密码 sentinel

本次版本 1.8.6

服务加入监控

启动 nacos, sentinel

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
server:port: 8401spring:application:name: cloud-alibaba-sentinel-servicecloud:nacos:discovery:server-addr: localhost:8848sentinel:transport:dashboard: localhost:8080port: 8719 # 默认端口
@Slf4j
@RestController
public class FlowLimitController {@GetMapping("/testA")public String testA() {return "into ... A ...";}@GetMapping("/testB")public String testB() {return "into ... B ...";}}

GET http://localhost:8401/testA

流控规则

流控模式

直接

每秒超过2qps

关联

压测 testB,访问 testA

链路

厚此薄彼

添加一个service 资源,cd来调用同一个 service

@Slf4j
@Service
public class FlowLimitService {@SentinelResource("common")public void common() {log.info("into ... common ...");}
}// controller
@GetMapping("/testC")
public String testC() {flowLimitService.common();return "into ... C ...";
}@GetMapping("/testD")
public String testD() {flowLimitService.common();return "into ... D ...";
}

新增配置

spring.cloud.sentinel:web-context-unify: false # controller 对 service 调用默认不是一个根链路

common上添加链路流控

c 超过qps会异常,d正常

流控效果

快速失败

warm up

排队等待

流控效果v2-并发线程数(对比 qps)

流控效果默认直快速失败,可能存在不准确?

熔断规则

慢调用比例

异常比例

异常数

@SentinelResource

rest 地址限流

@GetMapping("/")
public String rateLimitByUrl() {return "限流测试未使用注解";
}

返回默认信息

按SentinelResource+自定义限流返回

@GetMapping("/rateLimitByResource")
@SentinelResource(value = "ByResource", blockHandler = "byResourceHandler")
public String rateLimitByResource() {return "限流测试使用注解, 返回指定的字符串";
}public String byResourceHandler(BlockException blockException) {return "服务不可用, 这是自定义返回的字符串";
}

额外添加服务降级

@GetMapping("/rateLimitByFallback/{i}")@SentinelResource(value = "rateLimitByFallback", blockHandler = "byBlockHandler", fallback = "byFallback")public String rateLimitByFallback(@PathVariable("i") Integer i) {if (i == 0) {throw new RuntimeException("i == 0 异常");}return "使用注解并使用, Fallback";}public String byBlockHandler(@PathVariable("i") Integer i, BlockException blockException) {log.error("配置了自定义限流, {}", blockException.getMessage());return "服务不可用, 这是自定义返回的字符串";}public String byFallback(@PathVariable("i") Integer i, Throwable throwable) {log.error("程序逻辑异常, {}", throwable.getMessage());return "逻辑异常, 这是自定义返回的字符串";}

热点规则

@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey", blockHandler = "testHotKeyBlockHandler")
public String testHotKey(@RequestParam(value = "p1", required = false) String p1,@RequestParam(value = "p2", required = false) String p2) {return "testHotKey ...";
}public String testHotKeyBlockHandler(@RequestParam(value = "p1", required = false) String p1,@RequestParam(value = "p2", required = false) String p2, BlockException blockException) {return "testHotKey blockException ...";
}

对 p1 进行限流

参数例外项

授权规则

@Slf4j
@RestController
public class EmpowerController {@GetMapping("empower")public String requestSentinel() {log.info("授权规则");return "授权规则";}
}public class CustomRequestOriginParser implements RequestOriginParser {@Overridepublic String parseOrigin(HttpServletRequest httpServletRequest) {return httpServletRequest.getParameter("serverName");}
}

持久化规则

持久化到 nacos

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
spring:cloud:nacos:discovery:server-addr: localhost:8848sentinel:datasource:ds1:nacos:server-addr: localhost:8848data-id: ${spring.application.name}group-id: DEFAULT_GROUPdata-type: jsonrule-type: flow # com.alibaba.cloud.sentinel.datasource.RuleType (flow代表流控)

rule-type?

针对每一个rule-type单独配置 数据源

配置

nacos中添加 json 格式配置

测试重启,规则仍存在

整合OpenFeign实现 fallback 统一服务降级

blockHandler 处理 sentinel 流控问题,fallback 处理方法内抛出的异常

本例中,把 fallback 交给feign处理,再公共api-common中配置

服务提供者

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
server:port: 9001
spring:application:name: nacos-pay-providercloud:nacos:discovery:server-addr: localhost:8848 # nacos地址sentinel:transport:dashboard: localhost:8080port: 8719 # 默认端口8719
// openfeign和sentinel 进行流量降级和流量监控的case
@GetMapping("/pay/nacos/get/{orderNo}")
@SentinelResource(value = "getPayByOrderNo", blockHandler = "handlerBlockHandler")
public Result<PayDTO> getPayByOrderNo(@PathVariable("orderNo") String orderNo) {// 模拟查询PayDTO payDTO = new PayDTO(1024, orderNo, "pay" + IdUtil.simpleUUID(), 1, BigDecimal.valueOf(9.9));return Result.success(payDTO);
}public Result<PayDTO> handlerBlockHandler(String orderNo, BlockException e) {return Result.fail("服务提供者" + e.getMessage());
}

common

@FeignClient(value = "nacos-pay-provider", fallback = PayFeignSentinelFallback.class)
public interface PayFeignSentinelApi {@GetMapping("/pay/nacos/get/{orderNo}")Result<PayDTO> getPayByOrderNo(@PathVariable("orderNo") String orderNo);
}@Component
public class PayFeignSentinelFallback implements PayFeignSentinelApi {@Overridepublic Result<PayDTO> getPayByOrderNo(String orderNo) {return Result.fail("服务不可达");}
}

消费者

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
feign:sentinel:enabled: true
@GetMapping("/consume/pay/nacos/get/{orderNo}")
Result<PayDTO> getPayByOrderNo(@PathVariable("orderNo") String orderNo){return payFeignSentinelApi.getPayByOrderNo(orderNo);
}

sentinel配置&测试流控

单独测试服务端下流流控

localhost:9002/pay/nacos/get/1

测试 feign 异常

GET http://localhost:9000/consume/pay/nacos/get/1

让服务端宕机

整合 Gateway 实现服务限流

<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>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- loadbalancer -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency><groupId>javax.annotation</groupId><artifactId>javax.annotation-api</artifactId><version>1.3.2</version><scope>compile</scope>
</dependency>
server:port: 9528spring:application:name: cloud-alibaba-sentinel-gatewaycloud:nacos:discovery:server-addr: localhost:8848 # nacos地址gateway:routes:- id: pay_routh1uri: lb://nacos-pay-provider#          uri: http://localhost:9001predicates:- Path=/pay/**
@Configuration
public class GatewayConfiguration {private final List<ViewResolver> viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public GatewayConfiguration(List<ViewResolver> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) {this.viewResolvers = viewResolvers;this.serverCodecConfigurer = serverCodecConfigurer;}@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);}@Bean@Order(-1)public GlobalFilter sentinelGatewayFilter() {return new SentinelGatewayFilter();}@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 = (serverWebExchange, throwable) -> {HashMap<String, String> map = new HashMap<>();map.put("ErrorCode", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());map.put("ErrorMessage", "请求过于频繁, 触发了sentinel限流 ... ");return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(map));};GatewayCallbackManager.setBlockHandler(handler);}
}

http://localhost:9528/pay/nacos/get/1

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词