Round robin

本篇文章先讲述轮询调度算法 (Round-Robin)及其在此基础上改进型的权重轮询算法 (Weighted Round-Robin)。

  轮询调度算法(Round-Robin Scheduling)

  轮询调度算法的原理是每一次把来自用户的请求轮流分配给内部中的服务器,从1开始,直到N(内部服务器个数),然后重新开始循环。

  算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。

  轮询调度算法流程

  假设有一组服务器N台,S = {S1, S2, …, Sn},一个指示变量i表示上一次选择的服务器ID。变量i被初始化为N-1。其算法如下:

j = i;

do 

{

j = (j + 1) mod n;

i = j;

return Si;

} while (j != i);

return NULL;

  这种算法的逻辑实现如图1所示:

  轮询调度实现逻辑图

                                             图1 轮询调度实现逻辑图示

  轮询调度算法假设所有服务器的处理性能都相同,不关心每台服务器的当前连接数和响应速度。当请求服务间隔时间变化比较大时,轮询调度算法容易导致服务器间的负载不平衡。

  所以此种均衡算法适合于服务器组中的所有服务器都有相同的软硬件配置并且平均服务请求相对均衡的情况。


2

This recipe implements a round-robin generator, a generator that cycles through N iterables until all of them are exhausted:

>>> list(roundrobin('abc', [], range(4),  (True,False)))
['a', 0, True, 'b', 1, False, 'c', 2, 3]
Python, 11 lines  
Copy to clipboard
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from itertools import cycle, islice

def roundrobin(*iterables):
    pending = len(iterables)
    nexts = cycle(iter(iterable).next for iterable in iterables)
    while pending:
        try:
            for next in nexts: yield next()
        except StopIteration:
            pending -= 1
            nexts = cycle(islice(nexts, pending))

Round-robin is one of the simplest scheduling algorithms, where the scheduler assigns resources (e.g. processes) to each consumer in equal portions and in order. There is already a roundrobin recipe (http://docs.python.org/lib/deque-recipes.html) that uses a deque for popping iterables from the one end and pushing them to the other as long as they are not exhausted. This recipe uses itertools.cycle instead and is more efficient for long streams as it avoids all the pushing and popping.

nginx负载均衡策略分析[一](round_robin模块概要)

2013年10月03日  ⁄ 综合 ⁄ 共 2246字 ⁄ 字号  小 中 大  ⁄ 评论关闭
id="iframeu1788635_0" src="http://pos.baidu.com/acom?rdid=1788635&dc=2&di=u1788635&dri=0&dis=0&dai=2&ps=337x846&dcb=BAIDU_UNION_define&dtm=BAIDU_DUP_SETJSONADSLOT&dvi=0.0&dci=-1&dpt=none&tsr=0&tpr=1457151442277&ti=nginx%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AD%96%E7%95%A5%E5%88%86%E6%9E%90%5B%E4%B8%80%5D%EF%BC%88round_robin%E6%A8%A1%E5%9D%97%E6%A6%82%E8%A6%81%EF%BC%89%20%7C%20%E5%AD%A6%E6%AD%A5%E5%9B%AD&ari=1&dbv=0&drs=1&pcs=1240x672&pss=1240x672&cfv=19&cpl=11&chi=1&cce=true&cec=UTF-8&tlm=1457122642&ltu=http%3A%2F%2Fcncc.bingj.com%2Fcache.aspx%3Fq%3Dround%2Brobin%25e7%25ad%2596%25e7%2595%25a5%26d%3D4585055220334717%26mkt%3Dzh-CN%26setlang%3Den-US%26w%3DqembYKIegLMlCoKd5h7_dAUsu0Oo939n&ltr=http%3A%2F%2Fcn.bing.com%2Fsearch%3Fq%3Dround%2Brobin%25e7%25ad%2596%25e7%2595%25a5%26qs%3DHS%26pq%3Dround%26sc%3D8-5%26sp%3D1%26cvid%3DA05B43D91B6848788D08489ABC593B99%26FORM%3DQBRE&ecd=1&psr=1280x800&par=1280x734&pis=-1x-1&ccd=24&cja=true&cmi=51&col=en-us&cdo=-1&tcn=1457151442&qn=bfbb70a203148b35&tt=1457151442263.44.276.276" width="336" height="280" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="margin: 0px; padding: 0px; border-width: 0px; background-color: transparent; vertical-align: bottom;">

1.基本情况

模块名:round_robin

文件位置:ngx_http_upstream_round_robin.c

运行阶段:content_phase

RR策略做为默认策略

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
例如:
 upstream tomcats {
 server 10.1.1.107:88  max_fails=3 fail_timeout=3s weight=9;
 server 10.1.1.132:80  max_fails=3 fail_timeout=3s weight=9;
 }

上游调用:Ngx_http_upstream.c Ngx_http_upstream_ip_hash_module.c
功能:nginx在用作反向代理服务器时,对于后端的服务器可以采用两种分流策略:加权分流和ip hash。本模块主要完成加权分流功能。对于权重较高的机器,被选中的概率大,对于权重相同的机器,则采用轮询方式。
亮点:
1、在数据结构中设置了single字段,判断是否是只有一台后端服务器。如果是,则无需走分流策略模块,直接返回即可;
2、同时设置了失败次数和失败时间的上限。如果达到了失败次数上限,在一段时间内该server不参与分流。
3、backup服务器的使用。只有在现有server都无效时,才会请求backup服务器

2.关键数据结构

typedef struct {
//基本socket信息
    struct sockaddr                *sockaddr;
    socklen_t                       socklen;
    ngx_str_t                       name;
//当前权重值和设定权重值
    ngx_int_t                       current_weight;
    ngx_int_t                       weight;
//失败次数和访问时间
    ngx_uint_t                      fails;
    time_t                          accessed;
//失败次数上限值和失败时间阈值
    ngx_uint_t                      max_fails;
    time_t                          fail_timeout;
//服务器是否参与<span style="background-color: rgb(255, 204, 153);">策略</span>
    ngx_uint_t                      down;          /* unsigned  down:1; */
//ssl相关
#if (NGX_HTTP_SSL)
    ngx_ssl_session_t              *ssl_session;   /* local to a process */
#endif
} ngx_http_upstream_rr_peer_t; //后台服务器的具体信息

//<span style="background-color: rgb(255, 255, 102);">round robin</span>后端服务器信息
typedef struct ngx_http_upstream_rr_peers_s  ngx_http_upstream_rr_peers_t;

struct ngx_http_upstream_rr_peers_s {
    ngx_uint_t                      single;             //该群是否只有一台服务器
    ngx_uint_t                      number;             //该群后端服务器数量
    ngx_uint_t                      last_cached;	

 /* ngx_mutex_t                    *mutex; */
    ngx_connection_t              **cached;

    ngx_str_t                      *name;

    ngx_http_upstream_rr_peers_t   *next;               //下个upstream节点,即下一个服务器群的指针,next 一般指向backupserver(备份服务器群)

    ngx_http_upstream_rr_peer_t     peer[1];            //服务器群中的第一个服务器,如果还有其它的服务器,则会连续申请其它的peer
};


typedef struct {
    ngx_http_upstream_rr_peers_t   *peers;              //所有服务器群的指针
    ngx_uint_t                      current;            //当前服务器
    uintptr_t                      *tried;              //服务器位图指针,用于记录服务器当前的状态
    uintptr_t                       data;               //tried位图实际存储位置
} ngx_http_upstream_rr_peer_data_t;

3.函数功能说明

主要的函数列表如下

ngx_int_t   ngx_http_upstream_init_<span style="background-color: rgb(255, 255, 102);">round</span>_<span style="background-color: rgb(102, 255, 255);">robin</span>(ngx_conf_t *cf,    ngx_http_upstream_srv_conf_t *us)

ngx_int_t   ngx_http_upstream_init_<span style="background-color: rgb(255, 255, 102);">round</span>_<span style="background-color: rgb(102, 255, 255);">robin</span>_peer(ngx_http_request_t *r,    ngx_http_upstream_srv_conf_t *us)

ngx_int_t   ngx_http_upstream_create_<span style="background-color: rgb(255, 255, 102);">round</span>_<span style="background-color: rgb(102, 255, 255);">robin</span>_peer(ngx_http_request_t *r,    ngx_http_upstream_resolved_t *ur)

ngx_int_t   ngx_http_upstream_get_<span style="background-color: rgb(255, 255, 102);">round</span>_<span style="background-color: rgb(102, 255, 255);">robin</span>_peer(ngx_peer_connection_t *pc, void *data)

static ngx_http_upstream_rr_peer_t *   ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp)

void   ngx_http_upstream_free_<span style="background-color: rgb(255, 255, 102);">round</span>_<span style="background-color: rgb(102, 255, 255);">robin</span>_peer(ngx_peer_connection_t *pc, void *data,    ngx_uint_t state)

参考资料:

nginx round_robin模块剖析

开源中国ngx_http_upstream_round_robin.c

  权重轮询调度算法(Weighted Round-Robin Scheduling)

  上面所讲的轮询调度算法并没有考虑每台服务器的处理能力,在实际情况中,可能并不是这种情况。由于每台服务器的配置、安装的业务应用等不同,其处理能力会不一样。所以,我们根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能够接受相应权值数的服务请求。

  权重轮询调度算法流程

  假设有一组服务器S = {S0, S1, …, Sn-1},W(Si)表示服务器Si的权值,一个指示变量i表示上一次选择的服务器,指示变量cw表示当前调度的权值,max(S)表示集合S中所有服务器的最大权值,gcd(S)表示集合S中所有服务器权值的最大公约数。变量i初始化为-1,cw初始化为零。其算法如下:

while (true) {

  i = (i + 1) mod n;

  if (i == 0) {

     cw = cw - gcd(S); 

     if (cw <= 0) {

       cw = max(S);

       if (cw == 0)

         return NULL;

     }

  } 

  if (W(Si) >= cw) 

    return Si;

}

  这种算法的逻辑实现如图2所示,图中我们假定四台服务器的处理能力为3:1:1:1。

  权重轮询调度实现逻辑图

                                        图2 权重轮询调度实现逻辑图示

  由于权重轮询调度算法考虑到了不同服务器的处理能力,所以这种均衡算法能确保高性能的服务器得到更多的使用率,避免低性能的服务器负载过重。所以,在实际应用中比较常见。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值