如何在客户端实现服务的负载均衡
这时,就需要在客户端实现服务的负载均衡。而在Spring Cloud中推荐使用Ribbon来实现负载均衡。
1、Ribbon简介
Ribbon是Netflix发布的负载均衡器。它有助于控制HTTP和TCP客户端的行为。为Ribbon配置服务提供者地址列表后, Ribbon就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon默认为我们提供了很多的负载均衡算法,例如轮询、随机等。当然,我们也可为 Ribbon实现自定义的负载均衡算法。
2、架构
3、开始使用Ribbon
3.1. 为microservice order增加ribbon依赖
其实,该依赖是可以省略的,因为spring-cloud-starter-netflix-eureka-client中已经包含了spring-cloud-starter-netflix-ribbon:
3.2. 为RestTemplate设置@LoadBalanced注解
@SpringBootApplication@EnableEurekaClient@EnableFeignClientspublic class OrderApp { public static void main(String[] args) { SpringApplication.run(OrderApp.class, args); } @Bean @LoadBalanced //使用负载均衡 public RestTemplate restTemplate() { return new RestTemplate(); }}
3.3. 改造ItemService的实现
@Servicepublic class ItemService { // Spring框架对RESTful方式的http请求做了封装,来简化操作 @Autowired private RestTemplate restTemplate; public Item queryItemById(Long id) { // 该方法走eureka注册中心调用(去注册中心根据app-item查找服务,这种方式必须先开启负载均衡@LoadBalanced) String itemUrl = "http://app-item/item/{id}"; Item result = restTemplate.getForObject(itemUrl, Item.class, id); System.out.println("订单系统调用商品服务,result:" + result); return result; }}
可以发现,实现更加简化了。
这种方式关键在于获取RestTemplat对象时要加上@LosdBalanced注解,否则restTemplate.getFor Object方法会报java.net.UnknownHostException: app-item,而前面一种方式是手动指定了获取的服务实例,不需要加此注解。
提示: 如果这里使用了@FeignClient完成的Restful的调用同样也适用。
3.4. 重启订单服务进行测试
测试结果:
3.5. 测试负载均衡
测试方法:
第一步,启动2个microservice-item服务(多个也可以):
第二步,导入测试依赖,编写单元测试用例:
<!-- 引入SpringBoot的单元测试 --><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope></dependency>
第三步,编写测试用例:
@RunWith(SpringJUnit4ClassRunner.class)@SpringBootTest@Import(OrderApp.class)public class ItemServiceTest { @Autowired private LoadBalancerClient loadBalancerClient;//自动注入 @Test public void test() { String serviceId = "app-item"; for (int i = 0; i < 100; i++) { ServiceInstance serviceInstance = this.loadBalancerClient.choose(serviceId); System.out.println("第" + (i + 1) + "次:" + serviceInstance.getHost() + ": " + serviceInstance.getPort()); } }}
4、设置负载均衡策略
只需要在配置文件中添加配置
serviceId.ribbon.NFLoadBalancerRuleClassName=自定义的负载均衡策略类,
例如在order微服务的yml配置文件中添加:
app-item: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
其中app-item是要访问的服务id。
测试:
第1次:127.0.0.1: 8081
第2次:127.0.0.1: 9081
第3次:127.0.0.1: 9081
第4次:127.0.0.1: 8081
第5次:127.0.0.1: 9081
第6次:127.0.0.1: 8081
第7次:127.0.0.1: 9081
第8次:127.0.0.1: 9081
第9次:127.0.0.1: 8081
第10次:127.0.0.1: 8081
...
5、其它策略
接口:com.netflix.loadbalancer.IRule,其实现类:
策略描述:
AbstractLoadBalancerRule
负载均衡的抽象类,负责获得负载均衡器并保存在内部,通过负载均衡器维护的信息作为分配的依据,并以此设计一些算法来实现针对特定场景的高效策略。
RoundRobinRule
Ribbon默认的负载均衡机制,该策略实现了按照线性轮询的方式以此选择每个服务实例的功能。轮询index,选择index对应位置的server。
RandomRule
该策略实现了从服务实例清单中随机选择一个服务实例的功能。通过在index上随机,选择index对应位置的server。
RetryRule
该策略实现了一个具备重试机制的实例选择功能。该策略下在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server。