为什么有很多出名开源的C/C++方面的高性能网络库,比如libevent,boost-asio,有些企业还要自己写?
为什么有很多出名开源的C/C++方面的高性能网络库,比如libevent,boost-asio,有些企业还要自己写?
39 个回答
Levski 详情请看个人网站: http://levskiweng.me所以我认为LZ其实忽略了一个事实,也就是你看起来这些库解决的是同一个问题,所以你才会觉得是浪费,但实际上,这些不同的解决方案解决的不是同一个问题,至少不完全是一个问题。
那么接下来问题就变成了“为什么这些解决方案解决的不是同一个问题呢?”在这一点上,我同意@陈硕的观点,但是我觉得他没有说全,所以想补充一点说明,也就是我们该怎么评价通用性和针对性这两种针对解决问题思路。
一般来说,通用性解决方案的好处在于他有着较大的适用范围;但是缺点是在特定的场景下表现会退化,或者要实现如此的全能体验需要付出很大的代价(例如很笨重、耗费大量的内存等等)。举个现实中的例子,羊角锤(不是老罗的那个锤子OS哦)作为一个很通用的工具,可以用来敲钉子,可以用来起钉子,但是如果你用它敲堵墙试试?肯定能敲,但是估计LZ会累死吧。而针对性解决方案的好处在于他可以在特定场景下较好满足用户的需求,但是缺点是这种场景可能是考虑不完的,也就是只能适应特定的场合。
最后再举个网游角色的例子来结束:你是把角色的属性点全部放在一个方面来剑走偏锋;还是每个方面放一些属性点来全面发展,这完全取决于你的爱好(也就是你的需求):-)
比如性能你很看重,100是满分,那么 libevent 可能是 93 分,自己优化的可能性能达到了 95 的高分。
但是从稳定上来说 libevent 的稳定性打分是 98 分,你自己写的东西可能只有不到 80 分。
我推荐使用 libevent / libev / boost::asio 等成熟的网络库,无后顾之忧才是最好的。
说白了,用不用asio等库,很大程度是传统积淀造成的,特别是和老大们的偏好和意识有关系。老大们当年自己搞了个很丑的,凑合也能用,当时可能还没这么知名的库可以用。也可能是老大们没有意识到这些开源库,习惯性自己整个简单粗暴的。
虽然有的团队能写出比asio更优秀的,但大部分自己搞的都不如asio(不一定严格正确,拍脑袋想的结论),更多是上面的原因,老大的偏好与意识为主,老大喜欢接受开源库,团队在这块的积累就多。
知乎用户 libconcurrency,http://github.com/zhouzhenghui比如@陈硕 说很多写的比libevent/asio好,虽然我见过不多,但也不敢苟同。作为c库mudoo等好过libevent 我相信但比asio好的c++库几乎恐怕没有。还有所谓好坏往往只是评价的倾向性所得的结论,libevent容易被超越因为它只是单一的库,正如有些人说的,比直接用OS API方便不到哪里去,其实还有原因是受制于语言本身。我说asio好是因为其和整个boost库的整合,利用到了整个boost库或者说c++的强大之处。
另外无论asio,还是libevent,其实都不能单纯以网络库论,它们的核心在于as和evvent,就是提供一个程序运行的基本架构,这才是要用它们的的真正理由,方便你处理异步事件和并行同步。这一点上,一般自己写的库都不会比它们考虑的周全。更不用说正确性可靠性,性能大多数也比不过。
至于io,网络,跨平台,真的这只是副产品,哪怕作者自己可能也不一定意识到这一点。
所以这也往往是用与不用的蹊跷之处。
陈硕编程、C++、算法话题优秀回答者 Linux C++程序员,m…而专注某一平台(Linux)的性能更高的网络库只要5千行代码,几天就看下来了。
我见过的技术实力雄厚的公司都是自己写网络库的,而且都写得比libevent和asio更好。
我觉得能被楼主提名的库,的确很著名,然而著名不代表“强”,而是代表“适用范围广”,为了适应各种场景,一个项目可能往两方面走,要么做得很精简,很单一,让别人拿去拼装,这样做出的东西不见得就好用,要么就是把很多功能都整合起来,做得比较全,但要想兼顾各方面,性能等方面就得付出点代价了,就像其它答案提到这,要说这些库有名开源没错,但高性能可不见得,大体上讲“好用”也还过得去,但“很好用”也真不见得
举个现在我周边的例子吧,我是做云存储的,目前项目主攻redis,就是属于楼主说的很著名的软件一类,然而redis也有很多蛋疼的地方,比如全内存的成本问题,比如运维扩展性的问题,比如私有内存会因程序崩溃而丢数据的危险性,比如落地方式和全量同步的粗暴,比如aof信息的原始。。。综合看来自己做一套反而是成本最低的办法了
如果你自己拿个工具做小东西可能是感觉不到的,不妨也做一些开源的组件或框架来推荐给同事或好友使用,让他们给你提意见,对这方面的问题估计就能有很深的了解了
我自己的经历证明,除掉一些特例(比如Linux内核之类),只要你在项目中使用了你自己没能力写出来的库,出问题只是早晚的事。
反观成本,一个像libevent或者Boost.ASIO这样规模的库,从无到有整个实现一遍未必比你从头到尾去完整理解它们更麻烦。
对于小团队来说,为什么不使用libevent呢?我相信很多小团队还是乐意使用的.(包括nodejs,libevent,libuv,asio).因为小团队对于项目的要求是快速开发,够用就好,性能的要求是次要的.
对于大公司来说,拥有成百上千台服务器,底层的一点点,哪怕可能只有1%的优化,也能够节省大量的成本.另外,根据具体业务的区别,可以做一些特殊的优化,这些对于一个开源的网络库来说,都是不会去做的.
我个人也赞成一些技术公司应该有自己的”底蕴”和”沉淀”, 但维护这些自研的“库”也是需要成本的, 谁能保证当初设计的人就一直在你公司? 况且像libevent这样精简的库, 吃透的成本也不高. 总之, 我觉得是每个团队的阶段和情况不一样
我认为在技术选型中最忌讳完全基于个人喜好而做,这是对项目不负责任的表现。
成熟的技术人员一定会先基于客观事实权衡利弊,给各个选项打个分,综合评分很接近的时候才会依据喜好做出选择,而不是让个人喜好主宰选型。
很明显题主给出的是一个粗略的选择题:“自己轮一个” OR “使用著名开源库”
先看看我们需要在哪些维度去分析优劣,单从网络库这种功能上讲,大概有这么几个维度需要考量:
1.易用性(对应开发效率/成本)
2.稳定性(对应维护成本)
3.性能(硬件成本)
这三个维度哪个更重要视具体项目而定,不过就目前低廉的硬件成本和快速迭代的竞争环境来看,大多数项目的重要性顺序都是1>2>3的
1.首先看易用性,尽量少的心智负担,直观的表现形式,让用户最不易用错的约束性,尽量少的代码量;这些构成了易用性这个维度。在这个维度上,libevent、asio等几个著名开源库,因为回调模型导致其存在较重的的心智负担,表现形式也不够直观,回调中重入、生命期等问题也经常会让人用错。在这个维度上,也许自己轮的会更好吧。
2.再看稳定性,有着众多用户、作者活跃维护的开源库显然是完胜,这应该是毫无疑问的。
3.最后看性能,衡量一下自己的水准,如果有类似这几个开源库作者的编程能力,那么这几个开源库对你来说性能就是90分,自己针对性地造的轮子可以到95分;如果是一般人的水平,那么这几个开源库对你来说性能方面基本就是100分了。
综上所述,有以下几种情况有必要自己轮一个网络库:
1.项目对性能有极致要求(项目很高大上),或者硬件成本极高(比如阿里/google这种拥有数百万台服务器的公司),或者硬件资源受限(公司实在没钱买硬件/你的工资已经低廉到比硬件还便宜);同时要有很高的编程能力,能够付出相当长的时间成本把轮子跑到稳定,这通常需要数以月计的时间。(例如开源项目:muduo网络库)
2.在易用性方面有更高的要求,需要适应版本快速迭代的高速开发节奏;玩微服务架构,服务数量太多,如果不能分分钟撸一个服务出来,开发节奏完全跟不上;传统的回调模型太难写逻辑;(例如开源项目:libgo协程库)
3.写个玩具练手(以学习为目的)
其他情况就尽量使用开源项目吧,当然,上面提到的两个轮出来的项目目前也都是开源并且稳定的。
工欲善其事必先利其器,先琢磨透自己所使用的网络库,在下手。












