前言 在微服务中,对服务进行拆分之后,必然会带来微服务之间的通信需求,而每个微服务为了保证高可用性,又会去部署集群,那么面对一个集群微服务进行通信的时候,如何进行负载均衡也是必然需要考虑的问题。那么有需求自然就有供给,由此一大批优秀的开源的负载均衡组件应运而生,本文就让我们一起来分析一下 Spring Cloud Netflix 套件中的负载均衡组件 Ribbon。 一个问题引发的思考 首先我们来看一个问题,假如说我们现在有两个微服务,一个 user-center,一个 user-order,我现在需要在 user-center 服务中调用 user-order 服务的一个接口。 这时候我们可以使用 HttpClient,RestTemplate 等发起 http 请求,user-center 服务端口为 8001,如下图所示: @RestController @RequestMapping(value = "/user") public class UserController { @Autowired private RestTemplate restTemplate; @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } @GetMapping("/order") public String queryOrder(){ return restTemplate.getForObject("http://localhost:8002/order/query",String.class); } } 而 user-order 服务中只是简单的定义了一个接口,user-order 服务端口为 8002: @RestController @RequestMapping(value = "/order") public class UserOrderController { @GetMapping(value = "/query") public String queryAllOrder(){ return "all orders"; } } 这时候只需要将两个服务启动,访问 http://localhost:8001/user/order 就可以获取到所有的订单信息。 可以看到,这样是可以在两个微服务之间进行通讯的,但是,假如说我们的 user-order 服务是一个集群呢?这时候怎么访问呢?因为 user-order 服务已经是集群,所以必然需要一种算法来决定应该请求到哪个 user-order 服务中,最简单的那么自然就是随机或者轮询机制,轮询或者随机其实就是简单的负载均衡算法,而 Ribbon 就是用来实现负载均衡的一个组件,其内部支持轮询,等算法 Ribbon的简单使用 接下来我们看看 Ribbon 的简单使用。
-
首先改造 user-order 服务,在 user-order 服务中定义一个服务名配置:
spring.application.name=user-order-service
-
将 user-order 服务中的 UserOrderController 稍微改造一下,新增一个端口的输出来区分:
@RestController @RequestMapping(value = "/order") public class UserOrderController { @Value("${server.port}") private int serverPort; @GetMapping(value = "/query") public String queryAllOrder(){ return "订单来自:" + serverPort; } }
-
通过 VM 参数 -Dserver.port=8002 和 -Dserver.port=8003 分别来启动两个 user-order 服务。
-
接下来改造 user-center 服务,在 user-center 服务中引入 Ribbon 的相关依赖:
<