springcloudAlibaba_sentinel 和其他框架整合
nacos和openFeign整合
整合说明:
- 使用nacos作为服务注册中心
- 使用openFeign作为http调用框架
-
使用工程cloudalibaba-consumer-nacos-order83作为客户端,cloudalibaba-provider-payment9001作为服务端,服务端会以伪集群方式启动,对外暴露9001端口和9002端口
-
以集群模式启动nacos,对外暴露nginx地址:localhost:8888,nacos集群方式安装参考:docker-compose搭建nacos集群
1
$ dcp -f cluster-hostname.yaml up -d
-
cloudalibaba-provider-payment9001工程
-
pom
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>cloud2020</artifactId> <groupId>com.eh</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloudalibaba-config-nacos-client3377</artifactId> <dependencies> <!--服务注册与发现nacos--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--暴露监控端点供外部使用--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--整合web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--引入通用包,主要使用CommonResult类--> <dependency> <groupId>org.eh</groupId> <artifactId>cloud-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project>
-
yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
server: port: 9001 spring: application: name: cloudalibaba-provider-payment9001 cloud: nacos: discovery: #配置nacos地址 server-addr: localhost:8888 management: endpoints: web: exposure: include: '*'
-
主启动类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
package com.eh.cloud.alibaba.nacos.payment; import com.eh.cloud2020.common.entity.CommonResult; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @EnableDiscoveryClient @SpringBootApplication public class NacosPaymentMain9001 { public static void main(String[] args) { SpringApplication.run(NacosPaymentMain9001.class, args); } @RestController class PaymentController { @Value("${server.port}") private String serverPort; @GetMapping(value = "/payment/{id}") public CommonResult<String> getPayment(@PathVariable("id") Integer id) { return CommonResult.success("cloudalibaba-provider-payment9001,serverPort:" + serverPort + ",id:" + id); } } }
-
伪集群配置
-
启动9001和9002
-
测试
-
http://localhost:9001/payment/1
1 2 3 4 5
{ "code": 200, "desc": "处理成功", "data": "cloudalibaba-provider-payment9001,serverPort:9001,id:1" }
-
http://localhost:9002/payment/1
1 2 3 4 5
{ "code": 200, "desc": "处理成功", "data": "cloudalibaba-provider-payment9001,serverPort:9002,id:1" }
-
http://localhost:8888/nacos/ 服务列表
-
-
-
cloudalibaba-consumer-nacos-order83工程
-
pom
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
<dependencies> <!--服务注册与发现nacos--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--整合openFeign--> <!--SpringCloud openfeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--整合web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--引入通用包,主要使用CommonResult类--> <dependency> <groupId>org.eh</groupId> <artifactId>cloud-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
-
yml
1 2 3 4 5 6 7 8 9 10 11
server: port: 83 spring: application: name: cloudalibaba-consumer-nacos-order83 cloud: nacos: discovery: #配置nacos地址 server-addr: localhost:8888
-
业务类
使用feign引入服务端服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14
package com.eh.cloud.alibaba.nacos.consumer.service; import com.eh.cloud2020.common.entity.CommonResult; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(value = "cloudalibaba-provider-payment9001") public interface PaymentService { @GetMapping(value = "/payment/{id}") CommonResult<String> getPayment(@PathVariable("id") Integer id); }
-
主启动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
package com.eh.cloud.alibaba.nacos.consumer; import com.eh.cloud.alibaba.nacos.consumer.service.PaymentService; import com.eh.cloud2020.common.entity.CommonResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @EnableFeignClients // fegin @EnableDiscoveryClient // nacos 服务注册 @SpringBootApplication public class NacosOrderMain83 { public static void main(String[] args) { SpringApplication.run(NacosOrderMain83.class, args); } @RestController class OrderController { @Autowired private PaymentService paymentService; @GetMapping(value = "/order/payment/{id}") public CommonResult<String> paymentInfo(@PathVariable("id") Integer id) { CommonResult<String> paymentResult = paymentService.getPayment(id); return CommonResult.success("from order consumer:" + paymentResult.getData()); } } }
-
测试
- nacos服务注册中心会多出客户端实例
- 访问http://localhost:83/order/payment/1,多刷几次,端口号在9002和9001交替
-
至此,服务注册与发现nacos和服务调用openFeign的整合完毕,接下来开始整合熔断降级功能sentinel
整合sentinel
-
启动sentinel
1
$ java -jar sentinel-dashboard-1.8.0.jar
-
改造客户端 cloudalibaba-consumer-nacos-order83
-
pom
注意这里我将父pom中 cloud版本改成了Hoxton.SR5,因为2.2.3.RELEASE的cloudalibaba中的sentinel依赖feign中的一个方法parseAndValidateMetadata,这个方法在2.2.0.RELEASE版本拼写错误
1 2
// TODO: break this and correct spelling at some point List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType);
2.2.2.RELEASE改过来了
1
List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType);
如果用H.SR1依赖的还是2.2.0的方法名,启动时sentinel会报找不到方法
引入sentinel
1 2 3 4 5
<!--限流、熔断降级sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
完整配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
<dependencies> <!--限流、熔断降级sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!--服务注册与发现nacos--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--整合openFeign--> <!--SpringCloud openfeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--整合web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--引入通用包,主要使用CommonResult类--> <dependency> <groupId>org.eh</groupId> <artifactId>cloud-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
-
yml
增加sentinel相关配置,完整配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
server: port: 83 spring: application: name: cloudalibaba-consumer-nacos-order83 cloud: nacos: discovery: #配置nacos地址 server-addr: localhost:8888 # sentinel配置 sentinel: transport: dashboard: localhost:8080 # 指定应用与sentinel控制台交互的端口,应用本地会起一个该端口占用的httpserver # 默认8719,假如被占用了会自动从8719开始依次+1扫描,直至找到未被占用的端口 port: 8719 # 激活sentinel对feign的支持,可以像hystrix一样使用fallback进行降级 feign: sentinel: enabled: true
-
业务类
新增对服务端服务调用降级功能,针对服务级别的进行fallback处理,新增PaymentFallbackService类如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
package com.eh.cloud.alibaba.nacos.consumer.service; import com.eh.cloud2020.common.entity.CommonResult; import org.springframework.stereotype.Service; @Service public class PaymentFallbackService implements PaymentService { @Override public CommonResult<String> getPayment(Integer id) { return CommonResult.error(444, "服务端繁忙,请稍后再试"); } }
改造服务调用类PaymentService,指定fallback处理类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
package com.eh.cloud.alibaba.nacos.consumer.service; import com.eh.cloud2020.common.entity.CommonResult; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(value = "cloudalibaba-provider-payment9001", fallback = PaymentFallbackService.class) public interface PaymentService { @GetMapping(value = "/payment/{id}") CommonResult<String> getPayment(@PathVariable("id") Integer id); }
-
启动主程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
package com.eh.cloud.alibaba.nacos.consumer; import com.eh.cloud.alibaba.nacos.consumer.service.PaymentService; import com.eh.cloud2020.common.entity.CommonResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @EnableFeignClients // fegin @EnableDiscoveryClient // nacos 服务注册 @SpringBootApplication public class NacosOrderMain83 { public static void main(String[] args) { SpringApplication.run(NacosOrderMain83.class, args); } @RestController class OrderController { @Autowired private PaymentService paymentService; @GetMapping(value = "/order/payment/{id}") public CommonResult<String> paymentInfo(@PathVariable("id") Integer id) { CommonResult<String> paymentResult = paymentService.getPayment(id); if (200 == paymentResult.getCode()) { return CommonResult.success("from order consumer:" + paymentResult.getData()); } else { return CommonResult.error(paymentResult.getCode(), "from order consumer:" + paymentResult.getDesc()); } } } }
-
访问http://localhost:83/order/payment/1,可以看到sentinel dashboard服务列表上能看到服务
-
-
配置客户端对服务调用降级规则
如果对服务端调用耗时超过1ms就降级,降级规则如上
-
快速访问几次:http://localhost:83/order/payment/1,可以看到返回信息已经改成我们自定义的了
至此,nacos+feign+sentinel整合完毕
sentinel使用nacos作为数据源进行持久化
问题
到目前为止一切都进行地很好,但是还有一个问题,一旦我们重启配置了sentinel规则的应用,sentinel规则就将小时,如何将配置规则持久化呢?
解决
可以将限流配置规则持久化到Nacos配置中心,只要刷新应用的某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上Sentinel上的流控规则持续有效
首先需要在nacos配置中心增加数据源配置,如下:
-
Data ID:cloudalibaba-consumer-nacos-order83-datasource
-
Group:DEFAULT_GROUP
-
配置格式:JSON
-
配置内容
1 2 3 4 5 6 7 8 9 10 11
[ { "resource": "GET:http://cloudalibaba-provider-payment9001/payment/{id}", "limitApp": "default", "grade": 1, "count": 1, "strategy": 0, "controlBehavior": 0, "clusterMode": false } ]
参考:https://www.jianshu.com/p/fb3218b21da5
属性解释如下:
resource:资源名,即限流规则的作用对象
**limitApp:流控针对的调用来源,**若为 default 则不区分调用来源
grade:限流阈值类型(QPS 或并发线程数);0代表根据并发数量来限流,1代表根据QPS来进行流量控制
count:限流阈值
strategy:调用关系限流策略
controlBehavior:流量控制效果(直接拒绝、Warm Up、匀速排队)
clusterMode:是否为集群模式
注意:在完成了上面的整合之后,对于接口流控规则的修改就存在两个地方了:Sentinel控制台、Nacos控制台。
这个时候,通过Nacos修改该条规则是可以同步到Sentinel的,但是通过Sentinel控制台修改或新增却不可以同步到Nacos。因为当前版本的Sentinel控制台不具备同步修改Nacos配置的能力。
而Nacos由于可以通过在客户端中使用Listener来实现自动更新。所以,在整合了Nacos做规则存储之后,需要知道在下面两个地方修改存在不同的效果:
Sentinel控制台中修改规则:仅存在于服务的内存中,不会修改Nacos中的配置值,重启后恢复原来的值。Nacos控制台中修改规则:服务的内存中规则会更新,Nacos中持久化规则也会更新,重启后依然保持。
改造cloudalibaba-consumer-nacos-order83
-
pom
新引入
1 2 3 4 5 6 7 8 9 10
<!--持久化规则配置--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency> <!--由于要使用到nacos配置中心,需要暴露一些监控端点--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
完整配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
<dependencies> <!--持久化规则配置--> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency> <!--由于要使用到nacos配置中心,需要暴露一些监控端点--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--限流、熔断降级sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!--服务注册与发现nacos--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--整合openFeign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--整合web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--引入通用包,主要使用CommonResult类--> <dependency> <groupId>org.eh</groupId> <artifactId>cloud-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
-
yml
增加数据源——nacos配置中心相关配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
server: port: 83 spring: application: name: cloudalibaba-consumer-nacos-order83 cloud: nacos: discovery: #配置nacos地址 server-addr: localhost:8888 # sentinel配置 sentinel: transport: dashboard: localhost:8080 # 指定应用与sentinel控制台交互的端口,应用本地会起一个该端口占用的httpserver # 默认8719,假如被占用了会自动从8719开始依次+1扫描,直至找到未被占用的端口 port: 8719 datasource: d1: nacos: server-addr: localhost:8848 dataId: cloudalibaba-sentinel-service groupId: DEFAULT_GROUP data-type: json rule-type: flow # 暴露监控端点,供配置中心调用,nacos自带类似webhook+bus功能 management: endpoints: web: exposure: include: "*" # 激活sentinel对feign的支持,可以像hystrix一样使用fallback进行降级 feign: sentinel: enabled: true
-
一切妥当以后,重启客户端cloudalibaba-consumer-nacos-order83,发现流控规则里已经有了我们在nacos配置中心中进行的配置
-
编辑配置中心,将阈值设置成5 然后发布,刷新sentinel dashboard,可以看到阈值已经变成5了
至此,nacos+openFeign+sentinel+sentinel持久化整合完毕。