姜 立
(遼寧軌道交通職業學院,遼寧 沈陽 110023)
在日常生活中,對于一個中等規模的應用來說,同時達到千人以上在線的情況經常發生,系統集群可以很好地解決這個問題。現實情況下,一些應用不可能投入大量硬件設備,因為硬件設備價格高昂。如何能利用有限的系統資源,解決比較困難的部署問題,成為計算機軟件行業研究的主要問題。在設計過程中,如果采用一個用戶一個線程的設計方式那將造成CPU在成千上萬的線程間進行切換,后果不可想象,用戶多一點的時候完全解決不了問題,甚至系統崩潰。而Windows系統為我們提供了一個強大的工具,那就是完成端口(IOCP)[1]。
重疊I/O(Overlapped I/O),完成端口(Completion Ports),Windows完成端口把完成端口看成需要系統維護的隊列,應用調用系統接口,把重疊IO操作完成的事件放入隊列,用不同的CPU內核處理的強大功能。
(1)很多現網應用服務器采用的是Windows server系統,Windows server系統有諸多優點。而Windows IOCP就是Windows系統獨有的、系統自帶的強大功能,而其他系統要實現重疊IO功能,都需要應用自身實現,大大增加了開發難度。
(2)Windows IOCP完成端口技術則完全顛覆傳統設計模式,將并行的線程數量設計上限。目前IOCP完成端口是Windows下性能最好的I/O模型,同時它也是最復雜的內核對象[2]。其避免了大量用戶并發時原有模型采用的方式,極大地提高了程序的并行處理能力。完成端口會充分利用Windows內核來進行I/O的調度,是C/S通信模式中性能最好的網絡通信模型。使用“同步”的方式操作會阻塞住來自同一個線程的任何其他操作,所以要設計出高性能的服務器程序,通信一定要是異步的。完成端口模型的初衷,是為了解決一個客戶端一個連接線程的巨大缺點,充分利用內核對象的調度,只使用少量的幾個線程來處理和客戶端的所有通信,消除了無謂的線程上下切換,最大限度地提高了網絡通信的性能。
(3)提供長連接、短連接,RPC級功能實現。
所謂異步,區別于同步的地方就是同步可以理解為多個工作大家排對按順序一個接一個完成,所需要的時間是每個任務時間之和,異步操作則是大家同時開始工作,所需要的時間就是子任務里邊時間最長的。這樣就可以簡單通俗地理解異步操作的性能優勢,Windows的IOCP就是異步操作的最完美實例。
Windows的IOCP負責任務的調度和完成通知。設備句柄為同步對象,有兩種信號狀態:有或無。無信號狀態:IO請求發送時處理時;有信號狀態:操作完成時。可見,只有在任務完成時設備句柄信號才有有信號狀態。此時系統受信,系統通過Wait For Multiple Objects(或Wait For Single object)接口判斷操作是否完成[3]。
系統事件和IO操作一一對應,進行綁定。系統通過事件處理API處理IO操作,由于事件API本身就是異步高效操作,和IO操作結合,很好地簡化了操作流程。當I/O操作完成后系統采用事件API通知綁定的IO句柄,事件授信,IO執行操作完成。該技術解決了使一個設備內核對象變為有信號技術中一個設備只能對應一個操作的不足。
(1)大型多人在線游戲類型游戲(MMO游戲),目前大型的MMO游戲都采用了IOCP完成端口,如《三國鼎立》《英雄遠征》等。
(2)大型IM(即時通訊、實時傳訊)系統,IOCP提供長連接、短連接,可以簡單實現心跳機制,確保設備在線,應對運營商連接清理機制。
(3)企業ERP管理系統等等具有大量并發用戶請求的場合。
(4)穩定、高效的IOCP完成端口通信模型幾乎成為開發這類系統的基礎。
系統采用C/S結構設計,主要分為登錄、用戶管理、信息管理、設備管理管理、設備控制等模塊。服務器端應用完成端口技術,客戶端采用普通的Socket連接方式。服務器端數據庫系統采用MySql。系統通過IOCP服務器來訪問數據庫系統,用戶通過客戶端軟件進行Socket短連接到IOCP服務器,進行數據操作[4]。
(1)創建完成端口。
HANDLE m_hIOCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
(2)根據系統中CPU核心的數量建立對應的Worker線程。
SYSTEM_INFO si;
GetSystemInfo(&si) ;
int m_nProcessors = si.dwNumberOfProcessors;
m_phWorkerThreads[i] = ::CreateThread(0, 0, _WorkerThread, …) ;
(3)創建用于監聽的Socket,綁定到完成端口上,然后開始在指定的端口上監聽連接請求。
SOCKET m_sockListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
If(SOCKET_ERROR==bind(m_sockListen,(struct sockaddr*)&ServerAddress, sizeof(ServerAddress)));
listen(m_sockListen,SOMAXCONN)) ;
(4)在這個監聽Socket上投遞AcceptEx請求。
GUID GuidAcceptEx = WSAID_ACCEPTEX; WSAIoctl(m_pListenContext->m_Socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidAcceptEx,sizeof(GuidAcceptEx), &m_lpfnAcceptEx, sizeof(m_lpfnAcceptEx) , &dwBytes, NULL,NULL) ;
(5)Worker線程的工作。
BOOL bReturn=GetQueuedCompletionStatus(pIOCPModel->m_hIOCompletionPort,
(LPDWORD)&lpContext,&pOverlapped,INFINITE );
(6)收到Accept通知時執行_DoAccept。
(7)當收到Recv通知時, _DoRecv。
目前高性能異步IO技術已經日趨成熟,各大頂尖技術公司和知名企業都有自己的實現機制和方法。當前主流技術已經在高性能異步IO技術上繼續演進為微服務和云等,如阿里的Dubbo和apache的Spring Cloud等。但是Winows完成端口技術依然在特定環境為我們提供了一個可行的免費的解決方案,而且實現代價低,一臺普通的PC電腦便可以發揮出類似服務器的功能,可以承接大部分小型應用,因此目前仍然有很多技術人員熱衷于Winows完成端口技術的研究和開發。