分布式系统开发技术 | Ribbon负载均衡

本文章是在网易云课堂的课程学习中编写,部分图片从网易云课堂ppt引用

一、什么是负载均衡

1、服务端负载均衡 和 客户端负载均衡

image.png

【服务端负载均衡】
所有请求是向服务端发起调用的,比如 nginx、LVS(linux虚拟服务器)、F5等

【客户端负载均衡】
在服务消费者内部,通过负载均衡器选择调用的服务提供者,比如Ribbon负载均衡器

2、Ribbon客户端负载均衡

image.png

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的应答


image.png

三、Ribbon核心知识

1. Ribbon客户端负载均衡器的结构和初始化过程

【Ribbon初始化方式】

image.png
  • RibbonAutoConfiguration:ribbon的自动装配类
  • SpringClientFactory:内部包含了各种获取对象--如loadbalancer,instance,等方法
  • LoadBalancerClient:定义了各种方法,如URI获取,服务实例选择等。(默认RibbonLoadBalancerClient)

源码入口:
RibbonAutoConfiguration

image.png
image.png

其他概念:
【父子容器】用于资源隔离。父容器无法访问子容器,子容器可以访问父容器。比如 Spring 和 Spring MVC

2. Ribbon怎么实现负载均衡(策略)?

【Ribbon的IRule】
IRule是负载均衡规则,在Ribbon中提供了以下负载均衡规则:

image.png

若没有定义区域,则默认使用 轮询策略

实现自定义规则:

@Bean
 public IRule ribbonRule(){
       //自定义规则,这里使用随机数策略
     return new RandomRule();
 }

3. Ribbon的容错机制

【Iping机制】
相当于心跳,每隔一段时间判断服务实例是否正常

【lping机制的装载流程】

  • 未引入Eureka时,加载配置文件,一旦配置没有指定lping,默认调用 new DummyPing(),全部都返回true
  • 引入Eureka时,加载 EurekaRibbonClientConfiguration 装载一个lping,如果自定义配置lping,默认使用 NIWSDiscoveryPing ,通过Eureka的状态返回服务是否正常。

【重试机制】
如果调用后,某个服务出现异常,可以通过重试机制,发起重试,根据负载均衡规则重新调用服务。
源码:

image.png

在使用@LoadBalanced实现负载均衡的情况下,可引入Ribbon的重试机制。在maven引入:


     
         org.springframework.retry
         spring-retry
     

但若服务返回超时或其他错误,重试机制无法帮助我们解决这些问题,可以使用【hystrix】来处理

你可能感兴趣的:(分布式系统开发技术 | Ribbon负载均衡)