SlideShare a Scribd company logo
1 of 31
高性能并发网络服务器
设计与实现
http://www.ideawu.net/
网络服务器开发
 协议设计 ( 网络协议和应用协议 )
 语法 ( 报文格式 )
 语义 ( 指令的处理 , 交互时序等 )
 只要涉及到交互 ( 即使不是网络交互 ), 就需要协议
 网络实现 (IO)
 网络开发的基础是 socket
 任何对网络的封装 , 在三度关系之内必然是
socket( 最多三层封装 )
第一节 – 网络 IO
Talk is cheap, show me the code
serv = new TcpSocket();
serv.listen();
sock = serv.accept();
sock.read(buf);
sock.write(buf);
sock.close()
 一次服务
 没有并发
 短连接
 有没有协议 ?
 最简单的 TCP 服务器
重复服务
socket IO
 read/write 是可阻塞的
 阻塞是并发和高性能的死敌
 实现并发和高性能的途径就是解阻塞
 太简单了 !
 后面继续讲解 read/write...
并发服务
优缺点
 优点 :
 简单易用 , 一般工作得很好
 多线程 , 可以利用 CPU 多核
 缺点 :
 启动线程也有成本 , 很可能占大头
 线程的数量不受控制 , 危险 !
 问题在于 IO...
IO 多路复用
 专业地解决一个问题
 select/poll/epoll/kqueue 的 API 几乎一样 , 实
现不同 , 性能不同
 IO 多路复用接口的作用 , 就是测试
accept/read/write 等 IO 调用会不会阻塞
IO 多路复用示例
serv = new TcpSocket(); serv.listen();
select.add(serv, READ); // READ 表示只测试可读 ( 读不阻塞 )
while(1){
readable, writable = select.wait();
foreach(readable as sock){
if(sock == serv){
sock = serv.accept();
select.add(sock, READ);
}else{
sock.read(buf); sock.write(buf); sock.close();
}
}
// writable 为空 , 因为我们不测试可写
}
还不完善
第二节 – 报文解析
报文设计
 最重要的 TCP 协议是流式协议 ,
但几乎
所有的应用协议都是基于报文的
协议
 报文分隔
 用连接关闭来表示报文结束 . 如 ,
HTTP/1.0 的响应
 固定长度的报文 . 如 , TFTP 的数
据报文 .
 带自描述长度的固定长度首部的变
长报文 . 如 IP 包 , TCP 分段 .
 带结束符 . 如 , 行协议 , HTTP 协
议 . 逐字节解析和数据转义的影响
.
高层 文本 , 带结
束符
底层 二进制 , 固
定长度
SSDB 的报文格式
Packet := Block+ 'n'
Block := Size Data
Size := literal_integer 'n'
Data := size_bytes_of_data 'n'
示例 :
3
get
3
key
< 回车 >
优点
 简单
 带长度字段 , 支持二进制数据
 同时对人和对机器友好 , 报文数据文本化效果好
. 可以 telnet 到服务器进行交互
 解析器非常简单 , PHP 代码不过几十行
 同时兼容 LF 和 CRLF( 惯例 )
socket io 2
 read/write 读取 / 发送的是字节数组 . C 语言的
char[], PHP 的 string
 read 返回时读取的准确字节数无法预计
 导致 " 粘包 ", " 断包 "
 write 返回时不表示数据已到达对方机器
 所以 , 即便基于可靠传输的 TCP 协议 , 也需要应用层
协议进行确认来保证真正意义上的 " 可靠 "
带有报文解析的服务器
serv = new TcpSocket();
serv.listen();
sock = serv.accept();
client = new Client(sock);
client.recv(packet);
client.send(packet);
client.close()
 packet 一般是编程语言中的对象
序列化和反序列化
 read 收到的是字节数组 , 要进行反序列化转成编
程语言的对象
 反序列化的过程就是报文解析
解析报文
bytes = [];
while(1){
bytes += sock.read();
if(try_parse(bytes, &len) == READY){
// 已经解析出了一个报文 , 报文的长度是 len
// 从字节数组中清除掉已解析的
bytes.remove(len);
}
}
整合网络 IO 和报文解析
 将上例中的 read 和 try_parse 分离
 作业 ...
第三节 – 业务处理
 网络服务器 = 协议处理 + 网络 IO + 业务处
理
业务处理的位置
serv = new TcpSocket();
serv.listen();
sock = serv.accept();
client = new Client(sock);
request = client.recv();
response = process(request);
client.send(response);
client.close()
对于 SSDB,
LevelDB 相关的操
作封装在 process
中 .
IO 多路复用正确实践
 IO 多路复用的程序具有相同的核心逻辑 ( 主循
环 )
 初学者套用固定套路也能写出可用的代码
 初学者对 IO 多路复用的不完整理解 , 会导致程
序具有致命缺陷
IO 多路复用的基本框架
while(1){
readables = epoll.wait();
foreach(readables as r){
if(r.type == SERVER){
client = r.accept();
epoll.add(client);
}
if(r.type == CLIENT){
data = r.receive();
resp = process(data);
r.send(resp);
}
}
}
 经典套路
 易学上手
 process 可能阻塞
IO 多路复用 + 多线程 ( 错误 )
while(1){
readables = epoll.wait(200);
foreach(readables as r){
if(r.type == SERVER){
client = r.accept();
epoll.add(client);
}
if(r.type == CLIENT){
data = r.receive();
queue.push(data);
}
}
resp = queue.pop();
resp.client.send(resp);
}
 经典套路
 易学上手
 多线程
 queue.pop() 可
能阻塞
错误在哪 ?
时间点 客户端 服务器端
0ms 发出请求
10ms 网络延时 10ms, 收到请求
20ms 线程处理完毕
220ms epoll.wait() 阻塞了 200ms
220ms client.send()
230ms 网络延时 10ms, 收到响应
 从客户端的角度 , 请求花了 230ms
 从服务器端的角度 , 它只化了 20ms 处理请求
 问题出在错误的 epoll 使用 !
接上
epoll.wait(200) 的阻塞时间是 0ms ~ 200ms
参数决定阻塞上限 , 但不能改为 0, 否则 CPU 占用
100%
解决方案 :
SelectableQueue, 让 epoll 来监听 queue, 使得
epoll.wait() 不会无端阻塞
IO 多路复用 + 多线程 ( 正确 )
queue = new SelectableQueue();
epoll.add(queue);
while(1){
readables = epoll.wait();
foreach(readables as r){
if(r.type == SERVER){
client = r.accept();
epoll.add(client);
}
if(r.type == CLIENT){
data = r.receive();
queue.push(data);
}
if(r.type == QUEUE){
resp = queue.pop();
resp.client.send(resp);
}
}
}
 经典套路
 易学上手
 多线程
 需要实现
SelectableQueu
e
剩下的 ...
 就是看代码写代码 ...
FIN
Thanks
C++ 网络服务器开发框架 sim:
https://github.com/ideawu/sim
Changelog
2015-06-06 更新

More Related Content

What's hot

lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用hugo
 
async io frame
async io frameasync io frame
async io framerfyiamcool
 
Database.Cache&Buffer&Lock
Database.Cache&Buffer&LockDatabase.Cache&Buffer&Lock
Database.Cache&Buffer&LockLixun Peng
 
Track2 -刘继伟--openstack in gamewave
Track2 -刘继伟--openstack in gamewaveTrack2 -刘继伟--openstack in gamewave
Track2 -刘继伟--openstack in gamewaveOpenCity Community
 
一个 Mongodb command 的前世今生
一个 Mongodb command 的前世今生一个 Mongodb command 的前世今生
一个 Mongodb command 的前世今生dennis zhuang
 
Redis配置文件说明
Redis配置文件说明Redis配置文件说明
Redis配置文件说明jimmyyem
 
PostgreSQL 9 Standby
PostgreSQL 9 StandbyPostgreSQL 9 Standby
PostgreSQL 9 StandbyMarch Liu
 
统一接入的架构思考
统一接入的架构思考统一接入的架构思考
统一接入的架构思考yang bingwu
 
Build scalable microblog qcon beijing 2010
Build scalable microblog qcon beijing 2010Build scalable microblog qcon beijing 2010
Build scalable microblog qcon beijing 2010Tim Y
 
Php及drupal性能优化系列(二)
Php及drupal性能优化系列(二)Php及drupal性能优化系列(二)
Php及drupal性能优化系列(二)Robbin Zhao
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践rewinx
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践Frank Cai
 
对MySQL应用的一些总结
对MySQL应用的一些总结对MySQL应用的一些总结
对MySQL应用的一些总结Lixun Peng
 
使用Rpm&yum进行基础软件管理
使用Rpm&yum进行基础软件管理使用Rpm&yum进行基础软件管理
使用Rpm&yum进行基础软件管理haiyuan ning
 
Lamp优化实践
Lamp优化实践Lamp优化实践
Lamp优化实践zhliji2
 
构建基于Lamp的网站架构
构建基于Lamp的网站架构构建基于Lamp的网站架构
构建基于Lamp的网站架构Cosey Lee
 
Mysql展示功能与源码对应
Mysql展示功能与源码对应Mysql展示功能与源码对应
Mysql展示功能与源码对应zhaolinjnu
 
并发编程交流
并发编程交流并发编程交流
并发编程交流bluedavy lin
 
cdn的那些事儿
cdn的那些事儿cdn的那些事儿
cdn的那些事儿rfyiamcool
 
负载均衡
负载均衡负载均衡
负载均衡uptodate
 

What's hot (20)

lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用
 
async io frame
async io frameasync io frame
async io frame
 
Database.Cache&Buffer&Lock
Database.Cache&Buffer&LockDatabase.Cache&Buffer&Lock
Database.Cache&Buffer&Lock
 
Track2 -刘继伟--openstack in gamewave
Track2 -刘继伟--openstack in gamewaveTrack2 -刘继伟--openstack in gamewave
Track2 -刘继伟--openstack in gamewave
 
一个 Mongodb command 的前世今生
一个 Mongodb command 的前世今生一个 Mongodb command 的前世今生
一个 Mongodb command 的前世今生
 
Redis配置文件说明
Redis配置文件说明Redis配置文件说明
Redis配置文件说明
 
PostgreSQL 9 Standby
PostgreSQL 9 StandbyPostgreSQL 9 Standby
PostgreSQL 9 Standby
 
统一接入的架构思考
统一接入的架构思考统一接入的架构思考
统一接入的架构思考
 
Build scalable microblog qcon beijing 2010
Build scalable microblog qcon beijing 2010Build scalable microblog qcon beijing 2010
Build scalable microblog qcon beijing 2010
 
Php及drupal性能优化系列(二)
Php及drupal性能优化系列(二)Php及drupal性能优化系列(二)
Php及drupal性能优化系列(二)
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践
 
对MySQL应用的一些总结
对MySQL应用的一些总结对MySQL应用的一些总结
对MySQL应用的一些总结
 
使用Rpm&yum进行基础软件管理
使用Rpm&yum进行基础软件管理使用Rpm&yum进行基础软件管理
使用Rpm&yum进行基础软件管理
 
Lamp优化实践
Lamp优化实践Lamp优化实践
Lamp优化实践
 
构建基于Lamp的网站架构
构建基于Lamp的网站架构构建基于Lamp的网站架构
构建基于Lamp的网站架构
 
Mysql展示功能与源码对应
Mysql展示功能与源码对应Mysql展示功能与源码对应
Mysql展示功能与源码对应
 
并发编程交流
并发编程交流并发编程交流
并发编程交流
 
cdn的那些事儿
cdn的那些事儿cdn的那些事儿
cdn的那些事儿
 
负载均衡
负载均衡负载均衡
负载均衡
 

Viewers also liked

SSDB 入门基础
SSDB 入门基础SSDB 入门基础
SSDB 入门基础ideawu
 
SSDB(LevelDB server) vs Redis
SSDB(LevelDB server) vs RedisSSDB(LevelDB server) vs Redis
SSDB(LevelDB server) vs Redisideawu
 
LevelDB 간단한 소개
LevelDB 간단한 소개LevelDB 간단한 소개
LevelDB 간단한 소개종빈 오
 
Leveldb background
Leveldb backgroundLeveldb background
Leveldb background宗志 陈
 
7. Key-Value Databases: In Depth
7. Key-Value Databases: In Depth7. Key-Value Databases: In Depth
7. Key-Value Databases: In DepthFabio Fumarola
 
The Missing Manual for Leveled Compaction Strategy (Wei Deng & Ryan Svihla, D...
The Missing Manual for Leveled Compaction Strategy (Wei Deng & Ryan Svihla, D...The Missing Manual for Leveled Compaction Strategy (Wei Deng & Ryan Svihla, D...
The Missing Manual for Leveled Compaction Strategy (Wei Deng & Ryan Svihla, D...DataStax
 
BlueStore: a new, faster storage backend for Ceph
BlueStore: a new, faster storage backend for CephBlueStore: a new, faster storage backend for Ceph
BlueStore: a new, faster storage backend for CephSage Weil
 

Viewers also liked (7)

SSDB 入门基础
SSDB 入门基础SSDB 入门基础
SSDB 入门基础
 
SSDB(LevelDB server) vs Redis
SSDB(LevelDB server) vs RedisSSDB(LevelDB server) vs Redis
SSDB(LevelDB server) vs Redis
 
LevelDB 간단한 소개
LevelDB 간단한 소개LevelDB 간단한 소개
LevelDB 간단한 소개
 
Leveldb background
Leveldb backgroundLeveldb background
Leveldb background
 
7. Key-Value Databases: In Depth
7. Key-Value Databases: In Depth7. Key-Value Databases: In Depth
7. Key-Value Databases: In Depth
 
The Missing Manual for Leveled Compaction Strategy (Wei Deng & Ryan Svihla, D...
The Missing Manual for Leveled Compaction Strategy (Wei Deng & Ryan Svihla, D...The Missing Manual for Leveled Compaction Strategy (Wei Deng & Ryan Svihla, D...
The Missing Manual for Leveled Compaction Strategy (Wei Deng & Ryan Svihla, D...
 
BlueStore: a new, faster storage backend for Ceph
BlueStore: a new, faster storage backend for CephBlueStore: a new, faster storage backend for Ceph
BlueStore: a new, faster storage backend for Ceph
 

Similar to 高性能并发网络服务器设计与实现

Lysu's Java Socket notes
Lysu's Java Socket notesLysu's Java Socket notes
Lysu's Java Socket noteslysu
 
Java技术讲座 网络编程
Java技术讲座 网络编程Java技术讲座 网络编程
Java技术讲座 网络编程xujie
 
Unix socket
Unix socketUnix socket
Unix socketst900278
 
Erlang开发及应用
Erlang开发及应用Erlang开发及应用
Erlang开发及应用litaocheng
 
构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 Renaun Erickson
 
PHP 應用之一 socket funion : 偽 WEB Server
PHP 應用之一 socket funion : 偽 WEB ServerPHP 應用之一 socket funion : 偽 WEB Server
PHP 應用之一 socket funion : 偽 WEB Server志賢 黃
 
深入浅出Netty l.t
深入浅出Netty   l.t深入浅出Netty   l.t
深入浅出Netty l.toleone
 
第18讲 Hdlc和Ppp
第18讲 Hdlc和Ppp第18讲 Hdlc和Ppp
第18讲 Hdlc和PppF.l. Yu
 
线程与并发
线程与并发线程与并发
线程与并发Tony Deng
 
Rpc原理与实现
Rpc原理与实现Rpc原理与实现
Rpc原理与实现wavefly
 
Hbase使用hadoop分析
Hbase使用hadoop分析Hbase使用hadoop分析
Hbase使用hadoop分析baggioss
 
Io t security-ameba-ppt
Io t security-ameba-pptIo t security-ameba-ppt
Io t security-ameba-pptJou Neo
 
[圣思园][Java SE]Network
[圣思园][Java SE]Network[圣思园][Java SE]Network
[圣思园][Java SE]NetworkArBing Xie
 
Introduction of netty
Introduction of nettyIntroduction of netty
Introduction of nettyBing Luo
 
intro syslog syslogng
intro syslog syslogngintro syslog syslogng
intro syslog syslogngjuruntang
 
Syslog Ng
Syslog NgSyslog Ng
Syslog Ngflytod
 
syslog&syslog-ng
syslog&syslog-ngsyslog&syslog-ng
syslog&syslog-ngjurntang
 
gRPC - 打造輕量、高效能的後端服務
gRPC - 打造輕量、高效能的後端服務gRPC - 打造輕量、高效能的後端服務
gRPC - 打造輕量、高效能的後端服務升煌 黃
 
Openstack neutron 原理详解
Openstack neutron 原理详解Openstack neutron 原理详解
Openstack neutron 原理详解Yong Luo
 

Similar to 高性能并发网络服务器设计与实现 (20)

Lysu's Java Socket notes
Lysu's Java Socket notesLysu's Java Socket notes
Lysu's Java Socket notes
 
Java技术讲座 网络编程
Java技术讲座 网络编程Java技术讲座 网络编程
Java技术讲座 网络编程
 
Unix socket
Unix socketUnix socket
Unix socket
 
Erlang开发及应用
Erlang开发及应用Erlang开发及应用
Erlang开发及应用
 
构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接
 
PHP 應用之一 socket funion : 偽 WEB Server
PHP 應用之一 socket funion : 偽 WEB ServerPHP 應用之一 socket funion : 偽 WEB Server
PHP 應用之一 socket funion : 偽 WEB Server
 
Flash网络通讯处理 陈苏俊
Flash网络通讯处理 陈苏俊Flash网络通讯处理 陈苏俊
Flash网络通讯处理 陈苏俊
 
深入浅出Netty l.t
深入浅出Netty   l.t深入浅出Netty   l.t
深入浅出Netty l.t
 
第18讲 Hdlc和Ppp
第18讲 Hdlc和Ppp第18讲 Hdlc和Ppp
第18讲 Hdlc和Ppp
 
线程与并发
线程与并发线程与并发
线程与并发
 
Rpc原理与实现
Rpc原理与实现Rpc原理与实现
Rpc原理与实现
 
Hbase使用hadoop分析
Hbase使用hadoop分析Hbase使用hadoop分析
Hbase使用hadoop分析
 
Io t security-ameba-ppt
Io t security-ameba-pptIo t security-ameba-ppt
Io t security-ameba-ppt
 
[圣思园][Java SE]Network
[圣思园][Java SE]Network[圣思园][Java SE]Network
[圣思园][Java SE]Network
 
Introduction of netty
Introduction of nettyIntroduction of netty
Introduction of netty
 
intro syslog syslogng
intro syslog syslogngintro syslog syslogng
intro syslog syslogng
 
Syslog Ng
Syslog NgSyslog Ng
Syslog Ng
 
syslog&syslog-ng
syslog&syslog-ngsyslog&syslog-ng
syslog&syslog-ng
 
gRPC - 打造輕量、高效能的後端服務
gRPC - 打造輕量、高效能的後端服務gRPC - 打造輕量、高效能的後端服務
gRPC - 打造輕量、高效能的後端服務
 
Openstack neutron 原理详解
Openstack neutron 原理详解Openstack neutron 原理详解
Openstack neutron 原理详解
 

高性能并发网络服务器设计与实现

  • 2. 网络服务器开发  协议设计 ( 网络协议和应用协议 )  语法 ( 报文格式 )  语义 ( 指令的处理 , 交互时序等 )  只要涉及到交互 ( 即使不是网络交互 ), 就需要协议  网络实现 (IO)  网络开发的基础是 socket  任何对网络的封装 , 在三度关系之内必然是 socket( 最多三层封装 )
  • 4. Talk is cheap, show me the code serv = new TcpSocket(); serv.listen(); sock = serv.accept(); sock.read(buf); sock.write(buf); sock.close()  一次服务  没有并发  短连接  有没有协议 ?  最简单的 TCP 服务器
  • 6. socket IO  read/write 是可阻塞的  阻塞是并发和高性能的死敌  实现并发和高性能的途径就是解阻塞  太简单了 !  后面继续讲解 read/write...
  • 8. 优缺点  优点 :  简单易用 , 一般工作得很好  多线程 , 可以利用 CPU 多核  缺点 :  启动线程也有成本 , 很可能占大头  线程的数量不受控制 , 危险 !  问题在于 IO...
  • 9. IO 多路复用  专业地解决一个问题  select/poll/epoll/kqueue 的 API 几乎一样 , 实 现不同 , 性能不同  IO 多路复用接口的作用 , 就是测试 accept/read/write 等 IO 调用会不会阻塞
  • 10. IO 多路复用示例 serv = new TcpSocket(); serv.listen(); select.add(serv, READ); // READ 表示只测试可读 ( 读不阻塞 ) while(1){ readable, writable = select.wait(); foreach(readable as sock){ if(sock == serv){ sock = serv.accept(); select.add(sock, READ); }else{ sock.read(buf); sock.write(buf); sock.close(); } } // writable 为空 , 因为我们不测试可写 }
  • 13. 报文设计  最重要的 TCP 协议是流式协议 , 但几乎 所有的应用协议都是基于报文的 协议  报文分隔  用连接关闭来表示报文结束 . 如 , HTTP/1.0 的响应  固定长度的报文 . 如 , TFTP 的数 据报文 .  带自描述长度的固定长度首部的变 长报文 . 如 IP 包 , TCP 分段 .  带结束符 . 如 , 行协议 , HTTP 协 议 . 逐字节解析和数据转义的影响 . 高层 文本 , 带结 束符 底层 二进制 , 固 定长度
  • 14. SSDB 的报文格式 Packet := Block+ 'n' Block := Size Data Size := literal_integer 'n' Data := size_bytes_of_data 'n' 示例 : 3 get 3 key < 回车 >
  • 15. 优点  简单  带长度字段 , 支持二进制数据  同时对人和对机器友好 , 报文数据文本化效果好 . 可以 telnet 到服务器进行交互  解析器非常简单 , PHP 代码不过几十行  同时兼容 LF 和 CRLF( 惯例 )
  • 16. socket io 2  read/write 读取 / 发送的是字节数组 . C 语言的 char[], PHP 的 string  read 返回时读取的准确字节数无法预计  导致 " 粘包 ", " 断包 "  write 返回时不表示数据已到达对方机器  所以 , 即便基于可靠传输的 TCP 协议 , 也需要应用层 协议进行确认来保证真正意义上的 " 可靠 "
  • 17. 带有报文解析的服务器 serv = new TcpSocket(); serv.listen(); sock = serv.accept(); client = new Client(sock); client.recv(packet); client.send(packet); client.close()  packet 一般是编程语言中的对象
  • 18. 序列化和反序列化  read 收到的是字节数组 , 要进行反序列化转成编 程语言的对象  反序列化的过程就是报文解析
  • 19. 解析报文 bytes = []; while(1){ bytes += sock.read(); if(try_parse(bytes, &len) == READY){ // 已经解析出了一个报文 , 报文的长度是 len // 从字节数组中清除掉已解析的 bytes.remove(len); } }
  • 20. 整合网络 IO 和报文解析  将上例中的 read 和 try_parse 分离  作业 ...
  • 21. 第三节 – 业务处理  网络服务器 = 协议处理 + 网络 IO + 业务处 理
  • 22. 业务处理的位置 serv = new TcpSocket(); serv.listen(); sock = serv.accept(); client = new Client(sock); request = client.recv(); response = process(request); client.send(response); client.close() 对于 SSDB, LevelDB 相关的操 作封装在 process 中 .
  • 23. IO 多路复用正确实践  IO 多路复用的程序具有相同的核心逻辑 ( 主循 环 )  初学者套用固定套路也能写出可用的代码  初学者对 IO 多路复用的不完整理解 , 会导致程 序具有致命缺陷
  • 24. IO 多路复用的基本框架 while(1){ readables = epoll.wait(); foreach(readables as r){ if(r.type == SERVER){ client = r.accept(); epoll.add(client); } if(r.type == CLIENT){ data = r.receive(); resp = process(data); r.send(resp); } } }  经典套路  易学上手  process 可能阻塞
  • 25. IO 多路复用 + 多线程 ( 错误 ) while(1){ readables = epoll.wait(200); foreach(readables as r){ if(r.type == SERVER){ client = r.accept(); epoll.add(client); } if(r.type == CLIENT){ data = r.receive(); queue.push(data); } } resp = queue.pop(); resp.client.send(resp); }  经典套路  易学上手  多线程  queue.pop() 可 能阻塞
  • 26. 错误在哪 ? 时间点 客户端 服务器端 0ms 发出请求 10ms 网络延时 10ms, 收到请求 20ms 线程处理完毕 220ms epoll.wait() 阻塞了 200ms 220ms client.send() 230ms 网络延时 10ms, 收到响应  从客户端的角度 , 请求花了 230ms  从服务器端的角度 , 它只化了 20ms 处理请求  问题出在错误的 epoll 使用 !
  • 27. 接上 epoll.wait(200) 的阻塞时间是 0ms ~ 200ms 参数决定阻塞上限 , 但不能改为 0, 否则 CPU 占用 100% 解决方案 : SelectableQueue, 让 epoll 来监听 queue, 使得 epoll.wait() 不会无端阻塞
  • 28. IO 多路复用 + 多线程 ( 正确 ) queue = new SelectableQueue(); epoll.add(queue); while(1){ readables = epoll.wait(); foreach(readables as r){ if(r.type == SERVER){ client = r.accept(); epoll.add(client); } if(r.type == CLIENT){ data = r.receive(); queue.push(data); } if(r.type == QUEUE){ resp = queue.pop(); resp.client.send(resp); } } }  经典套路  易学上手  多线程  需要实现 SelectableQueu e