实战系列-Spring Cloud微服务中三把利器Feign、Hystrix、Ribbon

2022-08-07 12:45:32

导语
  在之前的分享中分享过关于Fegin的底层实现原理,以及Spring Cloud OpenFegin的启动原理。在这次的分享中主要总结一下Spring Cloud 微服务架构的三把利器。对于Fegin、Hystrix、Ribbon三个组件来说它们之间是什么样的关系。怎么样综合使用等这些问题就是这次分享的内容

Fegin介绍

GitHub地址 https://github.com/OpenFeign/feign.git

  首先通过上次的分析可以知道Fegin是通过Java 语言编写的基于HttpClient的绑定器,在Spring Cloud微服务架构中主要的功能就是实现声明式服务调用。Fegin可以请求其他服务定义的接口,实现服务之间的调用,通过Fegin调用客户端不需要在去编写多余Http请求服务接口,如果在调用过程中出现错误还可以调用其实现类来返回。

  Feign是一个声明式的web service客户端,它使得编写web service客户端更为容易。创建接口,为接口添加注解,即可使用Feign。Feign可以使用Feign注解或者JAX-RS注解,还支持热插拔的编码器和解码器。Spring Cloud为Feign添加了Spring MVC的注解支持,并整合了Ribbon和Eureka来为使用Feign时提供负载均衡。

Ribbon介绍

GitHub地址 https://github.com/Netflix/ribbon.git

  提到Ribbon最常听到的一个名词就是客户端负载均衡,就是说将服务端的负载均衡放到了客户端来实现。对于服务端来说可以启动多个不同端口的实例,通过客户端负载均衡来去调用这些实例。

  Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。提供了客户端组件的一系列完善的配置项,如连接超时,重试等。也就是说通过配置的方式可以列举出需要负载的后端所有的服务,Ribbon会通过对应的策略(轮询、权重、随机等)来去连接这些机器。当然在这些策略与实际业务不符合的时候还可以通过自定义的负载均衡算法来实现调用。因为这些工作都是由客户端来完成,所以被称为是客户端的负载均衡器。

  Ribbon的工作原理,Ribbon工作时分为两步:

  • 第一步 先选择 Eureka Server, 它优先选择在同一个Zone且负载较少的Server;
  • 第二步 再根据用户指定的策略,在从Server取到的服务注册列表中选择一个地址。Ribbon提供了多种策略,例如轮询、随机、根据响应时间加权等

Hystrix介绍

GitHub地址 https://github.com/Netflix/Hystrix.git

  从GitHub地址来看这个也是Netflix的项目,也是由Java来编写 。Hystrix作为熔断流量控制在客户端实现,使用的时候,在方法上进行注解,当请求出错时可以调用注解中的方法返回。
  Hystrix熔断器,容错管理工具,通过熔断机制控制服务和第三方库的节点也就是其他业务之间的调用。从而对延迟和故障提供更强大的容错能力。并且在Spring Cloud Hystrix中实现了线程隔离、断路器等一系列的服务保护功能。它也是基于Netflix的开源框架 Hystrix实现的,该框架目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备了服务降级、服务熔断、线程隔离、请求缓存、请求合并以及服务监控等功能。

三者关系

  在开发过程中,如果微服务项目加上了spring-cloud-starter-netflix-hystrix依赖,那么,feign会通过代理模式, 自动将所有的方法用 hystrix 进行包装。在对Feign进行包装的时候也提到过动态代理。

  在Spring Cloud技术体系之下Feign可以提供声明式的服务调用。在这个服务调用的过程中会通过Ribbon从Eureka注册中获取到对应的服务器列表出来,在后续的网络请求调用的过程中Ribbon的作用就是负责整体的负载均衡。将调用通过负载的形式调用到不同的实例上。这也就是实现了Spring Cloud的服务发现以及负载均衡的内容。

  那么在这个过程中好像没有Hystrix的作用。下面就来看看Hystrix的作用,在服务调用的过程中,为了防止因为某些故障而消耗整个服务调用资源,从而导致服务雪崩。所以在服务调用的过程中需要对整个的调用机制有一个熔断的逻辑。整个时候Hystrix就会排上用场。

  调用方会针对被调用微服务设置调用超时时间,一旦超时就会进入熔断逻辑,而这个故障指标信息也会返回给Hystrix组件,Hystrix组件会根据熔断情况判断被调微服务的故障情况从而打开熔断器,之后所有针对该微服务的请求就会直接进入熔断逻辑,直到被调微服务故障恢复,Hystrix断路器关闭为止。

  通过上面的描述就形成了如下的这样一个调用关系图在这里插入图片描述

如何配置

Feign配置说明

  在之前的分享中其实我们知道Feign并不是就简单的实现了一种HttpClient,它提供了很多HttpClient方式,其中最为轻量级的就是OKHTTP的配置。下面这种方式是基于Apache HttpClient的方式来实现的。

feign:#替换掉JDK默认HttpURLConnection实现的 Http Clienthttpclient:enabled:truehystrix:enabled:trueclient:config:default:#连接超时时间connectTimeout:5000#读取超时时间readTimeout:5000

Hystrix配置说明

  基于整个的Spring Cloud 微服务架构,Hystrix主要的功能是实现微服务之间网络调用故障的熔断、过载保护及资源隔离等。所以提供的配置说明也是关于这些内容的。如果单独使用的话还有其他的配置可以进行自定义。

hystrix:propagate:request-attribute:enabled:truecommand:#全局默认配置default:#线程隔离相关execution:timeout:#是否给方法执行设置超时时间,默认为true。一般我们不要改。enabled:trueisolation:#配置请求隔离的方式,这里是默认的线程池方式。还有一种信号量的方式semaphore,使用比较少。strategy: threadPoolthread:#方式执行的超时时间,默认为1000毫秒,在实际场景中需要根据情况设置timeoutInMilliseconds:10000#发生超时时是否中断方法的执行,默认值为true。不要改。interruptOnTimeout:true#是否在方法执行被取消时中断方法,默认值为false。没有实际意义,默认就好!interruptOnCancel:falsecircuitBreaker:#熔断器相关配置enabled:true#是否启动熔断器,默认为true,false表示不要引入Hystrix。requestVolumeThreshold:20#启用熔断器功能窗口时间内的最小请求数,假设我们设置的窗口时间为10秒,sleepWindowInMilliseconds:5000#所以此配置的作用是指定熔断器打开后多长时间内允许一次请求尝试执行,官方默认配置为5秒。errorThresholdPercentage:50#窗口时间内超过50%的请求失败后就会打开熔断器将后续请求快速失败掉,默认配置为50

Ribbon配置说明

  Ribbon在Spring Cloud中对于支持微服之间的通信,其主要功能包括客户端负载均衡器及用于中间层通信的客户端。在基于Feign的微服务通信中无论是否开启Hystrix,Ribbon都是必不可少的,Ribbon的配置参数主要如下:

ribbon:eager-load:enabled:true#说明:同一台实例的最大自动重试次数,默认为1次,不包括首次MaxAutoRetries:1#说明:要重试的下一个实例的最大数量,默认为1,不包括第一次被调用的实例MaxAutoRetriesNextServer:1#说明:是否所有的操作都重试,默认为trueOkToRetryOnAllOperations:true#说明:从注册中心刷新服务器列表信息的时间间隔,默认为2000毫秒,即2秒ServerListRefreshInterval:2000#说明:使用Apache HttpClient连接超时时间,单位为毫秒ConnectTimeout:3000#说明:使用Apache HttpClient读取的超时时间,单位为毫秒ReadTimeout:3000

注意 :在Spring Cloud中使用Feign进行微服务调用分为两层:Hystrix的调用和Ribbon的调用,Feign自身的配置会被覆盖。
  而如果开启了Hystrix,那么Ribbon的超时时间配置与Hystrix的超时时间配置则存在依赖关系,因为涉及到Ribbon的重试机制,所以一般情况下都是Ribbon的超时时间小于Hystrix的超时时间,否则会出现以下错误:

 o.s.c.n.z.f.r.s.AbstractRibbonCommand- The Hystrix timeout of10000msfor the command operation is set lower than the combination of the Ribbon   read and connect timeout,24000ms.

Ribbon和Hystrix的超时时间配置的关系

  那么Ribbon和Hystrix的超时时间配置的关系具体是什么呢?如下:

Hystrix的超时时间=Ribbon的重试次数(包含首次) * (ribbon.ReadTimeout + ribbon.ConnectTimeout)

而Ribbon的重试次数的计算方式为:

Ribbon重试次数(包含首次)= 1 + ribbon.MaxAutoRetries  +  ribbon.MaxAutoRetriesNextServer  +  (ribbon.MaxAutoRetries * ribbon.MaxAutoRetriesNextServer)

  整个关系可以通过上面那个图来得到。Ribbon的重试次数=1+(1+1+1)=4,所以Hystrix的超时配置应该>=4*(3000+3000)=24000毫秒。在Ribbon超时但Hystrix没有超时的情况下,Ribbon便会采取重试机制;而重试期间如果时间超过了Hystrix的超时配置则会立即被熔断(fallback)。

  如果不配置Ribbon的重试次数,则Ribbon默认会重试一次,加上第一次调用Ribbon,总的的重试次数为2次,以上述配置参数为例,Hystrix超时时间配置为2*6000=12000,

  由于很多情况下,大家一般不会主动配置Ribbon的重试次数,所以做简单说明,以上超时配置的值只是示范,超时配置有点大不太合适实际的线上场景,可以根据实际情况而定。

如果不启用Hystrix,Feign的超时时间则是Ribbon的超时时间,Feign自身的配置也会被覆盖。

总结

  本次分享中最为重要的就是上面那张图,其实配置在需要的时候查询官网或者是百度一下就可以了,实际使用过程中怎么样去配置在理解了原理之后就显得尤为重要了,上面举例子一样,如果不知道图中展示的过程,怎么可以了解整个的调用配置都是什么意思。希望本次总结可以让自己有所提升。

  • 作者:nihui123
  • 原文链接:https://blog.csdn.net/nihui123/article/details/107057321
    更新时间:2022-08-07 12:45:32