-
前言
-
Ribbon 简介
-
为服务消费者整合 Ribbon
-
使用属性自定义 Ribbon 配置
-
脱离 Eureka 使用 Ribbon
-
饥饿加载
前言
在前文《使用Eureka提供服务注册与发现》https://mp.weixin.qq.com/s/L2Tx6Lk0jl6GW-g0SeUXyw 中,通过基于 Eureka 实现服务注册与发现。一般来说,在生产环境中,各个微服务都会部署多个实例,那么服务消费者要如何将请求分摊到多个服务提供者实例上呢?
在 Spring Cloud 中,当 Ribbon 和 Eureka 配合使用时,Ribbon 可自动从 Eureka Server 获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例。
Ribbon 简介
Ribbon 是 Netflix 发布的负载均衡器,它有助于控制 HTTP 和 TCP 客户端的行为。为 Ribbon 配置服务提供者地址列表后, Ribbon 就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon 默认为我们提供了很多的负载均衡算法,例如轮询、随机等。当然,我们也可为 Ribbon 实现自定义的负载均衡算法。

为服务消费者整合 Ribbon
-
创建项目,复制项目 micro-consumer-movie ,将 artifactId 修改为 micro-consumer-movie-ribbon 。
-
为项目引入 Ribbon 的依赖,spring-cloud-starter-eureka 默认包含了 Ribbon 的依赖 spring-cloud-starter-ribbon 。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
-
为 RestTemplate 添加 @LoadBalance
注解,就可为 RestTemplate 整合 Ribbon ,使其具备负载均衡的能力。
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
-
启动 Eureka Server 注册中心 和 多个服务提供者 micro-provider-user 。
java -jar micro-discovery-eureka-0.0.1-SNAPSHOT.jar
java -jar micro-provider-user-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
java -jar micro-provider-user-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
-
修改服务消费者调用服务提供者的请求地址,http://localhost:8000/ 改为 http://micro-provider-user/ 。
@RestController
@RequestMapping("/movie/v1")
public class MovieController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource
private RestTemplate restTemplate;
@Resource
private LoadBalancerClient loadBalancerClient;
@GetMapping("/{id}")
public User findById(@PathVariable Long id){
User entity = restTemplate.getForObject("http://micro-provider-user/user/v1/"+id, User.class);
return entity;
}
@GetMapping("/log-instance")
public void logUserInstance(){
ServiceInstance serviceInstance = loadBalancerClient.choose("micro-provider-user");
logger.info("{}:{}:{}", serviceInstance.getServiceId(), serviceInstance.getHost(), serviceInstance.getPort());
}
}
micro-provider-user 是用户微服务的虚拟主机名(virtual host name),当 Ribbon 和 Eureka 配合使用时,会自动将虚拟主机名映射成微服务的网络地址。
在默认情况下,虚拟主机名和服务名称是一致的。当然,也可使用配置属性 eureka.instance.virtual-host-name 或 eureka.instance.secure-virtual-host-name 指定虚拟主机名。
-
启动服务消费者服务 micro-consumer-movie-ribbon ,测试 Ribbon ,多次访问 http://localhost:8010/movie/v1/1 ,可发现请求会均匀分布到两个用户微服务节点上,说明已经实现了负载均衡。
访问 http://localhost:8010/movie/v1/log-instance , logUserInstance() 方法中使用 LoadBalancerClient 的 API 更加直观地获取当前选择的用户微服务节点。
使用属性自定义 Ribbon 配置
Ribbon 支持使用属性自定义,支持的属性如下:
-
NFLoadBalancerClassName :配置 ILoadBalancer 的实现类 -
NFLoadBalancerRuleClassName :配置 IRule 的实现类。 -
NFLoadBalancerPingClassName :配置 IPing 的实现类。 -
NIWSServerListClassName :配置 ServerList 的实现类。 -
NIWSServerListFilterClassName :配置ServerListFilter 的实现类。
实践:通过属性来修改 Ribbon Client 的负载均衡规则。
-
复制项目 micro-consumer-movie-ribbon ,将 ArtifactId 修改为 micro-consumer-movie-ribbon-custom-props 。
-
修改 application.yml ,将名为 micro-provider-user 的 Ribbon Client 的负载均衡规则设为随机:
micro-provider-user:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
-
启动服务 micro-consumer-movie-ribbon-custom-props ,测试 http://localhost:8010/movie/v1/log-instance ,查看日志,会发现此时请求会随机分布到两个用户微服务节点上。
脱离 Eureka 使用 Ribbon
现实中某些微服务可能并没有注册到 Eureka Server 上 ,此时要想使用 Ribbon 实现负载均衡,要怎么办呢?

-
复制项目 micro-consumer-movie-ribbon ,将 ArtifactId 修改为 micro-consumer-movie-ribbon-without-eureka 。
-
删除 eureka 的依赖 spring-cloud-starter-eureka ,并为项目添加 Ribbon 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
-
去掉启动类上的
@EnableDiscoveryClient
注解。 -
修改配置 application.yml ,为 micro-provider-user 设置 Ribbon 客户端设置请求的地址列表:
server:
port: 8010
spring:
application:
name: micro-consumer-movie
micro-provider-user:
ribbon:
listOfServers: localhost:8000,localhost:8001
-
启动多个服务提供者 micro-provider-user 。
java -jar micro-provider-user-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer1
java -jar micro-provider-user-0.0.1-SNAPSHOT.jar --spring.profiles.active=peer2
-
启动服务 micro-consumer-movie-ribbon-without-eureka ,测试 http://localhost:8010/movie/v1/2 或 http://localhost:8010/movie/v1/log-instance 。
由结果可知,尽管电影微服务和用户微服务此时并没有注册到 Eureka 上, Ribbon 仍可正常工作,请求依旧会分摊到两个用户微服务节点上。
饥饿加载
Spring Cloud 会为每个名称的 Ribbon Client 维护一个子应用程序上下文,这个上下文默认是懒加载的。指定名称的 Ribbon Client 第一次请求时,对应的上下文才会被加载,因此,首次请求往往会比较慢。
从 Spring Cloud Dalston 开始,我们可配置饥饿加载。例如
ribbon:
eager-load:
enabled: true
clients: client1,client2
这样,对于名为 client1 , clent2 的 Ribbon Client ,将在启动时就加载对应的子应用程序上下文,从 而提高首次请求的访问速度。
代码仓库
https://gitee.com/chentian114/spring-cloud-practice
公众号
参考
《Spring Cloud 与Docker 微服务架构实战》 周立
原文始发于微信公众号(知行chen):使用 Ribbon 实现客户端负载均衡
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/45975.html