Wishlist 0 ¥0.00

关于负载均衡的一切:总结与思考

关于负载均衡的一切:总结与思考

古人云,不患寡而患不均。

在计算机的世界,这就是大家耳熟能详的负载均衡(load balancing),所谓负载均衡,就是说如果一组计算机节点(或者一组进程)提供相同的(同质的)服务,那么对服务的请求就应该均匀的分摊到这些节点上。负载均衡的前提一定是“provide a single Internet service from multiple servers”, 这些提供服务的节点被称之为server farm、server pool或者backend servers。

这里的服务是广义的,可以是简单的计算,也可能是数据的读取或者存储。负载均衡也不是新事物,这种思想在多核CPU时代就有了,只不过在分布式系统中,负载均衡更是无处不在,这是分布式系统的天然特性决定的,分布式就是利用大量计算机节点完成单个计算机无法完成的计算、存储服务,既然有大量计算机节点,那么均衡的调度就非常重要。

负载均衡的意义在于,让所有节点以最小的代价、最好的状态对外提供服务,这样系统吞吐量最大,性能更高,对于用户而言请求的时间也更小。而且,负载均衡增强了系统的可靠性,最大化降低了单个节点过载、甚至crash的概率。不难想象,如果一个系统绝大部分请求都落在同一个节点上,那么这些请求响应时间都很慢,而且万一节点降级或者崩溃,那么所有请求又会转移到下一个节点,造成雪崩。

事实上,网上有很多文章介绍负载均衡的算法,大多都是大同小异。本文更多的是自己对这些算法的总结与思考。

一分钟了解负载均衡的一切

本章节的标题和内容都来自一分钟了解负载均衡的一切这一篇文章。当然,原文的标题是夸张了点,不过文中列出了在一个大型web网站中各层是如何用到负载均衡的,一目了然。

常见互联网分布式架构如上,分为客户端层、反向代理nginx层、站点层、服务层、数据层。可以看到,每一个下游都有多个上游调用,只需要做到,每一个上游都均匀访问每一个下游,就能实现“将请求/数据【均匀】分摊到多个操作单元上执行”。

(1)【客户端层】到【反向代理层】的负载均衡,是通过“DNS轮询”实现的
(2)【反向代理层】到【站点层】的负载均衡,是通过“nginx”实现的
(3)【站点层】到【服务层】的负载均衡,是通过“服务连接池”实现的
(4)【数据层】的负载均衡,要考虑“数据的均衡”与“请求的均衡”两个点,常见的方式有“按照范围水平切分”与“hash水平切分”。

数据层的负载均衡,在我之前的《带着问题学习分布式系统之数据分片》中有详细介绍。

算法衡量

在我看来,当我们提到一个负载均衡算法,或者具体的应用场景时,应该考虑以下问题

第一,是否意识到不同节点的服务能力是不一样的,比如CPU、内存、网络、地理位置

第二,是否意识到节点的服务能力是动态变化的,高配的机器也有可能由于一些突发原因导致处理速度变得很慢

第三,是否考虑将同一个客户端,或者说同样的请求分发到同一个处理节点,这对于“有状态”的服务非常重要,比如session,比如分布式存储

第四,谁来负责负载均衡,即谁充当负载均衡器(load balancer),balancer本身是否会成为瓶颈

下面会结合具体的算法来考虑这些问题

负载均衡算法

轮询算法(round-robin)

思想很简单,就是提供同质服务的节点逐个对外提供服务,这样能做到绝对的均衡。Python示例代码如下

SERVER_LIST = [

    '10.246.10.1',

    '10.246.10.2',

    '10.246.10.3',

]

def round_robin(server_lst, cur = [0]):

    length = len(server_lst)

    ret = server_lst[cur[0] % length]

    cur[0] = (cur[0] + 1) % length

    return ret

 

可以看到,所有的节点都是以同样的概率提供服务,即没有考虑到节点的差异,也许同样数目的请求,高配的机器CPU才20%,低配的机器CPU已经80%了

加权轮询算法(weight round-robin)

加权轮训算法就是在轮训算法的基础上,考虑到机器的差异性,分配给机器不同的权重,能者多劳。注意,这个权重的分配依赖于请求的类型,比如计算密集型,那就考虑CPU、内存;如果是IO密集型,那就考虑磁盘性能。Python示例代码如下

 

WEIGHT_SERVER_LIST = {

    '10.246.10.1': 1,

    '10.246.10.2': 3,

    '10.246.10.3': 2,

}

 

def weight_round_robin(servers, cur = [0]):

    weighted_list = []

    for k, v in servers.iteritems():

        weighted_list.extend([k] * v)

 

    length = len(weighted_list)

    ret = weighted_list[cur[0] % length]

    cur[0] = (cur[0] + 1) % length

    return ret

 

随机算法(random)

这个就更好理解了,随机选择一个节点服务,按照概率,只要请求数量足够多,那么也能达到绝对均衡的效果。而且实现简单很多

 

def random_choose(server_lst):

    import random

    random.seed()

    return random.choice(server_lst)

 

加权随机算法(random)

如同加权轮训算法至于轮训算法一样,也是在随机的时候引入不同节点的权重,实现也很类似。

def weight_random_choose(servers):

    import random

    random.seed()

    weighted_list = []

    for k, v in servers.iteritems():

        weighted_list.extend([k] * v)

    return random.choice(weighted_list)

 

当然,如果节点列表以及权重变化不大,那么也可以对所有节点归一化,然后按概率区间选择

 

def normalize_servers(servers):

    normalized_servers = {}

    total = sum(servers.values())

    cur_sum = 0

    for k, v in servers.iteritems():

        normalized_servers[k] = 1.0 * (cur_sum + v) / total

        cur_sum += v

    return normalized_servers

 

def weight_random_choose_ex(normalized_servers):

    import random, operator

    random.seed()

    rand = random.random()

    for k, v in sorted(normalized_servers.iteritems(), key = operator.itemgetter(1)):

        if v >= rand:

            return k

    else:

        assert False, 'Error normalized_servers with rand %s ' % rand

哈希法(hash)

根据客户端的IP,或者请求的“Key”,计算出一个hash值,然后对节点数目取模。好处就是,同一个请求能够分配到同样的服务节点,这对于“有状态”的服务很有必要

def hash_choose(request_info, server_lst):

    hashed_request_info = hash(request_info)

    return server_lst[hashed_request_info % len(server_lst)]

 

 

只要hash结果足够分散,也是能做到绝对均衡的。

一致性哈希

哈希算法的缺陷也很明显,当节点的数目发生变化的时候,请求会大概率分配到其他的节点,引发到一系列问题,比如sticky session。而且在某些情况,比如分布式存储,是绝对的不允许的。

为了解决这个哈希算法的问题,又引入了一致性哈希算法,简单来说,一个物理节点与多个虚拟节点映射,在hash的时候,使用虚拟节点数目而不是物理节点数目。当物理节点变化的时候,虚拟节点的数目无需变化,只涉及到虚拟节点的重新分配。而且,调整每个物理节点对应的虚拟节点数目,也就相当于每个物理节点有不同的权重

最少连接算法(least connection)

以上的诸多算法,要么没有考虑到节点间的差异(轮训、随机、哈希),要么节点间的权重是静态分配的(加权轮训、加权随机、一致性hash)。

考虑这么一种情况,某台机器出现故障,无法及时处理请求,但新的请求还是会以一定的概率源源不断的分配到这个节点,造成请求的积压。因此,根据节点的真实负载,动态地调整节点的权重就非常重要。当然,要获得接节点的真实负载也不是一概而论的事情,如何定义负载,负载的收集是否及时,这都是需要考虑的问题。

每个节点当前的连接数目是一个非常容易收集的指标,因此lease connection是最常被人提到的算法。也有一些侧重不同或者更复杂、更客观的指标,比如最小响应时间(least response time)、最小活跃数(least active)等等。

一点思考

有状态的请求

首先来看看“算法衡量”中提到的第三个问题:同一个请求是否分发到同样的服务节点,同一个请求指的是同一个用户或者同样的唯一标示。什么时候同一请求最好(必须)分发到同样的服务节点呢?那就是有状态 — 请求依赖某些存在于内存或者磁盘的数据,比如web请求的session,比如分布式存储。怎么实现呢,有以下几种办法:

(1)请求分发的时候,保证同一个请求分发到同样的服务节点。

这个依赖于负载均衡算法,比如简单的轮训,随机肯定是不行的,哈希法在节点增删的时候也会失效。可行的是一致性hash,以及分布式存储中的按范围分段(即记录哪些请求由哪个服务节点提供服务),代价是需要在load balancer中维护额外的数据。

(2)状态数据在backend servers之间共享

保证同一个请求分发到同样的服务节点,这个只是手段,目的是请求能使用到对应的状态数据。如果状态数据能够在服务节点之间共享,那么也能达到这个目的。比如服务节点连接到共享数据库,或者内存数据库如memcached

(3)状态数据维护在客户端

这个在web请求中也有使用,即cookie,不过要考虑安全性,需要加密。

关于load balancer

接下来回答第四个问题:关于load balancer,其实就是说,在哪里做负载均衡,是客户端还是服务端,是请求的发起者还是请求的3。具体而言,要么是在客户端,根据服务节点的信息自行选择,然后将请求直接发送到选中的服务节点;要么是在服务节点集群之前放一个集中式代理(proxy),由代理负责请求求分发。不管哪一种,至少都需要知道当前的服务节点列表这一基础信息。

如果在客户端实现负载均衡,客户端首先得知道服务器列表,要么是静态配置,要么有简单接口查询,但backend server的详细负载信息,就不适用通过客户端来查询。因此,客户端的负载均衡算法要么是比较简单的,比如轮训(加权轮训)、随机(加权随机)、哈希这几种算法,只要每个客户端足够随机,按照大数定理,服务节点的负载也是均衡的。要在客户端使用较为复杂的算法,比如根据backend的实际负载,那么就需要去额外的负载均衡服务(external load balancing service)查询到这些信息,在grpc中,就是使用的这种办法

可以看到,load balancer与grpc server通信,获得grpc server的负载等具体详细,然后grpc client从load balancer获取这些信息,最终grpc client直连到被选择的grpc server。

而基于Proxy的方式是更为常见的,比如7层的Nginx,四层的F5、LVS,既有硬件路由,也有软件分发。集中式的特点在于方便控制,而且能容易实现一些更精密,更复杂的算法。但缺点也很明显,一来负载均衡器本身可能成为性能瓶颈;二来可能引入额外的延迟,请求一定先发到达负载均衡器,然后到达真正的服务节点。

load balance proxy对于请求的响应(response),要么不经过proxy,如LVS;要么经过Proxy,如Nginx。下图是LVS示意图(来源见水印)

而如果response也是走load balancer proxy的话,那么整个服务过程对客户端而言就是完全透明的,也防止了客户端去尝试连接后台服务器,提供了一层安全保障!

值得注意的是,load balancer proxy不能成为单点故障(single point of failure),因此一般会设计为高可用的主从结构

 其他

在这篇文章中提到,负载均衡是一种推模型,一定会选出一个服务节点,然后把请求推送过来。而换一种思路,使用消息队列,就变成了拉模型:空闲的服务节点主动去拉取请求进行处理,各个节点的负载自然也是均衡的。消息队列相比负载均衡好处在于,服务节点不会被大量请求冲垮,同时增加服务节点更加容易;缺点也很明显,请求不是事实处理的。

想到另外一个例子,比如在gunicorn这种pre-fork模型中,master(gunicorn 中Arbiter)会fork出指定数量的worker进程,worker进程在同样的端口上监听,谁先监听到网络连接请求,谁就提供服务,这也是worker进程之间的负载均衡。

references

  • wiki:Load balancing

  • 一分钟了解负载均衡的一切

  • grpc load-balancing.md

 

RD会话主机服务器2012上没有可用的远程桌面许可证服务器

A fully functional and activated 2012 Remote Desktop Session Host server displayed the following message:

wKiom1iW02ewtBbQAAAaOeKPUC0824.png-wh_50

This was a simple setup on one server with the: connection broker, Session Host and Licensing server with 2012 CAL’s installed.

Even though the licensing seems to be configured correctly, in server manager:

wKiom1iW1ACROPHrAAEm-BhPLIs747.png-wh_50

and powershell:

wKioL1iW1FySB4vPAAAGB2lDafg956.png-wh_50

Licensing diagnostics:

wKioL1iW1Jfyq48TAAHwAV0hXC4881.png-wh_50

 

everywhere you look, everything seems to be OK. But the license manager shows something odd:

wKiom1iW1O3ClPEDAAEwQRNasuU853.png-wh_50

 

 

No licenses are being used? This server was used since late 2012. Some interesting things could also be found in the event logs, the following events appear:

EventID: 1130
Source: TerminalServices-RemoteConnectionManager

The Remote Desktop Session Host server does not have a Remote Desktop license server specified. To specify a license server for the Remote Desktop Session Host server, use the Remote Desktop Session Host Configuration tool.

and:

EventID: 1128
Source: TerminalServices-RemoteConnectionManager

The RD Licensing grace period has expired and the service has not registered with a license server with installed licenses. A RD Licensing server is required for continuous operation. A Remote Desktop Session Host server can operate without a license server for 120 days after initial start up.

images/j2xml/ebf5dd45a9a457f5cde9df15aef38c1a.png

The solution was to delete the REG_BINARY in

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\RCM\GracePeriod

Only leaving the default.images/j2xml/ebbe1620446cf7cfab0beb023340655d.png

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Note: you must take ownership and give admin users full control to be able to delete this key.

After a reboot the server should be working again, licenses are now being used:

images/j2xml/f409757c6681d4211184181c9dfb359d.png

Although everything seemed to be ok and configured correctly with valid licenses, it seems that the setup was still in a 180 day grace period, even though it was correctly configured.
A possible bug in RDS 2012?

漫画赏析:80 端口之战

极客漫画|漫画赏析:80 端口之战

嗨,大家好,今天我们来聊聊 80 端口之战。著名的技术漫画站 turnoff.us 有这样的一副漫画,生动的描绘了固守 80 端口的 Apache 和新生代的 Nginx 之间的战争。你知道,80 端口是 Web 端口,就是这个端口构成了我们现在大部分的互联网。

作为新生代的 Nginx 对已经 22 岁之老的 Apache 说,“一边去,老头,这 80 口不用你看着了,你得给新人腾腾地方了!”

头顶羽毛(Apache 的 Logo 形象),身上的写着名字的牌子都是补上去的(a patch,即 Apache 这个词的出处)一脸懵逼,对小毛头 Nginx 说,“放尊重点,你觉得你已经能取代像我这样的老同志了吗?!”

“哈?C10K 你解决了吗?事件驱动呢?这些你行吗?”Nginx 说。(C10K 指并发上万连接,由于服务器和网络性能的提升,现在的服务程序面临着处理更大并发的请求,而一些老旧的应用面对这种大量请求显然有点力不从心)

“嗯,我可以给你一个‘小小’的列表,这都是我支持的模块……” Apache 顾左右而言它。

“这些都过时了!我猜它们根本就没人用过!” Nginx 看着那“小小”的列表,一脸嫌弃的反驳。(讲真,Apache 的很多模块你可能从未用过,尤其是那些内置的模块,而另外一些年久失修的第三方模块,甚至你都不知道能不能用了)

一看这么多模块唬不住 Nginx,Apache 又把 PHP、MySQL 等小弟叫出来助阵,“这些都是我的铁杆兄弟!”

“嘿,谁怕谁啊,谁没兄弟啊,我也有啊” Nginx 拽出来焕发了第二春的 Postgres 数据库和曾经的明日之星 Ruby,不过感觉这些兄弟们有点不太给力 :-d 。

那么你猜猜谁会赢?买定离手啊~

 

家庭服务器,改变互联网生活

    随着互联网的不断普及,互联网应用的不断深入,很多家庭和个人对于互联网的依赖越来越严重。毫不夸张的说,很多人已经离不开互联网而独立生活。

   而伴随互联网需求的日益增长,很多家庭和中小企业对于家用型服务器的需求也不断增常。一台家用服务器,可以满足一家人应用于互联网之上的工作娱乐需求,可以满足SOHO一族的互联网创业需求等。

 

什么是家庭服务器?

   以往对于服务器,大家虽然都比较熟悉,但也只是仅限于商用领域。而对于家庭服务器,相信这个理念很多人还不是非常了解。到底什么是家庭服务器呢?家庭服务器能用来干嘛呢?我想很多人也会存在这样的疑问?所以,先给大家介绍一下相关知识,让大家能更深入了解家庭服务器到底能给我们的生活带来那些改变。

 

   故名思义“家庭服务器”,其实就是一个数据中转中枢。首先,他可以帮助用户轻松的建立家庭数字中心,其次他还有保护电脑系统、保存不断增加的工作数据和多媒体内容等多项强大功能,不过最重的是通过网络,家庭服务器能让使用的“家庭”随时随地、安全的访问对方,并轻松的实现与亲朋好友随时分享。所以,相比于商用服务器,家庭服务器的服务范围其就是专为个人家庭定制专属家庭数据中心,帮助你轻松的管理家用电器,使你的家电能够实现智能照明、高清电视、视频监控等高科技完美生活。

 

家庭服务拥有海量存储、远程遥控

   以当今一个普通家庭拥有一台家庭服务器为例,他不仅可以同时满足爸爸的工作、妈妈的高清大片、儿子的在线学习、爷爷的旅游照片和奶奶的各种相声小品等日常功能。不管是工作文件、高清电影、海量照片,统统都可以放在家庭服务器。而且可以通过MSN帐号建立自己的网站,随时随地都可以安全访问,并且还可以轻松实现与其他亲朋好友分享。

 

   而对于SOHO创业一族来说,家庭服务器的作用更是非同小可。毕竟,在这个全民互联网的时代,很多人通过网络在家创业。譬如,开设自己的网店、承接网络威客任务、帮助别人设计装修网店网站等等实现自我社会价值的体现。

 

家庭服务器简单易用、安全节能

   过去没有家庭服务器,对于这些SOHO一族来说,如果单独购买商用服务器,不仅本实高昂,而且非常不易管理。所以,对于大多数人而言,选择租用IDC机房里的服务器自然就成了首选。不过,现在随着家庭服务器的面市,恰好解了SOHO一族的燃眉之急。因为,这种智能式的家庭服务器,在完全没有技术基础的情况下,也能够让人运用自如。让广大SOHO一族真正实现拥有独立的数据中心,不用再看IDC的店大欺客的脸色。更不用再担惊受怕机房出现故障,导致自己的业务无法开展的恶果。

 

   从中我们可以看出在安全性、稳定性和性能等方面,家庭服务器一点也不逊于商用服务器。而且,家庭服务器,还可以通过异地备份,很好的保障了使用者的数据安全。从成本方面来核算,买一台家庭服务器相对租用IDC服务器来说,也要占据很大的优势。再说,一台家庭服务器的耗电量,相当于一盏40W的电灯,也是非常节能。一台家庭服务器,绝对能够帮助刚刚创业的SOHO一族在互联网江湖大展身手。

未来家庭服务器将会使我们的生活更将丰富多彩

   综上所述,我们可以看出“家庭服务器”理念的推出,不仅大大降低了互联网创业者的门槛,更使得广大的普通家庭认识到了数字化家居生活的便捷。笔者在这里预计,在未来的一两年中,因“家庭服务器”理念的推出势必将会返岗互联网创业高潮推向另一个高峰。毕竟,互联网创业的门槛已经很低。而选择一台物美价优的强大的家庭服务器配合一条高速网线,普通家庭就可以轻松拥有强大数字化中心,开始闯荡互联网江湖。

 

   并且,对于很多个人和中小企业来说,“家庭服务器”的推出,能够更丰富互联网应用。一个企业需要一台家庭服务器,一个需要储存海量照片的摄影师需要一台家庭服务器,一个设计作品需要大空间的设计师需要一台家庭服务器。在未来的日子里,笔者相信随着“家庭服务器”走进更多的家庭,我们的互联网生活也将会更加丰富多彩。

 

About Us

Since 1996, our company has been focusing on domain name registration, web hosting, server hosting, website construction, e-commerce and other Internet services, and constantly practicing the concept of "providing enterprise-level solutions and providing personalized service support". As a Dell Authorized Solution Provider, we also provide hardware product solutions associated with the company's services.
 

Contact Us

Address: No. 2, Jingwu Road, Zhengzhou City, Henan Province

Phone: 0086-371-63520088 

QQ:76257322

Website: 800188.com

E-mail: This email address is being protected from spambots. You need JavaScript enabled to view it.