伺服器架構組成如何分析
『壹』 關於微服務架構特點分析
隨著互聯網的不斷發展,我們在進行伺服器開發組織架構上通常會採用分布式架構方法來進行設計。今天,我們就一起來了解一下,微服務架構都有哪些特點。
InfoQ:你近的QConSanFrancisco提出的一個關鍵前提是,組織如果要從單體大型應用轉變為基於微服務的體系結構就得要打破它們的龐大的整體流程。你能再進一步解釋一下嗎?
RafaelSchloming:對於轉變為微服務本身,人們實際上並不怎麼關心,他們真正關心的是提升特性的完成速度。為了提升特徵的完成速度就必需做出改變,而微服務只是這種改變所產生的一個附屬物罷了。
對於組織來說非常常見的一種情況是,當他們發展到一個臨界點,增加再多的人也不會提升特性的完成速度。當這種情況發生時,通常是因為組織用於產出特性的結構和/或過程成為了瓶頸,而不是人員的數量。
當一個組織遇到這種障礙,開始調查為什麼這些特性似乎花費的時間遠遠超出了合理的資源,答案往往是,每個特性都需要太多不同團隊的協調。
這會發生在兩個不同的維度上。你的人員可以按職能劃分為團隊:產品與開發、質保與運維。你的人員也可以按組件劃分:例如,前端與領域模型、搜索索引和消息通知。當單個特性需要跨多個不同的團隊進行協調時,交付特性的控制因素是不同團隊之間的溝通速度和效率。像這樣組織結構的組織實際上是被一個龐大的整體過程所阻礙的,這個過程要求每個特性(在某種程度上)要有許多許多的組織來理解它。
InfoQ:那麼如何解決這個問題呢?
Schloming:為了把很多人用在一個問題上,你需要把他們分成團隊,因為人們不能在非常大的群體中有效地溝通。你這么做的時候,其實就是在做出一系列的權衡。你所營造的是每支團隊內部具有高保真的溝通和協調,而團隊之間是低保真和相對較差的協調。
為改進一個組織內的特性完成速度,您可以將你的人組織成獨立的、跨職能的、自給自足的特性團隊,可以從頭到尾自主掌控一個完整的特性。這將以兩種方式提高特性的完成速度。先,由於不同的職能(產品、開發、質保和運維)都圈定於一個特性內,你就可以自定義該特性區域的流程了,例如,IT培訓http://www.kmbdqn.cn/分享對於一個沒有人正在使用的新特性,你的流程就不需要優先考慮其穩定性了。其次,由於該特性所需的所有組件都由同一個團隊擁有,因此,要想趕緊推出一個特性,就可以進行更快速有效的溝通和協調。
『貳』 伺服器有哪幾種結構,是如何劃分的又有什麼不同的區別
伺服器分塔式、機架式和刀片式這三種結構來劃分伺服器,伺服器的外形為什麼會有這樣的劃分呢?主要原因就是具體的應用環境不同,塔式伺服器長得跟我們平時用的台式機一樣,佔用空間比較大,一般是一些小型企業自己使用自己維護;而機架式伺服器長得就像卧著的台式機,可以一台一台的放到固定機架上,因此而得名,它可以拿去專業的伺服器託管提供商那裡進行託管,這樣每年只需支付一定的託管費,就免去了自己管理伺服器的諸多不便;而刀片伺服器是近幾年才比較流行的一種伺服器架構,它非常薄,可以一片一片的疊放在機櫃上,通過群集技術進行協同運算,能夠處理大量的任務,特別適合分布式服務,如作為WEB伺服器。
『叄』 網路伺服器的組成是什麼
伺服器
伺服器是指管理和傳輸信息的一種計算機系統。
伺服器是一種高性能計算機,作為網路的節點,存儲、處理網路上80%的數據、信息,因此也被稱為網路的靈魂。做一個形象的比喻:伺服器就像是郵局的交換機,而微機、筆記本、PDA、手機等固定或移動的網路終端,就如散落在家庭、各種辦公場所、公共場所等處的電話機。我們與外界日常的生活、工作中的電話交流、溝通,必須經過交換機,才能到達目標電話;同樣如此,網路終端設備如家庭、企業中的微機上網,獲取資訊,與外界溝通、娛樂等,也必須經過伺服器,因此也可以說是伺服器在「組織」和「領導」這些設備。
它是網路上一種為客戶端計算機提供各種服務的高性能的計算機,它在網路操作系統的控制下,將與其相連的硬碟、磁帶、列印機、Modem及各種專用通訊設備提供給網路上的客戶站點共享,也能為網路用戶提供集中計算、信息發表及數據管理等服務。它的高性能主要體現在高速度的運算能力、長時間的可靠運行、強大的外部數據吞吐能力等方面。
伺服器的構成與微機基本相似,有處理器、硬碟、內存、系統匯流排等,它們是針對具體的網路應用特別制定的,因而伺服器與微機在處理能力、穩定性、可靠性、安全性、可擴展性、可管理性等方面存在差異很大。尤其是隨著信息技術的進步,網路的作用越來越明顯,對自己信息系統的數據處理能力、安全性等的要求也越來越高,如果您在進行電子商務的過程中被黑客竊走密碼、損失關鍵商業數據;如果您在自動取款機上不能正常的存取,您應該考慮在這些設備系統的幕後指揮者————伺服器,而不是埋怨工作人員的素質和其他客觀條件的限制。
目前,按照體系架構來區分,伺服器主要分為兩類:ISC(精簡指令集)架構伺服器:這是使用RISC晶元並且主要採用UNIX操作系統的伺服器,如Sun公司的SPARC、HP公司的PA-RISC、DEC的Alpha晶元、SGI公司的MIPS等。
IA架構伺服器:又稱CISC(復雜指令集)架構伺服器,即通常所講的PC伺服器,它是基於PC機體系結構,使用Intel或與其兼容的處理器晶元的伺服器,如聯想的萬全系列、HP的Netserver系列伺服器等。
從當前的網路發展狀況看,以「小、巧、穩」為特點的IA架構的PC伺服器得到了更為廣泛的應用。
『肆』 伺服器結構
伺服器分塔式、機架式和刀片式這三種結構來劃分伺服器,伺服器的外形為什麼會有這樣的劃分呢?主要原因就是具體的應用環境不同,塔式伺服器長得跟我們平時用的台式機一樣,佔用空間比較大,一般是一些小型企業自己使用自己維護;而機架式伺服器長得就像卧著的台式機,可以一台一台的放到固定機架上,因此而得名,它可以拿去專業的伺服器託管提供商那裡進行託管,這樣每年只需支付一定的託管費,就免去了自己管理伺服器的諸多不便;而刀片伺服器是近幾年才比較流行的一種伺服器架構,它非常薄,可以一片一片的疊放在機櫃上,通過群集技術進行協同運算,能夠處理大量的任務,特別適合分布式服務,如作為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從根本上克服了伺服器集群的缺點。
『伍』 伺服器架構是什麼意思
常見的伺服器架構有以下三種:
伺服器集群架構:
伺服器集群就是指將很多伺服器集中起來一起進行同一種服務,在客戶端看來就像是只有一個伺服器。集群可以利用多個計算機進行並行計算從而獲得很高的計算速度,也可以用多個計算機做備份,從而使得任何一個機器壞了整個系統還是能正常運行。
伺服器負載均衡架構:
負載均衡
(Load
Balancing)
建立在現有網路結構之上,它提供了一種廉價有效透明的方法擴展網路設備和伺服器的帶寬、增加吞吐量、加強網路數據處理能力、提高網路的靈活性和可用性。
分布式伺服器架構:
所謂分布式資源共享伺服器就是指數據和程序可以不位於一個伺服器上,而是分散到多個伺服器,以網路上分散分布的地理信息數據及受其影響的資料庫操作為研究對象的一種理論計算模型伺服器形式。分布式有利於任務在整個計算機系統上進行分配與優化,克服了傳統集中式系統會導致中心主機資源緊張與響應瓶頸的缺陷,解決了網路GIS
中存在的數據異構、數據共享、運算復雜等問題,是地理信息系統技術的一大進步。
這個三種架構都是常見的伺服器架構,集群的主要是IT公司在做,可以保障重要數據安全;負載均衡主要是為了分擔訪問量,避免臨時的網路堵塞,主要用於電子商務類型的網站;分布式伺服器主要是解決跨區域,多個單個節點達到高速訪問的目前,一般是類似CDN的用途的話,會採用分布式伺服器。
『陸』 伺服器的內部結構是怎樣的
伺服器是計算機的一種,它比普通計算機運行更快、負載更高、價格更貴。伺服器在網路中為其它客戶機(如PC機、智能手機、ATM等終端甚至是火車系統等大型設備)提供計算或者應用服務。
伺服器具有高速的CPU運算能力、長時間的可靠運行、強大的I/O外部數據吞吐能力以及更好的擴展性。根據伺服器所提供的服務,一般來說伺服器都具備承擔響應服務請求、承擔服務、保障服務的能力。伺服器作為電子設備,其內部的結構十分的復雜,但與普通的計算機內部結構相差不大,如:cpu、硬碟、內存,系統、系統匯流排等。
(6)伺服器架構組成如何分析擴展閱讀:
優點
1、整合資源
完成資源整合是伺服器虛擬化的主要工作,在信息時代,各行各業在發展過程中,產生的數據呈現爆炸式增長,如何實現對這些數據和資源的綜合利用,是各大行業亟需解決的問題。計算機伺服器虛擬化技術的研發和應用,為實現資源整合提供技術支持和應用平台。
尤其是近年來,雲計算技術的不斷普及,集中化資源管理愈發先進,為雲技術的發展和推廣提供了條件,目前各大企業對計算機硬體資源的利用率不足20%,資源浪費現場依然非常嚴重,通過伺服器虛擬化技術可在原應用保持不變的基礎上,集中在某一計算機伺服器中,可促使企業的物力資源調利用率大大提升,從而降低了各項硬體的投入,節約了成本。
2、低能耗
在信息時代,技術革新的重中之重,也是降低資源消耗的主要途徑,雲計算技術備受推廣,在IT界大量推廣雲計算技術。計算機伺服器虛擬化是提升資源利用率的主要途徑,也可以對能耗進行合理的管理。虛擬化技術則可以模擬出不同場景,從而實現對計算機系統中各種硬體及軟體進行全面系統的檢查,發現問題立即顯示在界面上,提醒相關人員及時處理,從而達到降低能耗,實現綠色發展的目的。
3、降低運營成本
在信息化服務商不斷經營轉型的背景下,集約化對成本控制提出了更高的要求,投資愈發精細化,而企業實現IT化運行的關鍵自傲與集中對數據中心的投資,此項內容主要涉及到兩方面內容;
①計算機硬體和許可服務支持的投資。
②計算機系統運維承的成本投資,通過計算機伺服器虛擬化技術,能充分發揮伺服器應的性能。
4、應用更加平坦化
通過伺服器虛擬化技術可促使計算機伺服器應用平台更加平坦化和透明化,在信息時代,數據中心平台逐年增加,計算機伺服器的應用愈發復雜,不同平台在具體運行過程中,需要充分考慮不同操作系統和中間件的層面問題。通過伺服器虛擬化技術可有效解決此類問題,將應用和硬體平台相互隔離,實現了跨越平台的限制。
『柒』 Nginx伺服器架構初探
Nginx的每個模塊都基本符合單一職責原則
一般來說,Web伺服器完成並行處理請求工作的三種方式有:多進程方式、多進程方式和非同步方式
多進程方式是指,伺服器每當接收到一個客戶端時,就由伺服器主進程生成一個子進程出來和該客戶端建立連接進行交互,直到連接斷開,該子進程就結束了
多進程方式的優點在於,設計和實現相對簡單,各個子進程之間相對獨立,處理客戶端請求的過程彼此不受到干擾,並且當一個子進程產生問題時,不容易將影響蔓延到其他進程中,這保證了提供服務的穩定性。當子線程退出時,其佔用資源會被操作系統回收,也不會留下任何垃圾。
其缺點是操作系統中生成一個子進程需要進行大量內存復制等操作,在資源和時間上會產生一定的額外開銷。因此,如果Web伺服器接收大量並發請求,就會對系統資源造成壓力,導致系統性能下降。
Apache採用「預生成進程」方式,它將生成子進程的時機提前,在客戶端請求還沒有到來之前就預先生成好,當請求到來時,主進程分配一個子進程和該客戶端進行交互,交互完成之後,該進程也不結束,而被主進程管理起來等待下一個客戶端請求的到來
多線程方式是指當伺服器每當接收到一個客戶端時,會有伺服器主進程派生一個線程出來和該客戶端進行交互
由於操作系統產生一個線程的開銷遠遠小於產生一個進程的開銷,所以多線程方式在很大程度上減輕了Web伺服器對系統資源的要求。該方式使用線程進行任務調度,開發方面可以遵循一定的標准,這相對來說比較規范和有利於協作。
多個線程位於同一進程內,可以訪問同樣的內存空間,彼此之間相互影響;同時,在開發過程中不可避免地要由開發者自己對內存進行管理,其增加了出錯的風險
IIS伺服器使用了多線程方式對外提供服務
同步機制:發送方發送請求之後,需要等待接收到接收方發回的響應後,才接著發送下一個請求
非同步機制:發送方發送請求只有,不等待接收方響應這個請求,就繼續發送下一個請求。
在同步機制中,所有的請求在伺服器端得到同步,發送方和接收方對請求的處理步調是一致的;在非同步機制中,所有來自發送方的請求形成一個隊列,接收方處理完成後通知發送方
阻塞和非阻塞用來描述進程處理調用的方式,在網路通信中,主要指網路套接字Socket的阻塞和非阻塞方式,而Socket的實質也就是IO操作。
Socket的阻塞調用方式為,調用結果返回之前,當前線程從運行狀態被掛起,一直等到調用結果返回之前,才進入就緒狀態,獲取CPU繼續執行
Socket的非阻塞調用方式為,如果調用結果不能馬上返回,當前線程也不會被掛起,而是立即返回執行下一個調用
Nginx結合多進程機制和非同步機制對外提供服務。非同步機制使用的是非同步非阻塞方式
Nginx伺服器啟動後產生一個主進程和多個工作進程(可在配置文件中配置)。Ngnix伺服器的所有工作進程都用於接收和處理客戶端的請求。每個工作進程使用非同步非阻塞方式,可以處理多個客戶端的請求。當某個工作進程接收到客戶端的請求以後,調用IO進行處理,如果不能立即得到返回,就去處理其他的請求;而客戶端再次期間也無須等待響應,可以去處理其他的事情;當IO調用返回結果時,就會通知此工作進程;該進程得到通知,暫時掛起當前處理的事務,去響應客戶端的請求
IO調用把狀態通知給工作進程的兩種方式:
select/poll/epoll/kqueue等這樣的系統調用就是支撐第二種方案的。這種系統調用,也稱為事件模型。IO調用完全由事件驅動模型來管理,事件准備好之後就通知工作進程事件已經就緒
事件驅動就是在持續事務管理過程中,由當前時間點上出現的事件引發的調動可用資源執行相關任務,解決不斷出現的問題,防止事務堆積的一種策略
事件驅動模型一般由事件收集器、事件發送器和事件處理器三部分基本單元組成
事件收集器 專門負責收集所有的事件,包括來自用戶的(滑鼠、鍵盤事件等)、來自硬體的(時鍾事件等)和來自軟體的(操作系統、應用程序自身)。 事件發送器 負責將收集器收集到的事件分發到目標對象中。目標對象就是事件處理器所處的位置。 事件處理器 主要負責具體事件的響應工作,它往往要到實現階段才完全確定
目標對象中事件處理器的幾種方式:
大部分網路伺服器都採用第三種方式,形成了事件驅動庫。事件驅動庫又被稱為多路IO復用方法,最常見的偽:select、poll、epoll。Nginx伺服器還支持rtsig、kqueue、dev/poll和eventport
各個版本Linux和Windows平台都支持的基本事件驅動模型
使用select庫的一般步驟:
如果沒有指定其他事件驅動模型,Nginx自動編譯該庫。
使用--with-select_mole和--without-select_mole強制Nginx是否編譯該庫
Linux平台的事件驅動模型,Windows不支持。
poll和select的基本使用方式是相同的,區別在於:select需要為讀事件、寫事件和異常事件都分別創建一個描述符集合,因此在最後輪詢的時候,需要分別輪訓這三個集合。而poss庫只需要創建一個集合,在每個描述符對應的結構上分別設置讀事件、寫事件或異常事件,最後輪詢的時候,可以同時檢查這三種事件是否發生。poll庫是select庫的優化實現
如果沒有指定其他事件驅動模型,Nginx自動編譯該庫。
使用--with-poll_mole和--without-poll_mole強制Nginx是否編譯該庫
epoll屬於poll庫的一個變種,最大的區別在於效率
epoll庫通過相關調用通知內核創建一個有N個描述符的事件列表;然後,給這些描述符設置所關注的事件,並將它添加到內核的事件列表中。
完成設置之後,epoll庫就開始等待內核通知事件發生了。某一事件發生後,內核將發生事件的描述符列表上報給epoll庫。得到列表事件的epoll庫,就可以進行事件處理了
epoll庫是Linux平台上最高效的。它支持一個進程打開大數目的事件描述符,上限是系統可以打開文件的最大數目。同時,epoll庫的IO效率不隨描述符數目增加而線性下降,因為它只會對內核上報的「活躍」的描述符進行操作
使用rtsig模型時,工作進程會通過系統內核建立一個rtsig隊列用於存放標記事件發生(在Nginx伺服器應用中特指客戶端請求發生)的信號。每一個事件發生時,系統內核就會發生一個信號存放到rtsig隊列中等待工作進程的處理。
rtsig隊列有長度限制,如果超過該長度就會發生溢出。默認情況下,Linux系統事件信號隊列的最大長度設置為1024。在Liunx2.6.6-mm2之後的版本之前,通過修改內核參數/proc/sys/kernel/rtsig-max來自定義該長度設置。在Liunx2.6.6-mm2之後的版本中,該參數被取消,系統各個進程分別擁有各自的事件信號隊列,這個隊列的大小由Linux系統的RLIMIT_SIGPENDING參數定義,在執行setrlimit()系統調用時確定該大小。Linux提供了worker+rlimit_sigpending參數用於調節這種情況下的事件信號隊列長度
當rtsig隊列發生溢出時,Nginx將暫停使用rtsig模型,而調用poll庫處理未處理的事件,直到rtsig信號隊列全部清空,然後再次啟動rtsig模型,以防止新的溢出發生
編譯Nginx伺服器時,使用-with-rtsig_mole配置選項啟用rtsig模型的編譯
kqueue模型,主要用於FreeBSD4.1及以上版本、OpenBSD2.9及以上版本、NetBSD2.0及以上版本以及Mac OS X平台上。該模型也是poll庫的一個變種,其和poll庫的處理方式沒有本質上的區別。該模型同時支持條件觸發(只要滿足條件就觸發一個事件)和邊緣觸發(當狀態發生改變觸發一個事件)。在這些平台下,使用該模型用於請求處理,提高Nginx伺服器性能
/dev/poll模型,主要用於Solaris7 11/99及以上版本、HP/US 11.22及以上版本、IRIX6.5.15及以上版本和Tru 64 UNIX 5.1A及以上版本。它使用了虛擬的/dev/poll設備,開發人員可以將要監視的文件描述符加入這個設備,然後通過ioctl()調用來獲取事件通知。在以上平台中推薦使用
eventport模型,用於支持Solaris 10及以上版本。它可以有效防止內核崩潰等情況的發生
根據不同的部署平台,選擇不同的事件驅動模型以提升Nginx伺服器的處理性能
Nginx伺服器啟動後,產生一個主進程,主進程執行一系列工作後產生一個或者多個工作進程。
主進程主要進行Nginx配置文件解析、數據結構初始化、模塊配置和注冊、信號處理、網路監聽生成、工作進程生成和管理等工作;
工作進程主要進行進程初始化、模塊調用和請求處理等工作,是Nginx伺服器提供服務的主體
Nginx伺服器將接收到的Web請求通過代理轉發到後端伺服器,由後端伺服器進行數據處理和頁面組織,然後將結果返回。
Nginx伺服器為了提高對請求的響應效率,進一步降低網路壓力,採用了緩存機制,將歷史應答數據緩存到本地。在每次Nginx伺服器啟動後的一段時間內,會啟動專門的進程進行對本地緩存的內容重建索引,保證對緩存文件的快速訪問
依賴於管道機制,交互的准備工作都是在工作進程生成時完成的
Run Loops,指的是進程內部用來不停地調配工作,對事件進行循環處理的一種模型。
該模型是一個集合,集合中的每一個元素稱為一個Run-Loop。每個Run-Loop可運行在不同的模式下,其中可以包含它所監聽的輸入事件源、定時器以及在事件發生時需要通知的Run-Loop監聽器。為了監聽特定的事件,可以在Run Loops中添加相應的Run-Loop監聽器。當被監聽的事件發生時,Run-Loop會產生一個消息,被Run-Loop監聽器捕獲,從而執行預定的動作
Nginx伺服器在工作進程中實現了Run-Loop事件處理循環的使用,用來處理客戶端發送的請求事件
『捌』 伺服器內部硬體結構
伺服器的cpu是最核心的運算部件。伺服器的性能如果,都是由伺服器cpu來決定的。在選擇cpu的時候,需要考慮cpu的主頻、核心以及線程。
主頻:伺服器cpu的主頻主要是用來表示CPU的運算、處理數據的速度。一般來說,主頻越高,cpu處理數據的速度也就越快。
核心:一般情況下,每個核心都會有一個線程。幾核心就會有幾核心。但隨著技術的發展,出現了超線程的技術,可以使單核心具備兩個線程,既雙核四線程。
線程:伺服器的線程數越大,就表明速度也就越快,但相應的消耗功能也就越大。
2.伺服器內存
內存是計算機中重要的部件之一,它是與CPU進行溝通的橋梁。伺服器中所有程序的運行都是在內存中進行的,因此內存的性能對計算機的影響非常大。
它的主要作用是用於暫時存放CPU中的運算數據,以及與硬碟等外部存儲器交換的數據。只要計算機在運行中,CPU就會把需要運算的數據調到內存中進行運算,當運算完成後CPU再將結果傳送出來,內存的運行也決定了計算機的穩定運行。
3.伺服器硬碟
伺服器的硬碟主要是用來存儲各類數據。硬碟的容量直接影響到數據信息量的存儲。目前伺服器的硬碟主要分為SATA硬碟、SCSI硬碟、SAS硬碟以及SSD硬碟。
『玖』 解剖nginx伺服器架構
模塊化結構的思想是一個很久的概念,但也正是成熟的思想造就了Nginx的巨大優越性。
我們知道Nginx從總體上來講是有許多個模塊構成的。習慣將Nginx分為5大模塊分別為:核心模塊,標准HTTP模塊,可選HTTP模塊,郵件服務模塊和第三方模塊。
這5個模塊由上到下重要性一次遞減。
(1)核心模塊;
核心模塊是Nginx伺服器正常運行必不可少的模塊,如同操作系統的內核。它提供了Nginx最基本的核心服務。像進程管理、許可權控制、錯誤日誌記錄等;
(2)標准HTTP模塊;
標准HTTP模塊支持標準的HTTP的功能;
(3)可選HTTP模塊;
可選HTTP模塊主要用於擴展標準的HTTP功能,讓Nginx能處理一些特殊的服務;
(4)郵件服務模塊;
郵件服務模塊主要用於支持Nginx的郵件服務;
(5)第三方模塊;
第三方模塊是為了擴展Nginx伺服器應用,完成開發者想要的功能;
*******Nginx中的模塊命名有自己的習慣*********
一般以Ngx_作為前綴,——mole作為後綴,中間使用一個或者多個英文單詞描述模塊的工能,例如Ngx_core_mole表示該模塊提供Nginx的核心功能等;
具體各個模塊中包含哪些模塊可以自己去源碼中查詢,這里略過;
從架構設計上說,Nginx伺服器是與眾不同的。其一在於它的模塊化設計;其二也是更重要的一點在於它對與客戶端請求的處理機制上;
web伺服器和客戶端是一對多的關系,Web伺服器必須有能力同時為多個客戶端提供服務。一般來說完成並行處理請求工作有三種方式:
1.多進程方式;
2.多線程方式;
3.非同步方式;
這里簡單說明一下這三種方式:
(1)多進程方式
多進程方式指,伺服器每當收到一個客戶端時。就有伺服器主進程生成一個子進程出來和客戶端建立連接進行交互。指導連接斷開。該子進程就結束了。
多進程方式的優點是設計簡單,各個子進程相對獨立,處理客戶端請求時彼此不受干擾;缺點是操作系統生成一個子進程需要進行內存復制等操作,在資源和時間上會產生一定的開銷;當有大量請求時,會導致系統性能下降;
(2)多線程方式
多線程方式指每當伺服器接收到一個請求後,會由伺服器主進程派生出一個線程出來和客戶端進行交互。由於操作系統產生出一個線程的開銷遠遠小於一個進程的開銷。故多線程方式在很大程度上減輕了Web伺服器對系統資源的要求。但同時由於多個線程位於一個進程內,可以訪問同樣的內存空間。所以需要開發者自己對內存進程管理,增大了難度。
(3)非同步方式
非同步方式適合多進程和多線程完全不同的一種處理客戶端請求的方式。這里有幾個概念我們需要熟悉一下: 同步,非同步,阻塞,非阻塞 ;
在網路通信中同步和非同步是描述通信模式的概念。
同步:發送方發送完請求後,需要等待接收到接收方發回的響應,才能發送下一個請求;所有請求在服務端得到同步,發送方和接收方的步調是一致的;
非同步 :和同步機制相反,在非同步機制中,發送方發出一個請求後,不等接收方響應這個請求,就繼續發送下一個請求;所有來自發送方的請求形成一個隊列,接收方處理完成後通知發送方;
在進程處理調度方式上用阻塞與非阻塞。在網路通信中主要指套接字socket的阻塞和非阻塞,而socket的實質就是IO操作。
阻塞 :調用結果返回之前,當前線程從運行狀態被掛起,一直等到調用結果返回之後,才進入就緒狀態,獲取CPU後繼續執行。
非阻塞 :和阻塞方式正好相反,如果調用結果不能馬上返回,當前線程也不會馬上返回,而是立即返回執行下一個調用。
因此就衍生出4中方式:同步阻塞,同步非阻塞,非同步阻塞,非同步非阻塞
這里簡單解釋一下非同步非阻塞:發送方向接收方發送請求後,不用等待響應,可以繼續其他工作;接收方處理請求時進行的IO操作如果不能馬上得到結果,也不必等待,而是馬上返回去去做其他事情。當IO操作完成以後,將完成狀態和結果通知接收方,接收方再響應發送方。
與此同時Nginx伺服器處理請求是怎樣的呢???
Nginx伺服器的一個顯著的優勢就是能夠同時處理大量的並發請求。它結合多進程機制和非同步機制。非同步機制使用的是非同步非阻塞方式。(Master-Worker)。
每個工作進程使用非同步非阻塞方式,可以處理多個客戶端請求。當某個工作進程接收到客戶端的請求以後,調用IO進行處理,如果不能立即得到結果,就去處理其他的請求;而客戶端在此期間也無需等待響應,可以去處理其他事情;當IO返回時,就會通知此工作進程;該進程得到通知,暫時掛起當前處理的失誤去響應客戶端請求。
也就是:
Nginx採用非同步非阻塞方式來處理請求,處理請求具體到系統底層就是讀寫事件(所謂阻塞調用方式即請求事件還沒准備好,線程只能一直去等,等事件准備好了再處理;而非阻塞即事件沒准備好,馬上返回ENGAIN,告訴你事件還沒准准備好,而在這期間可以先去做其他事,再回頭看看事件准備好了嗎,時不時會看,需要的開銷也是不小的)
非同步可以理解為循環處理多個准備好的事件,不會導致無謂的資源浪費,當有更多的並發數只會佔用更多的內存而已;
從上面我們可以知道,Nginx伺服器的工作進程調用IO後,就取進行其他工作了;當IO調用返回後,會通知工作進程。 但IO調用時如何把自己的狀態通知給工作進程的呢??
一般解決這個問題有兩種方法:
(1)讓工作進程在進行其他工作的過程中間隔一段時間就去檢查一下IO的狀態,如果完成就響應客戶端,如果未完成,繼續工作。
(2)IO調用在完成後能主動通知工作進程。
當然最好的就是用第二種方法了;像select/poll/epoll等這樣的系統調用就是用來支持第二種解決方案的。這些系統調用也常被稱為事件驅動模型。他們提供了一種機制就只讓進程同時處理多個並發請求,不用關心IO調用的具體狀態。IO調用完全由事件驅動模型來管理。
Nginx中的事件驅動模型
就是用事件驅動處理庫(多路IO復用),最常用的就是select模型,poll模型,epoll模型。
關於這三個模型的詳解在這里可以看到:https://segmentfault.com/a/1190000003063859
通過這個上面的簡單講解,再加上伺服器的架構的了解,可以對Nginx有一個簡單的了解,希望對之後的源碼剖析有幫助。
大致上Nginx的架構就是這樣:
1.Nginx啟動後,會產生一個主進程,主進程執行一系列的工作後會產生一個或者多個工作進程;
2.在客戶端請求動態站點的過程中,Nginx伺服器還涉及和後端伺服器的通信。Nginx將接收到的Web請求通過代理轉發到後端伺服器,由後端伺服器進行數據處理和組織;
3.Nginx為了提高對請求的響應效率,降低網路壓力,採用了緩存機制,將 歷史 應答數據緩存到本地。保障對緩存文件的快速訪問;
##工作進程##
工作進程的主要工作有以下幾項:
接收客戶端請求;
將請求一次送入各個功能模塊進行過濾處理;
IO調用,獲取響應數據;
與後端伺服器通信,接收後端伺服器處理結果;
數據緩存
響應客戶端請求;
##進程交互##
Nginx伺服器在使用Master-Worker模型時,會涉及到主進程和工作進程的交互和工作進程之間的交互。這兩類交互都依賴於管道機制。
1.Master-Worker交互
這條管道與普通的管道不同,它是由主進程指向工作進程的單向管道,包含主進程向工作進程發出的指令,工作進程ID等;同時主進程與外界通過信號通信;
2.worker-worker交互
這種交互是和Master-Worker交互是基本一致的。但是會通過主進程。工作進程之間是相互隔離的,所以當工作進程W1需要向工作進程W2發指令時,首先找到W2的進程ID,然後將正確的指令寫入指向W2的通道。W2收到信號採取相應的措施。
『拾』 幾種經典的網路伺服器架構模型的分析與比較
相比於傳統的網路編程方式,事件驅動能夠極大的降低資源佔用,增大服務接待能力,並提高網路傳輸效率。 關於本文提及的伺服器模型,搜索網路可以查閱到很多的實現代碼,所以,本文將不拘泥於源代碼的陳列與分析,而側重模型的介紹和比較。使用 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 介面的原型: int accept(int s, struct sockaddr *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 介面的原型: FD_ZERO(int fd, fd_set* fds) FD_SET(int fd, fd_set* fds) FD_ISSET(int fd, fd_set* fds) FD_CLR(int fd, fd_set* fds) int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *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( ) 來啟動。 void ev_loop( ev_loop* loop, int flags ) Libev 支持八種事件類型,其中包括 IO 事件。一個 IO 事件用 ev_io 來表徵,並用 ev_io_init() 函數來初始化: void ev_io_init(ev_io *io, callback, int fd, int events) 初始化內容包括回調函數 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()。 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 事件驅動庫的伺服器模型。文章對各種模型的優缺點都做了比較,從比較中得出結論,即使用「事件驅動模型」可以的實現更為高效穩定的伺服器程序。文中描述的多種模型可以為讀者的網路編程提供參考價值。