1、远程调用 OpenFeign
1.1、 作用
作为远程调用的工具,http rpc client
生态:feign 依赖文件中集成了 负载均衡、熔断降级的作用。
发送远程调用的过程:
- 获取调用的服务列表,选一个进行调用。(ribbon 负载均衡)
- 获取ip 地址 端口号 port 通过http client 工具进行远程调用 (rpc 调用)
- 调用过程中如果有问题进行熔断降级。(hystrix 熔断 降级 监控)
1.2 、功能
自动装配:@EnableClientFeigns
通过注解:@FeignClient 进行代理 FeignInvocationHandler
1.3、 原理
对接口进行了代理 实际上使用的就是 restTemplete 客户端
代理对象产生的前奏 FeignClientFactoryBean # getObject 方法 类似于Mybatis 的mapper 的产生过程
代理对象产生的过程 getObject() 方法 使用服务的名字 进行远程的调用(serviceName or URL) 使用jdk的动态代理对象
增强逻辑的处理过程 FeignInvocationHandler # invok 方法 使用了restTemplet 对象 进行负载均衡 ribbon 构建ribbon请求对象 ,在 ribbon 中进行注册中心client 的调用 获取服务的列表 (ip:port)。
2、负载均衡 Ribbon
2.1、概念
核心概念是: 通过serverName 选择对应的实例列表 根据定义好的策略选择一个实例进行调用。
对restTemplete 添加拦截器
拦截 发送请求的参数设置 ip地址 和端口号
默认的负载策略是? ZoneAwareLoadBalancer 区域感知负载均衡器 (轮训)
2.2、原理
使用注解 @LoadBalanced
ILoadBanlancer实例 (继承接口 可以自定义负载均衡的策略)IRules接口
ribbon 拿到serverList 的过程:
lb.getAllServers() 获取全部的服务注册列表 (lb = ILoadBalancer类)
chooseServer()的时间 已经拿到了serverList
class DynamicServerListLoadBalancer{
// 动态的获取serverlist 对象
restOfInit(clientConfig) // 核心方法
// 从eurekaclient 的缓存中拿数据 缓存到自己的缓存中
// updateListOfServers()
// ribbon 从 eurekaclint 的缓存中进行更新serverList eurekaclient 从eurekaserver 更新 自己的缓存
}
serverList在容器是通过bean对象的方式存在的
2.3、策略
轮训策略 roundRibbonRule
随机策略 randomRule
Hash 策略
权重策略
自定义策略
2.4、组件关系
ribbon 是通过对 restTemplete 的代理
ribbon 和eurekaClient(获取服务列表) 共同使用的
ribbon 需要依赖 eureka/nacos注册中心 中的注册服务实例
2.5、问题解答
1、ribbon 获取全部的服务实例 是通过什么样的方式就行获取的? :::warning 通过eureka client 中的 缓存, 或者 ribbon 的本地缓存, serverList 在IOC 容器是通过 bean 的方式存在 :::
2、如果服务注册使用的不是eureka 那么serverList 是如何拿到了?
如果不是 eureka 使用的是 nacos 那么nacos包中会自动的集成了 ribbon
3、熔断降级 Hystrix
3.1、核心概念
3.1.1、熔断
3.1.2、降级
返回提示信息,进行兜底处理,返回默认值。
降级是对熔断的一种友好的处理。
3.1.3、舱壁模式
设置接受最大请求的数量,默认10 个线程处理连接。
线程池谓全部添加了@HystrixCommand 注解的方法提供服务。
超过了最大线程数量,其他的请求就要等待请求或者拒绝。
打破全局的形式:进行线程池的隔离,为每个方法设置最大的请求数量。
通过@HystrixPropertity注解设置属性值
3.1.4、跳闸
是自我修复的一种模式,切断服务对外提供的一切服务。
判断是否的跳闸的依据:
- Request 请求数量是否到达阈值
- Exception 错误数量是否到达阈值
- 开启时间窗口,检查接口是否可用
- 定制参数
- 利用springboot 自动检查机制
高级配置:
- 统计时间窗口
- 统计时间窗口内的最小请求数量
- 统计时间窗口内的错误数量的百分比
- 自我修复的时间窗口长度
3.2、原理
通过 AOP 代理 对应的注解。
HystrixCommandAspect 代理类,进行环绕通知。
3.3、注解
基础注解
@EnableCircuitBreaker 注解
@EnableHystrix 注解
业务注解
@HystrixCommand 注解
@HystrixCollapser 注解
@HystrixCommand(
commandProperties = {
//execution
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
@HystrixProperty(name = "execution.timeout.enabled", value = "true"),
@HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout", value = "true"),
@HystrixProperty(name = "execution.isolation.thread.interruptOnCancel", value = "false"),
@HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10"),
//fallback
@HystrixProperty(name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "10"),
@HystrixProperty(name = "fallback.enabled", value = "true"),
//circuit breaker 断路器
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
@HystrixProperty(name = "circuitBreaker.forceClosed", value = "false"),
@HystrixProperty(name = "circuitBreaker.forceOpen", value = "false"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
//Metrics
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000"),
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
@HystrixProperty(name = "metrics.rollingPercentile.enabled", value = "true"),
@HystrixProperty(name = "metrics.rollingPercentile.timeInMilliseconds", value = "60000"),
@HystrixProperty(name = "metrics.rollingPercentile.numBuckets", value = "6"),
@HystrixProperty(name = "metrics.rollingPercentile.bucketSize", value = "100"),
@HystrixProperty(name = "metrics.healthSnapshot.intervalInMilliseconds", value = "500"),
//request context
@HystrixProperty(name = "requestCache.enabled", value = "true"),
@HystrixProperty(name = "requestLog.enabled", value = "true")},
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "10"),
@HystrixProperty(name = "maximumSize", value = "10"),
@HystrixProperty(name = "maxQueueSize", value = "-1"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "5"),
@HystrixProperty(name = "keepAliveTimeMinutes", value = "1"),
@HystrixProperty(name = "allowMaximumSizeToDivergeFromCoreSize", value = "false"),
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000"),
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10")
}
)