网络编程资源
高性能 Socket 組件 HP-Socket v3.2.1-RC1 發布
http://bbs.csdn.net/topics/390763397
?
?
The C10K problem? 高性能服務器設計
http://www.cnblogs.com/fll/archive/2008/05/17/1201540.html
http://blog.sina.com.cn/s/blog_4aec22920100itkf.html
?
這周看了Dan Kegel那篇"The C10K problem",以下和大家分享一下。
故名思義,這文章是分析如果編寫一個服務器程序來支持上萬的客戶端連接的。
其關注的重點是io效率,目前大規模網絡程序的關鍵瓶頸。
作者認為需要權衡利弊的要點有以下
1.單線/進程處理多個I/O的做法: 其可選的方案有
?
?? ?b. 使用非阻塞IO。 即以非阻塞方式啟動IO,并等待IO就緒通知(select / poll等,通常對網絡IO有效,但不能提高磁盤IO的效率)
?? ?c. 使用異步IO。 調用 aio_write啟動IO,并等待IO的完成通知。
2.如果管理client連接
?? ?a. 一個進程處理一個client (經典unix方式)
?? ?b. 一個OS-level線程處理多個client, 對應每個client使用一個user-level線程(即線程庫,虛擬機提供的線程,協同等方式)
?? ?c. 一個OS-level線程處理一個client (java的內置線程等)
?? ?d. 一個OS-level線程處理一個活躍的client
3. 是否使用標準OS服務,還是把依靠具體OS內核
以上的選擇互相組合,產生一些常見解決方案.
1. 單線程處理多client,使用非阻塞IO 和水平觸發的就緒通知
**水平觸發(level-trigger)與邊界觸發(edge-trigger)對應,簡要說水平觸發意為根據狀態
也判斷是否觸發某事件, 而邊界觸發根據變化來判斷是否觸發某事件。
也就是傳統的io多路復用,這是目前大部分網絡程序的解決方式,它可以方便的在一個線程里管理多個
io。不需要考慮多線/程等問題, 代碼的邏輯不需要加入額外的復雜性。
但這里所指的非阻塞,是指在某個fd未就緒時的read或write操作, 程序不等待它的就緒而已。
這邊存在上面說對于磁盤IO并沒有提高效率的問題。
在大規模地對磁盤讀寫操作時, read 或write還是會導致整個程序長時間阻塞。
如果要避免這種情況,必須引入異步IO。 對于部分缺乏AIO的系統,就只能建立子線/進程來完成該操作。
另外一種對磁盤IO的優化方式是使用 內存映像IO。
這種方式的關鍵是判斷一組非阻塞的socket何時處于就緒狀態。
實現它們的方法有 select, poll, dev/poll 等。
2. 單線程處理多client,使用非阻塞IO 和就緒變化通知
意為使用邊界觸發的就緒通知。其實這種方案只是1的加速方式, 即只在fd狀況發生變化時
才去檢查fd是否變為就緒。這種實現必須去處理假事件,因為有些實現方式是fd接到任何包的時候都假定其變為就緒了。
實現它們的有 kqueue, epoll(指定ET模式)等。
一些通用的庫如libevent ACE等,把這些底層不同實現封裝起來,并提供不同IO策略的選擇。 按照
libevent作者Niels的測試數據 kqueue在所有之中性能最高。
3. 多個線程處理多個client, 使用異步IO
這是對于網絡IO和磁盤IO都很高效的方式。通常當異步IO發起后, 它使用邊界觸發的方式來提供IO的完成通知。
然后把完成的通知放到消息隊列里,等待程序的后續相應。
但這需要os提供AIO的支持,并且需要以異步的方式來設計程序,有一定復雜性。
4. 多個線程處理client
這是最簡單方式,就是讓但進/線程 的read 和 write 直接阻塞。
這個方法的最大缺點是, 需要支付每個進/線程的棧空間,并引入額外的上下文切換的開銷。
如果需要上萬個client, 建立上萬的進/線程目前是不太可能的。
5. 把服務器整合到os內核里
?? ?部分系統有這樣的嘗試,例如Liunx下的 khttpd 就是把web服務器整合到
系統內核里。 但這對我們的游戲參考價值不大。
?
轉載于:https://www.cnblogs.com/jingzhishen/p/3674230.html
總結
- 上一篇: CSV格式数据如何导入MySQL?
- 下一篇: ++i 与 i++