1、互聯網伺服器架構設計包括那些內容??
1 伺服器購買和操作系統選擇
2 伺服器託管,分IP 電信/網通 帶寬 高度
3 伺服器軟體 例如WEB服務 郵局服務 資料庫 游戲服務等
4 伺服器安全配置
5 伺服器日常維護
2、c/s模式伺服器的架構
1、c/s、b/s是當下兩種伺服器架構模型。
2、c/s架構是指客戶端/伺服器的架構,需要同時編寫兩套代碼,即客戶端一套,服務端一套,所以開發起來速度較慢,日後的維護工作量也較大。
3、b/s架構是指瀏覽器/伺服器構架,只需要編寫伺服器端的代碼即可,開發完成了,就可以將應用部署到一些中間伺服器上來發布自己的運用,拿web應該用來說,這些伺服器有IIS、jboss、weblogic、websphere、tomcat等等。
4、客戶端與伺服器交互時,伺服器會根據客戶端的不同請求進行相應的業務處理,之後將結果返回對客戶端。
以上只是簡單的描述了下c/s、b/s架構,更詳細說明樓主可以網上找些相關資料了解。
有問題歡迎提問,滿意請採納!
3、伺服器結構
伺服器分塔式、機架式和刀片式這三種結構來劃分伺服器,伺服器的外形為什麼會有這樣的劃分呢?主要原因就是具體的應用環境不同,塔式伺服器長得跟我們平時用的台式機一樣,佔用空間比較大,一般是一些小型企業自己使用自己維護;而機架式伺服器長得就像卧著的台式機,可以一台一台的放到固定機架上,因此而得名,它可以拿去專業的伺服器託管提供商那裡進行託管,這樣每年只需支付一定的託管費,就免去了自己管理伺服器的諸多不便;而刀片伺服器是近幾年才比較流行的一種伺服器架構,它非常薄,可以一片一片的疊放在機櫃上,通過群集技術進行協同運算,能夠處理大量的任務,特別適合分布式服務,如作為WEB伺服器。
看完上面的簡單介紹,相信各位對這3種伺服器已經有個基本的認識了,下面我們就來一一細說,為大家做更詳細的講解:
什麼是塔式伺服器:
塔式伺服器應該是大家見得最多,也最容易理解的一種伺服器結構類型,因為它的外形以及結構都跟我們平時使用的立式PC差不多,當然,由於伺服器的主板擴展性較強、插槽也多出一堆,所以個頭比普通主板大一些,因此塔式伺服器的主機機箱也比標準的ATX機箱要大,一般都會預留足夠的內部空間以便日後進行硬碟和電源的冗餘擴展。
由於塔式伺服器的機箱比較大,伺服器的配置也可以很高,冗餘擴展更可以很齊備,所以它的應用范圍非常廣,應該說目前使用率最高的一種伺服器就是塔式伺服器。我們平時常說的通用伺服器一般都是塔式伺服器,它可以集多種常見的服務應用於一身,不管是速度應用還是存儲應用都可以使用塔式伺服器來解決。
就使用對象或者使用級別來說,目前常見的入門級和工作組級伺服器基本上都採用這一伺服器結構類型,一些部門級應用也會採用,不過由於只有一台主機,即使進行升級擴張也有個限度,所以在一些應用需求較高的企業中,單機伺服器就無法滿足要求了,需要多機協同工作,而塔式伺服器個頭太大,獨立性太強,協同工作在空間佔用和系統管理上都不方便,這也是塔式伺服器的局限性。不過,總的來說,這類伺服器的功能、性能基本上能滿足大部分企業用戶的要求,其成本通常也比較低,因此這類伺服器還是擁有非常廣泛的應用支持。
什麼是機架式伺服器:
作為為互聯網設計的伺服器模式,機架伺服器是一種外觀按照統一標准設計的伺服器,配合機櫃統一使用。可以說機架式是一種優化結構的塔式伺服器,它的設計宗旨主要是為了盡可能減少伺服器空間的佔用,而減少空間的直接好處就是在機房託管的時候價格會便宜很多。
為什麼說機架式伺服器是作為為互聯網設計的伺服器模式?
正如大家所知,很多專業網路設備都是採用機架式的結構(多為扁平式,活像個抽屜),如交換機、路由器、硬體防火牆這些。這些設備之所以有這樣一種結構類型,是因為他們都按國際機櫃標准進行設計,這樣大家的平面尺寸就基本統一,可把一起安裝在一個大型的立式標准機櫃中。這樣做的好處非常明顯:一方面可以使設備佔用最小的空間,另一方面則便於與其它網路設備的連接和管理,同時機房內也會顯得整潔、美觀。
機架伺服器的寬度為19英寸,高度以U為單位(1U=1.75英寸=44.45毫米),通常有1U,2U,3U,4U,5U,7U幾種標準的伺服器。機櫃的尺寸也是採用通用的工業標准,通常從22U到42U不等;機櫃內按U的高度有可拆卸的滑動拖架,用戶可以根據自己伺服器的標高靈活調節高度,以存放伺服器、集線器、磁碟陣列櫃等網路設備。伺服器擺放好後,它的所有I/O線全部從機櫃的後方引出(機架伺服器的所有介面也在後方),統一安置在機櫃的線槽中,一般貼有標號,便於管理。
現在很多互聯網的網站伺服器其實都是由專業機構統一託管的,網站的經營者其實只是維護網站頁面,硬體和網路連接則交給託管機構負責,因此,託管機構會根據受管伺服器的高度來收取費用,1U的伺服器在託管時收取的費用比2U的要便宜很多,這就是為什麼這種結構的伺服器現在會廣泛應用於互聯網事業。
還有一點要說的是機架式伺服器因為空間比塔式伺服器大大縮小,所以這類伺服器在擴展性和散熱問題上受到一定的限制,配件也要經過一定的篩選,一般都無法實現太完整的設備擴張,所以單機性能就比較有限,應用范圍也比較有限,只能專注於某一方面的應用,如遠程存儲和Web服務的提供等,但由於很多配件不能採用塔式伺服器的那種普通型號,而自身又有空間小的優勢,所以機架式伺服器一般會比同等配置的塔式伺服器貴上20-30%。至於空間小而帶來的擴展性問題,也不是完全沒有辦法解決,由於採用機櫃安裝的方式,因此多添加一個主機在機櫃上是件很容易的事,然後再通過伺服器群集技術就可以實現處理能力的增強,如果是採用外接擴展櫃的方式也能實現大規模擴展,不過由於機架式伺服器單機的性能有限,所以擴展之後也是單方面的能力得到增倍,所以這類伺服器只是在某一種應用種比較出色,大家就把它劃為功能伺服器,這種伺服器針對性較強,一般無法移做它用。
什麼是刀片伺服器?
對於企業和網路信息提供商來說,無限增長的數據必須集中存儲和處理,於是未來的網路發展呈現出集中計算的趨勢。集中管理模式與現有的分散管理模式,對伺服器提出了新的要求:節約空間、便於集中管理、易於擴展和提供不間斷的服務,成為對下一代伺服器的新要求。
作為網路重要組成部分的伺服器來說,性能已不僅僅是評價伺服器的唯一指標了,用戶更關心的是符合自己實際需要的產品。目前伺服器集群已經在市場上得以廣泛應用,而新一代機架式伺服器也開始進入市場,為用戶提供了更多的選擇。但是隨著網路向更深層面發展,下一代伺服器將會是BladeServer(刀片伺服器)。
刀片伺服器是一種HAHD(HighAvailabilityHighDensity,高可用高密度)的低成本伺服器平台,是專門為特殊應用行業和高密度計算機環境設計的。其中每一塊"刀片"實際上就是一塊系統主板。它們可以通過本地硬碟啟動自己的操作系統,如WindowsNT/2000、Linux、Solaris等等,類似於一個個獨立的伺服器。在這種模式下,每一個主板運行自己的系統,服務於指定的不同用戶群,相互之間沒有關聯。不過可以用系統軟體將這些主板集合成一個伺服器集群。在集群模式下,所有的主板可以連接起來提供高速的網路環境,可以共享資源,為相同的用戶群服務。在集群中插入新的"刀片",就可以提高整體性能。而由於每塊"刀片"都是熱插拔的,所以,系統可以輕松地進行替換,並且將維護時間減少到最小。值得一提的是,系統配置可以通過一套智能KVM和9個或10個帶硬碟的CPU板來實現。CPU可以配置成為不同的子系統。一個機架中的伺服器可以通過新型的智能KVM轉換板共享一套光碟機、軟碟機、鍵盤、顯示器和滑鼠,以訪問多台伺服器,從而便於進行升級、維護和訪問伺服器上的文件。
克服伺服器集群的缺點
作為一種實現負載均衡的技術,伺服器集群可以有效地提高服務的穩定性和/或核心網路服務的性能,還可以提供冗餘和容錯功能。理論上,伺服器集群可以擴展到無限數量的伺服器。無疑,伺服器集群和RAID鏡像技術的誕生為計算機和數據池的Internet應用提供了一個新的解決方案,其成本遠遠低於傳統的高端專用伺服器。
但是,伺服器集群的集成能力低,管理這樣的集群使很多IDC都非常頭疼。尤其是集群擴展的需求越來越大,維護這些伺服器的工作量簡直不可想像,包括伺服器之間的內部連接和擺放空間的要求。這些物理因素都限制了集群的擴展。「高密度伺服器」--BladeServer的出現適時地解決了這樣的問題。高密度伺服器內置了監視器和管理工具軟體,可以幾十個甚至上百個地堆放在一起。配置一台高密度伺服器就可以解決一台到一百台伺服器的管理問題。如果需要增加或者刪除集群中的伺服器,只要插入或拔出一個CPU板即可。就這個意義上來說,BladeServer從根本上克服了伺服器集群的缺點。
4、伺服器類型的架構
服務來器是靜態IP吧
直接自\\IP不行,你去ping下伺服器IP看看,如果能連接,但ping不通IP的話,一般是伺服器上的服務里有什麼被禁用了,把相關的和網路有關的服務全部打開。
還有就是防火牆關系,我之前就是因為防火牆ping不通IP,但能連接。
ping不通IP的話,\\IP回車就不能直接連接。
5、什麼是分布式系統架構
分布式應用程序就是指應用程序分布在不同計算機上,通過網路來共同完成一項任務,通常為伺服器/客戶端模式。更廣義上理解「分布」,不只是應用程序,還包括資料庫等,分布在不同計算機,完成同一個任務。之所以要把一個應用程序分布在不同的計算機上,主要有兩個目的:
1) 分散伺服器的壓力
大型系統中,模塊眾多,並發量大,僅用一個伺服器承載往往會發生壓力過大而導致系統癱瘓的情況。可以在橫向和縱向兩方面來進行拆分,把這些模塊部署到不同的伺服器上。這樣整個系統的壓力就分布到了不同的伺服器上。
l 橫向:按功能劃分。
l 縱向:N層架構,其中的一些層分布到不同的伺服器上(分層的概念會在後文進行介紹)。
2) 提供服務,功能重用
使用服務進行功能重用比使用組件進行代碼重用更進一層。舉例來說,如果在一個系統中的三個模塊都需要用到報表功能,一種方法是把報表功能做成一個單獨的組件,然後讓三個模塊都引用這個組件,計算操作由三個模塊各自進行;另一種方法是把報表功能做成單獨的服務,讓這三個模塊直接使用這個服務來獲取數據,所有的計算操作都在一處進行,很明顯後者的方案會比前者好得多。
服務不僅能對內提供還能對外提供,如果其他合作夥伴需要使用我們的報表服務,我們又不想直接把所有的信息都公開給它們。在這種情況下組件方式就不是很合理了,通過公開服務並對服務的使用方做授權和驗證,那麼我們既能保證合作夥伴能得到他們需要的數據,又能保證核心的數據不公開。
6、我是如何設計游戲伺服器架構的
游戲構架設計到底是啥?如果你自己都解釋不清楚,那就沒人可以回答你。 從技術實現角度,游戲構架 = 構架 只是游戲的結構有特殊性,擁有一些游戲特有的結構。 從內容設計角度,游戲構架 = 游戲系統設計 當然這個系統設計本身概念也很模糊,按照國外已經成形的理論體系,是屬於核心機制和交互設計的混合內容,不過是從用戶使用角度加以定義的。 這兩者的知識量包含都很大,大學學習不過是學個基礎罷了。 如果走技術實現方向,那麼一般的計算機專業都可以,不過大量基礎學科得通過自己的努力掌握扎實。演算法、數據結構、對象分析等都是很基礎的能力。不斷的了解游戲技術基礎原理和方法這其實是游戲引擎設計的領域,相當艱深和……枯燥。 如果走內容構架方向,我個人認為最有效的基礎學科是:哲學。因為系統設計大都是方法論的抽象和還原。當然,心理和經濟,甚至是建築方面的專業也都可以。因為內容構架需要的知識量更龐雜指望速成是沒希望的,選好方向,調整好心態前進就好了。
7、游戲伺服器架構和web伺服器架構的區別
web伺服器,是專門用來做web應用的,直接面對web編程,框架一般指的是做這個系統用到的一些基礎的技術結構 比如java中的ssh就是框架. 架構也有指框架的, 也有指整個項目的設計結構, 比如伺服器的結構, 關聯等等. 舉幾個例子,比如獨立的文件伺服器一般都算到架構里. 集群負載均衡一般都說是架構. spri。
8、前端本地開發和伺服器部署的架構怎樣設計合適
在 Application Virtualization Server Management Console 中創建伺服器組之後,可以使用以下過程向該組中添加伺服器。注意 伺服器組中的所有專伺服器必須連屬接到相同的數據存儲。
如果您有一個資料庫的使用頻率非常高,而且由於這些資料庫經常發出更新請求而導致群集復制器過載的話,您需要考慮使用多個群集復制器。在一個伺服器中運行多個群集復制器,可以同時將新的更改復制到其它伺服器中。
如果一個群集復制器在把更改復制到一個資料庫時太忙,會有另外一個群集復制器把更改復制到其它的伺服器。這樣,通過共同分擔復制負荷的方式,多個群集復制器使得數據得到快速的更新並能嚴格的保持同步。
9、幾種經典的網路伺服器架構模型的分析與比較
前言
事件驅動為廣大的程序員所熟悉,其最為人津津樂道的是在圖形化界面編程中的應用;事實上,在網路編程中事件驅動也被廣泛使用,並大規模部署在高連接 數高吞吐量的伺服器程序中,如 http 伺服器程序、ftp 伺服器程序等。相比於傳統的網路編程方式,事件驅動能夠極大的降低資源佔用,增大服務接待能力,並提高網路傳輸效率。
關於本文提及的伺服器模型,搜索網路可以查閱到很多的實現代碼,所以,本文將不拘泥於源代碼的陳列與分析,而側重模型的介紹和比較。使用 libev 事件驅動庫的伺服器模型將給出實現代碼。
本文涉及到線程 / 時間圖例,只為表明線程在各個 IO 上確實存在阻塞時延,但並不保證時延比例的正確性和 IO 執行先後的正確性;另外,本文所提及到的介面也只是筆者熟悉的 Unix/Linux 介面,並未推薦 Windows 介面,讀者可以自行查閱對應的 Windows 介面。
阻塞型的網路編程介面
幾乎所有的程序員第一次接觸到的網路編程都是從 listen()、send()、recv()等介面開始的。使用這些介面可以很方便的構建伺服器 /客戶機的模型。
我們假設希望建立一個簡單的伺服器程序,實現向單個客戶機提供類似於「一問一答」的內容服務。
圖 1. 簡單的一問一答的伺服器 /客戶機模型
我們注意到,大部分的 socket介面都是阻塞型的。所謂阻塞型介面是指系統調用(一般是 IO介面)不返回調用結果並讓當前線程一直阻塞,只有當該系統調用獲得結果或者超時出錯時才返回。
實際上,除非特別指定,幾乎所有的 IO介面 (包括 socket 介面 )都是阻塞型的。這給網路編程帶來了一個很 大的問題,如在調用 send()的同時,線程將被阻塞,在此期間,線程將無法執行任何運算或響應任何的網路請求。這給多客戶機、多業務邏輯的網路編程帶 來了挑戰。這時,很多程序員可能會選擇多線程的方式來解決這個問題。
多線程伺服器程序
應對多客戶機的網路應用,最簡單的解決方式是在伺服器端使用多線程(或多進程)。多線程(或多進程)的目的是讓每個連接都擁有獨立的線程(或進程),這樣任何一個連接的阻塞都不會影響其他的連接。
具體使用多進程還是多線程,並沒有一個特定的模式。傳統意義上,進程的開銷要遠遠大於線程,所以,如果需要同時為較多的客戶機提供服務,則不推薦使 用多進程;如果單個服務執行體需要消耗較多的 CPU 資源,譬如需要進行大規模或長時間的數據運算或文件訪問,則進程較為安全。通常,使用 pthread_create () 創建新線程,fork() 創建新進程。
我們假設對上述的伺服器 / 客戶機模型,提出更高的要求,即讓伺服器同時為多個客戶機提供一問一答的服務。於是有了如下的模型。
圖 2. 多線程伺服器模型
在上述的線程 / 時間圖例中,主線程持續等待客戶端的連接請求,如果有連接,則創建新線程,並在新線程中提供為前例同樣的問答服務。
很多初學者可能不明白為何一個 socket 可以 accept 多次。實際上,socket 的設計者可能特意為多客戶機的情況留下了伏筆,讓 accept() 能夠返回一個新的 socket。下面是 accept 介面的原型:
?
1
intaccept(ints,structsockaddr *addr, socklen_t *addrlen);
輸入參數 s 是從 socket(),bind() 和 listen() 中沿用下來的 socket 句柄值。執行完 bind() 和 listen() 後,操作系統已經開始在指定的埠處監聽所有的連接請求,如果有請求,則將該連接請求加入請求隊列。調用 accept() 介面正是從 socket s 的請求隊列抽取第一個連接信息,創建一個與 s 同類的新的 socket 返回句柄。新的 socket 句柄即是後續 read() 和 recv() 的輸入參數。如果請求隊列當前沒有請求,則 accept() 將進入阻塞狀態直到有請求進入隊列。
上述多線程的伺服器模型似乎完美的解決了為多個客戶機提供問答服務的要求,但其實並不盡然。如果要同時響應成百上千路的連接請求,則無論多線程還是多進程都會嚴重占據系統資源,降低系統對外界響應效率,而線程與進程本身也更容易進入假死狀態。
很多程序員可能會考慮使用「線程池」或「連接池」。「線程池」旨在減少創建 和銷毀線程的頻率,其維持一定合理數量的線程,並讓空閑的線程重新承擔新的執行任務。「連接池」維持連接的緩存池,盡量重用已有的連接、減少創建和關閉連 接的頻率。這兩種技術都可以很好的降低系統開銷,都被廣泛應用很多大型系統,如 websphere、tomcat 和各種資料庫等。
但是,「線程池」和「連接池」技術也只是在一定程度上緩解了頻繁調用 IO 介面帶來的資源佔用。而且,所謂「池」始終有其上限,當請求大大超過上限時,「池」構成的系統對外界的響應並不比沒有池的時候效果好多少。所以使用「池」 必須考慮其面臨的響應規模,並根據響應規模調整「池」的大小。
對應上例中的所面臨的可能同時出現的上千甚至上萬次的客戶端請求,「線程池」或「連接池」或許可以緩解部分壓力,但是不能解決所有問題。
總之,多線程模型可以方便高效的解決小規模的服務請求,但面對大規模的服務請求,多線程模型並不是最佳方案。下一章我們將討論用非阻塞介面來嘗試解決這個問題。
使用select()介面的基於事件驅動的伺服器模型
大部分 Unix/Linux 都支持 select 函數,該函數用於探測多個文件句柄的狀態變化。下面給出 select 介面的原型:
?
1
2
3
4
5
6
FD_ZERO(intfd, fd_set* fds)
FD_SET(intfd, fd_set* fds)
FD_ISSET(intfd, fd_set* fds)
FD_CLR(intfd, fd_set* fds)
intselect(intnfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
structtimeval *timeout)
這里,fd_set 類型可以簡單的理解為按 bit 位標記句柄的隊列,例如要在某 fd_set 中標記一個值為 16 的句柄,則該 fd_set 的第 16 個 bit 位被標記為 1。具體的置位、驗證可使用 FD_SET、FD_ISSET 等宏實現。在 select() 函數中,readfds、writefds 和 exceptfds 同時作為輸入參數和輸出參數。如果輸入的 readfds 標記了 16 號句柄,則 select() 將檢測 16 號句柄是否可讀。在 select() 返回後,可以通過檢查 readfds 有否標記 16 號句柄,來判斷該「可讀」事件是否發生。另外,用戶可以設置 timeout 時間。
下面將重新模擬上例中從多個客戶端接收數據的模型。
圖4.使用select()的接收數據模型
上述模型只是描述了使用 select() 介面同時從多個客戶端接收數據的過程;由於 select() 介面可以同時對多個句柄進行讀狀態、寫狀態和錯誤狀態的探測,所以可以很容易構建為多個客戶端提供獨立問答服務的伺服器系統。
圖5.使用select()介面的基於事件驅動的伺服器模型
這里需要指出的是,客戶端的一個 connect() 操作,將在伺服器端激發一個「可讀事件」,所以 select() 也能探測來自客戶端的 connect() 行為。
上述模型中,最關鍵的地方是如何動態維護 select() 的三個參數 readfds、writefds 和 exceptfds。作為輸入參數,readfds 應該標記所有的需要探測的「可讀事件」的句柄,其中永遠包括那個探測 connect() 的那個「母」句柄;同時,writefds 和 exceptfds 應該標記所有需要探測的「可寫事件」和「錯誤事件」的句柄 ( 使用 FD_SET() 標記 )。
作為輸出參數,readfds、writefds 和 exceptfds 中的保存了 select() 捕捉到的所有事件的句柄值。程序員需要檢查的所有的標記位 ( 使用 FD_ISSET() 檢查 ),以確定到底哪些句柄發生了事件。
上述模型主要模擬的是「一問一答」的服務流程,所以,如果 select() 發現某句柄捕捉到了「可讀事件」,伺服器程序應及時做 recv() 操作,並根據接收到的數據准備好待發送數據,並將對應的句柄值加入 writefds,准備下一次的「可寫事件」的 select() 探測。同樣,如果 select() 發現某句柄捕捉到「可寫事件」,則程序應及時做 send() 操作,並准備好下一次的「可讀事件」探測准備。下圖描述的是上述模型中的一個執行周期。
圖6. 一個執行周期
這種模型的特徵在於每一個執行周期都會探測一次或一組事件,一個特定的事件會觸發某個特定的響應。我們可以將這種模型歸類為「事件驅動模型」。
相比其他模型,使用 select() 的事件驅動模型只用單線程(進程)執行,佔用資源少,不消耗太多 CPU,同時能夠為多客戶端提供服務。如果試圖建立一個簡單的事件驅動的伺服器程序,這個模型有一定的參考價值。
但這個模型依舊有著很多問題。
首先,select() 介面並不是實現「事件驅動」的最好選擇。因為當需要探測的句柄值較大時,select() 介面本身需要消耗大量時間去輪詢各個句柄。很多操作系統提供了更為高效的介面,如 linux 提供了 epoll,BSD 提供了 kqueue,Solaris 提供了 /dev/poll …。如果需要實現更高效的伺服器程序,類似 epoll 這樣的介面更被推薦。遺憾的是不同的操作系統特供的 epoll 介面有很大差異,所以使用類似於 epoll 的介面實現具有較好跨平台能力的伺服器會比較困難。
其次,該模型將事件探測和事件響應夾雜在一起,一旦事件響應的執行體龐大,則對整個模型是災難性的。如下例,龐大的執行體 1 的將直接導致響應事件 2 的執行體遲遲得不到執行,並在很大程度上降低了事件探測的及時性。
圖7. 龐大的執行體對使用select()的事件驅動模型的影響
幸運的是,有很多高效的事件驅動庫可以屏蔽上述的困難,常見的事件驅動庫有 libevent 庫,還有作為 libevent 替代者的 libev 庫。這些庫會根據操作系統的特點選擇最合適的事件探測介面,並且加入了信號 (signal) 等技術以支持非同步響應,這使得這些庫成為構建事件驅動模型的不二選擇。下章將介紹如何使用 libev 庫替換 select 或 epoll 介面,實現高效穩定的伺服器模型。
使用事件驅動庫libev的伺服器模型
Libev 是一種高性能事件循環 / 事件驅動庫。作為 libevent 的替代作品,其第一個版本發布與 2007 年 11 月。Libev 的設計者聲稱 libev 擁有更快的速度,更小的體積,更多功能等優勢,這些優勢在很多測評中得到了證明。正因為其良好的性能,很多系統開始使用 libev 庫。本章將介紹如何使用 Libev 實現提供問答服務的伺服器。
(事實上,現存的事件循環 / 事件驅動庫有很多,作者也無意推薦讀者一定使用 libev 庫,而只是為了說明事件驅動模型給網路伺服器編程帶來的便利和好處。大部分的事件驅動庫都有著與 libev 庫相類似的介面,只要明白大致的原理,即可靈活挑選合適的庫。)
與前章的模型類似,libev 同樣需要循環探測事件是否產生。Libev 的循環體用 ev_loop 結構來表達,並用 ev_loop( ) 來啟動。
?
1
voidev_loop( ev_loop* loop,intflags )
Libev 支持八種事件類型,其中包括 IO 事件。一個 IO 事件用 ev_io 來表徵,並用 ev_io_init() 函數來初始化:
?
1
voidev_io_init(ev_io *io, callback,intfd,intevents)
初始化內容包括回調函數 callback,被探測的句柄 fd 和需要探測的事件,EV_READ 表「可讀事件」,EV_WRITE 表「可寫事件」。
現在,用戶需要做的僅僅是在合適的時候,將某些 ev_io 從 ev_loop 加入或剔除。一旦加入,下個循環即會檢查 ev_io 所指定的事件有否發生;如果該事件被探測到,則 ev_loop 會自動執行 ev_io 的回調函數 callback();如果 ev_io 被注銷,則不再檢測對應事件。
無論某 ev_loop 啟動與否,都可以對其添加或刪除一個或多個 ev_io,添加刪除的介面是 ev_io_start() 和 ev_io_stop()。
?
1
2
void ev_io_start( ev_loop *loop, ev_io* io )
void ev_io_stop( EV_A_* )
由此,我們可以容易得出如下的「一問一答」的伺服器模型。由於沒有考慮伺服器端主動終止連接機制,所以各個連接可以維持任意時間,客戶端可以自由選擇退出時機。
圖8. 使用libev庫的伺服器模型
上述模型可以接受任意多個連接,且為各個連接提供完全獨立的問答服務。藉助 libev 提供的事件循環 / 事件驅動介面,上述模型有機會具備其他模型不能提供的高效率、低資源佔用、穩定性好和編寫簡單等特點。
由於傳統的 web 伺服器,ftp 伺服器及其他網路應用程序都具有「一問一答」的通訊邏輯,所以上述使用 libev 庫的「一問一答」模型對構建類似的伺服器程序具有參考價值;另外,對於需要實現遠程監視或遠程遙控的應用程序,上述模型同樣提供了一個可行的實現方案。
總結
本文圍繞如何構建一個提供「一問一答」的伺服器程序,先後討論了用阻塞型的 socket 介面實現的模型,使用多線程的模型,使用 select() 介面的基於事件驅動的伺服器模型,直到使用 libev 事件驅動庫的伺服器模型。文章對各種模型的優缺點都做了比較,從比較中得出結論,即使用「事件驅動模型」可以的實現更為高效穩定的伺服器程序。文中描述的 多種模型可以為讀者的網路編程提供參考價值。