上一篇文章初步体验了 Eureka 的基本使用,讲了关于服务的注册与发现。这一篇主要讲解基于 Ribbon 实现的服务调用。
(一)简介
Spring Cloud Ribbon 是一个基于 Http 和 TCP 的客服端负载均衡工具,它是基于 Netflix Ribbon 实现的。
客户端负载均衡即是当浏览器向后台发出请求的时候,客户端会向 Eureka Server 读取注册到服务器的可用服务信息列表,然后根据设定的负载均衡策略(没有设置即用默认的),抉择出向哪台服务器发送请求。
(二)搭建服务环境
1. 基于上一篇的工程,启动 eureka-service,spring-demo-service
启动完毕后,更改 spring-demo-service 的端口号,再启动一个 spring-demo-service 的实例,访问 http://localhost:8761,如下
spring-demo-service 在 eureka server 注册了两个实例。
2. 新创建一个 module(spring-demo-service-ribbon),创建过程参考上一篇
3. 添加 pom 依赖
-
<dependency>
-
<groupId>org.springframework.cloud
</groupId>
-
<artifactId>spring-cloud-starter-netflix-eureka-client
</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.cloud
</groupId>
-
<artifactId>spring-cloud-starter-netflix-ribbon
</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-web
</artifactId>
-
</dependency>
4. 启动类
-
@SpringBootApplication
-
@EnableEurekaClient
-
public
class ServiceRibbonApplication {
-
-
public static void main(String[] args) {
-
SpringApplication.run(ServiceRibbonApplication.class, args);
-
}
-
-
@Bean
-
@LoadBalanced
-
RestTemplate restTemplate() {
-
return
new RestTemplate();
-
}
-
}
在启动类中,通过 @EnableEurekaClient 向 eureka server 注册,并向容器中注入 restTemplate,同时通过 @LoadBalanced 开启 restTemplate 负载均衡功能。
5. 创建 SpringDemoRibbonService,通过 restTemplate 消费 spring-demo-service 服务的 port 接口
-
@Service
-
public
class SpringDemoRibbonService {
-
-
@Autowired
-
RestTemplate restTemplate;
-
-
public String port() {
-
return restTemplate.getForObject(
"http://SPRING-DEMO-SERVICE/port", String.class);
-
}
-
-
}
在这里,restTemplate 调用服务接口的方法不是仅此一种,API 大致如下,具体怎么选择应用,可以查看相关 API 文档,我们直接使用 getForObject 第一种,在这里我们直接用的程序名替代了具体的 url 地址,在 Ribbon 中它会根据服务名来选择具体的服务实例,根据服务实例在请求的时候会用具体的 url 替换掉服务名
6. 创建 SpringDemoRibbonController
-
@RestController
-
public
class SpringDemoRibbonController {
-
-
@Autowired
-
SpringDemoRibbonService springDemoRibbonService;
-
-
@RequestMapping(
"hello")
-
public String port() {
-
return springDemoRibbonService.port();
-
}
-
}
7. 配置文件 application.yaml
-
eureka:
-
client:
-
serviceUrl:
-
defaultZone:
http:/
/localhost:8761/eureka
/
-
server:
-
port: 8381
-
spring:
-
application:
-
name: spring-demo-service-ribbon
8. 启动 spring-demo-service-ribbon,在浏览器中多次访问 localhost:8381/hello,浏览器会轮流显示如下
此时说明基本使用 Ribbon 实现了客户端负载均衡的功能,当用 restTemplate 调用服务接口时,访问了不同端口的服务实例。
(三)稍作延伸:负载均衡策略常见的还有使用 Nginx 作为反向代理服务器,对服务的调用进行负载均衡,这种方式是服务器端负载均衡。
Ribbon 实现的是客户端负载均衡,它可以在客户端经过一系列算法来均衡调用服务。Ribbon 比 Nginx 更注重的是承担并发而不是请求分发,Ribbon 工作时分两步:
第一步:选择 Eureka Server,它优先选择在同一个 Zone 且负载较少的 Server。
第二步:根据用户指定的策略,在从 Server 取到的服务注册列表中选择一个地址,其中 Ribbon 提供了多种策略,例如轮询 RoundRobinRule、随机 RandomRule等。
下面以随机策略进行进一步的配置
配置文件修改如下:
-
eureka:
-
client:
-
serviceUrl:
-
defaultZone:
http:/
/localhost:8761/eureka
/
-
server:
-
port: 8381
-
spring:
-
application:
-
name: spring-demo-service-ribbon
-
-
#新增配置策略
-
spring-demo-service:
-
ribbon:
-
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
启动类修改如下:
-
@SpringBootApplication
-
@EnableEurekaClient
-
@EnableCircuitBreaker
-
public
class ServiceRibbonApplication {
-
-
public static void main(String[] args) {
-
SpringApplication.run(ServiceRibbonApplication.class, args);
-
}
-
-
@Bean
-
@LoadBalanced
-
RestTemplate restTemplate() {
-
return
new RestTemplate();
-
}
-
-
//新增注入随机策略 Bean
-
@Bean
-
public IRule ribbonRule() {
-
return
new RandomRule();
//这里配置策略,和配置文件对应
-
}
-
}
SpringDemoRibbonService 修改如下
-
@Service
-
public
class SpringDemoRibbonService {
-
-
@Autowired
-
RestTemplate restTemplate;
-
-
@Autowired
-
LoadBalancerClient loadBalancerClient;
-
-
public String port() {
-
this.loadBalancerClient.choose(
"spring-demo-service");
//随机访问策略
-
return restTemplate.getForObject(
"http://SPRING-DEMO-SERVICE/port", String.class);
-
}
-
-
}
修改完成后,修改 spring-demo-service 的端口号,再启动一个服务实例,然后重启 spring-demo-service-ribbon,在浏览器中多次访问 localhost:8381/hello,此时会发现,对 spring-demo-service 的服务实例调用是随机调用,而不再是之前轮流调用,说明负载策略配置成功。