1、远程调用 OpenFeign

1.1、 作用

作为远程调用的工具,http rpc client
生态:feign 依赖文件中集成了 负载均衡、熔断降级的作用。
发送远程调用的过程:

  1. 获取调用的服务列表,选一个进行调用。(ribbon 负载均衡)
  2. 获取ip 地址 端口号 port 通过http client 工具进行远程调用 (rpc 调用)
  3. 调用过程中如果有问题进行熔断降级。(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 的过程:

  1. lb.getAllServers() 获取全部的服务注册列表 lb = ILoadBalancer类)
  2. chooseServer()的时间 已经拿到了serverList
  3. class DynamicServerListLoadBalancer{
  4. // 动态的获取serverlist 对象
  5. restOfInit(clientConfig) // 核心方法
  6. // 从eurekaclient 的缓存中拿数据 缓存到自己的缓存中
  7. // updateListOfServers()
  8. // ribbon 从 eurekaclint 的缓存中进行更新serverList eurekaclient 从eurekaserver 更新 自己的缓存
  9. }
  10. 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、跳闸

是自我修复的一种模式,切断服务对外提供的一切服务。
判断是否的跳闸的依据:

  1. Request 请求数量是否到达阈值
  2. Exception 错误数量是否到达阈值
  3. 开启时间窗口,检查接口是否可用
  4. 定制参数
  5. 利用springboot 自动检查机制

高级配置:

  • 统计时间窗口
  • 统计时间窗口内的最小请求数量
  • 统计时间窗口内的错误数量的百分比
  • 自我修复的时间窗口长度

@DefalultPropertities

3.2、原理

通过 AOP 代理 对应的注解。
HystrixCommandAspect 代理类,进行环绕通知。

3.3、注解

基础注解
@EnableCircuitBreaker 注解
@EnableHystrix 注解
业务注解
@HystrixCommand 注解
@HystrixCollapser 注解

  1. @HystrixCommand(
  2. commandProperties = {
  3. //execution
  4. @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
  5. @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
  6. @HystrixProperty(name = "execution.timeout.enabled", value = "true"),
  7. @HystrixProperty(name = "execution.isolation.thread.interruptOnTimeout", value = "true"),
  8. @HystrixProperty(name = "execution.isolation.thread.interruptOnCancel", value = "false"),
  9. @HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "10"),
  10. //fallback
  11. @HystrixProperty(name = "fallback.isolation.semaphore.maxConcurrentRequests", value = "10"),
  12. @HystrixProperty(name = "fallback.enabled", value = "true"),
  13. //circuit breaker 断路器
  14. @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
  15. @HystrixProperty(name = "circuitBreaker.forceClosed", value = "false"),
  16. @HystrixProperty(name = "circuitBreaker.forceOpen", value = "false"),
  17. @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20"),
  18. @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000"),
  19. @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50"),
  20. //Metrics
  21. @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000"),
  22. @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10"),
  23. @HystrixProperty(name = "metrics.rollingPercentile.enabled", value = "true"),
  24. @HystrixProperty(name = "metrics.rollingPercentile.timeInMilliseconds", value = "60000"),
  25. @HystrixProperty(name = "metrics.rollingPercentile.numBuckets", value = "6"),
  26. @HystrixProperty(name = "metrics.rollingPercentile.bucketSize", value = "100"),
  27. @HystrixProperty(name = "metrics.healthSnapshot.intervalInMilliseconds", value = "500"),
  28. //request context
  29. @HystrixProperty(name = "requestCache.enabled", value = "true"),
  30. @HystrixProperty(name = "requestLog.enabled", value = "true")},
  31. threadPoolProperties = {
  32. @HystrixProperty(name = "coreSize", value = "10"),
  33. @HystrixProperty(name = "maximumSize", value = "10"),
  34. @HystrixProperty(name = "maxQueueSize", value = "-1"),
  35. @HystrixProperty(name = "queueSizeRejectionThreshold", value = "5"),
  36. @HystrixProperty(name = "keepAliveTimeMinutes", value = "1"),
  37. @HystrixProperty(name = "allowMaximumSizeToDivergeFromCoreSize", value = "false"),
  38. @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000"),
  39. @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "10")
  40. }
  41. )