讲解如何使用 RestTemplate 和 Ribbon 相结合作为服务消费者去消费服务,同时从源码的角度来深入讲解 Ribbon。
常见的负载均衡有两种方式。 一种是独立进 程单元,通过负载均衡策略,将请求转发到不同的执行单元上,例如 Ngnix。另一种是将负载 均衡逻辑以代码的形式封装到服务消费者的客户端上,服务消费者客户端维护了一份服务提供 者的信息列表,有了信息列表,通过负载均衡策略将请求分摊给多个服务提供者,从而达到负 载均衡的目的。例如 Ribbon。
Ribbon 是将负载 均衡逻辑封装在客户端中,并且运行在客户端的进程里。 Ribbon 是一个经过了云端测试的 IPC 库,司以很好地控制 HTTP 和 TCP 客户端的负载均衡行为。
在 Spring Cloud 构建的微服务系统中, Ribbon 作为服务消费者的负载均衡器,有两种使用 方式,一种是和 RestTemplate 相结合,另一种是和 Feign 相结合。Feign 已经默认集成了 Ribbon。
Ribbon 有很多子模块,但很多模块没有用于生产环境,目前Netflix 公司用于生产环境的 Ribbon 子模块如下。
ribbon-loadbalancer:可以独立使用或与其他模块一起使用的负载均衡器 API。
ribbon-eureka:Ribbon 结合 Eureka 客户端的 API,为负载均衡器提供动态服务注册列 表 信息。
ribbon-core: Ribbon 的核心 API。
和 RestTemplate 相结合
启动 eureka-server, 端口为 8761 。启动两个 eureka-client 实例,端口分别为 8762 和 8763。
在此基础上,创建一个 Module 工程,取名为 eureka-ribbon-client,其作 为服务消费者,通过 RestTemplate 来远程调用 eureka-client 服务 API 接口的“剧”,即消费 服务。
创建完成 eureka-ribbon-client 的 Module 工程之后, 在其 porn 文件中引入相关的依赖,包 括继承了主 Maven 工程的 porn 文件,引入了 Eureka Client 的起步依赖 spring-cloud-startereureka、Ribbon 的起步依赖spring-cloud-starter-ribbon,以及Web 的起步依赖spring-boot-starter- web, 代码如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
端口设为8764
spring:
application:
name: euraka-ribbon-client
server:
port:8764
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
另外,作为 Eureka Client 需要在程序的入口类加上注解@EnableEurekaClient 开启 Eureka Client 功能,代码如下:
写一个REST削 API 接口,在该 API 接口内部需要调用 eureka-client 的 API 接口"/hi”, 即服务消费。由于 eureka-client 为两个实例,它们的端口为 8762 和 8763。在调用 eureka-client 的 API 接口“/hi”时希望做到轮流访问这两个实例,这时就需要将 RestTemplate 和 Ribbon 相 结合,进行负载均衡。
通过查阅官方文档,可以知道如何将它们结合在一起,只需要在程序的 IoC 容器中注入一个 restTemplate 的 Bean, 并在这个 Bean 上加上@LoadBalanced 注解,此时 RestTemplate 就结合了 Ribbon 开启了负载均衡功能,代码如下:
写一个RibbonService 类,在该类的 hi()方法用 restTemplate 调用 eureka-client 的 API 接口 , 此时 Uri 上不需要使用硬编码(例如 IP 地址),只需要写服务名 eureka-client 即可,代码如下:
写一个 RibbonController 类,为该类加上@RestController 注解,开启 RestController 的功能, 写一个“/hi” Get 方法的接口,调用 RibbonService 类的 hi()方法,代码如下:
启动 eureka-ribbon-client 工程,在浏览器上访问 localhost:8764/hi?name= Eroisan