客户端负载均衡组件
Client Side Load Balancer : Ribbon
官网:链接
Ribbon 作为负载均衡,在客户端实现,服务段可以启动两个端口不同但 servername一样的服务
Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出 Load Balancer后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。简单地说,Ribbon是一个客户端负载均衡器。
Ribbon工作时分为两步:第一步先选择 Eureka Server, 它优先选择在同一个Zone且负载较少的Server;第二步再根据用户指定的策略,在从Server取到的服务注册列表中选择一个地址。其中Ribbon提供了多种策略,例如轮询、随机、根据响应时间加权等。
ribbon工作流程:
Ribbon 生产使用
在生产环境,Ribbon 与 eureka,feign 一起使用
作为一个微服务应用,我们每个请求都会带服务名访问对应的应用,比如请求一个如下的 url :
http://172.16.56.211:8883/E6-MS-TMS-BUSI-WEB/equip/findEquipTypeList,
http://172.16.56.211:8883/ 网关程序;
E6-MS-TMS-BUSI-WEB 微服务名,也是每个应用注册到 Eureka 的服务名称;
/equip/findEquipTypeList 具体的接口 Controller 地址
当一个请求访问网关程序, 验权通过后,请求会到 ribbon, ribbon 维护了一个当前可用的服务列表。(通过定时任务)。ribbon 通过负载均衡策略从当前可用服务列表中,选择某个服务机器,发起调用请求。
微服务服务之间存在相互调用,集成ribbon 后,每个服务内维护有其他服务的信息。在开发调试过程中,我们经常需要指定机器,发起调用。此时我们使用了配置文件,配置文件中配置服务名和机器的 ip 端口映射。在 ribbon 发起请求时,重写 RandomRule, 请求来后,会首先从配置文件中找对应的服务路由配置,如果没有再使用 ribbon 默认的负载均衡策略。这样就解决了微服务调试的问题。
源码
接口定义了负载均衡器上的操作行为,维护服务list,定义了选择服务的方法;
package com.netflix.loadbalancer;
import java.util.List;
/**
* Interface that defines the operations for a software loadbalancer. A typical
* loadbalancer minimally need a set of servers to loadbalance for, a method to
* mark a particular server to be out of rotation and a call that will choose a
* server from the existing list of server.
*
* @author stonse
*
*/
public interface ILoadBalancer {
/**
* Initial list of servers.
* This API also serves to add additional ones at a later time
* The same logical server (host:port) could essentially be added multiple times
* (helpful in cases where you want to give more "weightage" perhaps ..)
*
* @param newServers new servers to add
*/
public void addServers(List<Server> newServers);
/**
* Choose a server from load balancer.
*
* @param key An object that the load balancer may use to determine which server to return. null if
* the load balancer does not use this parameter.
* @return server chosen
*/
public Server chooseServer(Object key);
/**
* To be called by the clients of the load balancer to notify that a Server is down
* else, the LB will think its still Alive until the next Ping cycle - potentially
* (assuming that the LB Impl does a ping)
*
* @param server Server to mark as down
*/
public void markServerDown(Server server);
/**
* @deprecated 2016-01-20 This method is deprecated in favor of the
* cleaner {@link #getReachableServers} (equivalent to availableOnly=true)
* and {@link #getAllServers} API (equivalent to availableOnly=false).
*
* Get the current list of servers.
*
* @param availableOnly if true, only live and available servers should be returned
*/
@Deprecated
public List<Server> getServerList(boolean availableOnly);
/**
* @return Only the servers that are up and reachable.
*/
public List<Server> getReachableServers();
/**
* @return All known servers, both reachable and unreachable.
*/
public List<Server> getAllServers();
}
类图
baseLoadBalancer 实现了ILoadbalancer 基础接口,维护了一个 serverList ,实现了默认的chooseServer 方法。默认负载均衡策略是轮询 RoundRobinRule;
负载均衡的策略接口
public interface IRule{
/*
* choose one alive server from lb.allServers or
* lb.upServers according to key
*
* @return choosen Server object. NULL is returned if none
* server is available
*/
public Server choose(Object key);
public void setLoadBalancer(ILoadBalancer lb);
public ILoadBalancer getLoadBalancer();
}
具体策略说明:
策略名 | 策略描述 | 实现说明 |
---|---|---|
RandomRule | 随机选择一个 server | 在 index 上随机,选择 index 对应位置的 Server |
RoundRobinRule | 轮询选择 server | 轮询 index,选择 index 对应位置的 server |
ZoneAvoidanceRule | 复合判断 server 所在区域的性能和 server 的可用性选择 server | 使用 ZoneAvoidancePredicate 和 AvailabilityPredicate 来判断是否选择某个 server。ZoneAvoidancePredicate 判断判定一个 zone 的运行性能是否可用,剔除不可用的 zone(的所有 server);AvailabilityPredicate 用于过滤掉连接数过多的 server。 |
BestAvailableRule | 选择一个最小并发请求的 server | 逐个考察 server,如果 server 被 tripped 了则忽略,在选择其中activeRequestsCount 最小的 server |
AvailabilityFilteringRule | 过滤掉那些因为一直连接失败的被标记为 circuit tripped 的后端 server,并过滤掉那些高并发的的后端 server(activeConnections 超过配置的阈值) | 使用一个 AvailabilityPredicate 来包含过滤 server 的逻辑,其实就就是检查 status 里记录的各个 server 的运行状态 |
WeightedResponseTimeRule | 根据 server 的响应时间分配一个 weight,响应时间越长,weight 越小,被选中的可能性越低 | 一个后台线程定期的从 status 里面读取评价响应时间,为每个 server 计算一个 weight。weight 的计算也比较简单,responseTime 减去每个 server 自己平均的 responseTime 是 server 的权重。当刚开始运行,没有形成 status 时,使用 RoundRobinRule 策略选择 server。 |
RetryRule | 对选定的负载均衡策略机上重试机制 | 在一个配置时间段内当选择 server 不成功,则一直尝试使用 subRule 的方式选择一个可用的 server |
经典的负载均衡规则可以整理如下:
- 轮询(Round Robin) or 加权轮询(Weighted Round Robin)
- 随机(Random) or 加权随机(Weighted Random)
- 源地址哈希(Hash) or 一致性哈希(ConsistentHash)
- 最少连接数(Least Connections)
- 最小响应时间(ResponseTime)