小言_互联网的博客

Feign、Ribbon、Hystrix

270人阅读  评论(0)

🏆今日学习目标:

🍀Feign、Ribbon、Hystrix
创作者:林在闪闪发光
⏰预计时间:30分钟
🎉个人主页:林在闪闪发光的个人主页

 🍁林在闪闪发光的个人社区,欢迎你的加入: 林在闪闪发光的社区

高并发 Springcloud 解决方案

微服务架构的应用中, FeignHystrix,Ribbon三者都是必不可少的,可以说已经成为铁三角。

概念介绍

一、Feign 是什么?

Feign 使得用 Java 写 Http 客户端更加容易,这是 Feign 的核心能力!!!

Feign 将其抽象为一套通用逻辑,类似于写普通方法调用一样,Feign 做一层代理,封装这些冗余操作。

feign 大致提供了这些核心能力:

Feign是一款Java语言编写的HttpClient绑定器,在Spring Cloud微服务中用于实现微服务之间的声明式调用。Feign 可以定义请求到其他服务的接口,用于微服务间的调用,不用自己再写http请求,在客户端实现,调用此接口就像远程调用其他服务一样,当请求出错时可以调用接口的实现类来返回

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

使用方式

引用方式


  
  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-openfeign</artifactId>
  4. </dependency>
  5. <!--http连接池-->
  6. <dependency>
  7. <groupId>org.apache.httpcomponents</groupId>
  8. <artifactId>httpclient</artifactId>
  9. </dependency>
  10. <!-- openfeign的http请求工具类修改httpclient -->
  11. <dependency>
  12. <groupId>io.github.openfeign</groupId>
  13. <artifactId>feign-httpclient</artifactId>

启动方式

启动类增加 注解

 @EnableFeignClients

Feign内置了Ribbon  

Feign的标准写法


  
  1. //创建服务提供者
  2. @RestController
  3. @RequestMapping("/provider")
  4. public class ProviderController {
  5. @Autowired
  6. private UserService userService;
  7. @RequestMapping("/getUserById/{id}")
  8. public User getUserById (@PathVariable Integer id){
  9. return userService.getUserById(id);
  10. }
  11. }

   2.创建feign接口     


  
  1. /**
  2. * @FeignClient 一般采用服务名进行命名
  3. * name:指定FeignClient的名称,如果项目使用了Ribbon,name属性会作为微服务的名称,用于服务发现
  4. * url: url一般用于调试,可以手动指定@FeignClient调用的地址
  5. *
  6. * @RequestMapping 主要用于feign框架拼接传递url,弥补了Ribbon的url需要手动拼接的缺陷
  7. * @PathVariable("id") 当路径为restful风格时路径传参方式
  8. * @RequestParam("id") 当路径为?id=250 时传参方式
  9. * @RequestBody User user 当路径为对象时采用的传参方式,(集合、数组等都属于对象)
  10. */
  11. @FeignClient("feign-provider")
  12. @RequestMapping("/provider")
  13. public interface UserFeign {
  14. @RequestMapping("/getUserById/{id}")
  15. User getUserById (@PathVariable("id") Integer id);
  16. @RequestMapping("/deleteUserById")
  17. User deleteUserById (@RequestParam("id") Integer id); //?形式拼接参数,?id=250
  18. @RequestMapping("/addUser")
  19. User addUser (@RequestBody User user); //pojo--->json
  20. }

  
  1. //服务消费者
  2. @RestController
  3. @RequestMapping("/consumer")
  4. public class ConsumerController {
  5. @Autowired
  6. private UserFeign userFeign;
  7. @RequestMapping("/getUserById/{id}")
  8. public User getUserById (@PathVariable Integer id){
  9. return userFeign.getUserById(id);
  10. }
  11. }

  application.yml文件 

server:
  port: 80
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.209.129:8848
  application:
    name: feign-consumer

feign源码的github地址:

GitHub - OpenFeign/feign: Feign makes writing java http clients easier

二、什么是Ribbon?

Ribbon 作为负载均衡,在客户端实现,服务段可以启动两个端口不同但servername一样的服务

Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。简单地说,Ribbon是一个客户端负载均衡器。

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

使用方式

引用方式

(如果不使用ribbon的方式调用,直接使用feign即可;可不引用)


  
  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
  4. </dependency>

 调用的时候直接使用服务名


  
  1. String url= "http://EUREKA-PROVIDE/goods/findOne/"+id;
  2. Goods goods = restTemplate.getForObject(url, Goods.class);

负载均衡:

在provider中加上几行代码,显示调用的端口号


  
  1. @Autowired
  2. private GoodsService goodsService;
  3. @Value("${server.port}")
  4. private Integer port;
  5. @RequestMapping("/findOne/{id}")
  6. public Goods findOne (@PathVariable Integer id){
  7. Goods goods = goodsService.findOne(id);
  8. goods.setTitle(goods.getTitle()+ ":"+port); //将端口号,设置到了 商品标题上
  9. return goods;
  10. }

Ribbon负载均衡策略:

随机 :RandomRule
轮询 :RoundRobinRule(默认的负载均衡策略)
最小并发:BestAvailableRule(服务A-1,服务A-2,服务A-3,这三个服务中谁最闲一般认为是性能高)
过滤:AvailabilityFilteringRule(坏的服务过滤掉)
响应时间:WeightedResponseTimeRule(发送一个数据包到三个服务中,看谁最先响应,谁快就调用谁)
轮询重试:RetryRule(默认轮询10次,如果节点出现问题,会去找第二个,如果轮询到10次都挂了那就响应失败)
性能可用性:ZoneAvoidanceRule(综合考虑性能和可用性,看谁分数高就用谁)

三、Hystrix是什么?

hystrix 专注于解决分布式系统延迟和容错问题。换句话说,hystrix 主要解决服务通信间的网络延时、异常等,提供降级和熔断等能力。

还不够通俗?当你在服务 A 调用服务 B 的接口时,可能出现超时、异常的情况,很有可能是服务 B 压力过大,已不堪重负。这时,服务 A 该如何做?

我们可以考虑一些策略,比如,请求失败了,我们返回默认结果;失败率超过多少多少,直接短暂停用接口调用。

Hystrix 便是致力于解决这类问题,实现以上的各种处理策略,熔断、降级等。

遗憾的是,官方已经声明不在维护

Hystrix 在 Netflix 稳定运行多年,足够稳健,我们可以放心在生产环境使用。

使用方式

引用方式


  
  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-hystrix</artifactId>
  4. </dependency>

 启动类开启熔断

@EnableCircuitBreaker

调用方式

定义@HystrixCommand


  
  1. @RestController
  2. public class RemoteCallerController {
  3. @Autowired
  4. private IUserService iUserService;
  5. @GetMapping("/user/sayHi/{name}")
  6. @HystrixCommand(fallbackMethod="sayHiFallback")
  7. public CommonRsp<String> sayHi (@PathVariable("name") String name) throws Exception {
  8. return iUserService.sayHi(name);
  9. }
  10. public CommonRsp<String> sayHiFallback (@PathVariable("name") String name) throws Exception {
  11. return CommonRspUtils.buildSuccessRsp( "接口失败");
  12. }
  13. }

铁三角关系介绍

如果微服务项目加上了spring-cloud-starter-netflix-hystrix依赖,那么,feign会通过代理模式, 自动将所有的方法用 hystrix 进行包装。

在Spring Cloud微服务体系下,微服务之间的互相调用可以通过Feign进行声明式调用,在这个服务调用过程中Feign会通过Ribbon从服务注册中心获取目标微服务的服务器地址列表,之后在网络请求的过程中Ribbon就会将请求以负载均衡的方式打到微服务的不同实例上,从而实现Spring Cloud微服务架构中最为关键的功能即服务发现及客户端负载均衡调用。

另一方面微服务在互相调用的过程中,为了防止某个微服务的故障消耗掉整个系统所有微服务的连接资源,所以在实施微服务调用的过程中我们会要求在调用方实施针对被调用微服务的熔断逻辑。而要实现这个逻辑场景在Spring Cloud微服务框架下我们是通过Hystrix这个框架来实现的。

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

三者之间的关系图,大致如下:

 建议使用配置

Fegin配置说明


  
  1. feign:
  2. hystrix:
  3. enabled: true
  4. # feign 的 http 客户端支持 3 种框架;
  5. #HttpURLConnection、httpclient、okhttp;默认是HttpURLConnection(并不支持连接池)。
  6. httpclient:
  7. enabled: true # 开启 httpclient
  8. client:
  9. config:
  10. default:
  11. #默认日志记录NONE【性能最佳,适用于生产】:不记录任何日志(默认值)。
  12. #BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间。
  13. #HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
  14. #FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数据。
  15. loggerLevel: HEADERS
  16. #连接超时时间
  17. connectTimeout: 5000
  18. #读取超时时间
  19. readTimeout: 5000

Hystrix配置说明


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

Ribbon配置说明 


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

希望对未知的你们有所帮助

❤林林在闪闪发光


转载:https://blog.csdn.net/weixin_68829137/article/details/129191638
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场