高性能服务器架构 第一篇

 

转自:http://www.doserv.com/article/2012/0831/5299117.shtml

 

本文不会涉及到多任务应用程序,在单个程序里同时处理多个任务现在已经很常见。比如你的浏览器可能就在做一些并行处理,但是这类并行程序设计没有多大挑战性. 真正的挑战出现在服务器的架构设计对性能产生制约时,如何通过改善架构来提升系统性能. 对于在拥有上G内存和G赫兹CPU上运行的浏览器来说,通过DSL进行多个并发下载任务不会有如此的挑战性. 这里,应用的焦点不在于通过吸管小口吮吸,而是如何通过水龙头大口畅饮,这里麻烦是如何解决在硬件性能的制约.(作者的意思应该是怎么通过网络硬件的改善来增大流量)

一些人可能会对我的某些观点和建议发出置疑,或者自认为有更好的方法, 这是无法避免的. 在本文中我不想扮演上帝的角色;这里所谈论的是我自己的一些经验,这些经验对我来说, 不仅在提高服务器性能上有效,而且在降低调试困难度和增加系统的可扩展性上也有作用. 但是对某些人的系统可能会有所不同. 如果有其它更适合于你的方法,那实在是很不错. 但是值得注意的是,对本文中所提出的每一条建议的其它一些可替代方案,我经过实验得出的结论都是悲观的. 你自己的小聪明在这些实验中或许有更好的表现,但是如果因此怂恿我在这里建议读者这么做,可能会引起无辜读者的反感. 你并不想惹怒读者,对吧?

本文的其余部分将主要说明影响服务器性能的四大杀手:

1) 数据拷贝Data Copies -- 技巧什么的

2) 环境切换Context Switches -- 理性创建线程

3) 内存分配Memory allocation -- 内存池

4) 锁竞争Lock contention -- 没有好的办法, 和具体的业务特点, 软件的设计结构有密切的联系

在文章结尾部分还会提出其它一些比较重要的因素,但是上面的四点是主要因素. 如果服务器在处理大部分请求时能够做到没有数据拷贝,没有环境切换,没有内存分配,没有锁竞争,那么我敢保证你的服务器的性能一定很出色.

数据拷贝Data Copies

本节会有点短,因为大多数人在数据拷贝上吸取过教训. 几乎每个人都知道产生数据拷贝是不对的,这点是显而易见的,在你的职业生涯中, 你很早就会见识过它;而且遇到过这个问题,因为10年前就有人开始说这个词。对我来说确实如此. 现今,几乎每个大学课程和几乎所有how-to文档中都提到了它. 甚至在某些商业宣传册中,"零拷贝" 都是个流行用语. 尽管数据拷贝的坏处显而易见,但是还是会有人忽视它. 因为产生数据拷贝的代码常常隐藏很深且带有伪装,你知道你所调用的库或驱动的代码会进行数据拷贝吗?答案往往超出想象. 猜猜"程序I/O"在计算机上到底指什么?哈希函数是伪装的数据拷贝的例子,它有带拷贝的内存访问消耗和更多的计算. 曾经指出哈希算法是一种有效的"拷贝"似乎能够被避免,但据我所知,有一些非常聪明的人说过要做到这一点是相当困难的. 如果想真正去除数据拷贝,不管是因为影响了服务器性能,还是想在黑客大会上展示"零复制"技术,你必须自己跟踪可能发生数据拷贝的所有地方,而不是轻信宣传.

有一种可以避免数据拷贝的方法是使用buffer的描述符(或者buffer chains的描述符)来取代直接使用buffer指针,每个buffer描述符应该由以下元素组成:

一个指向buffer的指针和整个buffer的长度

一个指向buffer中真实数据的指针和真实数据的长度,或者长度的偏移

以双向链表的形式提供指向其它buffer的指针

一个引用计数

现在,代码可以简单的在相应的描述符上增加引用计数来代替内存中数据的拷贝. 这种做法在某些条件下表现的相当好,包括在典型的网络协议栈的操作上,但有些情况下这做法也令人很头大. 一般来说,在buffer chains的开头和结尾增加buffer很容易,对整个buffer增加引用计数,以及对buffer chains的即刻释放也很容易. 在chains的中间增加buffer,一块一块的释放buffer,或者对部分buffer增加引用技术则比较困难. 而分割,组合chains会让人立马崩溃.

我不建议在任何情况下都使用这种技术,因为当你想在链上搜索你想要的一个块时,就不得不遍历一遍描述符链,这甚至比数据拷贝更糟糕. 最适用这种技术地方是在程序中大的数据块上,这些大数据块应该按照上面所说的那样独立的分配描述符,以避免发生拷贝,也能避免影响服务器其它部分的工作. (大数据块拷贝很消耗CPU,会影响其它并发线程的运行)

关于数据拷贝最后要指出的是:在避免数据拷贝时不要走极端. 我看到过太多的代码为了避免数据拷贝,最后结果反而比拷贝数据更糟糕,比如产生环境切换或者一个大的I/O请求被分解了. 数据拷贝是昂贵的,但是在避免它时,是收益递减的(意思是做过头了,效果反而不好). 为了除去最后少量的数据拷贝而改变代码,继而让代码复杂度翻番,不如把时间花在其它方面.

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值