上一篇文章初步体验了 Eureka 的基本使用,讲了关于服务的注册与发现。这一篇主要讲解基于 Ribbon 实现的服务调用。
Spring Cloud Ribbon 是一个基于 Http 和 TCP 的客服端负载均衡工具,它是基于 Netflix Ribbon 实现的。
客户端负载均衡即是当浏览器向后台发出请求的时候,客户端会向 Eureka Server 读取注册到服务器的可用服务信息列表,然后根据设定的负载均衡策略(没有设置即用默认的),抉择出向哪台服务器发送请求。
启动完毕后,更改 spring-demo-service 的端口号,再启动一个 spring-demo-service 的实例,访问 http://localhost:8761,如下
spring-demo-service 在 eureka server 注册了两个实例。
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
org.springframework.boot
spring-boot-starter-web
@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 负载均衡功能。
@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 替换掉服务名
@RestController
public class SpringDemoRibbonController {
@Autowired
SpringDemoRibbonService springDemoRibbonService;
@RequestMapping("hello")
public String port() {
return springDemoRibbonService.port();
}
}
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8381
spring:
application:
name: spring-demo-service-ribbon
此时说明基本使用 Ribbon 实现了客户端负载均衡的功能,当用 restTemplate 调用服务接口时,访问了不同端口的服务实例。
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 的服务实例调用是随机调用,而不再是之前轮流调用,说明负载策略配置成功。