【SpringCloud框架之Ribbon负载均衡、OpenFeign服务调用】

川长思鸟来 2023-09-24 23:21 130阅读 0赞

本笔记内容为尚硅谷SpringCloud框架开发Ribbon、OpenFeign部分

目录

Spring Cloud Ribbon

一、概述

LB(负载均衡)

二、Ribbon负载均衡演示

1、架构说明

2、POM

3、RestTemplate的使用

三、Ribbon核心组件IRule

1、IRule

2、如何替换

四、Ribbon负载均衡算法

原理

OpenFeign服务接口调用

一、概述

二、OpenFeign使用步骤

1、接口+注解

2、新建Module

3、POM

4、YML

5、主启动

6、业务类

7、测试

8、小总结

三、OpenFeign超时控制

1、超时设置

2、YML文件里需要开启OpenFeign客户端超时控制

四、OpenFeign日志打印功能

1、日志打印功能

2、日志级别

3、配置日志bean

4、YML文件里需要开启日志的Feign客户端

5、后台日志查看


【SpringCloud框架之Eureka服务注册与发现】_蛋饼吧的博客-CSDN博客

【SpringCloud框架之Zookeeper、Consul服务注册与发现】_蛋饼吧的博客-CSDN博客


Spring Cloud Ribbon

一、概述


Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。

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

官网:Getting Started · Netflix/ribbon Wiki · GitHub

LB(负载均衡)

LB负载均衡(Load Balance)是什么

简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)。

常见的负载均衡有软件Nginx,LVS,硬件 F5等。

Ribbon本地负载均衡客户端 VS Nginx服务端负载均衡区别

Nginx是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求。即负载均衡是由服务端实现的。

Ribbon本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术。

集中式LB

即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;

进程内LB

将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。

Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。

前面我们讲解过了80通过轮询负载访问8001/8002

一句话:Ribbon=负载均衡+RestTemplate调用

Ribbon负载均衡演示


1、架构说明

03a3e7ebee9d4498ac5d4d7570e105f0.png

总结:Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。

2、POM

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

29f42d9d819145328ad68f62e7c6b5df.png

3、RestTemplate的使用

官网:RestTemplate (Spring Framework 5.2.2.RELEASE API)

abb6a9d0abd7485d95dfccefa47c4b7d.png

getForObject方法/getForEntity方法

d52bab0f13a049faa32ebc953e3ae4e3.png

postForObject/postForEntity

75d820b880b147ab847727e9caa08a47.png

三、Ribbon核心组件IRule


1、IRule

IRule:根据特定算法中从服务列表中选取一个要访问的服务

5deb473590fb45249dda4f5e2ec43004.png

9a59c3a065d54e5ebdedc8e97c078a51.png

2、如何替换

修改cloud-consumer-order80

官方文档明确给出了警告:

这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了

9161e3aefd99479e8db7055317c71204.png

新建package

com.atguigu.myrule

1042f163975b4550bbb127d31f688e10.png

上面包下新建MySelfRule规则类

  1. package com.atguigu.myrule;
  2. import com.netflix.loadbalancer.IRule;
  3. import com.netflix.loadbalancer.RandomRule;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. @Configuration
  7. public class MySelfRule
  8. {
  9. @Bean
  10. public IRule myRule()
  11. {
  12. return new RandomRule();//定义为随机
  13. }
  14. }

主启动类添加@RibbonClient,括号内暴露的服务名要大写

  1. @RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration=MySelfRule.class)

240356c8d0c24bfc9e1490a101b79da3.png

测试:http://localhost/consumer/payment/get/31

四、Ribbon负载均衡算法


原理

负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标 ,每次服务重启动后rest接口计数从1开始。

92027d2d1aea4637a27c7a7c40ec906f.png

1accfc048bc54b44b94548dc358ed7a5.png

OpenFeign服务接口调用

一、概述


Feign是一个声明式的Web服务客户端,让编写Web服务客户端变得非常容易,只需创建一个接口并在接口上添加注解即可。

GitHub - spring-cloud/spring-cloud-openfeign: Support for using OpenFeign in Spring Cloud apps

c1d821239aa742cf9429c604351f3a4b.png

Feign能干什么

Feign旨在使编写Java Http客户端变得更容易。

前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端的开发量。

Feign集成了Ribbon

利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用

Feign和OpenFeign两者区别

099c12f4281543ebb0eae54218072c3f.png

二、OpenFeign使用步骤


1、接口+注解

微服务调用接口+@FeignClient

2、新建Module

cloud-consumer-feign-order80

Feign在消费端使用

3c70824d951c405fbedf2a67526d47ca.png

3、POM

720c2c5148174948b5ef24401b46a72c.png

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>mscloud03</artifactId>
  7. <groupId>com.atguigu.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-consumer-feign-order80</artifactId>
  12. <dependencies>
  13. <!--openfeign-->
  14. <dependency>
  15. <groupId>org.springframework.cloud</groupId>
  16. <artifactId>spring-cloud-starter-openfeign</artifactId>
  17. </dependency>
  18. <!--eureka client-->
  19. <dependency>
  20. <groupId>org.springframework.cloud</groupId>
  21. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  22. </dependency>
  23. <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
  24. <dependency>
  25. <groupId>com.atguigu.springcloud</groupId>
  26. <artifactId>cloud-api-commons</artifactId>
  27. <version>${project.version}</version>
  28. </dependency>
  29. <!--web-->
  30. <dependency>
  31. <groupId>org.springframework.boot</groupId>
  32. <artifactId>spring-boot-starter-web</artifactId>
  33. </dependency>
  34. <dependency>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-starter-actuator</artifactId>
  37. </dependency>
  38. <!--一般基础通用配置-->
  39. <dependency>
  40. <groupId>org.springframework.boot</groupId>
  41. <artifactId>spring-boot-devtools</artifactId>
  42. <scope>runtime</scope>
  43. <optional>true</optional>
  44. </dependency>
  45. <dependency>
  46. <groupId>org.projectlombok</groupId>
  47. <artifactId>lombok</artifactId>
  48. <optional>true</optional>
  49. </dependency>
  50. <dependency>
  51. <groupId>org.springframework.boot</groupId>
  52. <artifactId>spring-boot-starter-test</artifactId>
  53. <scope>test</scope>
  54. </dependency>
  55. </dependencies>
  56. </project>

4、YML

  1. server:
  2. port: 80
  3. eureka:
  4. client:
  5. register-with-eureka: false
  6. service-url:
  7. defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

5、主启动

  1. package com.atguigu.springcloud;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.openfeign.EnableFeignClients;
  5. @SpringBootApplication
  6. @EnableFeignClients //开启
  7. public class OrderFeignMain80
  8. {
  9. public static void main(String[] args)
  10. {
  11. SpringApplication.run(OrderFeignMain80.class,args);
  12. }
  13. }

6、业务类

业务逻辑接口+@FeignClient配置调用provider服务

新建PaymentFeignService接口并新增注解@FeignClient

  1. package com.atguigu.springcloud.service;
  2. import com.atguigu.springcloud.entities.CommonResult;
  3. import com.atguigu.springcloud.entities.Payment;
  4. import org.springframework.cloud.openfeign.FeignClient;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.web.bind.annotation.GetMapping;
  7. import org.springframework.web.bind.annotation.PathVariable;
  8. @Component
  9. @FeignClient(value = "CLOUD-PAYMENT-SERVICE") //使用
  10. public interface PaymentFeignService
  11. {
  12. @GetMapping(value = "/payment/get/{id}")
  13. CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
  14. }

控制层Controller

  1. package com.atguigu.springcloud.controller;
  2. import com.atguigu.springcloud.entities.CommonResult;
  3. import com.atguigu.springcloud.entities.Payment;
  4. import com.atguigu.springcloud.service.PaymentFeignService;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.PathVariable;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import javax.annotation.Resource;
  9. @RestController
  10. public class OrderFeignController
  11. {
  12. @Resource
  13. private PaymentFeignService paymentFeignService;
  14. @GetMapping(value = "/consumer/payment/get/{id}")
  15. public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id)
  16. {
  17. return paymentFeignService.getPaymentById(id);
  18. }
  19. }

7、测试

  • 先启动2个eureka集群7001/7002
  • 再启动2个微服务8001/8002启动OpenFeign启动
  • http://localhost/consumer/payment/get/31
  • Feign自带负载均衡配置项

8、小总结

" class="reference-link">ed36b6f618fc407bb77eb18e9c3d4913.png

三、OpenFeign超时控制


1、超时设置

故意设置超时演示出错情况

服务提供方8001故意写暂停程序 ,PaymentController.java加入

  1. @GetMapping(value = "/payment/feign/timeout")
  2. public String paymentFeignTimeOut()
  3. {
  4. System.out.println("*****paymentFeignTimeOut from port: "+serverPort);
  5. //暂停几秒钟线程
  6. try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
  7. return serverPort;
  8. }

服务消费方80添加超时方法

添加超时方法PaymentFeignServic.java加入

  1. @GetMapping(value = "/payment/feign/timeout")
  2. String paymentFeignTimeOut();

服务消费方80添加超时方法

添加超时方法OrderFeignController.java加入

  1. @GetMapping(value = "/consumer/payment/feign/timeout")
  2. public String paymentFeignTimeOut()
  3. {
  4. return paymentFeignService.paymentFeignTimeOut();
  5. }

测试

http://localhost/consumer/payment/feign/timeout

错误页面

add9c4af8f954ac18addc765254985d1.png

默认Feign客户端只等待一秒钟,但是服务端处理需要超过1秒钟,导致Feign客户端不想等待了,直接返回报错。

为了避免这样的情况,有时候我们需要设置Feign客户端的超时控制。yml文件中开启配置

OpenFeign默认支持Ribbon

9ccc821e761a416c8f85d60a42affa9c.png

2、YML文件里需要开启OpenFeign客户端超时控制

a257dac107c042d5a359bbe9f7c12650.png

  1. server:
  2. port: 80
  3. eureka:
  4. client:
  5. register-with-eureka: false
  6. service-url:
  7. defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
  8. #设置feign客户端超时时间(OpenFeign默认支持ribbon)
  9. ribbon:
  10. #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  11. ReadTimeout: 5000
  12. #指的是建立连接后从服务器读取到可用资源所用的时间
  13. ConnectTimeout: 5000

四、OpenFeign日志打印功能


1、日志打印功能

Feign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 Feign 中 Http 请求的细节。

说白了就是对Feign接口的调用情况进行监控和输出

2、日志级别

  • NONE:默认的,不显示任何日志;
  • BASIC:仅记录请求方法、URL、响应状态码及执行时间;
  • HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息;
  • FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。

3、配置日志bean

config包下

  1. package com.atguigu.springcloud.cfgbeans;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import feign.Logger;
  5. @Configuration
  6. public class FeignConfig
  7. {
  8. @Bean
  9. Logger.Level feignLoggerLevel()
  10. {
  11. return Logger.Level.FULL;
  12. }
  13. }

4、YML文件里需要开启日志的Feign客户端

450fd87072c5424d8a5afdcc15f00442.png

  1. server:
  2. port: 80
  3. eureka:
  4. client:
  5. register-with-eureka: false
  6. service-url:
  7. defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
  8. #设置feign客户端超时时间
  9. #springCloud默认开启支持ribbon
  10. ribbon:
  11. #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  12. ReadTimeout: 5000
  13. #指的是建立连接后从服务器读取到可用资源所用的时间
  14. ConnectTimeout: 5000
  15. logging:
  16. level:
  17. # feign日志以什么级别监控哪个接口
  18. com.atguigu.springcloud.service.PaymentFeignService: debug

5、后台日志查看

bd1b1d4d605647fb864607fe7cfed747.png

结束!

发表评论

表情:
评论列表 (有 0 条评论,130人围观)

还没有评论,来说两句吧...

相关阅读