Spring Cloud Ribbon 全解 (2) - 基本组件简介

简介: Spring Cloud Ribbon 全解 (2) - 基本组件简介

本文基于SpringCloud-Dalston.SR5

对于一个负载均衡器,就是以用户请求为输入,请求响应为输出的代理模块。


image.png


这个模块基本上就是包括一个服务实例列表,根据请求还有负载均衡规则选择一个合适的实例来执行请求并返回响应。


image.png


这个服务实例列表,一般包含每个实例基本信息,然后还有,这个实例相关的负载均衡统计信息(例如请求失败多少次,有多少正在处理的请求等等,用于实例过滤和负载均衡规则选择Server)


image.png


再深入些,我们需要获取和更新这个服务列表(一般是从注册中心或者配置中获取),有时候我们还要根据一些规则过滤掉某些服务实例不参与负载均衡,同时,我们可能还需要与每个服务实例维持心跳来保证服务实例是可用的(虽然注册中心中也可以体现,但是心跳能更准确迅速地排除故障实例,减少响应时间)。


image.png


接下来,我们来看一下Ribbon的主要元素(先不仔细看实现),和上面的负载均衡器组成对应起来

  1. 所有Ribbon负载均衡器需要实现的接口IClient
  2. 服务实例列表维护机制实现的接口ServerList
  3. 负载均衡数据记录LoadBalancerStats
  4. 负责选取Server的接口ILoadBalancer
  5. 负载均衡选取规则实现的接口IRule
  6. 检查实例是否存活实现的接口IPing
  7. 服务实例列表更新机制实现的接口ServerListUpdater
  8. 服务实例列表过滤机制ServerListFilter


1. 所有Ribbon负载均衡器需要实现的接口IClient


IClient.java

public interface IClient<S extends ClientRequest, T extends IResponse> {
  /**
   * Execute the request and return the response. It is expected that there is no retry and all exceptions are thrown directly.
   */
    public T execute(S request, IClientConfig requestConfig) throws Exception; 
}

负载均衡器执行一个ClientRequest,并返回一个IResponse。注意,execute方法直接抛出所有异常,并且重试逻辑并不在实现execute的方法里面。而且,可以看出execute方法并没有指定通信协议,在SpringCloud环境下,通信协议是HTTP或者HTTPS

基本上Ribbon中可以被配置的元素,都是用IClientConfig这个类作为配置类。这里不详细分析源码,如果用到了其中的配置,我们会仔细分析其中的配置以及原理。默认实现是DefaultClientConfigImpl,其中每个配置都是基于Spring家族的Archaius实现的动态配置


ClientRequest.java

public class ClientRequest implements Cloneable {
    protected URI uri;
    protected Object loadBalancerKey = null;
    protected Boolean isRetriable = null;
    protected IClientConfig overrideConfig;
    //构造器和getter、setter省略
}

其中uri是请求需要发送到的uri地址;loadBalancerKey用于选择服务实例,即用作后面我们会提到的这个方法ILoadBalancer.chooseServer(Object key)的参数;isRetriable代表这个请求是否可以被重试;overrideConfig是请求相关的一些配置。


IResponse.java

public interface IResponse extends Closeable
{
   /**
    * Returns the raw entity if available from the response 
    */
   public Object getPayload() throws ClientException;
   /**
    * A "peek" kinda API. Use to check if your service returned a response with an Entity
    */
   public boolean hasPayload();
   /**
    * @return true if the response is deemed success, for example, 200 response code for http protocol.
    */
   public boolean isSuccess();
   /**
    * Return the Request URI that generated this response
    */
   public URI getRequestedURI();
   /**
    * 
    * @return Headers if any in the response.
    */
   public Map<String, ?> getHeaders();   
}

其实这个的实现类也会包含执行器逻辑,例如重试和异常处理等等


2. 服务实例列表维护机制实现的接口ServerList


public interface ServerList<T extends Server> {
    public List<T> getInitialListOfServers();
    public List<T> getUpdatedListOfServers();   
}

这个接口定义了如何更新并维护实例列表,getInitialListOfServers定义如何初次获取服务实例列表,getUpdatedListOfServers如何获取服务实例列表的更新


3. 负载均衡数据记录LoadBalancerStats


public class LoadBalancerStats {
    String name;
    //zone相关信息,默认用不到
    volatile Map<String, ZoneStats> zoneStatsMap = new ConcurrentHashMap<String, ZoneStats>();
    volatile Map<String, List<? extends Server>> upServerListZoneMap = new ConcurrentHashMap<String, List<? extends Server>>();
    //动态配置,连接失败上限
    private volatile DynamicIntProperty connectionFailureThreshold;
    //动态配置,熔断时间因子
    private volatile DynamicIntProperty circuitTrippedTimeoutFactor;
    //动态配置,最大熔断时间
    private volatile DynamicIntProperty maxCircuitTrippedTimeout;
    //动态配置,每个Server负载均衡统计数据过期时间配置
    private static final DynamicIntProperty SERVERSTATS_EXPIRE_MINUTES = 
        DynamicPropertyFactory.getInstance().getIntProperty("niws.loadbalancer.serverStats.expire.minutes", 30);
    //每个Server的负载均衡统计数据
    private final LoadingCache<Server, ServerStats> serverStatsCache = 
        CacheBuilder.newBuilder()
            .expireAfterAccess(SERVERSTATS_EXPIRE_MINUTES.get(), TimeUnit.MINUTES)
            .removalListener(new RemovalListener<Server, ServerStats>() {
                @Override
                public void onRemoval(RemovalNotification<Server, ServerStats> notification) {
                    notification.getValue().close();
                }
            })
            .build(
                new CacheLoader<Server, ServerStats>() {
                    public ServerStats load(Server server) {
                        return createServerStats(server);
                    }
                });
}


4. 负责选取Server的接口ILoadBalancer


ILoadBalancer.java

public interface ILoadBalancer {
  public void addServers(List<Server> newServers);
  public Server chooseServer(Object key);
  public void markServerDown(Server server);
  public List<Server> getServerList(boolean availableOnly);
}

addServers用来添加可以用来执行请求的Server;chooseServer根据传入的参数,结合某些负载均衡规则,返回某个Server;markServerDown用来标记某个Server为DOWN状态,这样一般下次调用chooseServer就不会选取这个Server;getServerList用来获取所有Server列表


Server.java

public class Server {
    public static final String UNKNOWN_ZONE = "UNKNOWN";
    String host;
    int port = 80;
    String id;
    boolean isAliveFlag;
    private String zone = UNKNOWN_ZONE;
    private volatile boolean readyToServe = true;
    //getter和setter省略
}

host和port代表实例提供服务的的ip和端口。id唯一标识这个Server,isAliveFlag标识这个Server是否还活着;zone代表所在区域


5. 负载均衡选取规则实现的接口IRule


public interface IRule{
    public Server choose(Object key);
    public void setLoadBalancer(ILoadBalancer lb);
    public ILoadBalancer getLoadBalancer();    
}

choose方法是根据key选择Server;setLoadBalancer和getLoadBalancer是设置相应的ILoadBalancer


6. 检查实例是否存活实现的接口IPing


public interface IPing {
    public boolean isAlive(Server server);
}

isAlive方法判断Server是否存活


7. 服务实例列表更新机制实现的接口ServerListUpdater


public interface ServerListUpdater {
    //定义了更新服务实例列表的操作doUpdate
    public interface UpdateAction {
        void doUpdate();
    }
    //开始调度更新服务实例列表,可以看到这里以UpdateAction为传参
    void start(UpdateAction updateAction);
    //停止更新服务实例列表
    void stop();
    //上次服务实例列表更新时间
    String getLastUpdate();
    //上次服务实例列表更新时间间隔
    long getDurationSinceLastUpdateMs();
    //已经错过几轮更新
    int getNumberMissedCycles();
    //使用线程池大小
    int getCoreThreads();
}

这个接口定义了如何更新服务实例列表


8. 服务实例列表过滤机制ServerListFilter


public interface ServerListFilter<T extends Server> {
    public List<T> getFilteredListOfServers(List<T> servers);
}

这个接口定义了如何过滤出需要的服务实例列表

相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
18小时前
|
监控 安全 Java
Spring cloud原理详解
Spring cloud原理详解
7 0
|
5天前
|
消息中间件 负载均衡 Java
【Spring Cloud 初探幽】
【Spring Cloud 初探幽】
13 1
|
6天前
|
Java 开发者 微服务
Spring Cloud原理详解
【5月更文挑战第4天】Spring Cloud是Spring生态系统中的微服务框架,包含配置管理、服务发现、断路器、API网关等工具,简化分布式系统开发。核心组件如Eureka(服务发现)、Config Server(配置中心)、Ribbon(负载均衡)、Hystrix(断路器)、Zuul(API网关)等。本文讨论了Spring Cloud的基本概念、核心组件、常见问题及解决策略,并提供代码示例,帮助开发者更好地理解和实践微服务架构。此外,还涵盖了服务通信方式、安全性、性能优化、自动化部署、服务网格和无服务器架构的融合等话题,揭示了微服务架构的未来趋势。
31 6
|
10天前
|
JSON Java Apache
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
|
11天前
|
负载均衡 Java 开发者
Spring Cloud:一文读懂其原理与架构
Spring Cloud 是一套微服务解决方案,它整合了Netflix公司的多个开源框架,简化了分布式系统开发。Spring Cloud 提供了服务注册与发现、配置中心、消息总线、负载均衡、熔断机制等工具,让开发者可以快速地构建一些常见的微服务架构。
|
12天前
|
消息中间件 Java RocketMQ
Spring Cloud RocketMQ:构建可靠消息驱动的微服务架构
【4月更文挑战第28天】消息队列在微服务架构中扮演着至关重要的角色,能够实现服务之间的解耦、异步通信以及数据分发。Spring Cloud RocketMQ作为Apache RocketMQ的Spring Cloud集成,为微服务架构提供了可靠的消息传输机制。
27 1
|
13天前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo: 微服务通信的高效解决方案
【4月更文挑战第28天】在微服务架构的发展中,服务间的高效通信至关重要。Spring Cloud Dubbo 提供了一种基于 RPC 的通信方式,使得服务间的调用就像本地方法调用一样简单。本篇博客将探讨 Spring Cloud Dubbo 的核心概念,并通过具体实例展示其在项目中的实战应用。
15 2
|
13天前
|
监控 Java Sentinel
Spring Cloud Sentinel:概念与实战应用
【4月更文挑战第28天】在分布式微服务架构中,确保系统的稳定性和可靠性至关重要。Spring Cloud Sentinel 为微服务提供流量控制、熔断降级和系统负载保护,有效预防服务雪崩。本篇博客深入探讨 Spring Cloud Sentinel 的核心概念,并通过实际案例展示其在项目中的应用。
23 0
|
13天前
|
Cloud Native Java Nacos
Spring Cloud Nacos:概念与实战应用
【4月更文挑战第28天】Spring Cloud Nacos 是一个基于 Spring Cloud 构建的服务发现和配置管理工具,适用于微服务架构。Nacos 提供了动态服务发现、服务配置、服务元数据及流量管理等功能,帮助开发者构建云原生应用。
20 0