• Home
  • About
    • Road to Coding photo

      Road to Coding

      只要那一抹笑容尚存, 我便心无旁骛

    • Learn More
    • Email
    • Github
  • Posts
    • All Posts
    • All Tags

从C10K谈起, 聊聊服务器的设计模型(下)

16 Mar 2019

并发模式

继上一节最后的事件模式之后, 我们稍微提一下两种并发模式

半同步/半异步并发模式

简单地说: 同步线程处理业务逻辑, 异步线程处理IO事件. 异步线程将请求插入请求队列.同步线程获取请求并处理即可, 这与我们平时所使用的范式是一致的

而半同步/半异步只是并发模式, 我们真正使用的基本是变体 -> 半同步/半反应堆模式, 即:

  • 异步线程只有一个, 主线程进行IO事件的控制
  • 同步线程有多个, 即为线程池. 从请求队列中获取事件进行处理
  • 如果插入队列的是socket, 即为Reactor, 如果是完成后的请求, 即为Proactor

缺点就是:

  1. 共享队列,很明显的需要加锁.耗费CPU时间.
  2. 工作线程同时只能处理一个请求, 请求过多时, 会明显造成延迟

那么, 有什么解决办法呢? 就是使用主从Reactor模式, (擦, 垃圾<高性能服务端编程>, 绕来绕去, 半同步/半异步 就是Reactor模式的`单Reator, 多线程配置`)

领导者/追随者模式

相比于上一种并发模式需要的加锁保护. 主从模式(leader/follower)就是为了取消锁机制的 简单地说: 此模式是各个线程之间轮换处理IO事件的一种模式, 领导者进行IO监听, 追随者或者休眠, 或者执行任务

每个领导者, 首先从线程池中推选出新的领导者, 然后进行IO事件的监听

包括的组件: 句柄集, 线程集, 事件处理器集, 具体的事件处理器集

缺点也比较明显: 只有一个句柄集, 不能像Reactor模式一样, 在多个线程中进行各自的监听连接 PS: 主从模式,实在用的少, 也没见过比较成熟的项目, 暂且搁浅了.

解决C10K问题

(解决方案, 参考自C10K问题的源网页 website»)

既然要说解决C10K问题, 我们就先考虑从哪些方面着手:

  1. 网络库
  2. IO策略
  3. 一些其他手法

网络库

当我们使用网络库的时候, 就不需要考虑这些问题了. (曲线救国, 变相解决) 如: ACE, Boost.Asio, libev等当然还有其他语言的诸多框架

IO策略

这是我们进行问题解决的直接有效办法, 有下面这几种策略:

  • 一个线程服务多个连接, 使用LT模式
  • 一个线程服务多个连接, 使用ET模式
  • 一个线程服务多个连接, 使用异步IO
  • 一个线程服务一个客户端
  • 将服务器代码构建进入内核空间

事实证明, 前三种方法是可行的. 前两种都是Reactor模式, 第三种是Proactor模式 至于第四种, 已经不可用, 一台机器要达到TPC, 去满足C10K, 根本不可能, 资源限制的问题 第五种, 基本没有成熟的项目, khttpd也仅仅是服务静态网页, 局限性很强, 构建多了, 也会造成内核膨胀

其他的一些方法

  • 1.将TCP堆栈带入用户空间 TCP堆栈中会发生很多的拷贝, 带入用户空间能够明显提升效率, 而且一些不必要的机制可以去除 Sina就曾开源过fastsocket就是一个类似的产品, (不过后来销声匿迹了, 代码在github上有)
  • 2.解除打开文件句柄的限制 这个”解除”并非是真正意义上的解除, 肯定不可能无限打开. 我们的意思是: 释放到合理可用的范围内 一般有两个方面: 全局限制, 进程限制. 全局限制修改/proc/core/fs/..., 进程限制修改ulimit -n
  • 3.零拷贝 我们之前介绍过一批函数sendfile(2), splice(2), tee(2), 所谓零拷贝是较少不必要的拷贝, 不可能做到真正的零拷贝
  • 4.避免小帧 避免小的帧,尽量达到一个MSS再发送, 但是, 如果是为了支持连接可以这么做. 使用writev等 但是, 我们一般进行服务端开发, 是要禁止Negle算法和ACK延滞算法的,为了响应效率,小帧在所不惜

上面这些基本上就是解决C10K问题的办法了.

现在面临C10K, 已经没有多少挑战难度了, C100K也行, C1000K扣扣剪剪也行, C10M才是真正的挑战

展望未来: 可能更多的解法在于:

  • 硬件,
  • OS本质上的问题(内核空间的切换开始开销),
  • 调度单位的重量(引入, corutine)

同时, 单机的性能已经趋于极致, 我们更多的研究关注点, 应该放在分布式的开发上咯


PS: Emmmm, 我复习网络编程的内容差不多就这写了, 以后机会了也可以去分析一下知名网络库的源码, 如Boost.Asio, 同时要了解的还有TCP/IP的相关内容, 继续复习去咯



NetworkProgramming Share Tweet +1