网站服务器需要接收用户请求、响应请求并将回馈的数据吐给用户,这个叫做服务。服务的量级不同,服务器的结构设计就不一样。对于每秒数万的服务器响应需求来说,几个进程或者线程就能够处理。对于上百万和千万的访问需求来说,就算是海量了。这个时候的结构设计就是非常要求之高了。目前国内能够做到这样的访问需求量的公司有多少呢?我不说你也知道。
一种很常见的服务器的工作环节图如:
如图所示,一般有一个主线程接收任务,并将任务放到任务池中,主线程可以查询子线程的状态,如果空闲就将任务转交给子线程,如果没有子线程空闲,则新建子线程处理需求。子线程空闲状态会接受任务并处理,将用户需要的数据查询数据库之后转交给用户。这个是基本的流程。目前有很多变种。
任务接受和处理分开:将任务接受模块用来专门接受用户的任务需求,并进行简单的分析,如果是无效的处理需求就不放到任务池中。处理模块不断去任务池中获取任务并进行处理,如果线程没有获得任务就休眠,如果任务数太多则分配更多的资源去新起线程进行处理。一般不需要将多余的空闲线程杀死,因为这些资源都是预留用来处理任务的,没有任务处理也没有其他工作可以做。
线程换为进程:有的任务较为独立的可以使用多进程来处理任务,不同进程处理不同类型的任务,同一个进程下的线程处理同一类型的任务,互不干扰。
主线程分发任务还是子线程主动获取任务:一般来讲,主线程分发任务就会产生轮询操作,这样不会有加锁的必要。如果是子线程自行获取任务,那么必须将任务加锁,防止其他线程来同时获取线程。这样就比较麻烦。
对数据库使用cache:经常访问的数据可以为其建立cache,提供获取数据的效率。当然,数据库也可以建立索引,提高数据存储的范式要求,同样可以提到作用。数据库操作这部分有mysql、mysqli、pdo等访问和管理方式,这需要根据系统的需求来确定。
我这里并不是想要讲解海量服务器的架构设计,我想说的是中小型服务器的一般设计方法。专业的方法名称有很多,如:迭代式、并发式、prefork式、线程池、分发模型、epoll方法等。对于各种模型的使用,我比较欣赏线程池的方式,Mysql服务器就是采用这种方式。通过主线程来管理子线程的工作,子线程根据状态接受主线程分发的任务,如果没有空闲子线程可以有主线程在新起线程进行工作,这样可以动态的根据任务量来做出响应的变化。子线程处理各自接收到的任务时相互独立,不需要关注。
不管是父进程和子进程,还是主线程和子线程,都涉及到进线程之间的通信,可以使用共享内存、管道、socket的方式去通信,在windows下还有发送消息的方法。这个是多线程编程的基础。如果要处理这样的需求就需要指定一个合适的通信方式。
这个是总结前人经验,欢迎讨论。
评论
2178657#1楼 2011-08-14 14:23 小军人
总结的不错。。。 回复 引用 查看
#2楼 2011-08-15 09:50 大菜
能否讲一下,怎么实现呢? 回复 引用 查看
#3楼[楼主] 2011-08-16 19:22 布同
@大菜
实现的话,几百行代码就可以实现一些基本的sever,复杂的也上不了万行。用到的主要是socket,thread,进程,数据库的相关操作函数。 回复 引用 查看