# SpringCloudH2020 **Repository Path**: alanlxx/SpringCloudH2020 ## Basic Information - **Project Name**: SpringCloudH2020 - **Description**: 1230000000000000000 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-02-08 - **Last Updated**: 2022-07-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: SpringCloud, SpringBoot ## README # Spring Cloud learning notes ## 一、什么是微服务架构 1. 微服务架构是一种`架构模式`,将`单一`的应用程序划分为`一组`小的服务, 2. 服务之间相互配合,提供一个完整的服务体系, 3. 每个服务`独立`的运行在`进程`中,采用`轻量级的通信机制`相互协作(通常基于HTTP的Restful API) 4. 每个服务都围绕着`一个`具体的业务进行构建,并且能够`独立`部署到生产环境等 ## 二、微服务架构中有什么 1. 服务注册与发现 7. 配置中心 2. 服务调用 8. 服务网关 3. 服务熔断 9. 服务监控 4. 服务负载均衡 10. 全链路追踪 5. 服务降级 11. 自动化构建部署 6. 服务消息队列 12. 服务调度 ## 三、什么是Spring Cloud ​ Spring Cloud 是微服务一站式解决方案,是多种微服务架构落地技术的集合体,称为微服务全家桶,为微 服务提供统一管理 ## 四、Spring Cloud 与 Spring Boot 版本对应 查看 ​ https://start.spring.io/actuator/info ## 五、注册与发现 ### 什么是服务治理 ​ 传统的RPC远程调用框架中,管理服务与服务之间的依赖关系比较复杂,所以需要服务治理, ​ 管理服务之间的`依赖关系`,可以实现服务调用,`复杂均衡`,`容错`等,实现服务注册与发现 ### 什么是服务注册 ​ 当服务`启动的时候`,会把服务的信息(比如:服务通讯地址,服务别名等)注册到注册到`注册中心`上, ​ 服务消费者通过`别名`的方式在注册中心上获取实际的服务通讯地址,实现RPC调用 ​ ![image-20210204170419366](https://i.loli.net/2021/02/04/y6GDJEYlAKOVnet.png) ### Eureka ​ **Eureka包括两个组件 Eureka Client 和 Eureka Server** #### Eureka Client ​ 是一个Java客户端,用于简化 Eureka Server 交互,同时 也具备一个内置的 使用`轮询负载`算法的 负载均衡器,在服务启动后,会向 Eureka Server 发送心跳包(`周期默认为30秒`),如果 Eureka Server 在`多个心跳周期`内没有收到 服务发送过来的心跳包, Eureka Server 将会从服务列表中移除该服 务(`默认90秒`) #### **Eureka Server** ​ 在服务启动的时候,会向 Eureka Server 中注册相关信息,这样 Eureka Server 就会将信息保存到 注册表中 #### Eureka 集群安装 ​ 1. **修改本地 host 文件** ​ 路径:C:\Windows\System32\drivers\etc ​ ![image-20210204175613102](https://i.loli.net/2021/02/04/WcQHmVKAkIlGx1E.png) ### CAP理论 ![image-20210908160702836](https://i.loli.net/2021/09/08/xXWIRUcpfkmnHgB.png) ​ C:强一致性 ​ A:高可用性 ​ P:分区容错性 (P:是分布式架构一定要满足的) Eureka满足的是:AP Zookeeper满足的是:CP Consul满足的是:CP Nacos:AP ## 六、负载均衡 ### RestTemplate #### getForObject() 和 getForEntity() 区别 ​ getForObject() 响应体为数据转化为对象,可以理解为JSON串 ​ getForEntity() 返回的是ResponseEntity对象,包含一些详细的信息,比如响应头,状态码,响应体等 ### LB(Load Balance)负载均衡是什么 ​ 简单来说就是,将用户请求平摊的分配到多个服务器上,从而达到系统的高可用 #### 集中式LB是什么 ​ 在服务消费方和服务提供方之间,使用一个LB设施,由LB通过某种策略将请求发送到服务提供方 #### 进程内LB是什么 ​ 将LB逻辑集成到服务消费方,消费方从注册中心在获取到服务列表,然后选择出合适的服务器请求 ​ Ribbon 就属于进程内LB ### Ribbon ​ Spring Cloud Ribbon 是基于NetFlix Ribbon 实现的一个客户端,负载均衡工具 ​ 主要提供客户端的负载均衡算法和服务调用 #### Ribbon 和 Nginx 有什么区别 ​ Nginx 是 服务端负载均衡,客户端所有的请求交给Nginx ,由Nginx 发起请求,负载均衡实在服务端实现的 ​ Ribbon 在调用微服务的时候,会在注册中心把服务列表缓存到 JVM 中,从而在本地实现RPC远程调用 #### Ribbon 实现定制化负载均衡规则 ![image-20210205151233638](https://i.loli.net/2021/02/05/vjWnatfBKNm3rHT.png) ![image-20210205151450249](https://i.loli.net/2021/02/05/3MYGcWq1AgZbiF4.png) ​ 1. 创建Config配置类,(注意:配置类不能放在能够被@ComentScan扫描到的包下,SpringBoot启动类 带有@ComentScan注解) ​ ![image-20210205152449435](https://i.loli.net/2021/02/05/ZN9VF4SuOxJ5XwU.png) ```java package com.richper.myrule; import com.netflix.loadbalancer.BestAvailableRule; import com.netflix.loadbalancer.IRule; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MySelfRule { // @Bean // @LoadBalanced // public IRule randomRule(){ // return new RandomRule(); // } @Bean @LoadBalanced public IRule BestAvailableRule(){ return new BestAvailableRule(); } } ``` ​ 2. 启动类加注解,表明使用的负载均衡配置 ​ @RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class) ​ name表示 微服务名称,configuration表示配置类 ```java package com.richper.springcloudh2020; import com.richper.myrule.MySelfRule; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; @SpringBootApplication @EnableEurekaClient @RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class) public class OrderApplication80 { public static void main(String[] args) { SpringApplication.run(OrderApplication80.class,args); } } ``` #### Ribbon轮询算法原理 ​ 注意:(服务重启后,接口请求次数会被重置为1) ![image-20210205153440770](https://i.loli.net/2021/02/05/ihwoRdJleGnKxIM.png) ![image-20210205153431508](https://i.loli.net/2021/02/05/OlVUW6EpYhIeLxi.png) ### Feign ### ![image-20210205170117138](https://i.loli.net/2021/02/05/ivkZYJ4dMaS6RLm.png) #### Feign 和 openFeign 区别 ![image-20210205170510469](https://i.loli.net/2021/02/05/gDEhTq12JX7YMwm.png) #### OpenFeign 超时时间控制 ​ openFeign 底层是 Ribbon , 其默认超时时间为1秒,响应时间超过1秒就会报异常 ​ 设置 超时时间: ```properties ribbon: #设置为5秒 ReadTimeout: 5000 #设置为5秒 ConnectTimeout: 5000 ``` #### OpenFeign日志级别 ![image-20210207103333319](https://i.loli.net/2021/02/07/b1BZXqEDiNYHUf8.png) **配置:** ```properties logging: level: com.richper.springcloudh2020.service.OrderFeignService: debug ``` ```java package com.richper.springcloudh2020.config; import feign.Logger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FeignConfig { @Bean Logger.Level level(){ return Logger.Level.FULL; } } ``` ## 七、服务降级 ### 服务雪崩 ​ 在一个调用链中,A调用B,B调用C,C调用D ​ 当一个服务出现故障时,导致整条链路故障的情形被称为服务雪崩 ### 服务降级 1. 当下游响应过慢时,下游主动放弃一些不太重要的业务,释放资源,提高响应速度。 ​ 2.当下游不可用时,上有主动调用本地降级逻辑,避免卡顿,响应用户。 ### 服务熔断 ​ 当一个下游服务出现故障或者响应过慢时,上游服务为了保证可用性不在调用此服务,直接返回,快速释 放资源。服务恢复正常以后,恢复调用链路 ### 服务限流 ​ 常用算法:计数器、令牌桶、漏桶。 ### Hystrix #### 服务降级 ##### 单个方法配置 客户端启动 80 需要 开启 feign hystrix配置 服务提供方不需要配置,直接使用注解配置 ```properties #启用Hystrix feign: hystrix: enabled: true ``` ```java @GetMapping("/payment_timeOut") @HystrixCommand(fallbackMethod = "payment_timeOutHandler",commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500") }) public String payment_timeOut(){ return hystrixOrderService.payment_timeOut(); } public String payment_timeOutHandler(){ return "线程池:"+Thread.currentThread().getName()+" 80系统忙,请稍后再试。, ┭┮﹏┭┮"; } ``` ##### 统一配置: ###### 第一种: ![image-20210207151032989](https://i.loli.net/2021/02/07/S8ZU1j7D5fsONEk.png) ```java package com.richper.springcloudh2020.controller; import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.richper.springcloudh2020.service.HystrixOrderService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @RestController @RequestMapping("/consumer") @DefaultProperties(defaultFallback = "payment_timeOutHandler") public class HystrixOrderController { @Resource private HystrixOrderService hystrixOrderService; @GetMapping("/payment_ok") public String payment_ok(){ return hystrixOrderService.payment_ok(); } @GetMapping("/payment_timeOut") // @HystrixCommand(fallbackMethod = "payment_timeOutHandler",commandProperties = { // @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500") // }) @HystrixCommand public String payment_timeOut(){ return hystrixOrderService.payment_timeOut(); } public String payment_timeOutHandler(){ return "线程池:"+Thread.currentThread().getName()+" 80系统忙,请稍后再试。, ┭┮﹏┭┮"; } } ``` ###### 第二种: ​ 1.创建HystrixOrderFallBack 实现 HystrixOrderService 类 ```java package com.richper.springcloudh2020.service.fallback; import com.richper.springcloudh2020.service.HystrixOrderService; import org.springframework.stereotype.Component; @Component public class HystrixOrderFallBack implements HystrixOrderService { @Override public String payment_ok() { return Thread.currentThread().getName()+" payment_ok-8005服务宕机请稍后再试, ┭┮﹏┭┮"; } @Override public String payment_timeOut() { return Thread.currentThread().getName()+" payment_timeOut-8005服务宕机请稍后再试, ┭┮﹏┭┮"; } } ``` 2. HystrixOrderService 注解 @FeignClient 添加 属性: fallback = HystrixOrderFallBack .class ```java package com.richper.springcloudh2020.service; import com.richper.springcloudh2020.service.fallback.HystrixOrderFallBack; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.GetMapping; @FeignClient(value = "CLOUD-HYSTRIX-PAYMENT-SERVICE",fallback = HystrixOrderFallBack.class) @Component public interface HystrixOrderService { @GetMapping("/payment_ok") String payment_ok(); @GetMapping("/payment_timeOut") String payment_timeOut(); } ``` #### 服务熔断 pom 依赖: ```xml org.springframework.cloud spring-cloud-starter-netflix-hystrix ``` 启动类配置 注解 : @EnableCircuitBreaker ```java package com.richper.springcloudh2020; import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean; @SpringBootApplication @EnableEurekaClient @EnableCircuitBreaker public class HystrixPaymentApp8005 { public static void main(String[] args) { SpringApplication.run(HystrixPaymentApp8005.class,args); } /** * 配置 hystrix dashboard 监控平台配置 spring cloud 升级后留下的坑 9001 监控 8001 * @return */ @Bean public ServletRegistrationBean getServlet(){ HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet(); ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean<>(streamServlet); servletRegistrationBean.setLoadOnStartup(1); servletRegistrationBean.addUrlMappings("/hystrix.stream"); servletRegistrationBean.setName("HystrixMetricsStreamServlet"); return servletRegistrationBean; } } ``` controller 示例: ```java package com.richper.springcloudh2020.controller; import cn.hutool.core.util.IdUtil; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.TimeUnit; @RestController public class HystrixPaymentController { //================服务熔断========华丽的分割线========服务熔断================== @GetMapping("/div/{id}") @HystrixCommand(fallbackMethod = "divFuse",commandProperties = { @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),//开启断路器,默认为false @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 时间范围内请求次数 @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),//时间范围 @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60")//时间范围内达到60%的错误率 }) //================注释========华丽的分割线========注释================== //10秒范围内10次请求达到60%的错误率,断路器从关闭状态更改为打开状态, // 在下一个时间范围内,尝试着通过一个请求,看服务是否恢复,如果没有恢复,则还是打开状态, // 如果恢复了,则关闭断路器,恢复服务调用链 public String div(@PathVariable("id") int id){ if (id <= 0){ throw new RuntimeException("ID不能为0"); } int i = 100 / id; return Thread.currentThread().getName()+" -> IdUtil.simpleUUID() :100 ➗ "+id+" = "+i; } public String divFuse(int id){ return Thread.currentThread().getName()+" :8005服务异常请稍后再试...id不能为0"; } } ``` #### 导致服务降级的几种原因 ​ 1.断路器为打开状态 ​ 2.信号量、队列满了 ​ 3.线程池没有可用资源处理 ​ 4.请求超时、异常、宕机等 ### Hystrix仪表盘图像化监控 ##### DashBoard 配置: ​ 1. 添加pom 依赖 ```xml org.springframework.cloud spring-cloud-starter-netflix-hystrix-dashboard org.springframework.cloud spring-cloud-starter-netflix-hystrix org.springframework.cloud spring-cloud-starter-openfeign org.springframework.cloud spring-cloud-starter-netflix-eureka-client com.richper.SpringCloudH2020 cloud-api-commons ${project.version} org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test ``` ​ 2.配置文件注册进Eurerka ```properties server: port: 9001 spring: application: name: cloud-consumer-dashboard-service # #热部署 # devtools: # restart: # enabled: true #是否支持热部署 eureka: client: #是否将自己注册进EurekaServer,默认为:true register-with-eureka: true #是否从EurekaServer抓取已有的注册信息,默认为:true,单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡 fetch-registry: true service-url: defaultZone: http://localhost:7001/eureka # 集群版 http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: instance-id: dashboard9001 # 访问路径可以显示ip地址 prefer-ip-address: true ``` ​ 3.启动类 ```java package com.richper.springcloudh2020; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; @SpringBootApplication @EnableHystrixDashboard public class DashboardApplication9001 { public static void main(String[] args) { SpringApplication.run(DashboardApplication9001.class,args); } } ``` ##### 服务端配置(被监听端)配置: ​ 1.添加Pom依赖 注意 web 和 actuator 依赖必须要有的 是核心包 ```xml org.springframework.cloud spring-cloud-starter-netflix-hystrix org.springframework.cloud spring-cloud-starter-netflix-eureka-client com.richper.SpringCloudH2020 cloud-api-commons ${project.version} org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.mybatis.spring.boot mybatis-spring-boot-starter com.alibaba druid-spring-boot-starter mysql mysql-connector-java org.springframework.boot spring-boot-starter-jdbc org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test ``` 启动类加配置: ```java package com.richper.springcloudh2020; import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean; @SpringBootApplication @EnableEurekaClient @EnableCircuitBreaker public class HystrixPaymentApp8005 { public static void main(String[] args) { SpringApplication.run(HystrixPaymentApp8005.class,args); } /** * 配置 hystrix dashboard 监控平台配置 spring cloud 升级后留下的坑 9001 监控 8001 * @return */ @Bean public ServletRegistrationBean getServlet(){ HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet(); ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean<>(streamServlet); servletRegistrationBean.setLoadOnStartup(1); servletRegistrationBean.addUrlMappings("/hystrix.stream"); servletRegistrationBean.setName("HystrixMetricsStreamServlet"); return servletRegistrationBean; } } ``` ##### 测试访问 地址:http://localhost:9001/hystrix 创建监听:http://localhost:8005/hystrix.stream ​ 注:http://localhost:端口号/hystrix.stream ![image-20210208163611503](https://i.loli.net/2021/02/08/RLxEXY6tdHsOgAM.png) ## 八、服务网关 ### Zuul 和 spring cloud GateWay 有什么区别? ​ `zuul` 采用的是 I/O 阻塞式架构模式,性能上不是特别的占优势,在 zuul 的基础上 改进 `zuul 2` 使用 `Netty`非阻塞 和 长连接的方式,但是 `zuul 2` 出了点问题,`spring` 出了 `GateWay` 也是基于`Netty` 非阻塞 和 长连接 方式,底层用的是 `webFlux` 和 `Netty` ### GateWay路由配置 ​ 在 网关 微服务上配置 第一种 配置文件: ```properties server: port: 9527 spring: application: #微服务名称 name: cloud-getway-service cloud: gateway: routes: - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名 #路由 匹配后提供服务的路由地址 uri: http://localhost:8005 predicates: - Path=/payment_ok # 断言,路径相匹配的进行路由 - id: payment_route2 uri: http://localhost:8005 predicates: Path=/div/** #断言,路径相匹配的进行路由 /div/** 表示 /div/{id} 后面的参数 #热部署配置 devtools: restart: enabled: true #是否支持热部署 eureka: client: #是否将自己注册进EurekaServer,默认为:true register-with-eureka: true #是否从EurekaServer抓取已有的注册信息,默认为:true,单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡 fetch-registry: true service-url: defaultZone: http://localhost:7001/eureka # 集群版 http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: instance-id: getway9527 # 访问路径可以显示ip地址 prefer-ip-address: true #每隔 30秒 向服务注册段发送一次心跳包,默认30秒 lease-renewal-interval-in-seconds: 30 #注册服务端 收到心跳包最后一次后等待时间上限35秒,默认90秒,超时将会剔除此服务 lease-expiration-duration-in-seconds: 35 ``` 第二种 配置类: ```java package com.richper.springcloudh2020.config; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class GetWayConfig { @Bean public RouteLocator consumerRoute(RouteLocatorBuilder routeLocatorBuilder){ return routeLocatorBuilder.routes(). route("route_1",r -> r.path("/guonei").uri("http://news.baidu.com/guonei")). route("route_2",r -> r.path("/lady").uri("http://news.baidu.com/lady")). route("route_3",r -> r.path("/mil").uri("http://news.baidu.com/mil")). route("route_4",r -> r.path("/guoji").uri("http://news.baidu.com/guoji")). route("route_5",r -> r.path("/finance").uri("http://news.baidu.com/finance")). route("route_6",r -> r.path("/ent").uri("http://news.baidu.com/ent")). route("route_7",r -> r.path("/sports").uri("http://news.baidu.com/sports")). route("route_8",r -> r.path("/internet").uri("http://news.baidu.com/internet")). route("route_9",r -> r.path("/tech").uri("http://news.baidu.com/tech")). route("route_10",r -> r.path("/game").uri("http://news.baidu.com/game")). route("route_11",r -> r.path("/auto").uri("http://news.baidu.com/auto")). route("route_12",r -> r.path("/house").uri("http://news.baidu.com/house")). route("route_12",r -> r.path("/").uri("http://news.baidu.com/")) .build(); } } ``` 示例 ![image-20210208162735808](https://i.loli.net/2021/02/08/UmqTiLQ6Ap4edl5.png) ### GateWay动态路由配置: ​ 在 网关 微服务上配置 #### 动态路由 实现 轮询负载 ​ 配置类: ```properties server: port: 9527 spring: application: #微服务名称 name: cloud-getway-service cloud: gateway: discovery: locator: enabled: true #开启从注册中心动态创建路由功能,利用微服务名进行路由 routes: - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名 #匹配后提供服务的路由地址 # uri: http://localhost:8005 uri: lb://CLOUD-HYSTRIX-PAYMENT-SERVICE #更改为 微服务名称 predicates: - Path=/id # 断言,路径相匹配的进行路由 - id: payment_route2 # uri: http://localhost:8005 uri: lb://CLOUD-HYSTRIX-PAYMENT-SERVICE #更改为 微服务名称 predicates: Path=/div/** #断言,路径相匹配的进行路由 /div/** 表示 /div/{id} 后面的参数 #热部署配置 devtools: restart: enabled: true #是否支持热部署 eureka: client: #是否将自己注册进EurekaServer,默认为:true register-with-eureka: true #是否从EurekaServer抓取已有的注册信息,默认为:true,单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡 fetch-registry: true service-url: defaultZone: http://localhost:7001/eureka # 集群版 http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: instance-id: getway9527 # 访问路径可以显示ip地址 prefer-ip-address: true #每隔 30秒 向服务注册段发送一次心跳包,默认30秒 lease-renewal-interval-in-seconds: 30 #注册服务端 收到心跳包最后一次后等待时间上限35秒,默认90秒,超时将会剔除此服务 lease-expiration-duration-in-seconds: 35 ``` #### GateWay 断言 类型 ##### Path: 匹配路径 ​ 例:- Path=/lb/** ##### After: 当前日期在指定日期之后 ​ 例:- After=2021-02-09T13:39:54.368+08:00[Asia/Shanghai] ​ 在2021年2月9号下午13点39分54秒之后 上海时间 ​ 日期格式获取: ```java import java.time.ZonedDateTime; public class T { public static void main(String[] args) { ZonedDateTime zdt = ZonedDateTime.now(); System.out.println(zdt);//2021-02-09T13:39:54.368+08:00[Asia/Shanghai] } } ``` ##### **Before**:当前日期在指定日期之前 ​ 例:- Before=2021-02-09T13:39:54.368+08:00[Asia/Shanghai] ​ Between: 当前日期在指定日期区间 ​ 例:- Between=2021-02-09T13:39:54.368+08:00[Asia/Shanghai],2021-03-09T13:39:54.368+08:00[Asia/Shanghai] ​ 两个日期之间逗号分隔 ##### Cookie: cookie匹配 ​ ![image-20210209134703676](https://i.loli.net/2021/02/09/SIxHZm23OgQ1Eyf.png) ​ 例:- Cookie=username,zzyy ​ 测试: curl http://localhost:9627/paymebt/lb --cokie “username,zzyy” ![image-20210209135357601](https://i.loli.net/2021/02/09/LhAkqydXbBg6ToJ.png) ##### ##### 等等…. ![image-20210209135715068](https://i.loli.net/2021/02/09/2jHPLAIXa5NeDEQ.png) ​ 文档地址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories ### GateWay 过滤器(Filter) ​ 第一种:文档地址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories ​ 第二种: #### GateWay 自定义全局过滤器 ​ 定义Filter类 实现 GlobalFilter 和 Ordered 接口 ```java package com.richper.springcloudh2020.filter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class RequestFilter implements GlobalFilter, Ordered { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { String userName = exchange.getRequest().getQueryParams().getFirst("userName"); if (userName == null) {//userName 为空 拦截,非法请求 ServerHttpResponse response = exchange.getResponse(); //设置 响应状态码,为 不接受 NOT_ACCEPTABLE response.setStatusCode(HttpStatus.NOT_ACCEPTABLE); return response.setComplete(); } return chain.filter(exchange); } /** * 过滤器加载的顺序,返回的值越小,代表这个过滤器越 先 被加载 * @return */ @Override public int getOrder() { return 0; } } ``` ## 九、配置中心 ![image-20210209142724988](https://i.loli.net/2021/02/09/eGXjPVTz1drIEBu.png) ### spring cloud config #### 1.创建gitee仓库 或者 github 等 #### 2.创建server端配置中心 ​ 如:cloud-config-center3344 ##### 添加 pom 依赖 ```xml org.springframework.cloud spring-cloud-config-server org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.springframework.boot spring-boot-starter-test test ``` ##### 配置 application.yml ```properties server: port: 3344 spring: application: name: cloud-config-server cloud: config: server: git: uri: https://gitee.com/alanlxx/SpringCloudH2020Config.git #gitee项目地址 search-paths: - SpringCloudH2020Config #项目名 # username: 账号 # password: 密码 label: master #读取分支 #热部署 devtools: restart: enabled: true #是否支持热部署 eureka: client: #是否将自己注册进EurekaServer,默认为:true register-with-eureka: true #是否从EurekaServer抓取已有的注册信息,默认为:true,单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡 fetch-registry: true service-url: defaultZone: http://localhost:7001/eureka # 集群版 http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: instance-id: config3344 # 访问路径可以显示ip地址 prefer-ip-address: true ``` #### 3.配置 本地 host 文件 ##### 路径:C:\Windows\System32\drivers\etc ​ 如: ![image-20210209151411926](https://i.loli.net/2021/02/09/KiPAzmbZFOM7BLI.png) #### 4.访问gitee文件方式 ##### 三种, ![image-20210209151527360](https://i.loli.net/2021/02/09/dqX7E5IlSjYOcRv.png) #### 5.创建client端配置中心 ​ 如:cloud-config-center3355 ##### 添加 pom 依赖 ```xml org.springframework.cloud spring-cloud-starter-config org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.springframework.boot spring-boot-starter-test test ``` ##### 添加 bootstrap.yml 配置文件 而不是 application.yml 两者区别在下方解释 ```yaml server: port: 3355 spring: application: name: cloud-config-client cloud: #Config客户端配置 config: label: master #分支名称 name: config #配置文件名称 profile: dev #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取http://config3344.com:3344/master/config-dev.yml uri: http://localhost:3344 #配置中心地址 #热部署 devtools: restart: enabled: true #是否支持热部署 eureka: client: #是否将自己注册进EurekaServer,默认为:true register-with-eureka: true #是否从EurekaServer抓取已有的注册信息,默认为:true,单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡 fetch-registry: true service-url: defaultZone: http://localhost:7001/eureka # 集群版 http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: instance-id: config3344 # 访问路径可以显示ip地址 prefer-ip-address: true ``` ##### 添加 controller 提供服务,向外暴漏 ```java package com.richper.springcloudh2020.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ConfigCenterController { @Value("${config.info}") private String configInfo; @GetMapping("/getConfigInfo") public String getConfigInfo(){ return configInfo; } } ``` ##### bootstrap.yml 和 application.yml 区别 ![image-20210209152414085](https://i.loli.net/2021/02/09/HtBjAYsogFnfdSI.png) #### 6.配置 client 端配置中心 手动动态刷新 添加 pom 依赖 ```xml org.springframework.boot spring-boot-starter-actuator ``` ​ 配置 bootstrap.yml ```yaml server: port: 3355 spring: application: name: cloud-config-client cloud: #Config客户端配置 config: label: master #分支名称 name: config #配置文件名称 profile: dev #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取http://config3344.com:3344/master/config-dev.yml uri: http://localhost:3344 #配置中心地址 #暴露监控端点 为 配置 config 动态刷新 management: endpoints: web: exposure: include: "*" #热部署 devtools: restart: enabled: true #是否支持热部署 eureka: client: #是否将自己注册进EurekaServer,默认为:true register-with-eureka: true #是否从EurekaServer抓取已有的注册信息,默认为:true,单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡 fetch-registry: true service-url: defaultZone: http://localhost:7001/eureka # 集群版 http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: instance-id: config3344 # 访问路径可以显示ip地址 prefer-ip-address: true ``` ​ Controller 添加 注解 ```java package com.richper.springcloudh2020.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RefreshScope public class ConfigCenterController { @Value("${config.info}") private String configInfo; @GetMapping("/getConfigInfo") public String getConfigInfo(){ return configInfo; } } ``` ​ 最后一步 刷新 3355 服务 ​ 发送 POST 请求 更新 ​ 此例子为 window cmd 窗口发送 POST 请求 localhost:3355 服务为例 ```bat curl -X POST "http://localhost:3355/actuator/refresh" ``` ## 十、消息总线 ### spring cloud bus 消息总线 #### 是什么、能做什么、原理是什么: ![image-20210209171132443](https://i.loli.net/2021/02/09/iELUscmCkwSolVx.png) ![image-20210209171229934](https://i.loli.net/2021/02/09/2fmcG7OrPaxTB8K.png) #### Erlang、RabbitMQ 安装 Erlang安装地址:https://www.erlang.org/download/otp_win64_21.3.exe RabbitMQ 安装地址:http://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.7.14/rabbitmq-server-3.7.14 RabbitMQ必须有Erlang环境才可以运行,连接的版本号可以修改对应版本号下载 安装好之后进入RabbtMQ的sbin目录执行命令 ```cmd rabbitmq-plugins enable rabbitmq_management ``` 执行完之后会出现以下程序 ![image-20210210094436511](https://i.loli.net/2021/02/10/6gwSCDu3vtXPp2O.png) 执行 start 运行完之后,可以打开网址:http://localhost:15672/ ​ 默认账号密码为:guest ![image-20210210094528929](https://i.loli.net/2021/02/10/ZuMLVCskOhr3NGQ.png) 如果 安装完之后仍无法访问 如下 ​ 进入 sbin目录 打开cmd ​ 输入以下命令: ​ 打开RabbitMQ节点 ​ `rabbitmqctl start_app` ​ 开启RabbitMQ管理模块的插件,并配置到RabbitMQ节点上 ​ `rabbitmq-plugins enable rabbitmq_management` ​ 关闭rabbitMQ节点 ​ `rabbitmqctl stop` #### 动态刷新全局广播配置 实现一处更新处处生效 ##### 1.config-server3344 配置中心 配置 ​ 添加 pom 依赖 ```xml org.springframework.cloud spring-cloud-starter-bus-amqp ``` ​ yml 配置文件 配置 增加了 rabbitMQ相关配置 暴露bus刷新配置的端点 ```properties server: port: 3344 spring: application: name: cloud-config-server cloud: config: server: git: uri: https://gitee.com/alanlxx/SpringCloudH2020Config.git #gitee项目地址 # uri: git@github.com:alanlxx/SpringCloudH2020Config.git #gitee项目地址 search-paths: - SpringCloudH2020Config #项目名 # username: 账号 # password: 密码 label: master #读取分支 #rabbitmq相关配置 rabbitmq: host: localhost port: 5672 username: guest password: guest #热部署 devtools: restart: enabled: true #是否支持热部署 eureka: client: #是否将自己注册进EurekaServer,默认为:true register-with-eureka: true #是否从EurekaServer抓取已有的注册信息,默认为:true,单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡 fetch-registry: true service-url: defaultZone: http://localhost:7001/eureka # 集群版 http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: instance-id: config3344 # 访问路径可以显示ip地址 prefer-ip-address: true ##rabbitmq相关配置,暴露bus刷新配置的端点 management: endpoints: #暴露bus刷新配置的端点 web: exposure: include: 'bus-refresh' ``` ##### 2.config-client3355、config-client3366 等 client端配置 ​ 添加 pom 依赖 ```xml org.springframework.cloud spring-cloud-starter-bus-amqp ``` ​ 配置 yml 配置文件 添加了 RabbitMQ配置 ```properties server: port: 3355 spring: application: name: cloud-config-client cloud: #Config客户端配置 config: label: master #分支名称 name: config #配置文件名称 profile: dev #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取http://config3344.com:3344/master/config-dev.yml uri: http://localhost:3344 #配置中心地址 rabbitmq: host: localhost port: 5672 username: guest password: guest #暴露监控端点 为 配置 config 动态刷新 management: endpoints: web: exposure: include: "*" #热部署 devtools: restart: enabled: true #是否支持热部署 eureka: client: #是否将自己注册进EurekaServer,默认为:true register-with-eureka: true #是否从EurekaServer抓取已有的注册信息,默认为:true,单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡 fetch-registry: true service-url: defaultZone: http://localhost:7001/eureka # 集群版 http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka instance: instance-id: config3355 # 访问路径可以显示ip地址 prefer-ip-address: true ``` ​ 3.刷新config-server3344服务端 POST请求 ​ 例如:curl -X POST "http://localhost:3344/actuator/bus-refresh" ``` curl -X POST "http://localhost:3344/actuator/bus-refresh" ``` #### 动态刷新定点广播配置 指定通知 ​ 全局通知配置完毕之后 ​ 唯一不同的是 POST 请求刷新 ​ curl -X POST "http://localhost:3344/actuator/bus-refresh/微服务名称:端口号" ​ 例: ```cmd curl -X POST "http://localhost:3344/actuator/bus-refresh/cloud-config-client:3355" ``` ![image-20210210102608425](https://i.loli.net/2021/02/10/A52VPd17TzlhDei.png) ## 十一、消息驱动 ### spring cloud stream ​ 统一消息中间件,可以让我们不用关注消息中间件(MQ)的细节,让开发、维护、切换降低难度, ​ stream驱动进行统一管理 ​ ![image-20210210104942313](https://i.loli.net/2021/02/10/mTdzs7lkpX4fxDR.png) ​ 中文手册:https://m.wang1314.com/doc/webapp/topic/20971999.html 通过定义绑定器Binder作为中间层,实现了应用程序和消息中间件之间的细节解耦 ## 十二、Spring Cloud Alibaba ### 1.简介 ​ Spring Cloud Alibaba 旨在为微服务开发提供一站式解决方案。该项目包含了开发分布式应用和服务所需的组件,让开发者可以使用Spring Cloud编程模型轻松开发分布式应用。 Spring Cloud 阿里巴巴的特点: 1. **流量控制和服务降级**:支持WebServlet、WebFlux、OpenFeign、RestTemplate、Dubbo接入限流降级功能。可以在运行时通过控制台实时修改限流和降级规则,同时支持限流Metrics的监控。 2. **服务注册和发现**:可以注册服务,客户端可以使用 Spring 管理的 bean,自动集成 Ribbon 来发现实例。 3. **分布式配置**:支持分布式系统中的外化配置,配置改变时自动刷新。 4. **Rpc Service**:扩展 Spring Cloud 客户端 RestTemplate 和 OpenFeign 以支持调用 Dubbo RPC 服务。 5. **事件驱动**:支持构建与共享消息系统连接的高度可扩展的事件驱动微服务。 6. **分布式事务**:支持高性能、易用的分布式事务解决方案。 7. **阿里云对象存储**:海量、安全、低成本、高可靠的云存储服务。支持随时随地在任何应用程序中存储和访问任何类型的数据。 8. **阿里云SchedulerX**:精准、高可靠、高可用的定时作业调度服务,响应时间秒级。 9. **阿里云短信**:覆盖全球的短信服务,阿里短信提供便捷、高效、智能的通讯能力,帮助企业快速联系客户。 手册地址:https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html gitHub:https://github.com/alibaba/spring-cloud-alibaba ### 2.Nacos ​ 官网:https://nacos.io/zh-cn/ ​ Nacos是注册中心+配置中心的组合 ​ **nacos = Eureka+Config+bus** ​ ​ 注册中心比较 ​ **Nacos支持CP和AP之间的切换** ![image-20210908145145501](https://i.loli.net/2021/09/08/vqCVJEQSNwlAxd2.png) ![image-20210908160851822](https://i.loli.net/2021/09/08/PKbk7idc6JLWQ5H.png) ​ 下载,解压之后可以直接运行**bin**目录下的**startup.cmd** ​ 访问地址:http://localhost:8848/nacos ​ 默认账号密码为: nacos **注册中心** ​ **服务提供者** 1. 新建Moudle ``` cloudalibaba-provider-payment9001 ``` 2. pom SpringCloud ailibaba nacos maven配置 ```xml com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test ``` 3. yml ```yaml server: port: 9001 spring: application: name: nacos-payment-provider cloud: nacos: discovery: server-addr: localhost:8848 #配置Nacos地址 #暴漏监控服务 management: endpoints: web: exposure: include: '*' ``` 4. 主启动类 @EnableDiscoveryClient 注解 ```java package com.richper.springcloudh2020; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class NacosPayment9001 { public static void main(String[] args) { SpringApplication.run(NacosPayment9001.class,args); } } ``` 5. 业务类 ```java package com.richper.springcloudh2020.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class PaymentController { @Value("${server.port}") private String port; @GetMapping("/getPayment/{id}") public String getPayment(@PathVariable String id){ return "nacos registry,server port:"+port+",id:"+id; } } ``` 6. 测试 nacos 底层封装有 netflix-ribbon 所以天生支持负载均衡 **服务消费者** 1. 新建Moudle ``` cloudalibaba-consumer-nacos-order83 ``` 2. pom ```xml com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery com.richper.springcloudh2020 cloud-api-commons ${project.version} org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test ``` 3. yml ```yaml server: port: 83 spring: application: name: nacos-order-consumer cloud: nacos: discovery: server-addr: localhost:8848 #消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者) service-url: nacos-user-service: http://nacos-payment-provider #用注解的形式,在Controller中获取服务URL ``` 4. 主启动类 ```java package com.richper.springcloudh2020; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class NacosOrder83 { public static void main(String[] args) { SpringApplication.run(NacosOrder83.class,args); } } ``` 5. RestTemplate 配置 ```java package com.richper.springcloudh2020.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class ApplicationContextConfig { @Bean @LoadBalanced public RestTemplate getRestTemplate(){ return new RestTemplate(); } } ``` 6. 业务类 ```java package com.richper.springcloudh2020.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; @RestController @RequestMapping("/consumer") public class OrderController83 { @Value("${service-url.nacos-user-service}") private String serverURL; @Resource private RestTemplate restTemplate; @GetMapping("/getPayment/{id}") public String getPayment(@PathVariable String id){ return restTemplate.getForObject(serverURL+"/getPayment/"+id,String.class); } } ``` **配置中心** ​ **例子Moudle**:cloudalibaba-config-nacos-client3377 ​ nacos配置文件例子: ​ 注意:config:后面一定要有空格,info:后面也是 config: ​ info: nacos,version 1.0.3 ![image-20210909154101964](https://i.loli.net/2021/09/09/krIpiVTJ1zsPjCU.png) **nacos命名空间、分组和dataId三者之间的关系** ![image-20210909162141515](https://i.loli.net/2021/09/09/TPYgxIzfkWHDp8K.png) ![image-20210909162119200](https://i.loli.net/2021/09/09/FtRr7WB43ljSJT1.png) ![image-20210909162257337](https://i.loli.net/2021/09/09/uwZ3Kvt4gNrs2Fx.png) ![image-20210909162456107](https://i.loli.net/2021/09/09/ypDXhjZ6Kdcbniz.png) **命名空间,分组配置** ![image-20210909170415142](https://i.loli.net/2021/09/09/l8nfsVFZ2bW6mMa.png) ![image-20210909170445762](https://i.loli.net/2021/09/09/uAaLx8d3KYoHyjZ.png) ![image-20210909170508301](https://i.loli.net/2021/09/09/BArImSME1bxKC8P.png) **nacos集群和持久化配置** ​ **集群架构** ![image-20210909171551564](https://i.loli.net/2021/09/09/w9FbGgEV4RP6Nto.png) ![image-20210909172535471](https://i.loli.net/2021/09/09/TnbmF1o2w3utAD9.png) ![image-20210909172227802](https://i.loli.net/2021/09/09/hHMpSC4o7ZUxKYm.png) ​ **`nacos`默认存储在`Derby`内嵌数据库中** ​ nacos官方集群架构说明:https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html ​ **内置数据库切换成外置数据库(`MySQL`)步骤** 1. 初始化数据库脚本, `conf`目录下`nacos-mysql.sql`脚本,执行创建数据库以及数据库表 2. 修改properties配置文件 `conf`目录下`application.properties`配置文件末尾追加 ```properties spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://11.162.196.16:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=nacos_devtest db.password=youdontknow ``` **注意:数据库名,数据库地址、账号、密码要填写正确~~** 3. 重启`nacos` ​ **nacos集群配置** ​ 待补充… ### 3.Sentinel ​ **官网文档**:https://sentinelguard.io/zh-cn/docs/introduction.html ​ **GitHub**:https://github.com/alibaba/Sentinel ![image-20210913171127802](https://i.loli.net/2021/09/13/CxKuhrzv6qoTmId.png) **`Sentinel` 介绍** ​ `Sentinel` 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统自适应保护等多个维度来帮助您保障微服务的稳定性。 #### Sentinel 基本概念 ##### 资源 资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。 只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。 ##### 规则 围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。 #### Sentinel 功能和设计理念 ##### 流量控制 流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。然而,从系统稳定性角度考虑,在处理请求的速度上,也有非常多的讲究。任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示: ![arch](https://i.loli.net/2021/09/13/PGzdMw78RXWhV41.jpg) 流量控制有以下几个角度: - 资源的调用关系,例如资源的调用链路,资源和资源之间的关系; - 运行指标,例如 QPS、线程池、系统负载等; - 控制的效果,例如直接限流、冷启动、排队等。 Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。 ##### 熔断降级 ###### 什么是熔断降级 除了流量控制以外,降低调用链路中的不稳定资源也是 Sentinel 的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,最终会导致请求发生堆积。这个问题和 [Hystrix](https://github.com/Netflix/Hystrix/wiki#what-problem-does-hystrix-solve) 里面描述的问题是一样的。 ![image](https://i.loli.net/2021/09/13/COf6KNPRqcYgBsp.png) Sentinel 和 Hystrix 的原则是一致的: 当调用链路中某个资源出现不稳定,例如,表现为 timeout,异常比例升高的时候,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源,最终产生雪崩的效果。 ###### 熔断降级设计理念 在限制的手段上,Sentinel 和 Hystrix 采取了完全不一样的方法。 Hystrix 通过[线程池](https://github.com/Netflix/Hystrix/wiki/How-it-Works#benefits-of-thread-pools)的方式,来对依赖(在我们的概念中对应资源)进行了隔离。这样做的好处是资源和资源之间做到了最彻底的隔离。缺点是除了增加了线程切换的成本,还需要预先给各个资源做线程池大小的分配。 Sentinel 对这个问题采取了两种手段: - 通过并发线程数进行限制 和资源池隔离的方法不同,Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。 - 通过响应时间对资源进行降级 除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。 ###### **系统负载保护** ​ Sentinel 同时提供[系统维度的自适应保护能力](https://sentinelguard.io/zh-cn/docs/system-adaptive-protection.html)。防止雪崩,是系统防护中重要的一环。当系统负载较高的 时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台 机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流 量就会导致这台机器也崩溃,最后导致整个集群不可用。 ​ 针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系 统在能力范围之内处理最多的请求。 #### **`Sentinel` 是如何工作的** `Sentinel` 的主要工作机制如下: - 对主流框架提供适配或者显示的 `API`,来定义需要保护的资源,并提供设施对资源进行实时统计和调用链路分析。 - 根据预设的规则,结合对资源的实时统计信息,对流量进行控制。同时,`Sentinel` 提供开放的接口,方便您定义及改变规则。 - `Sentinel` 提供实时的监控系统,方便您快速了解目前系统的状态。