origin:
由於個人工作的關係,接觸高效能伺服器的研發已經有一段時間了,在沒有接觸這個話題之前,我也和許多人一樣,認為伺服器的設計無非就是用一下winsock,呼叫呼叫函式那麼簡單。當親自完成了乙個在win平台上能承載上萬連線的測試模型後,才知道,原來,作高效能伺服器是這麼有挑戰性。你不僅需要在細支末節上對模型進行精雕細琢,更需要在總體架構方面進行權衡選擇。這兩方面,都會影響到你的伺服器效能的正常發揮。作為對「細枝末節」方面的介紹,請參照我之前寫的系列文章「完成埠之效能優化」。而從此篇文章開始的系列文章,將就乙個完整的高效能伺服器模型進行介紹,而對於伺服器集群架構方面,則不在此系列的討論範圍,那將是未來數週我將要完成的事。有朋友跟我說,希望我能提供底層模型的完整**或可供使用的動態鏈結庫及lib檔案。對於這個要求,我現在還在考慮之中。確實,有了**,要學得更快一點,但由於模型裡牽涉到一定的版權問題,所以,我會考慮將其進行必要的修改,而後再考慮是否向大家提供源**。不過,可以肯定的是,對於lib及dll的要求,我想我會盡快提交上來的。
所謂的「高效能」,我想不外乎兩個方面:
1、處理的併發請求要盡可能地多,具體表現為同一時間內同時連線的客戶端數量;
2、資料報的吞吐量要盡可能地大,具體表現為單位時間內伺服器的收、發資料量。
為了使大家能有乙個巨集觀概念的把握,我先介紹一下基於三層結構的伺服器通訊底層模型。對於軟體架構而言,沒有最好之說,放在不同的應用環境其表現都可能千差萬別,所以,我不保證這個架構是能讓所有人都看著舒服的,我只保證,在我當前的專案應用中,這個架構充分考慮了「效能」和「可擴充套件性」兩者的兼顧,讓我在很容易地開發新的伺服器時,仍然可以享受到很好的效能。
一、三層架構圖及簡單說明
三層架構圖如下:
ciocpserver
||||
ccutomhpserver
||||
ctestserver
以後我們要討論的就是這個看上去並不複雜的三層架構圖,下面就此架構圖中的主要類進行簡要說明。
ciocpserver:
完成埠伺服器基本通訊類,它使用winnt/2000/xp平台特有完成埠特性,對通訊模型進行封裝,向它的派生類提供以下基本擴充套件介面(可被過載的虛函式):
1、有客戶端連線時的處理介面;
2、客戶端斷開時的處理介面;
3、從客戶端收完資料後的處理介面;
4、向客戶端傳送完資料後的處理介面;
5、網路通訊及伺服器處理出現錯誤時的處理介面。
ccustomhpserver:
典型的高效能伺服器類,ciocpserver是其基類之一(之一?難道還有另外的基類,回答是:當然,呵呵,別急,後面會介紹),此類在ciocpserver的基礎上,封裝了三個資料佇列及三類處理執行緒,介紹如下:
1、接收資料報佇列及接收執行緒:用於存放剛收到的資料報,此資料報還沒有進行邏輯意義上的拆解,接收執行緒從此佇列中取出資料報,並將其形成乙個邏輯意義上完整的資料報加入到「處理資料報佇列」中;
2、處理資料報佇列及邏輯處理執行緒:已經拆解成了邏輯意義上的資料報,邏輯處理執行緒對此類資料報進行邏輯解析,這裡就是伺服器的主要邏輯部分,有的資料報在處理完成後,可能是需要向客戶端返回處理結果的,此時就需要邏輯執行緒在處理完成後將返回結果的資料報放入「傳送資料報佇列」中;
3、傳送資料報佇列及傳送執行緒:待傳送的資料報佇列,由傳送執行緒根據資料報裡的客戶端套接字傳送給特定客戶端。
ctestserver:
此類是乙個測試類,主要用於演示如何在ccustomhpserver的基礎上派生乙個真正的應用伺服器,並用於說明它需要過載實現ccustomhpserver的哪些重要虛函式。
基於以上的結構,我們的伺服器通訊模型,可以一層一層地實現,一層一層的測試。在ciocpserver中,它本身是不帶有任何資料佇列的,所有的網路資料都是即來即處理,沒有儲存資料,實現的是即時響應。在ciocpserver裡,有兩類重要執行緒:acceptthread執行緒和workerthread執行緒。其中,accetpthread執行緒使用accept或acceptex函式來接收客戶端的連線請求,並實現客戶端socket與完成埠控制代碼的繫結,「有客戶端連線時的處理介面」就是在這裡封裝的;而workerthread執行緒是我們在完成埠中常說的「工作者執行緒」,它由get函式觸發工作,除「有客戶端連線時的處理介面」之外的其它介面,都在這裡進行封裝。
在真正實現乙個高效能伺服器模型時,我們可能需要逐層地加以實現,這樣作,一是因為測試起來要簡單一些,二是因為在我們逐層實現時可以清楚地知道每一層在實現時的效率是什麼樣的,這樣就有利於我們找出提高效率的突破口。可以先從ciocpserver類開始,實現乙個簡單的echo伺服器,即:回顯伺服器。不用維護資料報佇列,對客戶端發過來的資料,即時返回給客戶端。作完這一層,屬於完成埠該作的事基本上就作完了,它包括:有大量客戶端連線時的客戶端連線佇列維護,客戶端連線、斷開、傳送、接收資料時的事件處理及執行緒同步。根據我的經驗,在處理底層的客戶端斷開事件時是乙個難點,新手往往會在接收到斷開事件時直接釋放掉當前客戶端物件,但比較好的作法是使用引用計數機制,而不是直接釋放。另外,在「釋放」這一點上,我也有自己的乙個看法,即:客戶端物件最好不要釋放,而把它放入閒置佇列或者關閉原來的socket之後,再重新生成乙個新的socket讓它與原客戶端物件關聯,把它作為乙個新的客戶端物件使用,這樣就避免了頻繁的客戶端物件的建立與釋放,當然,這樣作的前提是在接受客戶端連線方面最好使用acceptex函式而不是accept。
《未完待續》
基於win平台的高效能伺服器底層通訊模型設計 1
由於個人工作的關係,接觸高效能伺服器的研發已經有一段時間了,在沒有接觸這個話題之前,我也和許多人一樣,認為伺服器的設計無非就是用一下winsock,呼叫呼叫函式那麼簡單。當親自完成了乙個在win平台上能承載上萬連線的測試模型後,才知道,原來,作高效能伺服器是這麼有挑戰性。你不僅需要在細支末節上對模型...
基於win平台的高效能伺服器底層通訊模型設計 1
由於個人工作的關係,接觸高效能伺服器的研發已經有一段時間了,在沒有接觸這個話題之前,我也和許多人一樣,認為伺服器的設計無非就是用一下winsock,呼叫呼叫函式那麼簡單。當親自完成了乙個在win平台上能承載上萬連線的測試模型後,才知道,原來,作高效能伺服器是這麼有挑戰性。你不僅需要在細支末節上對模型...
基於win平台的高效能伺服器底層通訊模型設計 1
由於個人工作的關係,接觸高效能伺服器的研發已經有一段時間了,在沒有接觸這個話題之前,我也和許多人一樣,認為伺服器的設計無非就是用一下winsock,呼叫呼叫函式那麼簡單。當親自完成了乙個在win平台上能承載上萬連線的測試模型後,才知道,原來,作高效能伺服器是這麼有挑戰性。你不僅需要在細支末節上對模型...