服务器核心框架之讨论


#1

背景:

•因为工作中要用到文件上传功能,在网上搜了下库。搜到了Poco,里面的库有http自带功能。由于:加密、应用程序服务框架、数据库操作类(SQLite,MongoDB)等对工作中很有用,所以继BOOST,Google的protobuf后又引入了。 •刚开始服务端用BOOST的asio做的,性能很不错,只是担心以后维护麻烦,既然引入了Poco,自然就把服务端网络程序改成了Poco实现了,这一实现不要紧,一实现发现问题了,发现Poco是基于SELECT模型的,性能很差。无奈之下,本着吸取ASIO和Poco的优势,又将BOOST的ASIO重新用Poco的设计思想实现了一遍(由于有了两者深刻的认识,2个多小时就搞定)。 •于是担心,如果HTTP采用Poco也会有同样的问题,于是在网上搜到了AVHttp的库,看上去很牛B的样子,还加了里面的群。

群:

里面确实有几个高手,比如菜博士、jack,他们视MFC,Poco,ACE,Java如垃圾(我看了Poco,接口和java的非常像)。极力推崇BOOST,STL。

昨天在群里发表了个话题,我说了下服务器实现的思路(核心框架)。自以为还不错,没想到引来了不同意见。jack还卖了个关子,直到晚上10点左右才出来解释原因。

进入正题–服务器核心框架

我的思路是这样的:

开一个线程专门接收socket消息,接收到消息后,用智能指针封装下,分发出去,然后开线程处理,处理完后,再回调,发送出去。菜博士说我受到ACE的影响,我说绝对没有,没接触过ACE。(注:ACE是网上公认的设计模式的典范,他对设计模式很不感冒)。然后又说这样的实现有这样那样的缺点。现在想起来,可能是受了Poco的enqueueNotification的影响。如下图:

思路很像,只是是全异步的(没有waitXXXX,是立即处理的)

我的做法是关于socket部分用一个io(boost::asio::io_service),单独线程;接收到消息封装后就不管了,直接发送给处理的io(多个),固定线程数,比如5个。然后进行处理,处理完后,再通过智能指针包装下,再通过消息发送。

菜说这个做法有问题,后来jack也做了补充。他说了他们的想法,经过一个晚上的思考,我总于想明白了。确实效率很高。

我用比较通俗的语言概括:

1.我的做法像是工厂流水线,一个消息,比如有多个肥皂进来,分给多个工人,他们各自处理(比如包装),然后把处理结果(包装好的肥皂盒)再放回流水线上。具体为:多个io,每个io一个线程,分别进行处理。 2. 菜博士和java的做法是像切洋肉末 ,即将所有处理看成一个"处理",然后通过多个线程处理,处理完及完毕。好比你给他一块肉,他就像一个娴熟的厨师,叭叭叭切好,再给你肉末,完事!一个io,多个线程,分发处理。

对照我先前实现的框架,发现改动很少,呵呵。


#2

1、你的作法更倾向于并行交给线程池处理,固定的几个线程(几名工人),有任务来就交给空闲的工人,应该是最常用的方式。 2、至于dr所说的是集中精力将一件事情处理好后立即反馈,使用多个线程同时运算得到结果处理一笔数据的时候当然会快上很多,但是并发量很大的时候似乎会不太理想? 个人认为还是要看应用场合选择合适的实现方式吧。


#3

是,你说的有道理。dr说的方式其实对程序员要求挺高的。多线程要注意同步,性能上的确高一筹。而我先前的做法,只要框架固定,每个类能确保在同一个线程中运行。看具体需求应用了。


#4

本主题已置顶,它将始终显示在它所属分类的顶部。可以由版主解除置顶或者点击清除置顶按钮。


#5

我并不认为你理解了我的意思.

首先第一点, 我的设计里并不会引起同一个socket的处理被并发执行. 一个 socket 上的数据总是被串行处理. 相反,你的设计, 后发的数据都有可能先被执行.

第二,我的设计对程序员要求非常低. 因为程序员使用的是同步的模式规划逻辑. 不需要思考异步带来的一些流程改变.

第三,( to @zxf ) 所谓的 “看应用场合选择合适的实现方式” 其实是给不合适的东西硬找合适的理由. 因为你根本没给出到底你的方式适合什么.


#6

#7

这个程序有代码么?放到github 上么


#8

蔡博士 您那有以上帖子 说的应用 asio代码例子么 我想参考下


#9

asio为什么不好维护呢?写惯了asio写nodejs更熟悉啊,况且nodejs那么多人在用


#10

最近也在做这个事情,github上最火的是facebook的proxygen和微软的cpprestsdk