网络编程套路杂记1
edisonpeng@tencent.com
网络client程序
基本套路:
1. connect to server
同步sync + timeout方式
异步connect + callback方式
2. send request & recv response
同步方式send + recv方式.
异步方式:
异步回调
每个请求生成一个Token, 发送请求并把Token存放到一个TokenTracker中, 之后callback回来后在TokenTracker中查找相应token,并进行相应回调处理.这是典型的
ACT(Asynchronous Completion Token)模式, 通常结合主动对象模式(Active Object)来实现RPC中间件的AMI(Asynchronous method invocation).ICE就是一例.
异步FutureTask
在某个选定时刻进行同步等待. 也是基于ACT和Active Object来实现.
网络server程序
Stateless server
例如http server, 只需要维护 连接对象, 一个连接(connection)对象通常也包含其相关的请求对象(request).
a. 若每个连接的请求是时序同步执行的:每个连接通常只需关联一个请求对象.等接收完一个请求的数据后,屏蔽其网络事件,直到处理完一个请求后才重新注册其网络事件.
b. 若每个连接可同时发送多个请求,则每个连接会若干个请求对象.
无论是a还是b情况下,每个请求的数据的接收和响应的发送必须时序化.
Stateful Server
例如用户状态服务器, 连接和client session的对应关系可能是 一对一, 一对多 或者 多对一.
如果连接和session是一对一,则session直接作为连接的attachment.
如果连接和session是 一对多 或者 多对一 关系. 那么必须有单独的查找表用于记录 连接 -> session 的对应关系.
1. accept 新连接.
创建新连接对象,新连接交给连接管理器进行session维护.
这里client connection的处理可以分为: connection per process/thread, threadPool等.
2. 请求处理
主要涉及的工作包括: 数据读取, 请求解析, 请求过滤(包括黑白名单过滤, 权限验证等), 请求处理.
总的来说,此阶段的工作可以做成SEDA模型, 比如数据读取可以根据不同的类别作不同的权衡,信令数据用单线程读取,大块数据用多线程/线程池读取.
其余阶段依此类推.
示例: Java的开源网络框架Mina,还有facebook的cassandra都实现了SEDA的网络处理模型.
server设计的技巧
1. 海量连接管理
如果在unix/linux下, 比如httpserver, 可以预先分配一个65535的数组来管理连接,因为linux下连接的fd都是整型,且分配是自增的,这样连接的定位就是O(1)的.
2. 海量Session超时处理
比如Google的Chubby这种有大量client session的server, 我们可以按照一定的超时时间刻度对session进行分组,并对组按session lastTouchTime时间降序排序,这样我们每次只需要检查session队列尾部元素是否过期并批量清除.
2. 异步的技巧
通过引入队列buffering机制来消除编程上的异步语义,单机网络程序比如tencent的MCP, 分布式网络程序比如JMS.