原文地址:Spring Cloud 入门 之 Ribbon 篇(二) 博客地址:http://www.extlight.comjava
上一篇《Spring Cloud 入门 之 Eureka 篇(一)》 介绍了微服务的搭建,服务注册与发现。但在文章中留了一个小尾巴--如何正确使用 Eureka 进行服务发现并调用服务。git
本篇文章将介绍如何使用 Ribbon 完成发现服务的调用以及其负载均衡的规则的使用。github
Spring Cloud Ribbon 是基于 Netflix Ribbon 实现的一套客户端负载均衡工具,其主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务链接在一块儿。web
其运行原理以下图:算法
Ribbon 运行时分红 2 个步骤:spring
1) 先选择在同一个区域负载较少的 EurekaServer; 2) 再根据用户指定的策略,在从 EurekaServer 中获取注册列表中的服务信息进行调用。
其中,Ribbon 提供多种负载均衡策略:如轮询、随机、响应时间加权等。api
咱们在 order-server 项目的基础上进行修改。不清楚的读者请先转移至 《Spring Cloud 入门 之 Eureka 篇(一)》 进行浏览。服务器
此外,笔者额外的建立 2 个 goods-server 项目,即如今有 3 个 goods-server 项目给 order-server 服务实现客户端的负载均衡调用。并发
如今的项目列表以下:mvc
服务实例 | 端口 | 描述 |
---|---|---|
common-api | - | 公用的 api,如:实体类 |
eureka-server | 9000 | 注册中心(Eureka 服务端) |
goods-server | 8081 | 商品服务(Eureka 客户端) |
goods-server-02 | 8082 | 商品服务(Eureka 客户端) |
goods-server-03 | 8083 | 商品服务(Eureka 客户端) |
order-server | 8100 | 订单服务(Eureka 客户端) |
在 order-server 项目中:
<dependencies> <!-- common api --> <dependency> <groupId>com.extlight.springcloud</groupId> <artifactId>common-api</artifactId> <version>${parent-version}</version> </dependency> <!-- springmvc --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- eureka 客户端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- ribbon --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> </dependencies>
添加加 ribbon 的依赖。
@Configuration public class RestConfiguration { @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } }
正如上文介绍的,Ribbon 是客户端负载均衡工具,因此在 getRestTemplate 方法上添加 @LoadBalanced 注解实现负载均衡。
@Service public class OrderServiceImpl implements OrderService{ @Autowired private RestTemplate restTemplate; // @Autowired // private DiscoveryClient client; @Override public void placeOrder(Order order) throws Exception{ // 获取商品服务地址列表 // List<ServiceInstance> list = this.client.getInstances("GOODS"); // String uri = ""; // for (ServiceInstance instance : list) { // if (instance.getUri() != null && !"".equals(instance.getUri())) { // uri = instance.getUri().toString(); // break; // } // } // // Result result = restTemplate.getForObject(new URI(uri + "/goods/goodsInfo/" + order.getGoodsId()), Result.class); Result result = this.restTemplate.getForObject("http://GOODS/goods/goodsInfo/" + order.getGoodsId(), Result.class); if (result != null && result.getCode() == 200) { System.out.println("=====下订单===="); System.out.println(result.getData()); } } }
修改 DiscoveryClient 相关代码,使用 GOODS 做为请求商品服务的请求 URL。
完成上边 3 个操做后,启动 3 台 goods-server 服务 和 order-server 服务,经过 Postman 进行测试,运行结果以下:
上图中,经过 6 次请求返回的商品的端口信息可知,Ribbon 默认使用负载均衡的策略是轮询,对服务进行调用。
Ribbon 提供 IRule 接口,该接口定义了如何访问服务的方法,如下是该接口的实现类:
1) RoundRobinRule:轮询,默认使用的规则; 2) RandomRule:随机; 3) AvailabilityFilteringRule:先过滤因为屡次访问故障而处于断路器跳闸状态以及并发链接数量超过阀值得服务,而后从剩余服务列表中按照轮询策略进行访问; 4) WeightedResponseTimeRule:根据平均响应时间计算全部的权重,响应时间越快服务权重越有可能被选中; 5) RetryRule:先按照 RoundRobinRule 策略获取服务,若是获取服务失败则在指定时间内进行重试,获取可用服务; 6) BestAvailableRule:先过滤因为屡次访问故障而处于断路器跳闸状态的服务,而后选择并发量最小的服务; 7) ZoneAvoidanceRule:判断 server 所在区域的性能和 server 的可用性来选择服务器。
在 order-server 项目中:
@Configuration public class RestConfiguration { @Bean @LoadBalanced public RestTemplate getRestTemplate() { return new RestTemplate(); } @Bean public IRule testRule() { return new RandomRule(); } }
手动建立负载均衡规则对象,本次测试使用的策略是随机。
启动 order-server 项目后再次使用 Postman 测试,运行结果以下:
由图可知,随机策略已生效,负载均衡的策略由轮询变成了随机。