本文章是在网易云课堂的课程学习中编写,部分图片从网易云课堂ppt引用
一、什么是负载均衡
1、服务端负载均衡 和 客户端负载均衡
【服务端负载均衡】
所有请求是向服务端发起调用的,比如 nginx、LVS(linux虚拟服务器)、F5等
【客户端负载均衡】
在服务消费者内部,通过负载均衡器选择调用的服务提供者,比如Ribbon负载均衡器
2、Ribbon客户端负载均衡
Ribbon是一个客户端负载均衡器
二、Ribbon的集成使用
在《分布式系统开发技术 | Eureka》中代码的基础上,对 【服务消费者】进行改造
1. maven引入
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
1.4.2.RELEASE
2. 代码示例
2.1 Ribbon结合Restemplate使用
第一步:给template方法加上注解 @LoadBalanced 来实现负载均衡,这是Ribbon的一种内部应用模式
@Bean
@LoadBalanced
public RestTemplate template(){
return new RestTemplate();
}
第二步:使用Restemplate通过服务名调用
@GetMapping("index")
public Object getIndex(){
//使用RestTemplate对服务提供者进行访问,这里使用服务名去访问
return restTemplate.getForObject("http://HELLOSERVER/",String.class,"");
}
2.2 下面用一个原生态的demo,替换@LoadBalanced来实现Ribbon的执行流程
application.yml:
server:
port: 8083
spring:
application:
name: consumer-demo
##改造配置
eureka:
client:
#关闭服务注册
enabled: false
##1:定义一个serverlist给我们使用负载均衡
##格式{servcid}:ribbon:listOfServers
hello-server:
ribbon:
listOfServers: localhost:8001,localhost:8002
logging:
level:
org:
springframework:
cloud: debug
com:
netflix: debug
CustomerDemoApplication:使用@RibbonClients注解
@SpringBootApplication
@RestController
@RibbonClients(
@RibbonClient(value = "hello-server")
)
public class CustomerDemoApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerDemoApplication.class, args);
}
@Bean
public RestTemplate template(){
return new RestTemplate();
}
@Bean
public IRule ribbonRule(){
//自定义规则
return new RandomRule();
}
}
CustomerController:
@RestController
public class CustomerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
LoadBalancerClient loadBalancerClient; //注入LoadBalancerClient
@GetMapping("index")
public Object getIndex(){
//拿到服务实例
ServiceInstance serviceInstance = loadBalancerClient.choose("hello-server");
//IP地址
String ip = serviceInstance.getHost();
//端口
int port = serviceInstance.getPort();
return restTemplate.getForObject("http://"+ip+":"+port,String.class,"");
}
}
分别启动Eureka注册中心、服务提供者、消费者工程
可以看到,消费者发起请求,能收到服务端1/服务端2的应答
三、Ribbon核心知识
1. Ribbon客户端负载均衡器的结构和初始化过程
【Ribbon初始化方式】
- RibbonAutoConfiguration:ribbon的自动装配类
- SpringClientFactory:内部包含了各种获取对象--如loadbalancer,instance,等方法
- LoadBalancerClient:定义了各种方法,如URI获取,服务实例选择等。(默认RibbonLoadBalancerClient)
源码入口:
RibbonAutoConfiguration
其他概念:
【父子容器】用于资源隔离。父容器无法访问子容器,子容器可以访问父容器。比如 Spring 和 Spring MVC
2. Ribbon怎么实现负载均衡(策略)?
【Ribbon的IRule】
IRule是负载均衡规则,在Ribbon中提供了以下负载均衡规则:
若没有定义区域,则默认使用 轮询策略
实现自定义规则:
@Bean
public IRule ribbonRule(){
//自定义规则,这里使用随机数策略
return new RandomRule();
}
3. Ribbon的容错机制
【Iping机制】
相当于心跳,每隔一段时间判断服务实例是否正常
【lping机制的装载流程】
- 未引入Eureka时,加载配置文件,一旦配置没有指定lping,默认调用 new DummyPing(),全部都返回true
- 引入Eureka时,加载 EurekaRibbonClientConfiguration 装载一个lping,如果自定义配置lping,默认使用 NIWSDiscoveryPing ,通过Eureka的状态返回服务是否正常。
【重试机制】
如果调用后,某个服务出现异常,可以通过重试机制,发起重试,根据负载均衡规则重新调用服务。
源码:
在使用@LoadBalanced实现负载均衡的情况下,可引入Ribbon的重试机制。在maven引入:
org.springframework.retry
spring-retry
但若服务返回超时或其他错误,重试机制无法帮助我们解决这些问题,可以使用【hystrix】来处理