1. 程式人生 > >非阻塞伺服器需要注意的主要問題(譯)

非阻塞伺服器需要注意的主要問題(譯)

非阻塞伺服器有一個嚴重的問題,一些人甚至在沒解決這個問題的背景下就開發自己的應用框架(比如Python的Tornado

當你使用非阻塞伺服器的時候,你會獲得出色的效能並且不需要擔心可擴充套件性,然而同時你需要意識到一個問題:你的IO呼叫、網路系統呼叫也都是非阻塞的嗎?很多人忽略了,他們使用的非阻塞伺服器,其實是構建在阻塞庫之上的。

在這篇文章裡,我將深入對比多執行緒的伺服器與非阻塞的伺服器分別是如何工作的,以及你之所以需要在"使用的伺服器"與"使用的庫"在阻塞模式上保持一致的原因。

Non-blocking servers perform better

首先,我不會否認非阻塞伺服器比阻塞伺服器有更好的效能,尤其在那些有著數以萬計的高併發使用者的應用場景中。下面通過一些圖片對說明這個問題,這些圖片是WebFaction所測試的結果:

當他們從Apache向Nginx遷移時,發現:

Nginx每秒可以處理更多的請求:

nginx - req pr sec

Nginx比Apache使用更少的記憶體:

nginx - memory usage

真是令人吃驚的結果,那麼為何不把非阻塞技術引入到你的 Python/Java/Ruby/PHP 框架裡呢?

How blocking servers work

阻塞式伺服器通常是基於多執行緒的,一個執行緒處理一個請求,它的工作方式可以現象化地表示為:

Threaded server

關於阻塞式伺服器,有如下事實:

  • 處理高併發連線請求代價昂貴,伺服器需要量產執行緒——執行緒並不便宜。
  • 庫函式需要執行緒安全,這是多執行緒環境必需的。

How non-blocking servers work

非阻塞伺服器不需要多執行緒,它通過一個IO迴圈及(非同步)事件來處理請求,它的工作方式如下:

Non blocking server

關於非阻塞式伺服器,有如下事實:

  • 處理高併發連線請求不是困難,這也是它被用於comet技術的重要原因
  • 在IO迴圈中的所有操作都必須是非阻塞,否則會因為你一個操作而阻斷了整個迴圈
  • 不需要執行緒安全

Where Tornado (and others) go wrong

我以Tornado為例,但是其它的非阻塞式應用存在相同的問題:

Tornado使用了非阻塞式的伺服器,但他們同時使用的庫是阻塞式的,於是:

  • Tornado關於Mysql連線的庫是阻塞的,這意味如果你的查詢需要1s,那麼你的loop迴圈就需要停下來1s等待查詢的完成
  • 不要使用昂貴的系統呼叫,它會卡住整個迴圈
  • 同樣,不要在迴圈中渲染模板,原因同上

就像我之前提過的,阻塞整個loop是致命的,因為此時你什麼也做不了!

Conclusion

總之,非阻塞技術精巧且效能卓越,但要正確運用此技術,你必須使用同樣是阻塞式的IO和Network呼叫,否則你將後患無窮!還有,請注意Python, Ruby, Java or PHP等這些語言預設都是阻塞式的,所以當你同時使用非阻塞的伺服器和這些語言其中之一的話,請務必當心!