蛙蛙推荐:关于网络服务器可伸缩性的讨论

关于网络服务器可伸缩性的讨论

有状态服务和无状态服务

  网络应用服务器分为有状态和无状态的两种,无状态服务不保存用户的状 态,用户的每次请求都是独立的,不存在上下文;有状态服务保存用户的状态,用户的一次会话里的所有请求必须被路由到同一台物理机上,因为只有这个物理机上 才有这次会话的上下文。业务逻辑决定了这个服务是否是有状态的还是无状态的,比如你要做一个提供配置信息的服务,只要根据用户ID取出配置返回给客户端就 可以,用户的两次请求互不相关,两次请求可以分别被不同的物理机处理,但如果你要做一个提供购物车功能的服务,用户每次发送添加某物品到购物车的请求时, 必须由同一台物理机去处理,因为只有这台物理机保存着该用户之前的购物车里的物品信息。
  有状态服务可以设计成无状态服务,比如上面的购物车应 用,如果把购物车的信息存储到数据库里,那么任何一台物理机根据用户的请求ID,找到数据库里的该用户的购物车信息,就可以处理用户的请求。当然这种设计 下,会增加DB的压力,随着应用服务器的增多,DB需要进行可伸缩的设计,这个以后再讨论。

长连接和短连接

  像HTTP协议, 每次请求和应答完成后,底层的TCP连接会断开,再次请求会再次建立TCP连接,这样的连接叫短连接。即使HTTP协议支持KeepAlive,但也不能 假设某一用户的所有请求都是在同一条TCP连接上发送的,打开KeepAlive的目的是在整个TCP连接上可以连续的传输数据,从而减少了TCP建立连 接及TCP慢启动带来的性能损失,并不是说真正的长连接。
  长连接是指TCP连接建立成功后,在用户的整个会话过程中都保持连接,用户在会话过 程中发送的请求都会在一条连接上产生,也就是发送到同一台物理机,因为标识一条TCP连接由一个4元组构成,客户端的IP,端口及服务端的IP和端口,长 连接的例子是CMPP协议。

负载均衡

  负载均衡器用于把用户的请求根据一定的转发规则转发给物理机(RealServer), 对外公开一个虚拟IP,对内隐藏一组网络应用服务器。负载均衡是小规模的网络应用最常见的可伸缩性方案,随着用活跃户数量的增长,当现有的网络服务器数量 不足以满足用户的请求时,在负载后面增加相应的物理机就可以解决问题。
  最常见的负载均衡规则是按流量(按Session,最少连接数)负载和 按源IP(哈希)负载。
  对于无状态的服务,一般用流量负载就可以满足需求,负载均衡器会保存负载均衡器和物理机之间的连接数,新的连接请求上 来之后,会路由给连接数最少的物理机,因为物理机上不保存用户状态,所以用户的请求路由到哪台物理机都可以,这样的规则最终会达到每个物理机上的TCP连 接是基本均匀的。
  对于有状态的长连接服务,也可以用按流量负载,因为长连接建立起来后,负载均衡器会在客户端和物理机之间维护这条连接,因此 这个用户发送的每次请求都会路由到相同的物理机,用户每次请求都能找到用户的状态,也可以说是用户状态是承载在TCP长连接上的。
  对于按流量 负载这种方式有一个问题是,有一些用户的活跃度比较高,有可能好多活跃度高的用户都路由到了同一台机器,造成这台机器的负载比较高,造成这个问题的原因是 负载均衡器只关心连接数,并不知道这条连接上承载的用户的活跃度。

导航服务
  当用户数量增大到一定程度,最外层的负载均衡器也 会撑不住,这时候可以做多个负载均衡器,每个负载均衡器有不同的外网IP。用户可以先访问一个导航服务,导航服务根据用户ID来分配给用户所属的负载均衡 器IP,用户再去连接指定的负载均衡地址。导航根据用户ID指定负载均衡IP时可以依据一个映射规则,就是把用户ID划分成负载均衡器个数个段儿,然后每 个段映射到一个负载均衡器。

哈希定位
  对于内网中的服务间调用,如果要调用一个有状态服务,我们不需要使用导航服务,我们把导 航的规则内置到调用者服务器里就可以了,因为内网的服务可以随时更新,并且映射规则可以在数据库里读取,而发布出去的客户端就不一定能随时更新了。映射规 则其实也就是一个哈希规则,一个确定的用户ID肯定能算出一个明确的IP地址,这样内网调用可以省去负载均衡器的投资,因为负载规则被置于调用者机器里 了。

多机房部署
  当用户规模再大时,所有的服务器在一个机房都放不下了,需要部署到多个机房里,甚至因为具体业务的需要,需要 在不同运营商的机房去部署。最开始可能导航只部署在一个机房就可以了,因为它的作用只是分配外网负载均衡器的地址,功能简单,本身无状态,可按流量负载, 所以在一个机房里多部署几台就可以满足很大规模用户需求。当然为了容灾的考虑,怕导航所在的机房炸了,造成所有用户无法使用业务,可以在所有机房部署导航 服务,这时候导航如果还用一个域名的话,就需要使用Smart DNS服务,它使用BGP协议,根据客户端的IP及一个算法把导航的域名解析到合适的机房(链路最短或者速度最快)的导航外网负载IP。然后本机房的导航 只给客户端分配本机房的应用服务的外网负载地址,这样客户端就能找到最合适应用服务器。
  对于服务之间的调用,要想办法避免跨机房的调用,以减 少网间流量,因为两个机房在物理上是有距离的,只能通过光纤专线来连接,甚至还得需要DWDN设备,离的太远了还得用特殊的路由器进行协议转换,成本非常 高。如果因为业务需要,不可避免的需要一些跨机房的调用,可以在两个机房之间做一个起路由作用的服务,路由的规则需要自己设计,如机房A的用户需要找机房 B的用户的信息,A机房的调用者服务器根据映射规则得到B不再本机房,便把该请求转发给A机房的路由服务,A机房路由服务根据规则知道B在B机房,便把请 求转发给B机房的路由服务,B机房收到请求,根据B的用户ID定位到B所在应用服务器,转发请求,并接收应答,该应答最终通过这条链路回到A所在的应用服 务器上,完成整个调用过程。即便有办法实现跨机房的调用,也要尽量避免,比如一些查看信息类的调用,可以考虑用数据复制功能同步各机房的用户数据,以达到 每个机房都能在本地查看所有用户的信息。

有状态的Http服务
  对于有状态的短连接服务,常规的解决方案是按源IP负载或者7 层负载,按源IP负载是只要用户的IP不变,该用户发送的所有请求都会路由到相同的物理机上,所以只要用户整个会话过程中IP不切换,这种方式就很有效。 但现在移动互联网迅速发展,产生了大量的移动设备的客户端,他们在使用过程中由于基站切换会经常的改变源IP,而且运营商的一个IP会服务很多的用户,因 为源IP比较少,按照源IP进行哈希负载会造成严重的负载不均的问题,有可能某个IP上都是极为活跃的用户,都路由到了一台物理机上,而另一个IP上几乎 没什么客户端。7层负载会解决这个问题,7层负载设备可以进行HTTP协议解析,解析出Cookie,Uri,Http Headers等,并按照这些特征进行物理机的哈希定位。但是由于协议解析是CPU密集操作,通常会使负载设备的CPU占用率很高,如果这台设备上还进行 着其它4层的负载功能,有可能会影响其它服务的稳定性。
  还有一种基于软负载的方案,软负载前面使用流量负载,软负载服务器收到请求后,解析出 Http协议包,找出哈希的特征,cookie,url参数等,根据规则路由到唯一的物理机上,等物理机处理完请求返回应答后,软负载再把应答转发给客户 端。通常软负载没有硬件的负载均衡器性能高,而且会造成软负载和物理机之间流量增加,尤其是对于数据下载类的应用,请求很小,占用不了太大的流量,但应答 很大,而且需要从物理机到软负载再到外网负载转一大圈,比较浪费性能,好一点儿的软负载应该做到TCP状态迁移,只路由请求,让应答直接回在外网负载上, 由负载转发给客户端,减少一次链路。

参考连接
据复制技术与企业容灾
http://tech.watchstor.com/tech-30202.htm   
posted @ 2010-03-12 18:02  蛙蛙王子  Views(1963)  Comments(9Edit  收藏  举报