您的位置:首页 > 编程语言

epoll编程,如何实现高并发服务器开发?

2016-04-14 17:52 495 查看


epoll编程,如何实现高并发服务器开发?

1、本系统处理的业务为多客户端接入,一旦接入基本超过8个小时的长连接,但是登陆以后客户端基本不怎么活动,只有客户端触发相关设定事件才会产生活跃通信。

2、查了很多资料,单单多进程是不现实的,但是多线程开发linux系统在线程的数量上是有上限的,如何解决?

3、QQ、SKYPE等的多客户端登陆软件,服务器一般是如何设计开发的?

4、客户端接入时间随机,系统运行初期不会存在同一时间成千上万用户登陆的情况,但是用户一旦接入服务器就会长时间不会断开。

5、能否使用epoll技术跟多线程技术配合开发?HOW?

6、系统开发使用TCP协议。

7、希望大家能给个详细开发框架。

1
条评论

分享

按投票排序按时间排序


13 个回答

70赞同
反对,不会显示你的姓名



swxlion,分布式架构师,性能优化和高伸缩性系统架…

MingH黄成独静思 等人赞同

闲答。

按重要性和基础程度,打乱下顺序吧~~

先回问题,然后说怎么实现。

注:以下数据,均基于亚马逊AWS c3.xlarge 机型。

虚拟CPU:4

内存:7.5 GB

c3.xlarge 配置和价格: AWS | Amazon EC2

~~~~~~~~~~ 分割线 ~~~~~~~~~~

2、查了很多资料,单单多进程是不现实的,但是多线程开发linux系统在线程的数量上是有上限的,如何解决?

多线程数量限制?有!但这重要吗?想着开着无限的线程,每个线程都在跑?

线程调度是有系统资源开销的!!!!

线程调度是有系统资源开销的!!!!

线程调度是有系统资源开销的!!!!

重要的事情说三遍~~!!!

理论上,如果没有I/O等待等让CPU idle的事情,线程数最好等于CPU核心数目。

线程数最好等于CPU核心数目!!!

线程数最好等于CPU核心数目!!!

线程数最好等于CPU核心数目!!!

重要的事情再说三遍。

举个实际的栗子:

本人负责公司网络框架的架构设计和开发。在4核的 c3.xlarge 虚拟机上,压测框架时,2000 worker 线程的QPS(这里理解为TPS问题也不大)远远低于4个worker线程的QPS!

4个worker线程,再加其他辅助线程,QPS最大每秒35万。2000 worker线程,加同样的辅助线程,QPS最大每秒15万~~!

大部分的时间和其他系统资源都消耗在了线程的切换上~~!这就是为什么单线程的程序在某些情况下比多线程的程序要快~~!(单线程模拟多线程的线程库,不妨参考 state thread:http://state-threads.sourceforge.net。足够简单。)

1、本系统处理的业务为多客户端接入,一旦接入基本超过8个小时的长连接,但是登陆以后客户端基本不怎么活动,只有客户端触发相关设定事件才会产生活跃通信。

6、系统开发使用TCP协议。
目前开的框架,TCP长链接,最大压测链接108万,总 QPS 6万。

服务器也是c3.xlarge。开了18台机器做客户端压,每台机器6万链接(记得要修改 /proc/sys/net/ipv4/ip_local_port_range,不然一台机器出不了这么多链接)。

4、客户端接入时间随机,系统运行初期不会存在同一时间成千上万用户登陆的情况,但是用户一旦接入服务器就会长时间不会断开。

压测,每批次新加6万链接。

5、能否使用epoll技术跟多线程技术配合开发?HOW?

Linux上,必须的!!!

3、QQ、SKYPE等的多客户端登陆软件,服务器一般是如何设计开发的?

没有一般,都是根据具体需求实际定制!!!

没有一般,都是根据具体需求实际定制!!!

没有一般,都是根据具体需求实际定制!!!

但分布式、去中心化、无状态化、一致性哈希、……,都是必须的~~~!

但分布式、去中心化、无状态化、一致性哈希、……,都是必须的~~~!

但分布式、去中心化、无状态化、一致性哈希、……,都是必须的~~~!

(说了好几个三遍,累死了~~~喝点水~~)

不妨上网搜搜,将网络架构,服务器架构的演化。中小型公司按那些套路来,基本都能搞定。图太多,说起来太罗嗦。都是重复劳动,我就不写了,请自己搜。

你问大公司?请参考第一句话:没有一般,都是根据具体需求实际定制!!!

补充一点:网上搜的,都会对memcached、redis 等有很大的依赖。但我上家公司,也用,很重要,但只是给PHP端用。后端服务集群全用专用缓存~!!

专用缓存~~!含逻辑~~!自己开发~~!

专用缓存~~!含逻辑~~!自己开发~~!

专用缓存~~!含逻辑~~!自己开发~~!

又说三遍。

撑住1.6亿注册用户。

7、希望大家能给个详细开发框架。

框架?是参考架构设计吧?

框架有很多,比如ICE,Facebook Thrift、Apache Thrift 等~~

注意,后两个thrift不完全相同~~!!!

然后怎么做:

没有固定的套路!!!只有要注意的要点!!!

没有固定的套路!!!只有要注意的要点!!!

没有固定的套路!!!只有要注意的要点!!!

又是三遍。

要点:

尽量少的线程切换

尽量少的共享冲突

尽量无锁

工作中的线程数尽量等于CPU核心数

尽量没有等待时间片的线程

逻辑尽量简化,避免不必要的封装和转发

工程不是学术,OOP要给简单易用高性能好维护让道~~!

(就是ICE概念多,太复杂,上家公司才开发了自己的框架。就是因为Facebook Thrift 太罗嗦,一个异步都要绕好几道弯,链接还和CPU核心绑定(如果就一个链接,10万QPS,你会发现就一个核忙得要死,其他核心都在吃干饭~),现在公司才决定自己开发网络框架。)

EPOLL:Edge Trigger、OneShot!!!

不要在epoll_wait()线程中用太长时间处理非epoll_wait()的事情。

能用atomic的就不要用mutex(这是C++11的事了)

上面就不三遍了,太多太啰嗦~~~

~~~~~~~~~~~~~ 7月3日追加 ~~~~~~~~~~~~~~

感谢 Irons Du曾凌恒每天不吃冰淇淋 的评论,涉及到一些昨天忘了的事情。

PS:今次不三遍了~~:)

追加要点:

A. 数据库

数据库一定要分布。

如果有好的数据路由中间层服务,或者好的集群管理器,或者好的Sharding服务,是MongoDB还是MySQL完全不重要~~~!

如果使用MongoDB,需要注意查询 API 的where处理(自定义Javascript查询条件)。C API的 where 处理非常非常低效(至少去年还是这样。今年因项目的关系,没有跟进)

数据库一定要分库分表。

分表强烈建议使用Hash分表,尽量避免按区段分表。

Hash分表设计好了,要扩容也非常容易。区段分表貌似扩容很容易,但时间长了,你的热点数据分布就极其不均匀了。

分库分表,尽量异步并发查询(靠你的数据路由中间件了。当前两家公司都是自己开发的,外面的吹得太凶,不实用。)

除支付业务外,严格禁止联合查询、复合查询、事务操作!!!!

(支付一会单说)

分库分表,表都不在一台机器上了,联合查询、复合查询、事务操作必然失败~~~!

联合查询、复合查询、事务相关的操作请由中间层服务配合完成!!!

PS:MySQL等,联合查询、复合查询、事务操作,效率极低~~极低~~~!!!还会因为锁表时间过长而阻塞其他查询~~!!

支付的逻辑设计并分解好了,可以不用事务完成。要用事务,请确定相关的表均部署在同一台数据库实例上!!!

B. 去中心化、无状态:

高弹性架构这是必须的。

尽量将状态剥离成一个单独的状态服务(也是分布式集群),其他业务逻辑全部变成无状态的。状态信息请通过状态服务处理。

无状态的一般去中心化都很简单。无外乎一致性哈希、随机、轮转等等。

去中心化也是确保无单点故障!!!

如果非要有中心,请尽量选折以下两个方案:

1. 中心如果很简单,请确保在崩溃/杀死后,1秒钟内能立刻复活启动~~~

2. 中心改为管理集群,自动选举主核心。当原主核心失效后,新的核心自动接管当前集群网络。

C. 协议:

不要使用XML!!!这都不想说了,让我看到就是千万只神兽在胸中蹦腾~~!!!

如果文本,请使用JSON。如果二进制,请使用JSON对应的二进制化协议。BSON嘛~~持保留态度。

如果需要协议的灰度升级,如果在协议灰度升级时不想实现两套不同版本的接口,请远离使用IDL的协议/框架!!!

这也是这两家公司弃用 ICE和Facebook Thrift 的原因之一。

最后,如果你是初入行者,不妨多看看前面其他大拿推荐的资料,看看Reactor模式,看看Proactor。多看看其他框架,服务集群的设计。

但是!!

当你成长后,一切模式、设计,都是扯淡~~!

模式是死的,需求是变动的,人和思维是活的!

只有根据实际需求,具体设计!具体定制!!!

(还记得无字真经吗~~)

(貌似扯远了,已经不是服务器高并发了,而是高并发后端系统集群了。。。-_-! )

编辑于 2015-07-03 52
条评论 感谢

分享

收藏没有帮助举报作者保留权利

108赞同
反对,不会显示你的姓名



韦易笑,不为博眼球,只在近人心!

风过太平洋哇哈哈、知乎用户 等人赞同

一个成熟的高性能服务器,epoll相关的代码,不到万分之一。

而往往入门服务端的人,都天真的人为:高性能服务端开发 == EPOLL,真好笑,

之所以会出现 epoll这种被捧上天的垃圾,

明明就是 posix 或者最早版本的 unix/bsd/systemv 的设计考虑不完善。

按今天的眼光反思 posix 和 unix/bsd/systemv 当年的设计,epoll 这种补丁就不应该实现。

异步 reactor 框架应该就只有一个简单而统一的 selector 就足够了,所有系统都相同,提供:

register: 注册

unregister:删除

set:设置

wait:等待事件

read:读取事件

wake:将等待中的 wait 无条件唤醒

别以为这些 poll / epoll / kevent / pollset / devpoll / select / rtsig

是些什么 “高性能服务器” 的 “关键技术”,它们只是一个 API,而且是对原有系统 API设计不完善打的补丁,各个内核实现了一套自己的补丁方式,它们的存在,见证了服务端技术碎片化的遗憾结果。

之所以会有这些乱七八糟的东西,就是早期的 posix / unix/ bsd /systemv 设计不周全,或者不作为留下的恶果。并非什么 “关键技术”。

---------

不用提 windows 的 iocp了,proactor 会来强奸你代码结构,遭到大家唾弃是有原因的。不像 reactor那样优雅,所以 java nio 选择 reactor 是正确的。即便在 reactor 中,epoll 也是一个失败的例子,调用最频繁的 epoll_ctl 的系统占用估计大家都感受过吧,这方面 epoll 真该象 kevent / pollset 学习一下。

编辑于 2015-07-02 24
条评论 感谢

分享

收藏没有帮助举报作者保留权利

10赞同
反对,不会显示你的姓名



加百,Coder/PM,开源,喜爱爵士乐

风过太平洋过河卒李宻 等人赞同

题主的问题各种跳跃我也不知道从哪个说起,我就简单就一般的高性能服务器的最基础的几点随便说说吧,欢迎拍砖

我觉得高并发这个,明白道理是主要的,并不需要记住是否epoll/iocp什么的吧,只需要知道做高并发需要做到异步非阻塞就可以了,至于工具的使用,epoll也好iocp也好什么都好,能实现理论上的高并发模型就ok

其实所谓高并发,就是服务对于每次的请求和响应的时间足够短,一次请求20ms,和一次请求10ms,肯定是后者的并发更高,我们开发所需要做到的,就是缩短请求和响应这种交互的时间长度

那么服务在哪些方面是耗时间的呢?做到哪些是省时间呢?

先从单机来说:

我们的服务都是运行在服务器上的,程序运行中需要用到的硬件大概有四样就是cpu,内存,网卡,还有磁盘,这四样的速度依次递减,而且速度差距都是N多倍的

程序一旦启动肯定是运行在内存中这跑不了,从磁盘加载到内存,然后再从内存一坨一坨的输送指令和运算需要的数据到L3三级缓存L2二级缓存L1一级缓存再到cpu,可以想象,越慢的设备你越少用它,就越不会被拖后腿,不拖后腿了,速度肯定就快了啊,所以高并发服务开发中这些是要考虑的一个必要点,比如业务必须用到磁盘怎么办啊?那就把磁盘当磁带,磁盘的顺序写是很快的,磁针不需要来回跳的寻道嘛。所以要做到,少用磁盘,尽量顺序写。

内存的使用,主要是代码中不要太多的临界资源争抢,就是多个线程一起读写同一块内存,这样本来并行的运算变成串行了,导致性能下降。

还有网络,网络的使用通常是rpc形式的,比如读数据库,读外部缓存,一个请求发出去,然后阻塞等待,等数据返回后再解除阻塞。那如果改变下方式,一个请求发出去你不阻塞等待,而是直接回头去做别的事,等请求的响应返回了提醒你一声,你再回来处理这个响应,这效率是不是就高了呢?epoll的作用就是做这个的,就是用来提高利用率的,阻塞傻等着没活干肯定是浪费啊

再说cpu,cpu的繁忙程度代表你执行指令的密集度,一般都是在并发强压下cpu的load就应该很高了,如果怎么压也不高就代表有io在拖后腿,就考虑怎么样能减少io的频率,如果并发不大cpu还很繁忙,那肯定是代码业务逻辑需要的运算太多,开始考虑优化逻辑,这方面的优化是无止境的,我感觉这也是技术含量最高的部分,各种算法的特点要很熟悉,然后判断是不是适合你的这个业务场景,另外还有很多可以提升性能的trick,对所用操作系统的特性也要很了解,这需要很多年的实践经验的积累。

多线程/多进程,这目的是利用多核,为了充分利用cpu,多线程的开发是很复杂的,不好管理,进程间能少通信就尽量少通信,否则就是互相拖后腿,线程数量也不能一味求多,线程间切换的开销是很大的,锁的使用要仔细考虑。

还有多机集群的方式,很好理解,跟多核cpu的道理一样,有更多的人同时干活来分担工作量,肯定单位时间内干的活就更多,干完活用的时间更少。多机集群的设计更加复杂。

想到哪儿写到哪儿了,大概就这些。

所以你看,epoll在高并发服务器的开发中,仅仅算是很小的一部分了。

以上说得比较简单粗略,题主的问题全说明白可不容易,体力消耗也会很大,推荐看本书《构建高性能web站点》,浅显易懂挺好看的,当然这本书不能解答qq服务器是咋设计等问题,书的内容比较基础。

=============

补充一下题主说的长链接,长链接多active链接少,这场景很适合epoll来做,epoll只处理active的链接,不活跃的就放在一边不太需要操心,其实目前linux系统所有的网络链接管理都可以用epoll

编辑于 2015-07-14 1
条评论 感谢

分享

收藏没有帮助举报作者保留权利

11赞同
反对,不会显示你的姓名



银酱,来而往之

JanLoDaikon、wugui
master 等人赞同

服务器后端框架其中大致差不多,可从以下几个部分去综合考虑设计:

一、套接字IO模型(Linux)

1 应用场景:a.登陆低并发,大量长连接,少量活动连接,TCP;b.业务未知,对事件的响应时间未知。

2 进(线)程模型设计:1.a中的场景是最适合使用epollIO复用模型,这种情况下,epoll的效率比其他IO复用模型(select,poll)要高效。如果业务简单(不耗时,不阻塞):单进程+eppll足以应付,在epoll的主循环中依次处理事件即可。业务比较耗时:单进程多线程+epoll或多进程+epoll,主进(线)程负责监听和分发事件,工作进程(线程)处理事件。

发布于 2013-09-01 6
条评论 感谢

分享

收藏没有帮助举报作者保留权利

1赞同
反对,不会显示你的姓名


知乎用户,Life
in unix = linux(?),MIPS,ARM

知乎用户 赞同

看一看Nginx的代码不就好了吗?

--2016年1月29日01:02:57--

有这么难吗?



/*当然,对于这样一句话也能碰碎了某些人的玻璃心,我想真诚地对你说,我是故意的。*/


编辑于 2016-01-29 2
条评论 感谢

分享

收藏没有帮助举报作者保留权利

0赞同
反对,不会显示你的姓名


知乎用户,高频交易

前端接口机,后端UDP,还要啥战斗机。

发布于 2015-07-02 添加评论 感谢

分享

收藏没有帮助举报作者保留权利

1赞同
反对,不会显示你的姓名



ing
miss,你们这些愚蠢的人类

Dennis
Yang 赞同

使用erlang..

发布于 2015-04-16 添加评论 感谢

分享

收藏没有帮助举报作者保留权利

0赞同
反对,不会显示你的姓名



徐波,资深游戏开发者
博客: 战魂小筑

C++用boost.asio, libevent都可以

如果确实在乎线程限制, 使用golang的虚拟线程也是不错的选择.

发布于 2015-04-15 添加评论 感谢

分享

收藏没有帮助举报作者保留权利

1赞同
反对,不会显示你的姓名

匿名用户

Mark
Liang 赞同

高性能服务器说白了就一点 妥善的利用CPU 和IO。把时间都用在CPU计算上,IO等待的时间都去做计算即可。弱弱的推荐 github c1000kpracticeguide 。8年前的机器做个单机百万也木有问题。

编辑于 2015-07-18 添加评论 感谢

分享

收藏没有帮助举报作者保留权利

4赞同
反对,不会显示你的姓名

匿名用户

叨叨叨叨文尔东萧凯 等人赞同

nginx 多进程网络编程的巅峰

memcached 多线程网络编程的巅峰

redis单进程网络编程的巅峰~~

@陈硕 陈大大说的, loop per thread 是正解~~

编辑于 2015-07-15 4
条评论 感谢

分享

收藏没有帮助举报作者保留权利

3赞同
反对,不会显示你的姓名



阳阳,一句话简直不能介绍自己

kian
coder、知乎用户、潘伟龙 赞同

EPOLL单线程处理事件,收到的数据放入QUEUE,多线程取出数据做业务逻辑。

编辑于 2013-11-27 添加评论 感谢

分享

收藏没有帮助举报作者保留权利

1赞同
反对,不会显示你的姓名



华磊,想当架构师的程序员

She'sGone 赞同

epoll这种多路复用就绪通知技术确实适合海量并发长链连接的场景下,与select/poll等相比,它去除了最大连接数的限制,也减少了在内核态和用户态之间复制文件描述符的开销。

发布于 2016-01-05 添加评论 感谢

分享

收藏没有帮助举报作者保留权利

1赞同
反对,不会显示你的姓名



aaron,码农一枚

She'sGone 赞同

用Nginx核心部分+改造下nginx_tcp_proxy就搞定啦
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: