`

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
分享到:
评论

相关推荐

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

    springcloud入门代码基于Spring Cloud实现的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 这个服务 是动态路由的...

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

    Ribbon负载均衡机制Ribbon实现了客户端的负载均衡,调用服务使用的是用@LoadBalanced的RestTemplate:通过对其跟踪,定位到Load

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

    本篇文章主要介绍了Spring Cloud Ribbon实现客户端负载均衡的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

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

    本篇文章主要介绍了Spring Cloud Ribbon实现客户端负载均衡的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    SpringCloud.rar

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

    SpringCloud-Finchley.SR1-Ribbon客户端负载均衡demo

    良心demo,可以再学习的过程中参考一下,官网的教程是真的需要好好琢磨的,这个可以作为辅助参考,demo采用的版本均为最新版本:springcloud2.0-Finchley.SR1版本,大神提醒我一句学习springcloud不要想的太复杂,...

    SpringCloud微服务-客户端负载Ribbon

    什么是客户端负载我们在做服务...那么客户端负载均衡和服务端负载均衡有什么区别呢?如果我们把上图架构改造成下图所示:我们在客户端后面加了一个服务器清单(里面维护着后端可以用的服务),客户端访问后端服务的时

    springCloud介绍与搭建流程说明.zip

    Ribbon:客户端负载均衡的服务调用组件。 Feign:基于Ribbon和Hystrix的声明式服务调用组件。 Zuul:边缘服务工具,是提供动态路由,监控,弹性,安全等的边缘服务。 Spring Cloud Security:安全工具包,提供Zuul...

    SpringCloud客户端的负载均衡Ribbon的实现

    微服务架构,不可避免的存在单个微服务有多个实例,这篇文章主要介绍了SpringCloud客户端的负载均衡Ribbon的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    积分管理系统java源码-SpringCloud-Learning:SpringCloud-Learning

    Ribbon:客户端负载均衡 Feign:基于Ribbon和Hystrix的声明式服务调用组件 Zuul:网关组件 Spring Cloud Bus:事件、消息总线,用于传播集群中的状态变化或事件 Spring Cloud Consul:服务发现与配置管理工具 Spring...

    spring cloud 之 客户端负载均衡Ribbon深入理解

    下面小编就为大家带来一篇spring cloud 之 客户端负载均衡Ribbon深入理解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    SpringCloud+Eureka+Ribbon实践代码Demo

    SpringCloud+Eureka+Ribbon实践代码Demo,SpringCloud是基于SpringBoot。Eureka:注册中心、服务发现。Ribbon:客户端负载均衡,负责对eureka中的服务进行调用。

    Spring Cloud Alibaba:阿里巴巴中间件应用程序开发的一站式解决方案-开源

    Spring Cloud Alibaba为分布式应用程序开发提供了一站式解决方案。 它包含开发分布式应用程序所需的所有组件... 支持通过Spring Cloud Netflix的客户端负载均衡器Ribbon。 分布式配置:使用阿里巴巴Nacos作为数据存储。

    SpringCloud(三)Ribbon负载均衡原理与Feign客户端的使用

    它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有...

    springcloud全家桶(eureka+ribbon+feign+hystrix+turbine)

    ribbon,客户端负载均衡 feign, hystrix,熔断 turbine Spring Cloud Starters 同一个服务中的多数据库支持(AOP) 全链路traceId追踪 velocity 前端模板 mybatis, pageHelper (分页), druid (连接池) redis(序列...

    基于Ribbon的微服务通讯及负载均衡的实现_迟殿委.pdf

    文章首先介绍了微服务架构带来的好处及在面对大量请求访问时对微服务实例造成的负担,引出了基于SpringCloud Ribbon的客户端负载均衡技术。一方面提高了整个软件系统的高可靠性,对软件系统核心微服务持续运行提供保障...

Global site tag (gtag.js) - Google Analytics