[原]淺談幾種服務器端模型——同步阻塞迭代


引言:似乎現在阻礙服務端大部分情況下都屬於IO瓶頸,硬盤的轉速等,而計算的瓶頸大部分雲端計算采用分布式計算,如基於GFS的MapReduce模型,網格計算或者其他的一些分布式處理。所以,現在服務端的服務衡量指標基本集中在並發量,QPS,響應速度,穩定性等。其中一部分也不乏大量的計算,屬於CPU密集型的,根據業務的不同應該做相應的調整。今天的話題是淺談一下幾種常用的IO模型。

 

理解IO 模型是網絡編程的重點。

最簡單的同步迭代IO模型:

核心代碼就是這樣,這里我們假設前面的監聽套接口已建立。即已綁定套接口,並調用了listen()函數。

同步迭代IO大致如下,我們假設現在的模型是這樣的,服務端監聽客戶端的連接,並通過讀取fd的內容,處理后返回給客戶端,類似於http機制。這里省去了一些包裹函數等。

for(;;){
  fd = accept(...);

  read(fd,buf,n);

  dosomtething(buf);

  write(fd,buf,n);

    close(fd);
}

  

單進程模式下,如果沒有客戶端到來,進程一直阻塞在 accept調用上,對於新手來說,有點難理解阻塞的概念,總的來說,就是經過accept調用,陷入內核以后,進程停止其他的工作,等待accept()返回。阻塞在accept()不可怕,如果阻塞在read()系統調用,將導致整個服務器不能對其他的客戶端提供服務。

現在假設一個情景:

accept()得到一個客戶端的連接,此時的fd唯一標示該連接。

現在服務器進入read()系統調用,但是此時的客戶端並沒有發送數據,那么服務端一直阻塞在read系統調用。此時來了一個新的連接,但是服務端不能予以相應,就是accept()函數不能被服務器調用。那么這個連接是失敗的。可想而知,這樣的服務器模型是有多么的低效。不過,UDP恰恰常用這種方式,因為UDP 是非面向連接的,整個過程就是兩個函數

recvfrom(buf);
dosomething(buf);
sendto(buf);

因為UDP 的非面向連接性,而且采用的是費可靠傳輸,傳輸速率較TCP快。讀者可以查閱相關資料,但是最好需要設置客戶端的recvfrom()超時,因為在傳輸過程中數據丟失,會導致客戶端阻塞在recvfrom()調用上。

 

附一張圖說明read()的系統調用的阻塞:

即進程需要等待內核返回結果以后才能繼續處理其他業務。

總結:同步阻塞迭代方式的IO是最簡單的一種形式的IO模型,也是最低效的一種,但是研究東西都需要從最簡單的開始。吸取經驗。下一章講解多進程的並發式IO模型。

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM