您的位置:首页 > 理论基础 > 计算机网络

网络IO工作模型以及在分布式中的应用

2012-04-01 14:13 549 查看
为了写【流式计算和异构数据源的整合】这篇文章,我手贱,打算先写两篇基础文章
这是个说简单不简单,说难不难的问题,简单是因为现在会的人多了,难是新手总会犯浑;只能说这是些个成熟的模型;以下是个人看法,有不对的地方请指出;

主线程收发包,这是基调(one loop)

工作线程是一个线程池(multithread)

工作线程需对外发包

阻塞的把包发出去

下游socket-buffer满了的话,要等着对端socket-buffer有空闲空间

非阻塞把包发出去

工作线程任务结束,发包的事情交给主线程,主线程交给系统进程(这个过程是很多初学者不好理解的地方)

工作线程需对外请求结果

阻塞把包发出去

那就阻塞把结果包读回来吧,简单(其实不简单,还跟对端的收发包逻辑有关系)
工作线程不阻塞,继续干别的,等主线程把包读回来,这又是一个有点小绕的过程,读包的是主线程,主线程把包又得交给工作线程(这个工作线程不一定是发起请求的线程),这就需要工作线程知道这个任务是处理外部请求,还是处理自己的读包请求结果,至少有一个地方需要做dispatch外部请求还是自己的请求结果;

非阻塞把包发出去

阻塞把包读回来,理论上是可以的,单觉得这方式有点搞笑;(可以想象如果对端的回包方式如果跟自己的收发包方式不匹配的话,可能读错包了)

工作线程不阻塞,继续干别的,带来跟上面同样的问题

工作线程就是主线程(one thread)

工作时需要对外发包

阻塞把包发出

在把包发出去之前,是没法响应外部请求的,因为你用的是主线程,它被你自己卡死了(新手常犯错误的地方)

非阻塞把包发出去

这才对头,主线程可以干别的了

需要对外请求结果

阻塞把包发出去

阻塞把包读回来,自己承受被卡死的后果吧
非阻塞把包读回来,很自然的方式,但是在socket的管理上也是有技巧的;

非阻塞把包发出去

阻塞把包读回来,同上搞笑方式;
非阻塞把包读回来,很自然的方式;

多线程同时收发包(multi loop,multi thread)

这方式我本人没实际做过,此前一直以为lock的代价不会比one lookup,multi thread小,后来看到有人用spin-lock来做,效果貌似不错的样子,倒是蛮有意思的;

// =======================NB的分割线====================================

// =======================NB的分割线====================================

// =======================NB的分割线====================================

分布式计算中的应用

如果觉得上面说的有点复杂,下面我来简化一下,实际在你的分布式的系统里,往往只需要某些特定的模型的组合;以下是我的分布式计算框架中的IO模型原则


socket

“accept的socket”绝对不允许和“connect的socket”同一管理(这两个是属于完全不同的东西)
对所有服务,每个请求的回包,都必须从收到请求的socket返回
内部服务之间,全部必须使用长连接(内存换cpu)

one loop,multi thread

所有收发包,都必须采用非阻塞方式,但是对IO使用者提供阻塞接口;

one loop,one thread

所有收发包,都必须采用非阻塞方式,同时做IO的模块提供简洁的非阻塞接口;

对IO的使用者来说,这东西的确简单了很多,但是这还是可能把问题推到了一个理论上最难的IO模型(可怜的网络IO码农),下面介绍应用中的问题


收发包时的错误处理

对任意一个ip-port的请求,都会有这几个错误发生的可能:connect失败,写包失败,读包失败,读到包了,包校验失败,更恶心的是超时,因为超时可以发生在以上任意一个时机。

对某个ip-port处理失败后的重试

重试原始ip-port、重试另外的ip-port
在重试的过程,收发包同样会出现以上的错误,别忘了,在你决定retry的时候,和刚去retry的时候,也有可能timeout;

如何实现multi-get

一个请求要发往多种server,结果需要合并给用户
多个请求要发往同一种server的不同节点,结果合并给用户

包的内存管理

常见两种core-dump情况:double-free,mem-leak,引用栈上内存(这基本是完全没理解啥叫异步);

问题的解决

觉得太难的话,放弃c/c++,用erlang or node.js吧;
非要用c/c++?等我写完另外两篇文章,补上我认为稍好点的解决方案(其实不难,需要的是细心,为请求包,允许的发送ip-port列表,等同一session所需要的所有数据建立一个上下文,再做个class转门响应以上任意一个错误和成功的回调,同时需要考虑超时,并且维护好自己的socket)。// @@ TODO

// ====================================

饭前一口气说了一通,吃完饭,好像没啥说的了,归栈写上一篇【流式计算的总结】文章吧... ... 欢迎讨论。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: