成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

程序員應如何理解Reactor模式?

開發 前端
在這篇文章中我們詳細講解了高性能高并發目前流行的Reactor模式,其實其本質和咖啡館沒什么區別,如果你善于觀察和思考的話那么你會發現其實很多技術問題都能在現實生活中找到相似的場景。

?大家好,我是小風哥!今天我們聊聊reactor模式。

在設計高并發高性能服務器時,一項關鍵的考慮就是I/O。

I/O是一個問題

有的同學可能會有疑問,為什么I/O會成為問題?

假設有一個web server,每分鐘有數百萬次的請求過來,服務器在處理請求時要訪問數據庫,同時該服務器也可能要請求其它的服務,一張典型的后端server可能的架構如圖所示:

圖片

一個用戶請求過來后Server可能需要訪問數據庫,然后再去請求另外幾個server后才能得到用戶請求的處理結果,然后將response返回給客戶端,從這張圖中數一數涉及到哪些IO?

其實主要有兩種:

  • 數據庫操作的磁盤IO、文件IO
  • 網絡IO

現在你已經知道了涉及哪些IO,讓我們再來看一張圖:

圖片

我們可以看到,磁盤IO和網絡IO是非常慢的,也就是說我們通常用手機APP、PC瀏覽器打開一個頁面點擊一個按鈕到完全得到響應,這其中大部分的時間都消耗在了這兩種IO上,真正用在處理數據的CPU時間反而不是很多。

這告訴了我們一個道理,那就是高效處理IO對于高并發高性能服務器來說至關重要。

兩類經典設計模式

有兩類處理網絡請求的經典模型:

  • 基于線程(進程)的 Thread(Process)-per-connection,也就是每個請求一個線程(進程)
  • 基于事件驅動的Reactor模式,也就是反應器模式。

其中第一種模式我們在之前的文章中已經多次講解過了,這種模式會為每個請求都創建一個線程或者進程:

圖片

但這種模式的一個問題就在于當并發數較多時需要創建很多的線程,創建線程過多會有性能問題。

第二種基于事件的模式我們在之前的文章中也講解過,在這種模式下我們只需要一個線程就能同時處理多個用戶請求:

圖片

在基于事件的并發編程中有一種叫做Reactor的模式非常流行,Node.js以及Nginx就使用Reactor,在這篇文章中我們詳細的講解一下高性能高并發服務器中的Reactor模式。

當然,在了解Reactor之前我們先來看一下咖啡館是怎樣運作的。

咖啡館是怎樣運作的

假設你有一家咖啡館,作為老板的你在前臺接待喝咖啡的顧客,你的生意不錯,來這里喝咖啡的人絡繹不絕。

有時,有的人點的東西很簡單,比如來一杯咖啡或者牛奶之類,但也有一些顧客會點一些復雜的比如來一份意大利面等,作為前臺的你,如果這是停止接待顧客而且制作意大利面的話那么后續到來的所有顧客都要等待。

幸好,作為老板的你還有幾位大廚來幫忙,因此你只需要簡單的把制作意大利面的命令交代下去就好了,“張三去煮面條,李四去制作醬料,制作好后通知我”。

就這樣,即便前臺只有你一個人也能快速接待顧客的點餐,其實這背后本質上就是Reactor模式。

Reactor模式

實際上每個你可以把咖啡館這個例子中每個顧客理解為服務器接收的請求,前臺的服務員理解為一個單線程的while循環,這個while循環有一個很形象的名字,event loop,這個event loop要做的事情非常簡單,那就是接收用戶請求,然后讓handler,或者回調函數去處理,這里的handler或者回調函數就好比大廚張三和李四去,handler或者回調函數可以和event loop運行在同一個線程中,也可以和event loop各自運行在各自的線程中。

既然該模式是基于事件驅動,那么都有哪些事件呢?

我們需要關心的典型事件這樣幾種:

  • 網絡請求的到來,也就是socket編程中accept到客戶端連接
  • 文件可讀
  • 文件可寫

看到了吧,這幾種event都是和IO相關的,涉及網絡和文件。

有的同學可能會問,那么這個event loop是怎么知道有這些event到來呢?

這是涉及到了IO多路復用技術,典型的像Linux中的select、poll、epoll。

通過IO多路復用技術,我們可以一次監控一堆的文件描述符,當這些文件描述符對應的IO事件發生時會收到操作系統的通知,這時我們獲取到該event并交給相應的handler或者回調函數來處理。

總結下來,Reactor的核心組成部分就是event loop + IO多路復用 + 回調函數。

單線程 or 多線程

我們在上文提到過,處理event的handler可以和event loop運行在同一個線程中,也可以運行在不同的線程中。

如果是運行在同一個線程中那么我們無需面對復雜的多線程問題,但在當前的多核時代,單線程無法充分利用多核資源,此外如果某個請求比較復雜需要占用的CPU資源較多,那么在單線程下其它所有的用戶請求都要等待,基于以上考慮我們可以使用線程池(多線程)技術。

event loop在接收到event后,將event和處理event的handler(回調函數)打包發給線程池,線程池中的線程接收到打包后的任務后調用handler(回調函數)來處理相應的event。

這樣我們的組合就成了event loop + IO多路復用 + 回調函數 + 線程池。

把協程也加進來

回調函數的一大缺點在于如果處理用戶請求的邏輯比較復雜可能會導致回調地獄,關于回調地獄你可以參考這里,協程這種技術在一定程度上解決了這一問題,讓我們可以用同步的方式來進行異步編程,關于協程你可以參考這里和這里。

最終我們的組合就成了event loop + IO多路復用 + 協程 + 線程池。

接下來讓我們以Node.js來講解一下Reactor模式。

Node.js與Reactor模式

我們來看一下Node.js的架構圖:

圖片

這張架構圖已經無比清晰的展示了Reactor模式是如何運行的。

1, 當用戶請求到來后需要將其放到一個隊列當中,因為event loop是運行在單線程中的。

圖片

2,接下來event loop不斷檢測event queue中是否有event到來,如果隊列中有請求,那么根據隊列的“先來先服務”原則,event loop取出相應的event,并將其交給線程池。

圖片

3,該線程池不斷檢測是否有task到來,這里的task也就是將event和相應的回調函數打包后形成的。

4,線程接收到task后,線程池中的線程開始工作,比如查詢數據庫、讀取文件等等。

圖片

5,當線程處理完一個請求后調用task相應的回調函數,并將該處理結果response發送給event loop。

圖片

6,event loop在接收到處理結果后發送給客戶端。

圖片

怎樣,這是不是像極了上文中的咖啡館以及這里的核反應堆。

圖片

這就是Reactor模式。

此外,Node.js中的協程叫做Fiber,都是用來以同步的方式來進行異步編程的,這里就不詳細講解了。

Reactor vs Proactor

Reactor模式中使用的IO都是同步IO,什么是同步IO呢?

就是說調用方在IO完成之前會被阻塞等待,這種IO更具體的就叫做同步阻塞式IO。

但我們知道event loop是運行在一個線程中的,如果在event loop中調用同步阻塞式IO的話,那么整個線程會被暫停運行,由于event loop就像咖啡廳前臺,非常關鍵,如果event loop所在線程被阻塞那么所有的用戶請求都必須等待。

因此,在event loop中的IO不能是阻塞式的。

有同步阻塞式IO就有同步非阻塞式IO。

什么是同步非阻塞式IO呢?意思是當我們調用同步非阻塞式IO相關函數時,函數會立刻返回,并告訴我們文件是否可讀或者可寫,如果可讀或者可寫的話我們再真正的進行文件讀寫,這就是同步非阻塞式IO。

Reactor模式都是采用的同步非阻塞式IO。

與同步IO相對應的是異步IO。

在異步IO下我們需要將接收或者寫入數據的地址告訴操作系統,操作系統會將數據從進程地址空間寫入文件或者將文件內容寫到進程地址空間中,操作系統完成IO后會通知我們,這就是異步IO。

執行異步IO同樣不會阻塞調用線程。

關于同步以及異步的概念你可以參考這里。

而采用異步IO的事件驅動編程被稱為Proactor。

也就是說Reactor和Proactor的區別就在于一個采用同步IO一個采用異步IO。

接下來我們用一個讀文件的例子來講解這兩者的差異。

Reactor中的讀:

  • 告訴event loop,我們對某個文件可讀事件感興趣
  • event loop等待該事件
  • 事件到來,event loop被喚醒,并調用相應handler
  • 該handler開始讀取文件,并處理數據,完成后返回到event loop

而Proactor的讀是這樣的:

  • 我們發起一個針對某個文件的異步讀取操作,告訴event loop,我們不關心這個文件是否可讀,我們只關心這個文件是否讀取完成。
  • event loop開始等待該事件
  • 與此同時,操作系統開始執行真正的文件讀取,讀取完成后通知event loop讀取完成
  • event loop被喚醒,此時文件已經讀取完畢,調用相應的handler
  • handler開始處理數據,完成后返回到event loop。

現在你應該明白Reactor和Proactor的差異了吧。

總結

在這篇文章中我們詳細講解了高性能高并發目前流行的Reactor模式,其實其本質和咖啡館沒什么區別,如果你善于觀察和思考的話那么你會發現其實很多技術問題都能在現實生活中找到相似的場景。

希望這篇能對大家理解Reactor模式有幫助。?

責任編輯:武曉燕 來源: 碼農的荒島求生
相關推薦

2020-11-30 08:25:41

程序員高并發協程

2011-05-26 10:04:30

程序員

2011-05-31 09:22:39

程序員

2011-07-25 09:14:40

程序員

2011-05-31 09:37:53

程序員

2010-07-27 16:21:25

程序員

2011-06-02 09:02:36

程序員

2011-06-02 09:56:21

程序員團隊精神

2011-05-24 13:47:25

程序員

2011-05-30 14:50:56

程序員

2011-05-31 10:50:36

程序員

2021-11-29 10:27:24

設計模式程序員

2011-03-22 10:16:48

程序員

2023-05-06 07:24:22

程序員視頻算法

2018-08-28 15:30:54

編程語言Python日志系統

2013-12-23 14:53:25

2014-02-18 13:54:44

程序員權利

2014-07-30 16:11:11

程序員

2014-08-04 10:54:47

程序員

2015-03-16 15:33:11

JavaScript程序員應備素質
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美精品久久久 | 日韩在线综合 | 精品国产乱码一区二区三区a | 97人人干| av网站在线看 | 欧美vide | 亚洲午夜精品一区二区三区他趣 | 久久久av | 国产999精品久久久久久 | 欧美成人精品在线 | 国产成人免费视频 | 一区在线观看视频 | 中文字幕在线一区 | 久久99精品视频 | 午夜久久 | 婷婷免费在线 | 精品1区2区 | 伦理午夜电影免费观看 | 久久精品视频一区二区三区 | 国产视频一视频二 | 精品国产欧美在线 | 亚洲免费一区二区 | 免费不卡av| 色网在线观看 | 国产在线a| 日本在线播放 | 中文字幕 在线观看 | 久久久九九 | 亚洲成人在线免费 | 一区二区三区国产精品 | 色偷偷人人澡人人爽人人模 | 国产精品不卡一区二区三区 | 中文字幕免费 | 欧美天堂在线 | 狠狠久| 男人的天堂在线视频 | 亚洲一二三区精品 | 9191在线播放 | 国产97视频在线观看 | 精品久久久久一区二区国产 | 在线观看免费高清av |