# spring-cloud-config-server
**Repository Path**: M-N-A/spring-cloud-config-server
## Basic Information
- **Project Name**: spring-cloud-config-server
- **Description**: spring Cloud配置中心demo
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 2
- **Created**: 2023-09-10
- **Last Updated**: 2024-03-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# **限流**
**解释:** 限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量以达到保护系统的目的。
为了保证系统的稳定运行,一旦达到需要限制的阔值,就需要限制流量并采取一些措施以完成限制流量的目的。限流对某一时间窗口内的请求进行限制,保持系统的可用性和稳定性,防止因流量暴增而导致系统运行缓慢或宕机。
**限流的原因:**
互联网系统通常要面对大并发大流量的请求,在突发情况下(比如:秒杀、抢购),瞬时大流量会直接将系统打垮,无法对外提供服务。为了防止出现这种情况常见的解决方案之一是限流,当请求达到一定的并发数或速率,就进行等待、排队、降级、拒绝服务等。
## 限流算法
1. **计数器限流**
- 计数器限流算法最为简单粗暴,主要采用限制总并发数,比如数据库连接池大小、线程池大小、接口访问并发数等。
2. **漏桶算法**
- 漏桶算法思路很简单,我们把水比作是请求,漏桶比作是系统处理能力极限,水先进入到漏桶里,漏桶里的水按一定速率流出,当流出的速率小于流入的速率时,由于漏桶容量有限,后续进入的水直接溢出(拒绝请求),以此实现限流。
3. **令牌桶算法**
- 令牌桶算法的原理也比较简单,我们可以理解成医院的挂号看病,只有拿到号以后才可以进行诊病。系统会维护一个令牌(token)桶,以一个恒定的速度往桶里放入令牌(token),
这时如果有请求进来想要被处理,则需要先从桶里获取一个令牌(token),当桶里没有令牌(token)可取时,则该请求将被拒绝服务。令牌桶算法通过控制桶的容量、发放令牌的速率,来达到对请求的限制。
## guava
- https://zhuanlan.zhihu.com/p/621267375
# **Hystrix**
## 概念
- Hystrix 是一个用用于处理分布式系统的延迟和容错的开源库,可以保证一个服务出现故障时,不回导致整个系统出现雪崩效应,提高分布式系统弹性;
- 作为“断路器”,在一个服务出现故障时,可以通过短路监控,返回一个可以处理的响应结果,保证服务调用线程不会长时间被占用,避免故障蔓延;
## **Hystrix作用**
1. **服务降级**
- 服务出现故障时,给故障服务降级到事先准备好的故障处理结果,并将结果返回给服务消费者。
2. **服务熔断**
- 熔断机制是应对服务雪崩的一种链路保护机制,当服务出现故障时,服务会进行降级,熔断该服务节点,迅速返回错误响应信息。当检测到服务安全访问正常时,恢复其链路节点
3. **服务隔离(服务限流)**
- 判断线程池或者信号量是否已满,超出容量的请求直接降级,以达到限流的目的;
### **Hystrix隔离策略(资源隔离)**
1. **线程池隔离(默认策略)**
```
@Override
@HystrixCommand(fallbackMethod = "handleError",
commandKey = "hystrixTest", //commandKey,当前command的名称
groupKey = "hystrixTestGroup", groupKey:当前command所在的组。默认情况下根据group定义一个线程池,即同一个组的请求进入同一个线程池;也根据group聚合一些监控和报警信息等
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1000000"), //execution.isolation.thread.timeoutInMilliseconds:隔离策略为THREAD时,执行的超时时间,单位ms
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"), //execution.isolation.strategy:指定隔离策略。THREAD或SEMAPHORE
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000000000") //threadPoolKey:线程池的key,默认为group的名称
},
threadPoolKey = "hystrixTestThreadPool",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "5") //coreSize:线程池大小。默认10
})
public String hystrixTest() {
return "a";
}
```
#### 优点:
1. 保护应用程序以免受来自依赖故障的干扰,指定依赖程序线程池饱和不会影响应用程序的其他部分;
2. 当引入新客户端lib时,即使发生问题,也是在lib中,不会影响其他内容;
3. 当依赖从故障恢复正常时,应用程序会立即恢复正常性能;
4. 当应用程序一些配置参数错误时,线程池的运行状态很快会检测到,同时可以动态属性进行实时纠正错误的参数配置;
5. 如果服务的性能有变化(增加/减少 时间、更改重试次数),需要实时调整,可以通过线程池指定状态属性修改,而且不影响其他调用请求;
#### 缺点:
- 线程池隔离的主要缺点是增加了计算机开销。每个命令的执行都在单独的线程完成,增加了排队、调度和上下文切换的开销。
3. **信号量隔离**
```
@HystrixCommand(fallbackMethod = "handleError",
commandKey = "hystrixsemaphore",
g roupKey = "hystrixTestGroup-one",
commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE"),
@HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests",value = "10"), //execution.isolation.semaphore.maxConcurrentRequests 配置信号量的大小,达到最大并发信号量时,后续请求被拒
},
threadPoolKey = "SemaphoreThreadPool",
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "10")
})
```
#### 优点
1. 信号量隔离通过设置信号量来限制对任何给定依赖的并发调用量;
2. 信号量不需要切换线程,避免了不必要的开销;
#### 缺点
- 信号量隔离不支持异步,也不支持超时,当请求服务不可用时,信号量会控制超出限制的请求立即返回,可能出现长时间的等待;
### **Hystrix的设计原则**
1. 防止单个服务的故障耗尽整个服务的Servlet容器的线程池资源;
2. 快速失败机制,如果某个服务出现故障,则调用该服务的请求快速失败,而不是线程等待;
3. 提供回退方案,在请求发生故障时,提供设定好的回退方案;
4. 使用熔断器机制,防止故障扩散到其他服务;
5. 提供熔断器的监控组件(Hystrix DashBoard),可以实时监控熔断器的状态;
### **Hystrix的工作机制**
1. 当服务的某个API接口的失败次数在一定时间内小于设定的阔值时,熔断器处于关闭状态,API接口正常提供服务;
2. 当该API接口处理请求的失败次数在一定时间内大于设定的阔值,Hystrix判断该API接口故障,开启熔断器,API接口执行快速失败逻辑,不执行业务逻辑,请求线程不会处于阻塞状态;失败的业务逻辑走指定的`fallbackMethod`
方法
3. 处于打开状态的熔断器在一定时间后会处于半大开状态,将一部分数量请求执行正常的业务逻辑,剩余的请求执行快速失败逻辑;
4. 若执行正常逻辑的业务的请求失败了,则熔断器继续打开,若成功了,则熔断器关闭。
### **熔断器**
熔断器配置,Circuit Breaker 主要6个参数:
1. `circuitBreaker.enable` #是否开启熔断器,默认TRUE
2. `circuitBreaker.forceOpen` #熔断器强制打开,始终保持打开状态,不关注熔断器的实际状态。默认值 FALSE
3. `circuitBreaker.forceClose` #熔断器强制关闭,始终保持关闭状态,不关注熔断开关的实际状态。默认值 FALSE
4. `circuitBreaker.errorThresholdPercentage` #错误率,默认值为50%,当出现出错比例大于错误率的数值的情况,触发熔断器;
5. `circuitBreaker.requestVolumeThreshold` #默认值20,一段时间内至少有20个请求才进行`errorThresholdPercentage`
计算。(例:当一段时间内有19个请求,且全部请求都失败,错误率100%,可因为总请求数不满20个,熔断器不会开启)
6. `circuitBreaker.sleepWindowMillisSeconds` #半开启试探睡眠时间,默认值5000ms。(例:当熔断器开启5000ms后,会尝试放行部分流量进行试探,以确定服务是否恢复正常)
### **Hystrix的回退降级**
**目的:** 在事务高峰期,为了保证核心服务的正常运行,需要停掉一些不太重要的业务,或某些服务不可用时,执行备用逻辑从故障服务快速失败或快速返回,以保障主体业务不受影响。
**Hystrix走服务降级逻辑的情况:**
1. 执行construct或run抛出异常;
2. 熔断器打开导致命令短路;
3. 命令的线程池和队列或信号量超额,命令被拒绝;
4. 命令执行超时;
**Hystrix降级回退方式**
1. Fail Fast快速失败;
- 快速失败是最普通的命令执行方法,命令没有重写降级逻辑。如果命令发生任何类型的故障,将直接抛出异常;
2. Fail Fast无声失败;
- 无声失败指在降级中通过返回null,空Map,空List或其他类似的响应来完成;
3. FallBack:Static
- 指在降级方法中返回静态默认值。这不会导致服务以“无声失败”的方式被删除,而是选择默认的失败逻辑;
4. FallBack:Stubbed
- 当命令返回一个包含多个字段的复合对象时,适合以Stubbed的方式回退;
5. FallBack:Cache via NetWork
- 从缓存服务中查询旧数据版本。(由于会发起远程调用,建议重新封装Command,使用不同TheadPoolKey,与主线程池进行隔离)
6. Primary+Secondary with Fallback
-
有时系统具有两种行为-主要和次要,或主要和故障转移。主要和次要逻辑涉及到不同的网络调用和业务逻辑,所以需要将主次逻辑封装在不同的Command中,使用线程池进行隔离。为了实现主从逻辑切换,可以将主次command封装在外观HystrixCommand的run方法中,并结合配置中心设置的开关切换主从逻辑。由于主次逻辑都是经过线程池隔离的HystrixCommand,因此外观HystrixCommand可以使用信号量隔离,而没有必要使用线程池隔离引入不必要的开销。
- (场景):当系统升级新功能,如果新版本的功能出现问题,通过开关控制降级调用旧版本的功能;
### Hystrix指令参考网址
- https://blog.csdn.net/truelove12358/article/details/117998125
## Hystrix参考网址
- https://blog.csdn.net/weixin_50616848/article/details/124542186
- http://www.linkedkeeper.com/1157.html
- https://blog.csdn.net/qq_34561892/article/details/128022263
- https://blog.csdn.net/weixin_43696529/article/details/107746126
- https://www.sohu.com/a/465169669_827544
- http://www.uml.org.cn/wfw/201906063.asp
- https://c.biancheng.net/springcloud/hystrix.html
## resilience4j
spring-cloud-starter-circuitbreaker-resilience4j
# feign 和 openfeign
## **Feign**
- `Feign`是`SpringCloud`组件中的一个轻量级RESTful的HTTP服务客户内置的`Ribbon`
,用来做客户端的负载均衡,去调注册中心的服务。`Feign`使用方式:使用`Feign`的注解定义接口,调用该接口,就可以调用服务;
### **Feign的作用**
1. Feign是一种声明式服务调用组件,在`RestTemplate`的基础上做了进一步的封装,通过`Feign`,开发者只要声明一个接口并通过注解进行简单的配置即可实现对HTTP接口的绑定;
2. 通过`Feign`,可以像调用本地方法一样来调用远程服务,且完全感觉不到有是在进行远程调用;
3. `Feign`支持多种注解,有自带注解以及`JAX-RS`注解等,但Feign并不支持`SpringMVC`注解;
## **openFeign**
- **解释:**
`openFeign`是`SpringCloud`在`Feign`的基础上支持了`SpringMVC`的注解,且具备`Feign`的所有功能,如`RequestMapping`及其衍生类注解;@`FeignClient`
可以解析`SpringMVC`的`@RequestMapping`注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务;
### **`openFeign`在`consumer`消费者中的传参方式**
1. 传JSON数据
```java
@FeignClient(value = "openFeign-provider")
public interface OpenFeignService {
/**
* 参数默认是@RequestBody标注的,这里的@RequestBody可以不填
* 方法名称任意
*/
@PostMapping("/openfeign/provider/order2")
Order createOrder2 (@RequestBody Order order);
}
```
2. POJO表单参数
```java
@FeignClient(value = "openFeign-provider")
public interface OpenFeignService {
/**
* 参数默认是@RequestBody标注的,如果通过POJO表单传参的,使用@SpringQueryMap标注
*/
@PostMapping("/openfeign/provider/order1")
Order createOrder1 (@SpringQueryMap Order order);
}
```
3. URL中携带参数
```java
@FeignClient(value = "openFeign-provider")
public interface OpenFeignService {
@GetMapping("/openfeign/provider/test/{id}")
String get (@PathVariable("id") Integer id);
}
```
4. 普通表单参数
```java
@FeignClient(value = "openFeign-provider")
public interface OpenFeignService {
/**
* 必须要@RequestParam注解标注,且value属性必须填上参数名 * 方法参数名可以任意,但是@RequestParam注解中的value属性必须和provider中的参数名相同
*/
@PostMapping("/openfeign/provider/test2")
String test (@RequestParam("id") String arg1, @RequestParam("name") String arg2);
}
```
### `openfeign`超时
`openfeign`的默认连接超时时间是10S,默认读超时时间是60S
feign.client.config.default.connectTimeout=3000 # default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间
feign.client.config.default.readTimeout=3000
### `openfeign`常用注解
1. `@FeignClient`
- 说明:用于`OpenFeign`组件对`@RequestMapping`注解的接口解析,并以动态代理的方式生产实现类,实现负载均衡和服务调用;
2. `@EnableFeignClients`
- 用于开启OpenFeign的功能,当`SpringCloud`项目启动时,会扫描被`@FeignClient`修饰的接口类,并生成相应的代理实现类注册到Spring容器中;
3. `@RequestMapping`
- SpringMVC注解,在SpringMVC中使用该注解映射请求,通过它来指定控制器(`Controller`类)可以处理哪些接口请求;
4. `@GetMapping`
- SpringMVC注解,用来映射GET请求,是一个组合注解,相当于 @RequestMapping(method = RequestMethod.GET);
5. `@PostMapping`
- SpringMVC注解,用来映射POST请求,是一个组合注解,相当于 @RequestMapping(method = RequestMethod.POST);
### openfeign 开启 hystrix 熔断机制,旧版本使用 feign.hystrix.enabled 新版本使用:feign.circuitbreaker.enabled
### **openfeign参考**
- https://blog.csdn.net/qq_40811542/article/details/130581397
- https://blog.csdn.net/ldw201510803006/article/details/126414836
- https://c.biancheng.net/springcloud/open-feign.html
# **sentinel**
## sentinel控制台下载及打包
1. 下载源码:`git clone https://github.com/alibaba/Sentinel.git`
2. 打包命令:
- `cd Sentinel`
- `mvn clean package -Dmaven.test.skip=true`
## [`Sentinel`特性](https://blog.csdn.net/truelove12358/article/details/107507455)
1. 轻量级,高性能 :核心 sentinel-core 没有任何多余依赖,打包后只有不到 200KB,非常轻量级。开发者可以放心地引入 sentinel-core 而不需担心依赖问题。同时,Sentinel 提供了多种扩展点,用户可以很方便地根据需求去进行扩展,并且无缝地切合到 Sentinel 中。
2. 流量控制: Sentinel 可以针对不同的调用关系,以不同的运行指标(如 QPS、并发调用数、系统负载等)为基准,对资源调用进行流量控制,将随机的请求调整成合适的形状。Sentinel 支持多样化的流量整形策略,在 QPS 过高的时候可以自动将流量调整成合适的形状。
1. 直接拒绝模式:即超出的请求直接拒绝。
2. 慢启动预热模式:当流量激增的时候,控制流量通过的速率,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。
3. 匀速器模式:利用 Leaky Bucket 算法实现的匀速模式,严格控制了请求通过的时间间隔,同时堆积的请求将会排队,超过超时时长的请求直接被拒绝。Sentinel 还支持基于调用关系的限流,包括基于调用方限流、基于调用链入口限流、关联流量限流等,依托于 Sentinel 强大的调用链路统计信息,可以提供精准的不同维度的限流。
3. 系统负载保护 :Sentinel 对系统的维度提供保护,负载保护算法借鉴了 TCP BBR 的思想。当系统负载较高的时候,如果仍持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。
4. Sentinel 提供 HTTP API 用于获取实时的监控信息,如调用链路统计信息、簇点信息、规则信息等。如果用户正在使用 Spring Boot/Spring Cloud 并使用了Sentinel Spring Cloud Starter,还可以方便地通过其暴露的 Actuator Endpoint 来获取运行时的一些信息,如动态规则等。
## `Sentinel`工作原理
1. **资源:** 只要通过Sentinel API 定义的代码,就是资源,能够被Sentinel保护起来
2. **规则:** 围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整;
## `Sentinel`功能和设计理念
1. 流量控制
- 资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
- 运行指标,例如QPS、线程池、系统负载等;
- 控制的效果,例:直接限流、冷启动、排队等;
2. 熔断降级
- `Sentinel` 和 `Hystrix` 的原则一致:当调用链路中某个资源出现不稳定,例如,表现为timeout,异常比例升高的时候,就对当前资源调用进行限制,并让请求快速失败,避免影响到其他资源;
- 在限制手段上,`Sentinel`和`Hystrix`采用完全不一样的方法
- `Hystrix` 通过线程池的方式,来对依赖(API)进行隔离。好处是资源和资源之间做到了最彻底的隔离。缺点是增加了线程的切换成本,还要预先给各个资源做线程池的大小分配。
- `Sentinel`采取两种手段:`通过并发线程数进行限制` 和 `通过响应时间对资源做出降级` 处理
3. 系统负载保护
- `Sentinel` 同时提供系统维度的自适应保护能力,让系统入口流量和系统负载达到一个平衡,保证系统在能力范围内处理最多的请求。
## `Sentinel`实践
- 模板
```
Entry entry = null;
// 务必保证 finally 会被执行
try {
// 资源名可使用任意有业务语义的字符串,注意数目不能太多(超过 1K),超出几千请作为参数传入而不要直接作为资源名
// EntryType 代表流量类型(inbound/outbound),其中系统规则只对 IN 类型的埋点生效
entry = SphU.entry("自定义资源名");
// 被保护的业务逻辑
// do something...
} catch (BlockException ex) {
// 资源访问阻止,被限流或被降级
// 进行相应的处理操作
} catch (Exception ex) {
// 若需要配置降级规则,需要通过这种方式记录业务异常
Tracer.traceEntry(ex, entry);
} finally {
// 务必保证 exit,务必保证每个 entry 与 exit 配对
if (entry != null) {
entry.exit();
}
}
```
### `Sentinel`资源保护方式
1. 基于API实现`SphU.entry(RESOURCE_NAME)`
- **缺点**
- 业务侵入性强,需要在`controller`层写入非业务代码;
- 配置不灵活,若需要添加新的受保护资源,需要手动添加 init 方法来添加流控规则;
1. 依赖及源码
```xml
com.alibaba.csp
sentinel-core
1.8.5
```
```java
// 源码
@Slf4j
@RestController
@RequestMapping("demo")
public class DemoController {
private static final String RESOURCE_NAME = "demo";
@RequestMapping(value = "/test")
public String test () {
try (Entry entry = SphU.entry(RESOURCE_NAME)) {
// 被保护的逻辑
log.info("hello world");
return "hello world";
} catch (BlockException ex) {
// 处理被流控的逻辑
log.info("blocked!");
return "被流控了";
}
}
/**
* 定义流控规则
*/
@PostConstruct
private static void initFlowRules () {
List rules = new ArrayList<>();
FlowRule rule = new FlowRule();
//设置受保护的资源
rule.setResource(RESOURCE_NAME);
// 设置流控规则 QPS
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置受保护的资源阈值
// Set limit QPS to 20.
rule.setCount(1);
rules.add(rule);
// 加载配置好的规则
FlowRuleManager.loadRules(rules);
}
}
```
2. 基于注解方式`@SentinelResource`
1. 依赖
```xml
com.alibaba.csp
sentinel-annotation-aspectj
1.8.5
```
2. 配置切面支持
```java
@Configuration
public class SentinelAspectConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect () {
return new SentinelResourceAspect();
}
}
```
3. 逻辑@sentinelResource,并配置blockHandler和fallback
```java
@Slf4j
@RestController
@RequestMapping("annotation")
public class AnnotationController {
@SentinelResource(value = "annotation",
blockHandler = "handleException",
fallback = "fallbackException")
@RequestMapping("/test")
public String test () {
int i = 1 / 0;
return "helloworld";
}
public String handleException (BlockException ex) {
return "被流控了";
}
public String fallbackException (Throwable t) {
return "被异常降级了";
}
@RequestMapping(value = "/findOrderByUserId/{id}")
@SentinelResource(value = "findOrderByUserId",
fallback = "fallback", fallbackClass = ExceptionUtil.class,
blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class
)
public R findOrderByUserId (@PathVariable("id") Integer id) {
}
}
```
4. 编写ExceptionUtil,如果指定了class,则方法必须是static方法
```java
public class ExceptionUtil {
public static R fallback (Integer id, Throwable e) {
return R.error(-1, "===被异常降级啦===");
}
public static R handleException (Integer id, BlockException e) {
return R.error(-2, "===被限流啦===");
}
}
```
5. 流控规则设置可以通过`Sentinel dashboard`配置
- 客户端接入`sentinel dashboard`控制台
1. 依赖
```xml
com.alibaba.csp
sentinel-transport-simple-http
1.8.5
```
2. 客户端启动JVM参数
- 模板:`-Dcsp.sentinel.dashboard.server=sentinel.dashboard.host:sentinel.dashboard.port`
- 例:`-Dcsp.sentinel.dashboard.server=localhost:8080`
6. 注解实现类 SentinelResourceAspect 实现原理借助`Spring IOC` `@Aspect` `@Pointcut` `@Around`
```java
@Aspect
public class SentinelResourceAspect extends AbstractSentinelAspectSupport {
public SentinelResourceAspect () {
}
@Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")
public void sentinelResourceAnnotationPointcut () {
}
@Around("sentinelResourceAnnotationPointcut()")
public Object invokeResourceWithSentinel (ProceedingJoinPoint pjp) throws Throwable {
Method originMethod = this.resolveMethod(pjp);
SentinelResource annotation = (SentinelResource) originMethod.getAnnotation(SentinelResource.class);
if (annotation == null) {
throw new IllegalStateException("Wrong state for SentinelResource annotation");
} else {
String resourceName = this.getResourceName(annotation.value(), originMethod);
EntryType entryType = annotation.entryType();
int resourceType = annotation.resourceType();
Entry entry = null;
try {
entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
Object var8 = pjp.proceed();
return var8;
} catch (BlockException var15) {
Object var18 = this.handleBlockException(pjp, annotation, var15);
return var18;
} catch (Throwable var16) {
Class extends Throwable>[] exceptionsToIgnore = annotation.exceptionsToIgnore();
if (exceptionsToIgnore.length > 0 && this.exceptionBelongsTo(var16, exceptionsToIgnore)) {
throw var16;
} else if (this.exceptionBelongsTo(var16, annotation.exceptionsToTrace())) {
this.traceException(var16);
Object var10 = this.handleFallback(pjp, annotation, var16);
return var10;
} else {
throw var16;
}
} finally {
if (entry != null) {
entry.exit(1, pjp.getArgs());
}
}
}
}
}
```
3. SpringCloud Alibaba整合`Sentinel`
1. 依赖
```xml
org.springframework.boot
spring-boot-starter-actuator
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
```
2. 配置
```
spring:
application:
name: mall-user-sentinel-demo
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
sentinel:
transport:
# 添加sentinel的控制台地址
dashboard: 127.0.0.1:8080
# 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer
# port: 8719
#暴露actuator端点
management:
endpoints:
web:
exposure:
include: '*'
```
`AbstractSentinelInterceptor`
3. 在sentinel控制台设置流控规则
1. 资源名:API接口;
2. 针对来源:默认是default,当多个微服务调用该资源时,可以设置微服务名来针对指定的服务设置阔值;
3. 阔值类型:分为QPS和线程数;假设阔值为10。
1. QPS类型:对每秒访问接口的次数>10的进行限流;
2. 线程数:为接收请求该资源分配的线程数>就进行限流;
4. Sentinel Dashboard 控制台
1. **实时监控:** 监控接口的通过的QPS和拒绝的QPS 。同一个服务下的所有机器的簇点信息会被汇总,并且秒级地展示在"实时监控"下。实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制。
- 注意:请确保 Sentinel 控制台所在的机器时间与自己应用的机器时间保持一致,否则会导致拉不到实时的监控数据。
2. **簇点链路:** 用来显示微服务的所监控的API。簇点链路(单机调用链路)页面实时的去拉取指定客户端资源的运行情况。
- 注意: 簇点监控是内存态的信息,它仅展示启动后调用过的资源。
3. **流控规则:** 流量控制(flow control),其原理是监控应用流量的 QPS
或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。同一个资源可以创建多条限流规则。FlowSlot
会对该资源的所有限流规则依次遍历,直到有规则触发限流或者所有规则遍历完毕。一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果。
参考文档: https://github.com/alibaba/Sentinel/wiki/流量控制
转:https://blog.csdn.net/menxu_work/article/details/126987083
### `Sentinel`参考
- https://blog.csdn.net/menxu_work/article/details/126987083
- https://blog.csdn.net/qq_42263280/article/details/128631130
- https://blog.csdn.net/qq_43599766/article/details/124889912
- https://blog.csdn.net/litianyu0730/article/details/125926732
# Dubbo
## Dubbo: 熔断-服务降级
1. **熔断的作用:**
- Dubbo引用熔断(服务降级)的目的是为了防止provider无报错情况下长时间的响应 ,影响了其他服务进度,从而导致降低了consumer消费性能
2. **解决provider长时间未响应思路** :
- 遇到长时间未响应及频繁超时等情况时,将consumer调用provider的请求,直接短路掉,不实际调用,而是直接返回一个mock的值。等provider服务恢复稳定之后,再重新调用
1. 一定是先降级优先级地的接口,两权相害取其轻
2. 如果服务链路整体没有性能特别差的点,比如就是外部流量突然激增,那么就从外到内开始降级。
3. 如果某个服务能检测到自身负载上升,那么可以从这个服务自身做降级。
3. **Dubbo服务降级使用**
- mock机制
- 四种mock调用策略
1. `mock = "true"`
- 指定 mock 策略为布尔类型,且为 true,当调用远程服务失败后, 就会执行调用其他provider
- `@DubboReference(retries = 1,mock = "true")`
2. `mock = "具体的mock实现类"`
- 指定 mock 策略为具体的 mock 实现类, 当调用远程服务失败时, 就会执行 mock 实现类的 sayHello 方法(调用其他provider).
- `@DubboReference(mock = "com.cxl.service.UserService")`
3. `mock = "抛出自定义异常"`
- 指定 mock 策略为抛出自定义异常, 当远程服务调用失败后, 会给服务消费者抛出自定义异常.
- `@DubboReference(retries = 1,mock = "throw com.cxl.excep.CustomExcep")`
4. `mock="返回 mock 数据"`
- 指定 mock 属性值为返回 mock 数据,当远程服务调用失败后,就会给服务消费者返回 null,(mock数据可以不写,默认返回null)。
- `@DubboReference(retries = 1,mock = "return null")`
- fail:策略
1. `mock = "force:true"`
- 指定 mock 策略为布尔类型,且为 true,当调用远程服务失败后, 就会执行调用其他provider
- `@DubboReference(retries = 1,mock = "force:true")`
2. `mock = "force:执行的Mock实现类"`
- 指定 mock 策略为具体的 mock 实现类, 当调用远程服务失败时, 就会执行 mock 实现类的 sayHello 方法(调用其他provider).
- `@DubboReference(mock = "force:com.cxl.service.UserService")`
3. `mock = "force:抛出自定义异常"`
- 指定 mock 策略为抛出自定义异常, 当远程服务调用失败后, 会给服务消费者抛出自定义异常.
- `@DubboReference(retries = 1,mock = "force:throw com.cxl.excep.CustomExcep")`
4. `mock="force:返回 mock 数据"`
- 指定 mock 属性值为返回 mock 数据,当远程服务调用失败后,就会给服务消费者返回 null,(mock数据可以不写,默认返回null)。
- `@DubboReference(retries = 1,mock = "force:return null")`
转自:[https://blog.csdn.net/m0_62866192/article/details/122045271](https://blog.csdn.net/m0_62866192/article/details/122045271)
参考:[https://blog.csdn.net/qq_40788718/article/details/107851593](https://blog.csdn.net/qq_40788718/article/details/107851593)