设计的出发点:
第一,网络模型,epoll的事件触发机制,reactor还是Proactor,其实都差不多啦
第二,单线程还是多线程
一句话,根据业务需要设计(是io型的还是cpu计算型的),多线程可以充分利用多核处理的优势,但是,有可能占用较多的cpu的资源。
另外,多线程并不能提高并发数量(受进程打开fd限制和epoll限制),但是,可以平滑服务,可以降低请求延迟时间。
如果是单线程,可以充分利用epoll的timeout模型,可是,这里会发生长任务占用cpu资源的情况
如果是多线程,可以利用消费者--生产者模型、任务队列,结合线程池。
需要注意的是,多线程带来的切换开销和锁是不容忽视的,不需要以为追求多线程,应该根据业务场景设计。
第三,线程还是进程(取决于是否fork,原则上,尽可能使用线程,当让,会fork的除外,线程切换开销等等都比进程小, 其实,线程在Linux里面是通过clone系统调用产生的,也有自己的task_struct结构)。
第四,进程间通讯
有共享内存,fifo,消息队列,pipe等,注意共享内存,需要结合锁。
建议采取tcp方式,这种方式有很多好处,方便扩展,很容易将多个进程部署到多台服务器上
第五,心跳包
一台服务器需要知道另一台服务器的提供服务情况,就需要不断地发送心跳包
第六,锁和条件变量
递归锁还是非递归锁?
默认的锁都是非递归锁,不过还是建议创建mutex时候指定属性,保证代码可移植。建议采取非递归锁,递归锁会带来不必要的麻烦,会隐藏程序的bug。
锁的封装,原则是Resource Acquisition Is Initialization
条件变量一定要结合锁。
为了资源的释放(线程取消点),需要安装线程退出的回调函数,并对可能的代码进行保护(pthread_testcancle包围代码)