服务调用端负载均衡-Ribbon
1.什么是负载均衡
负载均衡是微服务架构中必须使用的技术,通过负载均衡来实现系统的高可用、集群扩容等功能。负载均衡可通过硬件设备及软件来实现,硬件比如:F5、Array等 ,软件比如:LVS、Nginx等 。
如下图是负载均衡的架构图:
用户请求先到达负载均衡器(也相当于一个服务),负载均衡器根据负载均衡算法将请求转发到微服务。负载均衡算法有:轮训、随机、加权轮训、加权随机、地址哈希等方法,负载均衡器维护一份服务列表,根据负载均衡算法将请求转发到相应的微服务上,所以负载均衡可以为微服务集群分担请求,降低系统的压力。
2.什么是Ribbon
Ribbon是Netflix发布的云中间层服务开源项目,其主要功能是提供客户端实现负载均衡算法。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,Ribbon是一个客户端负载均衡器,我们可以在配置文件中Load Balancer后面的所有机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器,我们也很容易使用Ribbon实现自定义的负载均衡算法。
下图展示了Eureka使用Ribbon时的大致架构:
Ribbon工作时分为两步:第一步选择Eureka Server,它优先选择在同一个Zone且负载较少的Server;第二步再根据用户指定的策略,再从Server取到的服务注册列表中选择一个地址。其中Ribbon提供了很多策略,例如轮询round robin、随机Random、根据响应时间加权等。
3.Ribbon组件和原理
Ribbon是Netflix发布的开源项目,主要功能是为REST客户端实现负载均衡。它主要包括六个组件:
- ServerList,负载均衡使用的服务器列表。这个列表会缓存在负载均衡器中,并定期更新。当Ribbon与Eureka结合使用时,ServerList的实现类就是DiscoveryEnabledNIWSServerList,它会保存Eureka Server中注册的服务实例表。
- ServerListFilter,服务器列表过滤器。这是一个接口,主要用于对Service Consumer获取到的服务器列表进行预过滤,过滤的结果也是ServerList。Ribbon提供了多种过滤器的实现。
- IPing,探测服务实例是否存活的策略。
-
IRule,负载均衡策略,其实现类表述的策略包括:轮询、随机、根据响应时间加权等,其类结构如下图所示。
我们也可以自己定义负载均衡策略,比如我们就利用自己实现的策略,实现了服务的版本控制和直连配置。实现好之后,将实现类重新注入到Ribbon中即可。
-
ILoadBalancer,负载均衡器。这也是一个接口,Ribbon为其提供了多个实现,比如ZoneAwareLoadBalancer。而上层代码通过调用其API进行服务调用的负载均衡选择。一般ILoadBalancer的实现类中会引用一个IRule。
- RestClient,服务调用器。顾名思义,这就是负载均衡后,Ribbon向Service Provider发起REST请求的工具。
Ribbon工作时会做四件事情:
- 优先选择在同一个Zone且负载较少的Eureka Server;
- 定期从Eureka更新并过滤服务实例列表;
- 根据用户指定的策略,在从Server取到的服务注册列表中选择一个实例的地址;
- 通过RestClient进行服务调用。
4.如何使用Ribbon
下面的例子,我们将利用之前构建的eureka-server
作为服务注册中心、eureka-client
作为服务提供者作为基础。而基于Spring Cloud Ribbon实现的消费者,我们可以根据eureka-consumer
实现的内容进行简单改在就能完成,具体步骤如下:
- 根据
eureka-consumer
复制一个服务消费者工程,命名为:eureka-consumer-ribbon
。在pom.xml
中增加下面的依赖:
<dependencies>
...
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
</dependencies>
- 修改应用主类。为
RestTemplate
增加@LoadBalanced
注解:
@EnableDiscoveryClient
@SpringBootApplication
public class Application {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
- 修改Controller。去掉原来通过
LoadBalancerClient
选取实例和拼接URL的步骤,直接通过RestTemplate发起请求。
@RestController
public class DcController {
@Autowired
RestTemplate restTemplate;
@GetMapping("/consumer")
public String dc() {
return restTemplate.getForObject("http://eureka-client/dc", String.class);
}
}
在完成了上面你的代码编写之后,读者可以将eureka-server、eureka-client、eureka-consumer-ribbon都启动起来,然后访问http://localhost:2101/consumer ,来跟踪观察eureka-consumer-ribbon服务是如何消费eureka-client服务的/dc
接口的,并且也可以通过启动多个eureka-client服务来观察其负载均衡的效果。可以看到这里,我们除了去掉了原来与LoadBalancerClient
相关的逻辑之外,对于RestTemplate
的使用,我们的第一个url参数有一些特别。这里请求的host位置并没有使用一个具体的IP地址和端口的形式,而是采用了服务名的方式组成。那么这样的请求为什么可以调用成功呢?因为Spring Cloud Ribbon有一个拦截器,它能够在这里进行实际调用的时候,自动的去选取服务实例,并将实际要请求的IP地址和端口替换这里的服务名,从而完成服务接口的调用。
推荐阅读
-
linux服务器之LVS、Nginx和HAProxy负载均衡器对比总结
-
nginx服务器安装及配置文件详解(转载) 修改nginx配置文件 nginx 配置 nginx负载均衡配
-
Nginx之代理配置以及负载均衡 nginx 负载 负载均衡 服务器负载均衡软
-
SpringCloud客户端的负载均衡Ribbon的实现
-
spring cloud 之 客户端负载均衡Ribbon深入理解
-
SpringCloud客户端的负载均衡Ribbon的实现
-
具有负载均衡功能的MySQL服务器集群部署及实现
-
spring cloud 之 客户端负载均衡Ribbon深入理解
-
详解spring cloud中使用Ribbon实现客户端的软负载均衡
-
Spring Cloud Ribbon实现客户端负载均衡的方法