[TOC]
Ribbon 简介
Ribbon 是 Netflix 发布的开源项目,主要目的是为客户端提供负载均衡算法和服务调用。Ribbon 客户端组件提供一系列完善的配置项如连接超时,重试等。简单地说,就是在配置文件中列出 Load Balancer(简称 LB)后面所有机器,Ribbon 会自动的帮助你基于某种规则 (如简单轮询,随机连接等) 去连接这些机器。我们很容易使用 Ribbon 实现自定义的负载均衡算法。
负载均衡 + RestTemplate 示例
一、Ribbon 默认的负载规则 – 轮询
1、启动 eureka 集群
localhost:7001
localhost:7002
pom 依赖
<!-- eureka server 依赖包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
配置文件 application.yaml
-- 7001
server:
port: 7001
eureka:
instance:
# eureka 服务端的实例名称
hostname: eureka7001.com
client:
# 表示是否将自己注册到 Eureka Server,默认为 true。register-with-eureka: false
# 表示是否从 Eureka Server 获取注册信息,默认为 true。fetch-registry: false
service-url:
# 设置与 Eureka Server 交互的地址
defaultZone: http://eureka7002.com:7002/eureka/
server:
enable-self-preservation: false # 禁用自我保护机制
eviction-interval-timer-in-ms: 2000 # 2 秒钟
-- 7002
server:
port: 7002
eureka:
instance:
# eureka 服务端的实例名称
hostname: eureka7002.com
client:
# 表示是否将自己注册到 Eureka Server,默认为 true。register-with-eureka: false
# 表示是否从 Eureka Server 获取注册信息,默认为 true。fetch-registry: false
service-url:
# 设置与 Eureka Server 交互的地址
defaultZone: http://eureka7001.com:7001/eureka/
server:
enable-self-preservation: false # 禁用自我保护机制
eviction-interval-timer-in-ms: 2000 # 2 秒钟
主启动类 7001、7002
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication7001 {public static void main(String[] args) {SpringApplication.run(EurekaApplication7001.class, args);
}
}
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication7002 {public static void main(String[] args) {SpringApplication.run(EurekaApplication7002.class, args);
}
}
2、两个服务提供者 payment 8001 和 payment 8002。并注册到 eureka 注册中心
启动类 8001 和 8002
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class PaymentMain8001 {public static void main(String[] args) {SpringApplication.run(PaymentMain8001.class, args);
}
}
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class PaymentMain8002 {public static void main(String[] args) {SpringApplication.run(PaymentMain8002.class, args);
}
}
提供者业务类 8001 和 8002 部分代码
@RestController
@Slf4j
public class PaymentController {
@Autowired
private PaymentService paymentService;
@Value("${server.port}")
private String serverPort;
@GetMapping(value = "/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {Payment res = paymentService.getPaymentById(id);
log.info("************************** 查询结果: " + res);
if (res != null) {return new CommonResult(200, " 查询成功, serverPort: " + serverPort, res);
}
return new CommonResult(444, " 查询失败 ",null);
}
}
3、消费者服务 order
以轮询的方式 通过 eureka
调用 payment8001
和payment8002
启动类
@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {public static void main(String[] args) {SpringApplication.run(OrderMain80.class, args);
}
}
消费者服务部分代码
@RestController
public class OrderController {
private static final String PROVIDER_URL = "http://CLOUD-PAYMENT-SERVICE";
@Resource
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {return restTemplate.getForObject(PROVIDER_URL + "/payment/get/"+id, CommonResult.class);
}
}
访问localhost/consumner/payment/get/6
第一次访问结果:调用的 8002
{
"code": 200,
"message": " 查询成功, serverPort: 8002",
"data": {
"id": 4,
"serial": "jeffcail00004"
}
}
第二次访问结果:调用的 8001
{
"code": 200,
"message": " 查询成功, serverPort: 8001",
"data": {
"id": 4,
"serial": "jeffcail00004"
}
}
第三次访问结果:调用的 8002
{
"code": 200,
"message": " 查询成功, serverPort: 8002",
"data": {
"id": 4,
"serial": "jeffcail00004"
}
}
第四次访问结果:调用的 8001
{
"code": 200,
"message": " 查询成功, serverPort: 8001",
"data": {
"id": 4,
"serial": "jeffcail00004"
}
}
因为 Rabbion 默认的负载均衡机制为 轮询
。
二、Ribbon 负载规则 – 随机
在主主启动类所在的 package 的同级目录下,新建 ribbonrule package。新建 MyselfRule.java 类
MyselfRule.java 类
@Configuration
public class MyselfRule {
@Bean
public IRule myRule() {return new RandomRule(); // 定义为随机规则
}
}
在主启动类上添加 @RibbonClient 注解
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MyselfRule.class)
public class OrderMain80 {public static void main(String[] args) {SpringApplication.run(OrderMain80.class, args);
}
}
重启 order
服务,然后访问 localhost/consumner/payment/get/4
第一次结果:
{
"code": 200,
"message": " 查询成功, serverPort: 8001",
"data": {
"id": 4,
"serial": "jeffcail00004"
}
}
第二次结果:
{
"code": 200,
"message": " 查询成功, serverPort: 8001",
"data": {
"id": 4,
"serial": "jeffcail00004"
}
}
第三次结果:
{
"code": 200,
"message": " 查询成功, serverPort: 8002",
"data": {
"id": 4,
"serial": "jeffcail00004"
}
}
第四次结果:
{
"code": 200,
"message": " 查询成功, serverPort: 8002",
"data": {
"id": 4,
"serial": "jeffcail00004"
}
}