美文网首页
第3章 多线程服务器的适用场合与常用编程模型

第3章 多线程服务器的适用场合与常用编程模型

作者: Junior888 | 来源:发表于2018-09-26 22:56 被阅读0次
1. 进程与线程

“进程(process)”是操作里最重要的两个概念之一,一个进程是“内存中正在运行的程序”。

每个进程都有自己独立的地址空间,可以把“进程”比喻为“人”。每个人都有自己的记忆(memory),人与人之间通过谈话(消息传递)来进行交流,谈话可以是面谈(同一台服务器),也可以在电话里谈(不同的服务器,使用网络通信)。

“线程”这个概念大概是在1993年以后才开始流行,线程的特点是共享地址空间,从而可以高效地共享数据。

2. 单线程服务器的常用编程模型

在高性能的网络程序中,使用得最为广泛的应该就是“non-blocking IO + IO multiplexing”这种模型,即Reactor模式。程序的基本结构就是一个时间循环(event loop),以事件驱动(event-driven)和事件回调的方式实现业务逻辑:

while(!done)
{
  int timeout_ms = max(1000, getNextTimeCallBack());
  int retval = ::poll(fds, nfds, timeout_ms);
  if(retval < 0)
  {
    //错误处理,回调用户的 error handler
  }
  else
  {
    //处理到期的 timer,回调用户的 timer handler
    if(retval > 0)
    {
      //处理IO事件,回调用户的IO event handler
    }
  }
}

Reactor 模型的优点很明显,编程不难,效率也不错。不仅可以用于读写socket,连接的建立甚至DNS解析都可以用非阻塞方式进行,以提高并发度的吞吐量,对于 IO 密集型的应用是一个不错的选择。

当然基于事件驱动的编程模型也有其本质的缺点,它要求事件回调函数必须是非阻塞的。对于设计网络 IO 的请求响应式协议,它容易割裂业务逻辑,使其散布多个回调函数之中,相对不容易理解和维护。

3. 多线程服务器的常用编程模型

non-blocking IO + one loop per thread 作为本节重点。

3.1 one loop per thread

程序里的每个 IO 线程有一个 event loop(或者叫做Reactor),用于处理读写事件和定时事件。这种做法的好处是:

  • 线程数目基本固定,可以在程序启动的时候设置,不会被频繁创建于销毁;
  • 可以很方便地在线程间调配负载;
  • IO 事件发生的线程是固定的,同一个 TCP 连接不必考虑事情并发。
3.2 线程池

对于没有 IO 而光有计算任务的线程,使用 event loop 优点浪费,我会用一种补充方案,即用 blocking queue 实现的任务队列(TaskQueue):

typedef boost::function<void()> Functor;
BlockingQueue<Functor> taskQueue;
void workerThread()
{
  while (running)
  {
    Functor task = taskQueue.take();
    task();
  }
}

用这种方式实现线程池特别容易,以下是启动容量(并发数)为N的线程池:

int N = num_of_computing_threads;
for(int i =0 ; i < N; ++i)
{
  create_thread(&workerThread);  //伪代码,启动线程
}

使用起来也很简单:

Foo foo;
boost::function<void()> task = boost::bind(&Foo::calc, &foo);
taskQueue.post(task);
4. 进程间通信只用TCP

linux下进程间通信(IPC)的方式数不胜数,包括:匿名管道(pipe)、具名管道(FIFO)、POSIX消息队列、共享内存、信号(signals)等,更不比说Sockets了。
同步原语也很多,如:互斥器(mutex)、条件变量(condition variable)、读写锁(read-writer lock)、文件锁(record locking)、信号量(semaphore)等等。

相关文章

网友评论

      本文标题:第3章 多线程服务器的适用场合与常用编程模型

      本文链接:https://www.haomeiwen.com/subject/dywpgftx.html