🌥️SpringCloud实战-客户端负载均衡之Ribbon
|字数总计:1.4k|阅读时长:6分钟|阅读量:|
客户端负载均衡组件之Ribbon
。
Ribbon
整体架构
Ribbon
是Netflix
开源的客户端负载均衡组件,基于HTTP
和TCP
。Spring Cloud Ribbon
基于Ribbon
实现,提供轮询、随机等负载均衡策略进行服务调用,也可自定义负载均衡算法。配合Eureka Server
使用时的架构图如下:
使用了Ribbon
的Eureka Client
服务消费者在发送请求之前,会从Eureka Server
注册中心获取服务提供者列表,然后按照配置的负载均衡策略去发起请求,从而实现客户端的负载均衡。
Ribbon
本身也会维护一份服务提供者地址列表。如果它发现服务提供者不可用,则会重新从Eureka Server
注册中心获取有效的服务提供者地址列表进行更新。
为服务消费者配置Ribbon
在IDEA
中创建一个名叫ribbon
的maven
工程,然后在pom.xml
中引入以下依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <properties> <spring.boot.version>2.2.0.RELEASE</spring.boot.version> <spring.cloud.version>Hoxton.SR1</spring.cloud.version> </properties>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring.cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> </dependencies>
|
由于spring-cloud-starter-netflix-eureka-client
依赖中已经包含了spring-cloud-starter-netflix-ribbon
依赖,所以无需单独引入。
在src/main/resources
目录下创建application.yml
配置文件,并添加以下配置项:
1 2 3 4 5 6 7 8 9
| server: port: 9003 spring: application: name: ribbon-service-consumer eureka: client: service-url: defaultZone: http://localhost:520/eureka/,http://localhost:521/eureka/
|
编写启动类RibbonApplication
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package com.sunchaser.sparrow.microservice.springcloud.netflix.ribbon;
import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate;
@SpringBootApplication public class RibbonApplication { public static void main(String[] args) { new SpringApplicationBuilder(RibbonApplication.class) .web(WebApplicationType.SERVLET) .run(args); }
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
|
与eureka-client-service-consumer
微服务相比,我们只需要在RestTemplate
上加入@LoadBalanced
注解即可开启ribbon
的客户端负载均衡功能。
下面我们使用带有负载均衡功能的RestTemplate
来消费eureka-client-service-provider
提供的服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package com.sunchaser.sparrow.microservice.springcloud.netflix.ribbon.controller;
import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate;
@RestController @Slf4j public class ConsumerController {
@Autowired private RestTemplate restTemplate;
@Autowired private LoadBalancerClient loadBalancerClient;
@GetMapping("/consumer/{id}") public String consume(@PathVariable String id) { return restTemplate.getForObject("http://eureka-client-service-provider/provider?id=" + id, String.class); }
@GetMapping("/print/provider/instance") public String getProviderInstanceList() { ServiceInstance serviceInstance = this.loadBalancerClient.choose("eureka-client-service-provider"); log.info("service instance:{}", serviceInstance); return serviceInstance.toString(); } }
|
运行启动类RibbonApplication
,即可将该服务消费者注册至注册中心。
由于我们在consume
方法中将http
请求的地址指定为了http://eureka-client-service-provider
,这意味着我们要将服务提供者的虚拟主机名改为eureka-client-service-provider
,当Ribbon
和Eureka
配合使用时,会自动将虚拟主机名映射成微服务的网络地址。
修改eureka-client-provider
微服务的src/main/resources/application.yml
文件,添加以下配置项:
1
| eureka.instance.virtual-host-name=eureka-client-service-provider
|
同样地方式启动两个服务提供者实例,先修改Run/Debug Configurations
配置:点击Edit Configurations...
,找到EurekaClientProviderApplication
的启动配置,勾选Allow parallel run
后点击OK
保存。
低版本IDEA
对应的勾选项是Single instance only
。
启动步骤:
1、将application.yml
配置文件中的server.port
端口号配置项设置为9000
后启动项目。
2、修改application.yml
配置文件中的server.port
端口号配置项设置为9001
后启动项目。
随后即可在http://localhost:520
或http://localhost:521
注册中心页面上看到两个provider
服务提供者实例:
客户端的负载均衡消费
发送GET
请求:GET
http://127.0.0.1:9003/consumer/1
,可看到输出为:provide:1
。同时可在其中一个服务提供者实例的控制台上看见被调用的日志信息(另一个实例的控制台无相应日志输出):
1
| 2021-09-21 16:44:20.398 INFO 43868 --- [nio-9001-exec-2] c.s.s.m.s.n.e.c.p.c.ProviderController : provide invoked: id=1
|
再次请求,即可在另一个实例的控制台上看到同样的日志输出。这就是客户端的负载均衡调用。
我们还可以通过getProviderInstanceList
方法查看本次负载均衡策略选择的服务提供者的实例信息。发送GET
请求:GET
http://127.0.0.1:9003/print/provider/instance
,可看到输出为:
1
| RibbonServer{serviceId='eureka-client-service-provider', server=192.168.0.103:9001, secure=false, metadata={management.port=9001}}
|
再次请求,可看到输出为:
1
| RibbonServer{serviceId='eureka-client-service-provider', server=192.168.0.103:9000, secure=false, metadata={management.port=9000}}
|
两次请求客户端选择的服务提供者实例不同,这就是客户端的负载均衡调用。