当前位置: 首页 > news >正文

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

http://www.lryc.cn/news/471485.html

相关文章:

  • mysql中的mvcc理解
  • ETF申购赎回指南:详解注意事项与低费率券商推荐!
  • List<T>属性和方法使用
  • 记一次:使用使用Dbeaver连接Clickhouse
  • Java面向对象编程进阶(四)
  • 【51单片机】第一个小程序 —— 点亮LED灯
  • 如何通过自动化有效地简化 Active Directory 操作?
  • Java-POI导出EXCEL(动态表头)
  • 利用 Direct3D 绘制几何体—9.流水线状态对象
  • 【开源项目】libfaketime安装、使用——小白教程
  • java.util.concurrent包
  • Django创建项目模块+创建映射类+视图
  • 使用AMD GPU和LangChain构建问答聊天机器人
  • 2024年808数据结构答案
  • Amazon Linux 2023 安装 Docker
  • 接口测试(八)jmeter——参数化(CSV Data Set Config)
  • GGD证明推导学习
  • Flink难点和高频考点:Flink的反压产生原因、排查思路、优化措施和监控方法
  • Swarm - Agent 编排工具
  • 使用Python中的jieba库进行简单情感分析
  • `pip` 下载速度慢
  • 【WRF数据准备】基于GEE下载静态地理数据-叶面积指数LAI及绿色植被率Fpar
  • 网管平台(进阶篇):网管软件的配置方式
  • 推荐系统中的AB测试
  • .NET 8 Web API 中的身份验证和授权
  • Vue弹窗用也可以直接调用Js方法了
  • 【c语言测试】
  • 一种将树莓派打造为游戏机的方法——Lakka
  • 如何在 MySQL 中创建一个完整的数据库备份?
  • 京准电钟HR-901GB双GPS北斗卫星时钟服务器