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

程序員應(yīng)如何理解Reactor模式?

開發(fā) 前端
在這篇文章中我們?cè)敿?xì)講解了高性能高并發(fā)目前流行的Reactor模式,其實(shí)其本質(zhì)和咖啡館沒什么區(qū)別,如果你善于觀察和思考的話那么你會(huì)發(fā)現(xiàn)其實(shí)很多技術(shù)問題都能在現(xiàn)實(shí)生活中找到相似的場景。

?大家好,我是小風(fēng)哥!今天我們聊聊reactor模式。

在設(shè)計(jì)高并發(fā)高性能服務(wù)器時(shí),一項(xiàng)關(guān)鍵的考慮就是I/O。

I/O是一個(gè)問題

有的同學(xué)可能會(huì)有疑問,為什么I/O會(huì)成為問題?

假設(shè)有一個(gè)web server,每分鐘有數(shù)百萬次的請(qǐng)求過來,服務(wù)器在處理請(qǐng)求時(shí)要訪問數(shù)據(jù)庫,同時(shí)該服務(wù)器也可能要請(qǐng)求其它的服務(wù),一張典型的后端server可能的架構(gòu)如圖所示:

圖片

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

其實(shí)主要有兩種:

  • 數(shù)據(jù)庫操作的磁盤IO、文件IO
  • 網(wǎng)絡(luò)IO

現(xiàn)在你已經(jīng)知道了涉及哪些IO,讓我們?cè)賮砜匆粡垐D:

圖片

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

這告訴了我們一個(gè)道理,那就是高效處理IO對(duì)于高并發(fā)高性能服務(wù)器來說至關(guān)重要。

兩類經(jīng)典設(shè)計(jì)模式

有兩類處理網(wǎng)絡(luò)請(qǐng)求的經(jīng)典模型:

  • 基于線程(進(jìn)程)的 Thread(Process)-per-connection,也就是每個(gè)請(qǐng)求一個(gè)線程(進(jìn)程)
  • 基于事件驅(qū)動(dòng)的Reactor模式,也就是反應(yīng)器模式。

其中第一種模式我們?cè)谥暗奈恼轮幸呀?jīng)多次講解過了,這種模式會(huì)為每個(gè)請(qǐng)求都創(chuàng)建一個(gè)線程或者進(jìn)程:

圖片

但這種模式的一個(gè)問題就在于當(dāng)并發(fā)數(shù)較多時(shí)需要?jiǎng)?chuàng)建很多的線程,創(chuàng)建線程過多會(huì)有性能問題。

第二種基于事件的模式我們?cè)谥暗奈恼轮幸仓v解過,在這種模式下我們只需要一個(gè)線程就能同時(shí)處理多個(gè)用戶請(qǐng)求:

圖片

在基于事件的并發(fā)編程中有一種叫做Reactor的模式非常流行,Node.js以及Nginx就使用Reactor,在這篇文章中我們?cè)敿?xì)的講解一下高性能高并發(fā)服務(wù)器中的Reactor模式。

當(dāng)然,在了解Reactor之前我們先來看一下咖啡館是怎樣運(yùn)作的。

咖啡館是怎樣運(yùn)作的

假設(shè)你有一家咖啡館,作為老板的你在前臺(tái)接待喝咖啡的顧客,你的生意不錯(cuò),來這里喝咖啡的人絡(luò)繹不絕。

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

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

就這樣,即便前臺(tái)只有你一個(gè)人也能快速接待顧客的點(diǎn)餐,其實(shí)這背后本質(zhì)上就是Reactor模式。

Reactor模式

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

既然該模式是基于事件驅(qū)動(dòng),那么都有哪些事件呢?

我們需要關(guān)心的典型事件這樣幾種:

  • 網(wǎng)絡(luò)請(qǐng)求的到來,也就是socket編程中accept到客戶端連接
  • 文件可讀
  • 文件可寫

看到了吧,這幾種event都是和IO相關(guān)的,涉及網(wǎng)絡(luò)和文件。

有的同學(xué)可能會(huì)問,那么這個(gè)event loop是怎么知道有這些event到來呢?

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

通過IO多路復(fù)用技術(shù),我們可以一次監(jiān)控一堆的文件描述符,當(dāng)這些文件描述符對(duì)應(yīng)的IO事件發(fā)生時(shí)會(huì)收到操作系統(tǒng)的通知,這時(shí)我們獲取到該event并交給相應(yīng)的handler或者回調(diào)函數(shù)來處理。

總結(jié)下來,Reactor的核心組成部分就是event loop + IO多路復(fù)用 + 回調(diào)函數(shù)。

單線程 or 多線程

我們?cè)谏衔奶岬竭^,處理event的handler可以和event loop運(yùn)行在同一個(gè)線程中,也可以運(yùn)行在不同的線程中。

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

event loop在接收到event后,將event和處理event的handler(回調(diào)函數(shù))打包發(fā)給線程池,線程池中的線程接收到打包后的任務(wù)后調(diào)用handler(回調(diào)函數(shù))來處理相應(yīng)的event。

這樣我們的組合就成了event loop + IO多路復(fù)用 + 回調(diào)函數(shù) + 線程池。

把協(xié)程也加進(jìn)來

回調(diào)函數(shù)的一大缺點(diǎn)在于如果處理用戶請(qǐng)求的邏輯比較復(fù)雜可能會(huì)導(dǎo)致回調(diào)地獄,關(guān)于回調(diào)地獄你可以參考這里,協(xié)程這種技術(shù)在一定程度上解決了這一問題,讓我們可以用同步的方式來進(jìn)行異步編程,關(guān)于協(xié)程你可以參考這里和這里。

最終我們的組合就成了event loop + IO多路復(fù)用 + 協(xié)程 + 線程池。

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

Node.js與Reactor模式

我們來看一下Node.js的架構(gòu)圖:

圖片

這張架構(gòu)圖已經(jīng)無比清晰的展示了Reactor模式是如何運(yùn)行的。

1, 當(dāng)用戶請(qǐng)求到來后需要將其放到一個(gè)隊(duì)列當(dāng)中,因?yàn)閑vent loop是運(yùn)行在單線程中的。

圖片

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

圖片

3,該線程池不斷檢測是否有task到來,這里的task也就是將event和相應(yīng)的回調(diào)函數(shù)打包后形成的。

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

圖片

5,當(dāng)線程處理完一個(gè)請(qǐng)求后調(diào)用task相應(yīng)的回調(diào)函數(shù),并將該處理結(jié)果response發(fā)送給event loop。

圖片

6,event loop在接收到處理結(jié)果后發(fā)送給客戶端。

圖片

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

圖片

這就是Reactor模式。

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

Reactor vs Proactor

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

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

但我們知道event loop是運(yùn)行在一個(gè)線程中的,如果在event loop中調(diào)用同步阻塞式IO的話,那么整個(gè)線程會(huì)被暫停運(yùn)行,由于event loop就像咖啡廳前臺(tái),非常關(guān)鍵,如果event loop所在線程被阻塞那么所有的用戶請(qǐng)求都必須等待。

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

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

什么是同步非阻塞式IO呢?意思是當(dāng)我們調(diào)用同步非阻塞式IO相關(guān)函數(shù)時(shí),函數(shù)會(huì)立刻返回,并告訴我們文件是否可讀或者可寫,如果可讀或者可寫的話我們?cè)僬嬲倪M(jìn)行文件讀寫,這就是同步非阻塞式IO。

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

與同步IO相對(duì)應(yīng)的是異步IO。

在異步IO下我們需要將接收或者寫入數(shù)據(jù)的地址告訴操作系統(tǒng),操作系統(tǒng)會(huì)將數(shù)據(jù)從進(jìn)程地址空間寫入文件或者將文件內(nèi)容寫到進(jìn)程地址空間中,操作系統(tǒng)完成IO后會(huì)通知我們,這就是異步IO。

執(zhí)行異步IO同樣不會(huì)阻塞調(diào)用線程。

關(guān)于同步以及異步的概念你可以參考這里。

而采用異步IO的事件驅(qū)動(dòng)編程被稱為Proactor。

也就是說Reactor和Proactor的區(qū)別就在于一個(gè)采用同步IO一個(gè)采用異步IO。

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

Reactor中的讀:

  • 告訴event loop,我們對(duì)某個(gè)文件可讀事件感興趣
  • event loop等待該事件
  • 事件到來,event loop被喚醒,并調(diào)用相應(yīng)handler
  • 該handler開始讀取文件,并處理數(shù)據(jù),完成后返回到event loop

而Proactor的讀是這樣的:

  • 我們發(fā)起一個(gè)針對(duì)某個(gè)文件的異步讀取操作,告訴event loop,我們不關(guān)心這個(gè)文件是否可讀,我們只關(guān)心這個(gè)文件是否讀取完成。
  • event loop開始等待該事件
  • 與此同時(shí),操作系統(tǒng)開始執(zhí)行真正的文件讀取,讀取完成后通知event loop讀取完成
  • event loop被喚醒,此時(shí)文件已經(jīng)讀取完畢,調(diào)用相應(yīng)的handler
  • handler開始處理數(shù)據(jù),完成后返回到event loop。

現(xiàn)在你應(yīng)該明白R(shí)eactor和Proactor的差異了吧。

總結(jié)

在這篇文章中我們?cè)敿?xì)講解了高性能高并發(fā)目前流行的Reactor模式,其實(shí)其本質(zhì)和咖啡館沒什么區(qū)別,如果你善于觀察和思考的話那么你會(huì)發(fā)現(xiàn)其實(shí)很多技術(shù)問題都能在現(xiàn)實(shí)生活中找到相似的場景。

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

責(zé)任編輯:武曉燕 來源: 碼農(nóng)的荒島求生
相關(guān)推薦

2020-11-30 08:25:41

程序員高并發(fā)協(xié)程

2011-05-31 09:22:39

程序員

2011-05-26 10:04:30

程序員

2011-07-25 09:14:40

程序員

2011-05-24 13:47:25

程序員

2011-05-31 09:37:53

程序員

2010-07-27 16:21:25

程序員

2011-06-02 09:02:36

程序員

2011-06-02 09:56:21

程序員團(tuán)隊(duì)精神

2011-05-30 14:50:56

程序員

2011-05-31 10:50:36

程序員

2021-11-29 10:27:24

設(shè)計(jì)模式程序員

2011-03-22 10:16:48

程序員

2023-05-06 07:24:22

程序員視頻算法

2018-08-28 15:30:54

編程語言Python日志系統(tǒng)

2015-03-16 15:33:11

JavaScript程序員應(yīng)備素質(zhì)

2013-12-23 14:53:25

2014-02-18 13:54:44

程序員權(quán)利

2014-07-30 16:11:11

程序員

2014-08-04 10:54:47

程序員
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 成人免费视频7777777 | 91欧美精品 | 中文字幕日韩欧美 | 欧美区精品 | 国产精品毛片一区二区三区 | 亚洲福利一区 | www一级片 | 中文字幕av亚洲精品一部二部 | 国产精品区一区二区三 | 日韩精品视频网 | 欧美大片在线观看 | 999免费网站 | 日日夜夜精品视频 | 热99精品视频 | 成人免费淫片aa视频免费 | 在线观看国产h | 亚洲欧美日韩在线不卡 | 亚洲一区中文字幕在线观看 | 成人久久网 | 欧美精品1区2区3区 精品国产欧美一区二区 | www.天天操| 国产精品国产成人国产三级 | 国产高清视频一区二区 | 午夜视频精品 | 成人午夜网站 | 国产精品一区在线观看 | 日日爽 | 久草免费视| 欧美一级小视频 | 日韩成人免费av | 中文字幕一区二区不卡 | 天堂一区二区三区 | 91久久精品日日躁夜夜躁欧美 | 中文字幕在线网 | 粉嫩粉嫩芽的虎白女18在线视频 | 成人在线视频网站 | 福利在线观看 | 最新中文字幕在线播放 | 久久久国产一区二区 | 午夜手机在线视频 | 午夜激情在线视频 |