高性能服務器軟件開發

關於這本書的簡單介紹:
注意,在這裏我們討論的高性能服務器軟件設計並不是通常意義上的高性能Web程序設計,比如說在J2EE、.NET框架下如何使用線程池提高性能,如何優化ASP,PHP程序,或者如何調整Apache,IIS等Web服務器以獲得更好的性能等等。
這裏討論的是真正高性能的從硬件到操作系統底層,然後到IO模型、應用模型的服務器設計,當然,作爲一家之言,裏面同樣充滿了誤解、偏見和無知,但是在指責我之前,請仔細思考你指責的理由,進行仔細的測試之後把你的完整意見告訴我,我會很感謝這種建設性的指責而不是其他。
我們面臨的問題
目前已經存在,而且將會越來越多的大量網絡應用,它們包括:
即時聊天服務器
FTP服務器
基於互聯網的媒體應用
大型購物網站
大型門戶網站
在線網絡遊戲
而在實際使用的時候,我們經常碰到下面的情況:
連接數過多,網站無法訪問。
無法下載文件,或者下載速度非常緩慢
同時連接的數量受到很大限制。
站點非常脆弱,經常受到這樣那樣的攻擊而癱瘓。
對於這些情況,通常的解決方案是:
增加硬件的性能
使用服務器集羣和負載均衡技術
更大的帶寬
這些真的需要嗎?
我們有沒有仔細的思考我們的硬件本身的限制,操作系統的限制,我們的應用程序的限制,真正的瓶頸在哪裏?
讓我們首先來看一看基本的c/s網絡應用。
基本的客戶/服務器網絡應用系統:
第一類 非基於連接的系統
電子郵件,百萬級的,使用的頻率有限,同時訪問的用戶有限,連接的數量受到限制
即時聊天、視頻或者其他在線媒體
這些系統有自己的功能限制。
基於連接的靜態系統
ftp下載
http訪問
基於連接的動態系統
包括動態頁面的Web 站點,動態的內容和用戶無關
包括用戶的概念以及用戶相關數據的系統,經常有一個後臺數據庫。
包括業務邏輯的系統,例如電子購物站點,信息港,以及最近流行的在線遊戲。
根本的問題是什麼
如何以儘可能少的CPU 時間,內存佔用,支持更多的網絡連接,發送/接收更多的數據。
從下往上系統的根本構造包括:
1.         硬件設施:包括CPU 的計算能力,硬盤、總線的帶寬,網絡設施的吞吐能力。
2.         操作系統:操作系統對併發連接的支持和開銷,操作系統的IO開銷
3.         網絡應用模型:基本的網絡IO模型,事件通知的機制
4.         應用模型:結合實際應用的應用系統設計
5.         編碼和實現:好的編碼和差的實現之間的差別是非常巨大的,在這裏我提出一些可能有偏見或者偏激的看法。
1,2硬件設施和操作系統的開銷比較。
我們將1,2結合起來進行比較:
選擇下面一些基本的硬件平臺:
典型的筆記本電腦,P4M平臺,100M網卡,512M內存
典型的臺式機,P4平臺,100M網卡,512內存
典型的服務器,xeon平臺,千兆網卡,1G內存
典型的AMD64位服務器,千兆網卡,1G內存
軟件系統包括:
Windows系統:
Windows2000 Profession
Windows2000 Advance Server
自由的Unix類系統:
Linux 2.4內核
Linux 2.6內核
FreeBSD5.1內核
主要的性能評估包括:
影響服務器性能的操作系統的基本調用評估
l         分配/釋放內存的開銷
l         創建/中止線程/進程的開銷
l         互斥鎖的開銷(上下文切換的開銷)
l         內存映像文件的創建/讀寫開銷
操作系統網絡性能的基本評估
l         套接字的創建/釋放開銷
l         套接字的綁定開銷
l         建立網絡連接的開銷
l         發送數據/接收數據的吞吐量
l         一次標準HTTP請求/響應的延時和開銷。
初步的結果表明,硬件方面,Xeon系統顯然超過了通常的筆記本和臺式機,而AMD 的64位系統在較低的主頻下有非常好的性能表現(我們仍然使用32位軟件進行測試)。而操作系統方面,所有的類Unix系統都全面超過Windows平臺,而Linux2.6內核是各個平臺中表現最好的。
網絡IO模型的設計和評估:
基本概念,操作系統採用何種方式通知應用軟件應該去某一個套接字上獲取數據或者發送數據。
最簡單的辦法,採用輪詢的機制循環檢查套接字的狀態,在很多時候,這種方式的效率反而最高。
輪詢方式具體的應用範圍:
其次,使用每個連接一個線程的方式,這種方式可行性決定於
操作系統可以使用線程的數量
操作系統線程創建和線程間切換的開銷。(初步的測試表明,linux2.6內核每秒可以創建5000以上的線程)
兩種基本的消息觸發方式:
條件觸發和邊沿觸發
常見的select就是條件觸發。
Window平臺:
包括常見的Select模型
event select模型
IO完成端口模型,實際上就是一種邊沿觸發的機制。
Linux平臺
基本的select模型,最大的問題在於尋找哪一個socket上面發生的事件(socket的本質是文件句柄,所以數量巨大)
邊沿觸發: 
   2.4內核推薦的實時信號模型
   2.6內核推薦的epoll模型
FreeBSD
基本的select模型
邊沿觸發的kqueue模型
性能評估:
基本的測試表明,在同時併發連接數量,每個連接的延時和吞吐量上,Linux 2.6內核都是勝利者,其性能顯著超過了2.4內核以及FreeBSD。所有的類Unix系統都將Windows系統遠遠拋在後面。在各種IO模型的比較下, linux2.6內核的epoll同樣成爲勝利者,而IO完成端口仍然是最後一名,顯然,對易用性和圖形性能的要求使得Windows並不適合作爲一個服務器端的操作系統。
應用系統的模型:
基本的Web服務器:
1靜態頁面的提供:
內存映像文件
直接文件發送,減少了文件的數據從核心拷貝到應用層然後再拷貝到核心的開銷
在Windows和Linux環境下都有相應的系統調用。
核心服務器,直接在覈心完成基本的HTTP服務:
khttpd
2動態內容的提供:
基本的硬編碼方式提供動態頁面
使用簡單的應用程序密切相關的腳本語言,
使用通用的腳本語言:
高性能的LUA
高性能但是過於龐大的Java
其它腳本語言PHP,ASP等等。
3 數據庫系統
本地存儲還是通過網絡訪問數據庫服務器?
Oracle、Sybase、SQL Server和其他的數據庫服務器
mySQL、mSQL、Postgres等open source數據庫服務器
本地:
Berkely DB
如果不需要複雜的事務處理和恢復功能,可以使用簡單高性能的,基本B *Tree存儲機制。
4 J2EE和.NET框架,複雜性的好處和代價。
其他應用服務器:
數據庫應用
在線遊戲
流媒體播放,RTP和其他並不廣爲人知的協議
下一代應用?P2PBT
新的思路,帶來的好處,當然也會由此帶來新的問題:
可能對整個互聯網帶寬和流量的影響
可能帶來的法律問題
下面該看看應用系統了,好的設計同樣是非常重要的:
真正高性能的程序設計
more small, more fast
more simple, more fast
更小的代碼更快
更簡單的代碼更快
現代計算機的體系,速度往往取決於CPU cache 的命中情況。
因此,更小、更簡單的代碼往往會獲得更好的性能。
l         刪除冗餘代碼,和一般理解相反,放在那裏不動的代碼即使沒有使用也會影響系統的性能。
l         不要低估或者高估編譯器的優化,除了代碼本身所能提供的信息以外,編譯器永遠不知道你到底要做什麼。
l         不要夢想複用,在代碼級重複使用你代碼的可能性接近於0
l         層層的封裝是效率的殺手
l         動態運行時解析,類型….帶來的問題遠遠大於所承諾的好處。
l         專用、專用再專用,把你的代碼限制在一個非常具體的場景中,通用的代碼往往意味着低效、潛在的誤用和其他錯誤。
l         不要做期待之外的事情,所有的bonus都是要付出代價的!
l         優化最常見的情況,而不是最糟糕的情況。
l         內存分配和釋放是非常昂貴的操作(從時間上,穩定性上都是)
l         不要想象,使用工具觀察你的代碼,vTune或者gProf等等,只有這樣才能發現真正的瓶頸所在。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章