当前位置:网站首页>Sentinel服务熔断实战(sentinel整合ribbon+openFeign+fallback)
Sentinel服务熔断实战(sentinel整合ribbon+openFeign+fallback)
2022-04-23 18:36:00 【华为云】
@toc
源码地址:gitee仓库地址
1、Ribbon系列
1.1 启动nacos和sentinel
1.2 创建两个服务提供者payment9003和payment9004
新建cloudalibaba-provider-payment9003/9004两个一样的做法
由于9003和9004除了端口号不一样,其他几乎一致,这里只演示9003端口的搭建方式。
pom.xml
<dependencies> <!--SpringCloud ailibaba nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity --> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <!-- SpringBoot整合Web组件 --> <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> <!--日常通用jar包配置--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
application.yml
server: port: 9003spring: application: name: nacos-payment-provider cloud: nacos: discovery: server-addr: localhost:8848 #配置Nacos地址management: endpoints: web: exposure: include: '*'
记得修改不同的端口号
主启动类
@SpringBootApplication@EnableDiscoveryClientpublic class PaymentMain9003{ public static void main(String[] args) { SpringApplication.run(PaymentMain9003.class, args); }}
业务类
@RestControllerpublic class PaymentController{ @Value("${server.port}") private String serverPort; public static HashMap<Long,Payment> hashMap = new HashMap<>(); static { hashMap.put(1L,new Payment(1L,"28a8c1e3bc2742d8848569891fb42181")); hashMap.put(2L,new Payment(2L,"bba8c1e3bc2742d8848569891ac32182")); hashMap.put(3L,new Payment(3L,"6ua8c1e3bc2742d8848569891xt92183")); } @GetMapping(value = "/paymentSQL/{id}") public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id) { Payment payment = hashMap.get(id); CommonResult<Payment> result = new CommonResult(200,"from mysql,serverPort: "+serverPort,payment); return result; }}
这里为了测试,并没有去连接数据库,模拟了几个数据,效果都是一样的。
启动服务并测试业务类是否正常:http://localhost:9003/paymentSQL/1
http://localhost:9004/paymentSQL/1
两个服务提供者搭建成功。
1.3 搭建服务消费者order84
1.3.1 基础模块搭建
新建cloudalibaba-consumer-nacos-order84
pom.xml
<dependencies> <!--SpringCloud ailibaba nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--SpringCloud ailibaba sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!-- 引入自己定义的api通用包,可以使用Payment支付Entity --> <dependency> <groupId>com.atguigu.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <!-- SpringBoot整合Web组件 --> <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> <!--日常通用jar包配置--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
application.yml
server: port: 84spring: application: name: nacos-order-consumer cloud: nacos: discovery: server-addr: localhost:8848 sentinel: transport: #配置Sentinel dashboard地址 dashboard: localhost:8080 #默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口 port: 8719#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)service-url: nacos-user-service: http://nacos-payment-provider
主启动类
@EnableDiscoveryClient@SpringBootApplicationpublic class OrderNacosMain84{ public static void main(String[] args) { SpringApplication.run(OrderNacosMain84.class, args); }}
业务类
负载均衡配置:
@Configurationpublic class ApplicationContextConfig{ @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); }}
CircleBreakerController
@RestController@Slf4jpublic class CircleBreakerController{ public static final String SERVICE_URL = "http://nacos-payment-provider"; @Resource private RestTemplate restTemplate; @RequestMapping("/consumer/fallback/{id}") @SentinelResource(value = "fallback") public CommonResult<Payment> fallback(@PathVariable Long id) { CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id); if (id == 4) { throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常...."); }else if (result.getData() == null) { throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常"); } return result; }}
上面代码在id=1/2/3时正常,id=4时抛出IllegalArgumentException异常,大于4的时候抛出空指针异常。
这里的测试目的:fallback管运行异常,blockHandler管配置违规
上面并没有配置@SentinelResource,会直接给客户返回error页面,非常不友好。
1.3.2 只配置fallback
@RequestMapping("/consumer/fallback/{id}")// @SentinelResource(value = "fallback") @SentinelResource(value = "fallback",fallback = "handlerFallback") public CommonResult<Payment> fallback(@PathVariable Long id) { CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id); if (id == 4) { throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常...."); }else if (result.getData() == null) { throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常"); } return result; }// //fallback方法 public CommonResult handlerFallback(@PathVariable Long id,Throwable e) { Payment payment = new Payment(id,"null"); return new CommonResult<>(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment); }
注意:这里并没有配置sentinel。
访问测试:
http://localhost:84/consumer/fallback/1
http://localhost:84/consumer/fallback/4
http://localhost:84/consumer/fallback/5
此时就执行指定的fallback,对调用者比较友好。
1.3.3 只配置blockHandler
@RequestMapping("/consumer/fallback/{id}") @SentinelResource(value = "fallback",blockHandler = "blockHandler") public CommonResult<Payment> fallback(@PathVariable Long id) { CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id); if (id == 4) { throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常...."); }else if (result.getData() == null) { throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常"); } return result; }// //fallback方法// public CommonResult handlerFallback(@PathVariable Long id,Throwable e) {// Payment payment = new Payment(id,"null");// return new CommonResult<>(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment);// }// //blockHandler public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) { Payment payment = new Payment(id,"null"); return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException "+blockException.getMessage(),payment); }
这里需要配置下sentinel
异常超过2次以后,断路器打开,断电跳闸,系统被保护。
测试:
第一次访问:http://localhost:84/consumer/fallback/4
发现还是给了个error页面,注意,我们上面配置的是当异常数大于2的时候断路器才会打开。
再访问几次。
可以看到,被限流了。
1.3.4 fallback和blockHandler都配置
@RequestMapping("/consumer/fallback/{id}")// @SentinelResource(value = "fallback")// @SentinelResource(value = "fallback",fallback = "handlerFallback")// @SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler负责在sentinel里面配置的降级限流 @SentinelResource(value = "fallback", fallback = "handlerFallback", blockHandler = "blockHandler", ) public CommonResult<Payment> fallback(@PathVariable Long id) { CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id); if (id == 4) { throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常...."); }else if (result.getData() == null) { throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常"); } return result; } //fallback方法 public CommonResult handlerFallback(@PathVariable Long id,Throwable e) { Payment payment = new Payment(id,"null"); return new CommonResult<>(444,"兜底异常handlerFallback,exception内容 "+e.getMessage(),payment); }// //blockHandler public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) { Payment payment = new Payment(id,"null"); return new CommonResult<>(445,"blockHandler-sentinel限流,无此流水: blockException "+blockException.getMessage(),payment); }
这里需要配置Sentinel流控
配置解释:1秒只能处理1个请求,否则就限流。
我们测试,http://localhost:84/consumer/fallback/4,一直频繁访问触发限流降级。
==结论:若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。==
1.3.5 忽略属性配置
我们给@SentinelResource
注解添加配置exceptionsToIgnore = {IllegalArgumentException.class}
此时如果我们传的参数id=4,则会忽略IllegalArgumentException
异常。
此时再访问:http://localhost:84/consumer/fallback/4
此时异常打印到前台了,对用户不友好。
2、Feign系列
我们一般服务调用都是使用OpenFeign的,在FeignClient中统一处理fallback
2.1 修改84模块。
在服务消费者(order84)模块中引入OpenFeign
<!--SpringCloud openfeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
2.2 配置文件application.yml中激活Sentinel对Feign的支持
2.3 业务类
带@FeignClient
注解的业务接口
/** * 使用 fallback 方式是无法获取异常信息的, * 如果想要获取异常信息,可以使用 fallbackFactory参数 */@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)//调用中关闭9003服务提供者public interface PaymentService{ @GetMapping(value = "/paymentSQL/{id}") public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);}
fallback = PaymentFallbackService.class的实现类
@Componentpublic class PaymentFallbackService implements PaymentService{ @Override public CommonResult<Payment> paymentSQL(Long id) { return new CommonResult<>(44444444,"服务降级返回,-------PaymentFallbackService",new Payment(id, "errorSerial......")); }}
Controller:
主启动类
添加@EnableFeignClients
启动Feign的功能
访问测试:http://localhost:84/consumer/paymentSQL/1
测试84调用9003,此时故意关闭9003微服务提供者,看84消费侧自动降级,不会被耗死
关闭9003的服务提供者
再次访问http://localhost:84/consumer/paymentSQL/1
可以看到,已经出发了服务降级。返回的是我们在FeignClient接口中指定的falback。
3、三种熔断框架比较
到此,Sentinel整合服务熔断的测试就介绍完了,关于Sentinel限流那块配置太多,不好细讲,最好去看看官网。我去年也发过限流的文章,去我SpringCloud Alibaba专栏里面找
版权声明
本文为[华为云]所创,转载请带上原文链接,感谢
https://bbs.huaweicloud.com/blogs/349222
边栏推荐
- 【ACM】455. 分发饼干(1. 大饼干优先喂给大胃口;2. 遍历两个数组可以只用一个for循环(用下标索引--来遍历另一个数组))
- Domestic GD chip can filter
- The first leg of the national tour of shengteng AI developer creation and enjoyment day was successfully held in Xi'an
- Serial port debugging tools cutecom and minicom
- Kettle paoding jieniu Chapter 17 text file output
- QT error: no matching member function for call to ‘connect‘
- 昇腾 AI 开发者创享日全国巡回首站在西安成功举行
- Daily network security certification test questions (April 15, 2022)
- Loop path
- Iptables - L executes slowly
猜你喜欢
Jeecg boot microservice architecture
Machine learning practice - naive Bayes
【ACM】376. Swing sequence
Stm32mp157 wm8960 audio driver debugging notes
Promote QT default control to custom control
logstash 7. There is a time problem in X. the difference between @ timestamp and local time is 8 hours
Use Chenxi bookkeeping book to analyze the balance of revenue and expenditure of each account in a certain period of time
CANopen STM32 transplantation
Spark performance optimization guide
解决:cnpm : 无法加载文件 ...\cnpm.ps1,因为在此系统上禁止运行脚本
随机推荐
使用晨曦记账本,分析某个时间段每个账户收支结余
Test post and login function
Machine learning theory (7): kernel function kernels -- a way to help SVM realize nonlinear decision boundary
CANopen usage method and main parameters of object dictionary
Resolves the interface method that allows annotation requests to be written in postman
Differences between SSD hard disk SATA interface and m.2 interface (detailed summary)
Daily CISSP certification common mistakes (April 12, 2022)
深入理解 Golang 中的 new 和 make 是什么, 差异在哪?
In shell programming, the shell file with relative path is referenced
Teach you to quickly rename folder names in a few simple steps
数据库上机实验四(数据完整性与存储过程)
QT excel operation summary
Nodejs installation
Keil RVMDK compiled data type
配置iptables
Tangle
MATLAB从入门到精通(二)
ctfshow-web362(SSTI)
Use Chenxi bookkeeping book to analyze the balance of revenue and expenditure of each account in a certain period of time
Quantexa CDI(场景决策智能)Syneo平台介绍