`

SpringCloud(五):客户端负载均衡器—Ribbon

阅读更多


 (编写不易,转载请注明:http://shihlei.iteye.com/blog/2404997)

一 概述

负载均衡,简单说即将 “负载” 按照一定策略分摊到不同的执行单元中执行。

 

 服务的负载均衡目前主要实现策略:

1)服务器端反向代理:硬负载 F5, 软负载 LVS,Nginx;可以透明接入,但要独立搭建高可用架构。

2)客户单端负载均衡器:lib形式提供,可以根据需要灵活控制策略,但需要客户端集成。

 

Ribbon 属于客户端负载均衡器,主要应用于服务消费者,支持RestTemplate,Feign等请求技术集成,支持从配置文件或从Eureka重拉取Server实例列表,其他需要原生开发。

 

负载均衡算法:

随机,轮询,响应时间加权等等

 

git:https://github.com/Netflix/ribbon

 

本文规划:

1)Ribbon 原生使用及自定义rule。

2)SpringCloud RestClient集成Ribbon及简要说明实现机制。

 

二 Ribbon demo

1) 原生demo

(1)添加依赖

<dependency>
            <groupId>com.netflix.ribbon</groupId>
            <artifactId>ribbon-loadbalancer</artifactId>
            <version>2.2.5</version>
</dependency>

 

(2)demo

package x.demo.netflix.ribbon;

import java.util.Arrays;
import java.util.List;

import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.LoadBalancerBuilder;
import com.netflix.loadbalancer.NoOpPing;
import com.netflix.loadbalancer.RoundRobinRule;
import com.netflix.loadbalancer.Server;

/**
 * LoadBalancerDemo
 */
public class LoadBalancerDemo {

    public static void main(String[] args) {
        // 负载均衡规则
        IRule rule = new RoundRobinRule();
        // ping 规则
        IPing ping = new NoOpPing();

        // 添加Server 列表
        List<Server> serverList = Arrays.asList(
                new Server("server1"),
                new Server("server2"),
                new Server("server3"),
                new Server("server4"),
                new Server("server5")
        );

        //初始化LoadBalancer
        ILoadBalancer loadBalancer =
                LoadBalancerBuilder
                        .newBuilder()
                        .withRule(rule)
                        .withPing(ping)
                        .buildFixedServerListLoadBalancer(serverList);

        // 简单查看效果
        for (int i = 0; i < 10; i++) {
            System.out.println(loadBalancer.chooseServer(null));
        }
    }
}

 

2)Ribbon 结果简单分析

Ribbon 源码比较简单,结构也比较清晰,很方便看,主要体系:LoadBalancer,Rule,Ping 可以简单看看。


 

(1)LoadBalancer 体系:

【1】 接口级别:

a)ILoadBalancer:定义LoadBalancer的基本行为,主要是从ServerList中根据策略选择一个Server实例进行请求。

核心方法:

  • addServers:向LoadBalancer增加Server实例。
  • chooseServer:通过某种策略,从ServerList选择一个Server实例。
  • markServerDown:通知LoadBalancer某个Server实例已Down,下次请求可以忽略。
  • getReachableServers:获取可用的Server实例列表。
  • getAllServers:获取所有Server实例列表。

 

b)AbstractLoadBalancer:抽象LoadBalancer的一般操作。

 

【2】实现级别:

c)BaseLoadBalancer:基础实现,把实现依赖抽象成如下几大块,做用户定制和扩展,

主要依赖:

 

  • IClientConfig:提供配置信息,如ping 超时时间等。
  • IRule:提供Server实例选择策略。
  • IPing:提供验证实例是否可用策略。

d)DynamicServerListLoadBalancer:可动态添加ServerList(yml文件等),并提供Filter过滤能力

e) ZoneAwareLoadBalancer:提供Zone 负载均衡

 

 

(2)Rule体系

 

 

【1】接口级别:

a)IRule:提供Server选择策略

核心方法:Server choose(in Object key)

b)AbstractLoadBalancerRule:抽象Rule的一般操作,主要维护一个ILoadBalancer实例,提供get,set方法,完成绑定,以便获得SeverList供选择使用

 

【2】实现级别:

d)RandomRule

e)RoundRobinRule(及ClientConfigEnabledRoundRobinRule),

f)WeightedResponseTimeRule(返回时间权重规则)

g)BestAvailableRule(最低并发规则)

 

【3】其他包装类:

h)RetryRule:支持重试的规则

 

(3)Ping体系


 

【1】接口级别:

a)IPing:提供判读Sever实例是否可用的策略

核心方法:boolean isAlive(Server server)

b)AbstractLoadBalancerPing:主要维护一个ILoadBalancer实例,提供get,set方法,完成绑定,以便获得SeverList以便尝试时使用

 

【2】实现级别:

c)NoOpPing:无任何操作,永远返回true,有效。

d)DummyPing:也是永远返回true。

e)NIWSDiscoveryPing:基于发现的Ping规则

 

3)自定义一个Rule实现只使用第一个服务器

 

package x.demo.springcloud.webfront.service.impl.ribbon;

import java.util.List;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.Server;

/**
 * 只请求第一台server
 *
 */
public class FirstServerRule extends AbstractLoadBalancerRule {

    @Override
    public Server choose(Object key) {
        List<Server> servers = getLoadBalancer().getReachableServers();
        return servers.get(0);
    }

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {
    
    }
}
 

三 SpringCloud Ribben + RestClient

1)概述

SpringCloud 对 LoadBalancer 进行了高层抽象,用于多种Http客户端获得负载均衡的能力。Ribbon作为一种基础实现,通过SpringCloud AutoConfiguration机制集成。

 

注:demo 默认使用《SpringCloud文章系列》的 “microservice-time” 时间微服务,作为服务提供者,为简化项目复杂度,禁用Eureka 服务发现能力。

 

具体项目环境可参见《SpringCloud(一): SpringBoot 创建简单的微服务》

 

本文主要改造微服务客户端项目:

spring-cloud-webfront:服务调用者,调用“时间”微服务,返回当前时间。

 

 

2)集成使用Demo

(1)添加依赖

 

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
 

 

(2)RestClient  集成 Ribbon

只需要通过在@Configuration中添加创建RestTemplate的Bean,并使用@LoadBalanced进行注解即可

 

package x.demo.springcloud.webfront.service.impl.ribbon;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * RestTemplateRibbon
 *
 */
@Configuration
public class RestTemplateRibbonConfiguration {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
} 

 

(3)配置服务器信息

a)yml 文件配置方式 

 

spring:
  profiles: Standalone
  application:
    name: webfront

server:
  port: 20001

# 自定义配置
timeMisroService:
  v1:
    uri: http://microservice-time/time/v1

# Ribbon 负载均衡配置
# 取消eureka 依赖
ribbon:
  eureka:
    enabled: false
# microservice-time 相对于虚拟主机,RestTemplate 必须使用microservice-time 访问 才能走复杂均衡策略
microservice-time:
  ribbon:
    # LoadBalancer
    NFLoadBalancerClassName:  com.netflix.loadbalancer.DynamicServerListLoadBalancer
    # 由于禁用了Ribbon Eureka获取服务ip端口,需要手动提供
    listOfServers: 127.0.0.1:10001,127.0.0.1:10002
    # 负载均衡策略
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
    # ping策略
    NFLoadBalancerPingClassName: com.netflix.loadbalancer.NoOpPing

注:

      microservice-time.ribbon 是针对 microservice-time 的 ribbon配置,microservice-time 相当于虚拟主机,使用时host需要使用 microservice-time 作为虚拟主机,如地址http://microservice-time/time/v1,Ribbon根据策略获取实际的IP和端口,这里是通过microservice-time.ribbon.listOfServers获取的

 

其他定制项:

 

  • NFLoadBalancerClassName: 默认 DefaultClientConfigImpl
  • NFLoadBalancerPingClassName: 默认 DummyPing
  • NFLoadBalancerRuleClassName: 默认 ZoneAvoidanceRule
  • NIWSServerListClassName: 默认 ConfigurationBasedServerList
  • NIWSServerListFilterClassName: 默认 ZonePreferenceServerListFilter 

 

b)程序配置方式:
使用 @RibbonClient 配置RibbonClinet,通过 configuration 属性执行配置Bean;注:这个Bean不能添加@Configuration 否则配置全局生效
package x.demo.springcloud.webfront.service.impl.ribbon;

import java.util.Arrays;
import java.util.List;

import com.netflix.loadbalancer.IPing;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.NoOpPing;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;

/**
 * Ribbon 负载均衡配置
 * <p>
 * 特别注意:
 * 这里是针对 name = "microservice-time" 的服务进行的配置,所以不能 添加 @Configuration ,否则接入容器,会全局生效
 *
 */
@RibbonClient(name = "microservice-time", configuration = TimeMicroServiceConfiguration.class)
public class TimeMicroServiceConfiguration {

    @Bean
    public IRule rule() {
        return new RandomRule();
    }

    @Bean
    public IPing ping() {
        return new NoOpPing();
    }

    @Bean
    public ServerList<Server> serverList() {
        List<Server> servers = Arrays.asList(new Server("127.0.0.1", 10001), new Server("127.0.0.1", 10002));

        ServerList<Server> serverList = new ServerList<Server>() {
            @Override
            public List<Server> getInitialListOfServers() {
                return servers;
            }

            @Override
            public List<Server> getUpdatedListOfServers() {
                return servers;
            }
        };

        return serverList;
    }
}

(4)service 层

 

package x.demo.springcloud.webfront.service;

public interface TimeService {
    /**
     * 获取当前时间
     * @return 当前时间,格式:yyyy-MM-dd HH:mm:ss
     */
    String now();
}


package x.demo.springcloud.webfront.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import x.demo.springcloud.webfront.service.TimeService;

@Service
public class TimeServiceRestClientImpl implements TimeService {

    @Value("${timeMisroService.v1.uri}")
    private String timeMicroServiceV1Uri;

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 获取当前时间
     *
     * @return 当前时间,格式:yyyy-MM-dd HH:mm:ss
     */
    @Override
    public String now() {
        String url = timeMicroServiceV1Uri + "/now";
        ProtocolResult<String> result = restTemplate.getForObject(url, ProtocolResult.class);
        return result.getBody();
    }
}

(5)启动类

 

package x.demo.springcloud.webfront;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringCloudWebfrontApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudWebfrontApplication.class, args);
    }
}

(6)查看结果(略)

 

(7)SpringCloud Ribbon + FeignClien:

FeignClent 默认集成了Ribbon支持,只要依赖添加完成就可完成集成工作。
如果需要定制某个FeignClient的RibbonClient ,FeignClinet 的name使用服务的虚拟主机名,采用 上面
二 SpringCloud Ribben + RestClient 》 2)集成demo 》(3)配置服务器信息 即可完Ribbon的配置

 

四 SpringCloud LoadBalancer 源码分析

1)概述

SpringCloud LoadBalancer 进行了高层抽象,针对RestClent的扩展主要使用了RestTemplate的 ClientHttpRequestInterceptor 机制在请求时拦截走LoadBalancer的实现。
其实现结构如下:

 

(1)LoadBalancerClient体系

a)ServiceInstanceChooser:Service实例选择器接口

核心方法:ServiceInstance choose(String serviceId) :根据serviceId 选择一个 Service 实例。

 

b)LoadBalancerClient:负载均衡客户端接口,具有选择服务实例,执行请求的能力,继承自 ServiceInstanceChooser;

核心方法:

执行请求方法:

T execute(String serviceId, LoadBalancerRequest<T> request) 

T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request)

重建请求链接方法:

URI reconstructURI(ServiceInstance instance, URI original);

 

c)RibbonLoadBalancerClient:基于Ribbon实现的LoadBalancerClient,内部依赖 Ribbon的ILoadBalancer体系

 

(2) ClientHttpRequestInterceptor体系:

a)RestTemplate:Rest请求客户端,提供Rest服务访问能力

 

b)ClientHttpRequestInterceptor:RestTemplate提供的拦截器,可以在请求之根据需要进行拦截,一般用实现Header头改写,添加Token等通用的面向切面编程。

 

c)RetryLoadBalancerInterceptor:实现了ClientHttpRequestInterceptor,拦截Http请求,依赖 LoadBalancerClient 选择Service实例,重新发起请求。实现负载均衡。

 

 

(3)AutoConfiguration体系:

a)LoadBalancerAutoConfiguration:配置负载均衡客户端(di主要通过这个进行配置)如果是 RestTemplate 的形式,则在restTemplate 中通过添加RetryLoadBalancerInterceptor; 用于拦截请求。

 

b)RibbonAutoConfiguration:查看spring.factories文件,拉起Ribbon的默认配置及组装点

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration

 
  • 大小: 549.7 KB
  • 大小: 284.4 KB
  • 大小: 170.8 KB
  • 大小: 425.9 KB
分享到:
评论

相关推荐

    Spring Cloud Ribbon实现客户端负载均衡的方法

    Spring Cloud Ribbon 实现客户端负载均衡的方法 Spring Cloud Ribbon 是基于 Netflix OSS 的一个开源项目,提供了客户端负载均衡的功能。在本篇文章中,我们将介绍如何使用 Spring Cloud Ribbon 来实现客户端负载...

    springcloud入门代码基于Spring Cloud实现的Ribbon客户端负载均衡模板代码

    而Ribbon是Netflix开源的客户端负载均衡器,它与Spring Cloud结合,可以自动地在多个服务器实例间分配请求,提高系统的可用性和可靠性。 首先,我们要了解Ribbon的工作原理。Ribbon是一个客户端负载均衡器,它驻留...

    SpringCloud使用Ribbon实现负载均衡

    Spring Cloud是构建微服务架构的一套工具集,其中Ribbon是它提供的一个客户端负载均衡器,可以帮助我们实现服务间的智能路由。本篇文章将详细探讨如何在Spring Cloud中使用Ribbon实现负载均衡。 首先,我们要理解...

    73-Spring Cloud客户端负载均衡Ribbon笔记1

    Spring Cloud中的Ribbon是实现客户端负载均衡的关键组件。在传统的服务端负载均衡中,像Nginx这样的代理服务器会接收请求并根据预设的算法(如轮询、权重轮询、随机等)转发到后端服务。而在客户端负载均衡模式下,...

    客户端负载均衡器Ribbon(实验代码)

    客户端负载均衡器Ribbon是Netflix开发的一个开源组件,主要用于实现微服务架构中的客户端负载均衡功能。在本实验代码中,我们将深入理解Ribbon的工作原理及其在实际应用中的配置与使用。 Ribbon是一个轻量级的库,...

    02Spring Cloud Ribbon:负载均衡的服务调用1

    在Spring Cloud生态系统中,Spring Cloud Ribbon是一个至关重要的组件,它主要负责实现客户端的负载...通过对`RestTemplate`方法的灵活运用,我们可以方便地处理HTTP请求,同时享受到Ribbon带来的客户端负载均衡优势。

    SpringCloud——客户端负载平衡器(Ribbon)

    Ribbon是一个客户端负载均衡器,它可以很好地控制HTTP和TCP客户端的行为。

    02_SpringCloud客户端负载均衡Ribbon.md

    SpringCloud的复杂均衡 属于客户端;nginx辅助均衡属于服务器端 ,restTemplate 进行RPC调用.对外使用 rest http方式。DiscoveryClient 可以自己实现一个负载均衡的算法(使用请求总数 % 服务列表个数).算法文件跟新...

    spring_cloud_gateway负载均衡,动态路由

    spring cloud gateway的负载均衡和动态路由的实现 demo_01,demo_02,demo_03 这三个服务相当于是集群的微服务 gateway这个服务是 springcloude gateway + ribbon 做的负载均衡 gateway_01 这个服务 是动态路由的...

    SpringCloud 服务负载均衡和调用 Ribbon、OpenFeign的方法

    总的来说,SpringCloud 通过 Ribbon 和 OpenFeign 提供了灵活的客户端负载均衡解决方案,可以根据不同的场景和需求选择合适的工具和策略。无论是自定义负载均衡规则还是利用默认策略,都能帮助开发者有效地管理和...

    02 微服务负载均衡器Ribbon&LoadBalancer实战.pdf

    本教程将详细讲解两种常用的客户端负载均衡器——Ribbon和LoadBalancer,以及它们在Spring Cloud Alibaba框架中的实践。 首先,负载均衡的基本概念是将工作负载分布到多个操作单元,以协同处理任务。在微服务场景下...

    Spring Cloud Ribbon实现客户端负载均衡的示例

    cloud-sample-tutorial-consumer`,并在`pom.xml`中添加对`spring-cloud-starter-eureka`和`spring-cloud-starter-ribbon`的依赖,这两个依赖分别用于Eureka服务发现和Ribbon客户端负载均衡。 在`application....

    springCloud路由网管负载均衡及拦截过滤的简单实现.

    Spring Cloud集成Ribbon或Netflix Eureka实现了客户端负载均衡。当`uri`以`lb://`开头时,Spring Cloud Gateway会使用Ribbon进行负载均衡,自动轮询调用服务实例。Ribbon会根据配置的策略(如轮询、随机等)选择一...

    springcloud-ribbon负载均衡demo

    其中,Spring Cloud Ribbon是一个客户端负载均衡器,它可以与Spring Cloud Netflix Eureka结合使用,实现服务间的智能路由和负载均衡。在这个"springcloud-ribbon负载均衡demo"中,我们将探讨Ribbon的基本概念、工作...

    SpringCloud.rar

    Spring Cloud Netflix:核心组件,可以对多个Netflix OSS开源套件进行整合,包括以下几个组件: Eureka:服务治理组件,包含服务注册与发现 Hystrix:容错管理组件,实现了熔断器 Ribbon:客户端负载均衡的服务调用...

    基于SpringCloud的Idea集成Ribbon客户端负载均衡设计源码

    该项目是一款基于SpringCloud框架的Idea集成Ribbon客户端负载均衡设计源码,总文件量达86个,涵盖33个Java源文件、12个XML配置文件、6个HTML文件、5个Git忽略文件、4个数据库文件、4个JAR包、4个属性文件、4个YAML...

    SpringCloud 70道面试题和答案.docx

    * Spring Cloud Ribbon:客户端负载均衡 * Spring Cloud Feign:声明性的 Web 服务客户端 * Spring Cloud Hystrix:断路器 * Spring Cloud Config:分布式统一配置管理 Spring Cloud 和 SpringBoot 的关系 * ...

    SpringCloud-Ribbon负载均衡服务调用及手写Ribbon算法代码

    在Spring Cloud生态中,Ribbon是一个重要的客户端负载均衡器,它与Netflix的Eureka服务注册中心结合,使得微服务间的调用能够实现智能路由和负载均衡。本篇将深入探讨Spring Cloud Ribbon的工作原理、功能特性以及...

    springCloud路由网管负载均衡的简单实现

    Ribbon是客户端负载均衡器,而Eureka是服务发现组件。在Spring Cloud中,通常使用Eureka来注册和发现服务,Ribbon则会自动选择Eureka中的一个服务实例进行请求。引入`spring-cloud-starter-netflix-eureka-client`和...

Global site tag (gtag.js) - Google Analytics