负载平衡中间件的相关概念
1 负载分配的粒度
基于中间件层的负载平衡通常是指通过负载平衡服务在一组或多组服务对象间对客户请求进行均衡的分配,这些服务对象可能是在不同的服务程序空间,也可能分布和运行在不同的主机上。而所谓负载分配的粒度是指将客户请求与副本对象进行绑定的时机,根据时机的不同可以分为每请求、每会话和按需三种粒度。
l
每请求
客户的每个请求都可能转发到不同的副本对象上,也就是说客户每次激发一个请求时都会绑定到一个副本对象上。这种绑定方式中客户拥有的是负载平衡器的对象引用,通过负载平衡器将客户调用转发给某个真实的副本对象。这允许服务器以细粒度来调节负载。对于数量少、处理时间长的请求来说,可以有效地达到调节负载的目的;但对于数量庞大、处理时间短的请求来说,这种方式增加了一个连接和请求的转发过程,延时太大,降低了系统的吞吐量。
l
每会话(session)
在分布式中间件的上下文中会话定义为一个客户端出于远程方法调用的目的连接到一个给定的服务器时间周期。客户机的对象请求在其会话期间被绑定到同一个副本对象上,实际上该方法相对客户而言变成了不迁移策略,一旦被绑定到某个副本对象 ,以后的远程操作都将指向同一个副本对象,但对大量的客户请求来说也实现了客户负载在多个副本对象间的平衡,只是粒度较大。这样的绑定粒度减少了系统调度的开销,避免集中式管理模式下的性能瓶颈。
l
按需(on demand)
无论何时,只要负载平衡器认为必要,就可以将客户的请求重新绑定到另一个副本对象。这种设计强迫客户方将请求发送给与当前请求目标不同的另外一个副本对象。这实际上是对每会话的改进,以实现负载的迁移。
2 静态负载分配与动态负载分配
所谓静态负载分配,是将一个指定来源(如某台客户机或某个局域网段)的请求分配给一个固定的服务对象,即在系统的生命周期内,当有新的请求到达时,始终交由该服务对象处理。但是考虑到这种固定的静态分配方法事先并不了解系统的参数,固定或静态的负载分配模式往往会产生比较差的结果,所以实际上应用得更多的是动态负载方法。而对于动态负载分配来说,当有新的请求到达时,将根据系统所采用的策略动态地分配给服务对象副本,从而达到负载平衡的目的。
3 自适应负载分配模式与非自适应负载分配模式
自适应负载分配模式和非自适应负载分配模式都是动态负载分配策略的组成部分之一。
在非自适应模式中,负载的分配不考虑系统本身发生的改变,常使用随机副本选择算法和轮转副本选择算法这些较为简单的算法,不需要使用成员的负载信息,开销较小,但这些算法只是简单的对服务对象副本进行动态的选择,不具有反馈性,只能在某些特定条件下恰当地平衡负载:
l
专用主机
l
同类主机
l
客户产生同样的负载,连接同样长的时间或客户连接的时间很短
在自适应负载分配模式中,服务对象副本的选择和分配考虑到系统过去和现在的性能表现,并且受到前期的决策以及系统变化的影响,即带有反馈性,能够很好的起到平衡系统负载的作用。自适应负载分配模式包括最小负载副本选择算法、加权最小负载副本选择算法等。在这些算法中,当新的请求到来时,将选择当前负载最小的副本响应请求,同时将副本的负载值增大,从而保证服务对象副本的处理尽可能平衡。自适应策略更适合大量请求产生不同的负载又无法实现预测的情况,但它也存在问题:
负载采样值延时的影响。通常情况下都是采用周期性的方式获得副本的负载,这意味着做负载平衡决策时,负载值并不代表成员的当前负载,而是过去的负载。当在一个短的时间内有很多客户链接时,这引起的问题将会很大,因为在负载值被更新之前,成员的实际负载将急剧地增加。增加负载更新的频率将减少错误,但也会因为额外的网络通信增加负载平衡的开销。因此,必须确定一个优化值。
成员负载峰值的冲击。我们获取的负载信息只是某一时刻的抽样,服务器很有可能在此刻出现峰值(过于繁忙或过于空闲)然后很快又平滑起来,如果基于获取的峰值做负载决策,自然影响系统性能。
4 负载平衡服务的结构
将绑定粒度与成员选择策略进行组合,通常可以定义以下几种负载平衡体系结构。
l
非自适应每会话体系结构
这种体系结构的负载平衡器,在客户/服务器会话最初建立时选择目标副本对象,也就在此时,客户得到一个副本对象的引用,并与其建立连接,如图1.10所示。不管服务器的负载状况,客户将始终与最初绑定的那个服务器进行交互。这种体系结构适合实现轮转或随机算法的负载平衡算法。
图1.10
非自适应每会话体系结构
基于每会话客户绑定体系结构的负载平衡服务可以很好地满足应用透明性、系统可用性、最小的开销、CORBA互操作性等要求,带来的运行开销相比其它的体系结构都要小。然而,非自适应每会话体系结构不能自适应地处理动态客户请求操作模式。尤其是,重定向仅仅在客户激发第一个请求时执行,在请求执行过程中并没有重新分配客户的机制。因此可能多个会带来高负载的客户被绑定到同一个服务器,即使另一些服务器负载又比较空闲,系统整体也会因此严重下降。
l
非自适应每请求体系结构
这种体系结构和非自适应每会话体系结构有很多相同的特点。主要的不同是,每次请求派发时,客户都会被绑定到一个副本对象,而不是只在初始请求时绑定一次。由于通信开销地增加,这种体系结构的缺点将导致系统性能地降低。
l
非自适应按需体系结构
这种体系结构与前面介绍的非自适应每会话有同样特点。不过,它允许在某个绝对时间点重新混合客户的绑定。因为是非自适应体系结构,运行时信息,如CPU负载,并不被用来决定什么时候执行重新绑定,客户的重新绑定将由系统每隔一段时间间隔执行。
l
自适应每会话体系结构
类似于非自适应每会话体系结构,主要的不同是,自适应每会话体系结构会利用系统运行时的负载信息来选择副本,因此减少了将新客户绑定到重负载成员的可能性。尽管如此,这种策略只是轻微的改进,因为客户产生的负载会在绑定决策之后发生变化。
l
自适应每请求体系结构
如图1.11所示,这种设计引入一个前端服务器,作为一个代理接收所有客户请求。在这种情况下,前端服务器作为一个负载平衡器,根据它的负载平衡算法选择合适的后端服务器,然后把请求转发给副本对象;并接收副本对象的应答,然后将其返回给客户。当想要平衡负载时,被称为“负载建议”的消息可以由负载平衡器发送给后端服务器。这些建议引起副本对象或者接收请求;或者将请求重定向回负载平衡器。
图1.11
自适应每请求体系结构
这种自适应的请求转发体系结构主要优点是良好的伸缩性和公正性。例如,前端服务器可以在为每个请求选择目标对象之间检查每个副本对象的负载,这使它能够更加均匀地分配负载。然而,由于一个前端服务器要处理每个请求,这种体系结构带来过多的延时和网络开销。而且它引入了两种新的网络消息:1)来自前端服务器对副本对象的请求;2)副本对象对前端服务器相应的应答。
l
自适应按需体系结构
如图1.12所示,客户最初收到的是对负载平衡器的对象引用。负载平衡器使用相应的机制如CORBA标准的LOCATION_FORWARD消息,将客户的初始请求重定向到合适的目标对象副本上。客户将继续使用这个从LOCATION_FORWARD应答消息体中获得的对象引用,直接与副本对象通信,直到会话完成。而当负载平衡器发现副本过载时,将通过过载警告消息将请求重定向到负载较轻的副本,重新建立连接并发送请求。
图1.12
自适应按需体系结构
和非自适应体系结构不同,按需转发请求的自适应负载平衡器可以持续地监测副本对象的负载,使用负载信息和应用指定的策略决定如何平等地分配负载。当负载不平衡时,负载平衡器可以通知一个或多个副本,要求它们将后续的客户重定向回负载平衡器,负载平衡器再将它们透明地重新定向到一个负载较轻的副本。使用这种体系结构,分布式对象计算系统整体可以从不均等的客户/副本绑定中恢复出来。这种策略很好地满足了前面列出的大部分要求。尤其是,它仅要求对应用初始化做很小的改变,不需要改变对象实现本身。主要缺点是冗余服务器必须准备接收来自负载平衡器的消息,将客户定向到负载平衡器。尽管不需更改应用逻辑,开发者必须更改服务程序初始化,激活部件以响应“负载建议”消息。
5 分散式负载管理与集中式负载管理
集中管理模式[17, 18],如图1.13所示,一般指采用一个集中的负载平衡器(load balancer),它负责管理所有对象副本,并负责将客户请求调度给后端的服务器。分散管理模式,如图1.14所示,系统没有全局的管理者,管理功能由驻留在客户方和服务方的代理协调实现 。分散模式常用的一种是多路代理的方式,代理保持多个副本对象的引用,由代理根据一定的策略选择某一副本对象执行请求。
集中管理模式可以简化系统设计与实现,但随着应用规模以及对象数量的增加,集中式负载平衡器可能会成为系统性能的瓶颈,而且存在单点失效问题,同时在广域环境下,网络延迟增大,集中式负载平衡难以实现;分散管理模式中,各个代理之间协调,管理的难度和复杂度较大,伸缩性相对较差。
图1.13
集中管理模式
图1.14
分散管理模式
6 负载迁移
在自适应的策略中,尽管平衡器会根据成员的负载状况决定成员的选择,但受以下一些因素的影响,也可能潜在地使系统负载不均,造成某个成员过载:
l
客户产生的负载不恒定
l
突发性的客户负载
l
不同客户会话时间的差异
l
主机的异构性
l
错误的成员选择
成员过载的一种解决方式就是采用负载迁移,即将客户请求从负载较重的成员重新绑定到一个负载较轻的成员上。这通常是通过向过载成员发送一个警告消息来实现的,收到警告消息的成员将收到的下一个客户请求重定向回平衡器接受重新调度。这样就可以解决系统负载不匀的情况,带来更高的平均吞吐率。
但负载迁移机制也会引入新的问题,如当负载由一个成员的副本转移到另一个成员的副本上,引起目标成员过载时,就会导致系统的不稳定,严重时可能引起系统“抖动”。另一个问题是,过载的成员只能在收到客户的下一个请求时才能执行重定向动作,而当这发生时,成员的负载也许已经降下来了。