當前位置:編程學習大全網 - 編程語言 - libevent 回調函數 可以交替執行嗎

libevent 回調函數 可以交替執行嗎

壹.C10K的問題

C10K的問題在上個世紀90年代就被提出來了。大概的意思是當用戶數超過1萬時,很多設計不良好的網絡服務程序性能都將急劇下降、甚至癱瘓。並且,這個問題並不能通過升級硬件設備解決,是操作系統固有的問題,也就是說,如果妳的服務器最高能支撐1000個並發,盡管妳升級了計算能力高壹倍的 cpu,內存再翻壹番,硬盤轉速在快壹倍,也無法支撐2000個並發。

經典的網絡編程模型有4個:

1. Serve one client with each thread/process, and use blocking I/O。即對每個客戶都使用不同的線程或進程進行服務,在每個線程或進程中使用阻塞I/O。這是小程序和java常用的策略,對於交互式的應用也是常見的選擇,這種策略很能難滿足高性能程序的需求,好處是實現極其簡單,容易實現復雜的交互邏輯。我們常用的Apache、ftpd等都是這種工作。

2. Serve many clients with single thread, and use nonblocking I/O and readiness notification。即對所有的客戶使用單壹壹個線程或進程進行服務,在這個線程或進程裏,采用異步IO的策略。這是經典模型,優點在於實現較簡單,方便移植,也能提供足夠的性能;缺點在於無法充分利用多CPU的資源。

3. Serve many clients with each thread, and use nonblocking I/O and readiness notification 對經典模型2的簡單改進,仍然采用異步IO的策略,但對所有的客戶使用多個線程或進程進行服務。缺點是容易在多線程並發上出bug,甚至某些OS不支持多線程進行readiness notification

4. Serve many clients with each thread, and use asynchronous I/O 在有AI/O支持的OS上,能提供相當高的性能。不過AI/O編程模型和經典模型差別相當大,基本上很難寫出壹個框架同時支持AI/O和經典模型。這個模型主要是用於window平臺上。

在linux上開發高性能的網絡應用,只能選著第2、3種方式。考慮到復雜性,我們往往只采用第2種。下面就討論壹下第二種模型。

我們知道,實現異步IO壹般是采用select 或poll來實現。Select 定義如下:

int select(int n, fd_set *rd_fds, fd_set *wr_fds, fd_set *ex_fds, struct timeval *timeout);

Poll 的接口如下:

int poll(struct pollfd *ufds, unsigned int nfds, int timeout);

然而 Select 和Poll 在連接數增加時,性能急劇下降。這有兩方面的原因:首先操作系統面對每次的select/poll 操作,都需要重新建立壹個當前線程的關心事件列表,並把線程掛在這個復雜的等待隊列上,這是相當耗時的。其次,應用軟件在select/poll 返回後也需要對傳入的句柄列表做壹次掃描來判斷哪些句柄是可用的,這也是很耗時的。這兩件事都是和並發數相關,而I/O 事件的密度也和並發數相關,導致CPU 占用率和並發數近似成O(n2)的關系。

因為以上的原因,Unix 上開發了性能更高的epoll, kqueue, /dev/poll 這3個程序接口來解決上述問題。其中epoll 是linux 的方案,kqueue 是freebsd 的方案,/dev/poll 是最古老的Solaris 的方案,使用難度依次遞增。

簡單的說,這些api 做了兩件事:

1. 避免了每次調用select/poll 時kernel 分析參數建立事件等待結構的開銷,kernel 維護壹個長期的事件關註列表,應用程序通過句柄修改這個列表和捕獲I/O 事件。

2. 避免了select/poll 返回後,應用程序掃描整個句柄表的開銷,Kernel 直接返回具體的事件列表給應用程序。

二. libevent庫

由於epoll, kqueue, /dev/poll每個接口都有自己的特點,程序移植非常困難,於是需要對這些接口進行封裝,以讓它們易於使用和移植,其中libevent庫就是其中之壹。

按照libevent的官方網站,libevent庫提供了以下功能:當壹個文件描述符的特定事件(如可讀,可寫或出錯)發生了,或壹個定時事件發生了,libevent就會自動執行用戶指定的回調函數,來處理事件。目前,libevent已支持以下接口/dev/poll, kqueue(2), event ports, select(2), poll(2) 和 epoll(4)。Libevent的內部事件機制完全是基於所使用的接口的。因此libevent非常容易移植,也使它的擴展性非常容易。目前,libevent已在以下操作系統中編譯通過:Linux,BSD,Mac OS X,Solaris和Windows。

使用libevent庫進行開發非常簡單,也很容易在各種unix平臺上移植。壹個簡單的使用libevent庫的程序如下:

三.libevent庫的應用

Go2代理是壹個大流量的代理應用,月流量近TB。其中圖片、flash、zip文件占總流量的絕大部分。為了減少流量成本,需要將部分進行分流。開始時,使用了傳統的php代理來分流,但Go2並發訪問極大,多進程架構的php無法承受,在虛擬主機vps上啟動數秒後就立即癱瘓。後改用 python的twisted網絡架構,采用了twisted的異步tcp通訊功能。運行壹段時間後,發現twisted的異步dns穩定性不太好,經常發生系統級的崩潰。最後,經過分析比較,決定采用libevent庫來做Go2 的分流代理應用。

Libevent庫支持異步socket,支持異步dns,並本身還帶了個簡單的http 服務器。Go2 的分流代理應用就是使用了libevent庫的以上三個功能。

1、簡單的http 服務器:實現的分類代理的用戶端的輸入,輸出管理。

2、異步socket,實現了高並發性的用戶接入,和高並發性的目的服務器訪問。

3、異步dns,解決了dns查詢時的並發性和高效性。

  • 上一篇:軌道計算的月球軌道計算
  • 下一篇:計算機等級證考試分為幾級啊 具體有什麽用
  • copyright 2024編程學習大全網