谈分布式网络程序设计1
首先肯定都是大家常谈的确定需求,什么样的需求会催生什么样的设计。有的需求需要高可靠性,比如分布式数据库;有的需求需要高性能,稳定、高速、但是可靠性不需要很高,比如搜索引擎。这里谈的便是类似搜索引擎的这种需求的分布式系统。本人有幸参与了一个类似这种系统的项目,顺便写下个人心得。
网络数据的收发的设计方式有好多种,主要有2种:一个线程一个连接的方式;或者使用select,一个线程专门负责所有的连接的接受和发送。这2种方式各有各的好处,不过通常在高性能的服务器程序则使用的是第二种方式,占系统资源少,而且性能也很好。此外,流水线技术是目前cpu中最基本的技术之一,若将此用于网络程序设计,也可以大幅提高性能。它在网络程序中的表现实际上就是使用队列,若请求的处理过程分好几步,那么在每一步都设置一个队列,性能比将大大提升。cpu的流水线技术的原因在于各个部件都处于繁忙状态,所以cpu单位时间内处理性能提高。而网络程序采用流水线技术(队列)则能尽量促使各个节点处于繁忙状态,从而提高程序的性能。
但是队列的采用使得网络程序复杂化。当在高并发的用户访问下,很容易导致其它的一些问题,需要设计师好好的采用应付措施。
第一个问题,就是超时。当单位时间内的用户的请求数超过系统能够处理的极限时,超时是肯定有的,毕竟硬件已经处理不过来了,这里就有好多策略可以考虑,尤其是分布式系统的节点的层数比较深的时候,在什么时候判断超时是个很有讲究的问题。因为判断超时不仅仅只影响用户(告诉用户系统繁忙,请稍候再试),也影响到系统的正常处理能力。超时时间设的越长,用户等待的时间就越长;设的短,则本来可以处理的请求,被判断成超时处理了。这里就有一个阈值,要是谁能在这里做研究,来个什么机器学习的,最终得到一个比较佳的值,那俺可是佩服的五体头地,以后部署不同配置的机器,性能测试可以少做很多了。
第二个问题,锁的问题。一个分布式的系统,肯定是多线程的,那么锁的选择是需要考虑的。不同类型的锁导致系统的行为不一样,而且有些锁可能会导致系统出问题。本人参与的那个项目原先采用这么一个锁,汇编写的,汇编的代码很短,一个锁操作只用了十几个cpu周期,性能估计比pthread好十几倍,但是它有一个问题,它没有先进先出的原则。俺们调了两天才发现这个锁把心跳请求饿死了,使得系统行为出现异常。最后我们还是采用的pthread,呵呵。
第三个问题,因为队列的使用,肯定是需要等待,采用select的网络数据的收发的设计,有时候网络的发送成了瓶颈之一,因为给所有的其它连接的请求是通过一个线程发送的,这样很可能因为某个等待而导致网络性能下降,比如某个连接的另一端的接收缓冲区满了的,这边将发不出去当前请求,从而导致后面的请求都发不出去。可以有几种方法应对这种问题:使用FD_READ,FD_WRITE,每个连接都配置接受和发送数据的cache,这个是最常用的方法了;或者可以把发送的请求按不同类型的连接分给不同的线程去做发送,这有时候也是一种好方法。
其他的问题暂时回忆不起来,今天就暂写这么多吧。