现在的位置: 首页 > 综合 > 正文

网络并发 工作经验总结(2W/S级别吞吐)

2012年08月22日 ⁄ 综合 ⁄ 共 1929字 ⁄ 字号 评论关闭

协议设计原则:

第一条 使用文本协议, 尽量使用http协议;(文本协议利于调试和测试,也利于脚本使用, http协议成熟,比较多工具支持)
第二条 如果效率成为问题,可以在实现了文本协议之后,支持二进制协议;(这样程序的BUG可以用文本协议及早发现,后来调试也更方便);
第三条 选择二进制协议时(protocal_buffer, memcache协议, MessagePack),考虑脚本语言的兼容性(ruby, python可否使用),如果自己定义二进制协议,必须实现 ruby, python 的接口,这样方便以后调试和测试。



非 阻塞IO和多路分发(epoll),一开始可以使用LT模式,这样程序更容易实现些,后期可以改成ET模式。
ET模式要求一定要读完数据,所以缓存要考虑清楚,例如最大长度,超过就要丢弃请求(RESET或返回错误).


如果有的操作会阻塞,比如数据库操作,文件操 作,mmap, 那就用多线程。这样前端就是异步,后端就是同步的,简称半同步半异步。

用mutrace, 或valgrind 检测程序的mutex和rw_lock 会不会有大量 contention, 如果有的话,减小锁粒度或使用无锁算法(比如circle buffer, RCU, MS-queue).

 

多线程需要队列配合,如果线程是不会长时间休眠的,可以 每个线程都有一个队列,

但如果线程会长时间休眠,就需要使用一个线程组一个队列,线程每次从线程组的队列中取消,

这样可以避免因为线程休眠导致的任务阻塞(就是一个线程持有多个任务,但它休眠了,其它线程没有任务,有CPU也没办法抢到任务).

 


整数操作,尽量用atomic_interger operator, 不要去加锁。


大 量false的成员查找,可以使用 bloomfilter把 false成员挡掉,从而免去查询cache和数据的开销。
(例如 有3亿用户,但只有1千万有头像,那么用bloomfilter过滤掉 99%的用户访问,cache只要承受1%的压力,
这时只 要两个hash就可以了,我使用的是bobhash和 time33)


适当使用无锁算法(失败-重做原则)


一 个请求,不要跨越太多的线程处理,因为线程调度和同步需要比较多的时间,这会带来比较大的时延。

减少内存拷贝,可以参考Linux的 sk_buffer实现

减小锁粒度,例如容器操作,可以先swap后操作,这样只要在swap操作的时候加锁,后续操作可以不用加锁。

critical_section 和 spin_lock 可以省去陷入内核的时间,但是如果线程在 获得锁的时候被休眠了,那么其它线程就会白白浪费cpu.


服 务器最好主动关闭连接,如果客户端能确保主动关闭,那么可以考虑被动关闭来节省资源。 不然被动关闭需要超时机制来保证socket会被关闭掉。

主 动关闭会导致大量的 TimeWait,如果是socket异常,会客户端不合要求的请求,可以考虑用linger选项来 reset连接,从而节约服务器资源。

linger(onoff=1, linger = 0)会导致RESET包,无论是主动关闭还是被动关闭,也不管数据包有没有发送完.(shutdown函数不受影响)


http 的 header 可以用vector或固定几个变量来保存,不要使用 map<string,string>, 因为map<string,string>的insert和find效率都比较低。

编译时使用 -O2选项,这样可以提高 10-20%的效率。


用 g++ -pg 和 gprof 来剖析CPU性能问题, Oprofile 来进行更深入的剖析(L1 L2 Cache)。

 
内存泄露问题用 valgrind加上 ab 压力测试一段时间,就可以看出泄露部分。


CPU 100% 问题 gdb 随机断点几次,用 bt看堆栈基本可以看出,还可以使用 gprof 来看哪个函数占了最多的cpu。


strace 可以跟踪系统调用,和调用占用的时间,这个可以用来查进程休眠时间问题(CPU占用低,进程经常休眠)。


压力测试可以使用 ab, httperf, autobench。
功能测试:selenium


测试出系统性能曲线后,就要限 制前端的接入数量,保证系统高效。(接入过多,反而拖累系统,但也要考虑并发数的问题,所以要在吞吐和并发数之间折中)。


多路分 发的方式:
1. libevent, 使用c接口,这样可以分发到任意函数。(效率最高,灵活性大)
2. 通过虚函数分发。这个的缺点是,不能分发到不同函数。(最多人这么实现)

3. boost的 asio方式分发,使用function和bind对象来定制分发函数。(灵活性最大)

原文地址:http://www.cnblogs.com/napoleon_liu/archive/2010/07/16/1778503.html

抱歉!评论已关闭.