色屁屁www影院免费观看入口,欧美性猛交ⅹxxx乱大交妖精,欧美激情第5页,欧美性猛交xxxx三人,欧美一a级做爰片大开眼界

達(dá)觀動(dòng)態(tài)

達(dá)觀愿與業(yè)內(nèi)同行分享 助力各企業(yè)在大數(shù)據(jù)浪潮來臨之際一起破浪前行

Tornado原理淺析及應(yīng)用場(chǎng)景探討

本文章主要目的是介紹tornado的工作原理及延伸的關(guān)鍵技術(shù),為了便于讀者理解,會(huì)通過幾個(gè)簡(jiǎn)單易懂的例子,再配合原理圖進(jìn)行講解。由于本文主要是分析tornado的工作原理,所以牽扯到一些操作系統(tǒng)的細(xì)節(jié)會(huì)簡(jiǎn)單略過,希望讀者把握文章重點(diǎn),不要迷失在理解各種操作系統(tǒng)名詞的“深淵”里。當(dāng)你真正了解了tornado的工作原理后,相應(yīng)的應(yīng)用場(chǎng)景也就能舉一反三了。

?1

?

本文主要通過以下三點(diǎn)進(jìn)行講解:

?

  • Tornado的背景及技術(shù)介紹

  • 簡(jiǎn)單代碼后鮮為人知的秘密

  • Tornado的應(yīng)用場(chǎng)景

?

一、Tornado的背景及技術(shù)介紹

與傳統(tǒng)框架的區(qū)別

?

首先談一下傳統(tǒng)的一些web服務(wù)器框架吧,沒有對(duì)比就沒有“傷害”嘛,這里主要和Django為代表的傳統(tǒng)框架進(jìn)行比較,這一類的Python web應(yīng)用部署的時(shí)候一般是采用WSGI協(xié)議與服務(wù)器對(duì)接的,而這類服務(wù)器通常是基于多線程/多進(jìn)程的,也就是說每有一個(gè)網(wǎng)絡(luò)請(qǐng)求,服務(wù)器都會(huì)有一個(gè)線程/進(jìn)程進(jìn)行處理。

?

這里要重點(diǎn)介紹一下WSGI協(xié)議。

?

WSGI協(xié)議的由來:

例子:

中國(guó)有三家有名的通信運(yùn)營(yíng)商,分別是移動(dòng)、聯(lián)通和電信,這三家通信商的手機(jī)號(hào)是可以跨平臺(tái)撥打的,假設(shè)三家通信商負(fù)責(zé)通信的協(xié)議不同且無法互通,用移動(dòng)的手機(jī)號(hào)就無法給聯(lián)通電信的手機(jī)打電話,為了方便通信就需要一個(gè)統(tǒng)一的規(guī)范。

WSGI協(xié)議的角色就是這個(gè)統(tǒng)一的規(guī)范,是描述web server如何與web application通信的規(guī)范,要實(shí)現(xiàn)WSGI協(xié)議,就必須同時(shí)實(shí)現(xiàn)web server和web application,目前常見的有Tornado、Flask和Django。

?

WSGI協(xié)議具體做了什么:

1. 定義調(diào)用方式:讓W(xué)eb服務(wù)器知道如何調(diào)用python應(yīng)用程序,并把用戶的請(qǐng)求告訴應(yīng)用程序。

2. 定義接收方式:讓python應(yīng)用程序知道用戶的請(qǐng)求是什么,以及如何返回結(jié)果給web服務(wù)器。

application對(duì)象形式:
????????????? #application是定義的應(yīng)用端的調(diào)用方式
????????????? defsimple_app(environ, start_response):

???????????????????? # environ解釋了第一點(diǎn),將客戶的需求告訴應(yīng)用端
???????????????????? # start_response解釋了第二點(diǎn),回調(diào)函數(shù)
???????????????????? pass

3. 定義以上兩點(diǎn)后,WSGI還去充當(dāng)了服務(wù)器和應(yīng)用程序間的中間件,即充當(dāng)應(yīng)用程序又充當(dāng)服務(wù)器,可以形象的用下圖表示。?

2

其中大致流程是這樣的:

1. Server收到客戶端的HTTP請(qǐng)求后,生成了environ_s,并且已經(jīng)定義了start_response_s。

2. Server調(diào)用Middleware的application對(duì)象,傳遞的參數(shù)是environ_s和start_response_s。

3. Middleware會(huì)根據(jù)environ執(zhí)行業(yè)務(wù)邏輯,生成environ_m,并且已經(jīng)定義了start_response_m。

4. Middleware決定調(diào)用Application的application對(duì)象,傳遞參數(shù)是environ_m和start_response_m。Application的application對(duì)象處理完成后,會(huì)調(diào)用start_response_m并且返回結(jié)果給Middleware,存放在result_m中。

5. Middleware處理result_m,然后生成result_s,接著調(diào)用start_response_s,并返回結(jié)果result_s給Server端。Server端獲取到result_s后就可以發(fā)送結(jié)果給客戶端了。

??

WSGI是個(gè)同步模型,不支持非阻塞的請(qǐng)求方式,Tornado默認(rèn)是不推薦使用WSGI的,如果在Tornado中使用WSGI,將無法使用Tornado的異步非阻塞的處理方式,相應(yīng)的異步接口也就無法使用,性能方面也就大打折扣,這個(gè)也是Tornado性能如此優(yōu)越的原因。

?

二、C10K問題的提出

考慮兩種高并發(fā)場(chǎng)景:

?

1. 用戶量大,高并發(fā)。如秒殺搶購(gòu),雙十一,618和春節(jié)搶票。

2. 大量的HTTP持久連接。

?

對(duì)于以上兩種熟悉的場(chǎng)景,通?;诙噙M(jìn)程/線程的服務(wù)器是很難應(yīng)付的。

基于上述高并發(fā)場(chǎng)景,引出了C10k問題,是由一名叫DanKegel的軟件工程師提出的,即當(dāng)同時(shí)的連接數(shù)以萬計(jì)的時(shí)候,服務(wù)器性能會(huì)出現(xiàn)急劇下降甚至直接崩潰的情況,這就是著名的C10k問題。

?

值得一提的,騰訊QQ就遇到過C10k問題,當(dāng)時(shí)采用了udp的方式避開了這個(gè)問題,當(dāng)然過程是相當(dāng)痛苦的,后來也就專用了tcp,主要是當(dāng)時(shí)還沒有epoll技術(shù)。

?

簡(jiǎn)要地分析下C10k的本質(zhì)問題,其實(shí)無外乎是操作系的問題,連接多了,創(chuàng)建的進(jìn)程線程就多了,數(shù)據(jù)拷貝也就變得頻繁(緩存I/O、內(nèi)核將數(shù)據(jù)拷貝到用戶進(jìn)程空間、阻塞),進(jìn)程/線程上下文切換消耗又大,直接就導(dǎo)致操作系統(tǒng)奔潰。

?

可見,解決C10k問題的關(guān)鍵就是減少這些CPU等核心計(jì)算資源消耗,從而榨干單臺(tái)機(jī)器的性能,突破C10k描述的瓶頸;那么常規(guī)的解決思路有哪些呢,其實(shí)無外乎下面兩種方法:

解決一、對(duì)于每個(gè)連接處理分配一個(gè)獨(dú)立的進(jìn)程/線程。提升單臺(tái)機(jī)器的能力,盡可能多提供進(jìn)程/線程,一臺(tái)機(jī)器不夠就增加多臺(tái)機(jī)器。

解決二、用一個(gè)進(jìn)程/線程來同時(shí)處理若干個(gè)連接。

針對(duì)方法一,假設(shè)每臺(tái)機(jī)器都達(dá)到了一萬連接,同時(shí)有一億個(gè)請(qǐng)求,那么就需要一萬臺(tái)機(jī)器,所以這種解決方法不太實(shí)際。

針對(duì)方法二,需要有新的技術(shù)支持這種方案,實(shí)際上是可行的,也是現(xiàn)在普遍采取的方法,針對(duì)這種方法,其實(shí)有過多種技術(shù)支持,接下來重點(diǎn)介紹下。

?

三、epoll技術(shù)的引入

接下來我們根據(jù)技術(shù)的迭代發(fā)展來引入epoll技術(shù)。

實(shí)現(xiàn)方式一:傳統(tǒng)的循環(huán)遍歷的方式處理多個(gè)連接

這種方式明顯的缺點(diǎn)就是,當(dāng)其中任何一個(gè)socket的文件數(shù)據(jù)不ready的時(shí)候,線程/進(jìn)程會(huì)一直等待,進(jìn)而導(dǎo)致后面要處理的連接都被阻塞,整個(gè)應(yīng)用也就阻塞了。

?

實(shí)現(xiàn)方式二:select技術(shù)

首先解釋下select,它是個(gè)系統(tǒng)調(diào)用函數(shù),格式如下:

?int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, const struct??

?timeval? *timeout);

nfds:select監(jiān)視的文件句柄數(shù)

readfds:select監(jiān)視的可讀文件句柄集合,就是個(gè)long類型的數(shù)組。

writefds: select監(jiān)視的可寫文件句柄集合。

exceptfds:select監(jiān)視的異常文件句柄集合。

timeout:本次select()的超時(shí)結(jié)束時(shí)間。

?

還有幾個(gè)對(duì)fds集合操作的宏:

?

FD_ZERO(fd_set *fdset):清空fdset與所有文件句柄的聯(lián)系。

FD_SET(int fd,fd_set *fdset):建立文件句柄fd與fdset的聯(lián)系。

FD_CLR(int fd,fd_set *fdset):清除文件句柄fd與fdset的聯(lián)系。FD_ISSET(int fd,fd_set *fdset):檢查fdset聯(lián)系的文件句柄fd是否

可讀寫,當(dāng)>0表示可讀寫。

??

實(shí)現(xiàn)過程:

?

1. 首先fdset集合里需要監(jiān)控的文件句柄由程序員來添加,當(dāng)前連接需要監(jiān)控哪些文件句柄,那么通過FD_SET宏來進(jìn)行添加。

2. 然后調(diào)用select()函數(shù)將fd_set從用戶空間拷貝到內(nèi)核空間。

3. 注冊(cè)一個(gè)回調(diào)函數(shù)。

4. 內(nèi)核對(duì)文件句柄進(jìn)行監(jiān)控。

5. 當(dāng)有滿足可讀寫等條件時(shí)/超時(shí)調(diào)用回調(diào)函數(shù)并將文件句柄集合拷貝回用戶???? 空間。

6. 應(yīng)用通過輪詢的方式查找所有文件句柄,用FD_ISSET宏來判讀具體是哪個(gè)文件句柄可操作。

7. 當(dāng)再次有新連接處理需要監(jiān)控,再次重復(fù)以上步驟往內(nèi)核拷貝fdset。

用圖表示整個(gè)流程如下:

?3

缺點(diǎn)分析:

?1.? 句柄上限:單個(gè)進(jìn)程通過輪詢的方式監(jiān)控所有的文件句柄,當(dāng)文件句柄越多,處理的效率越低,為了保證效率,文件句柄也就設(shè)置了上限,這個(gè)上限和內(nèi)存也是又一定關(guān)系的,32位機(jī)默認(rèn)是1024。

2.? 重復(fù)初始化:每次監(jiān)控都重復(fù)將fdset從用戶空間拷貝到內(nèi)核空間,然后又從內(nèi)核空間拷貝到用戶空間,這個(gè)過程重復(fù)比較耗費(fèi)系統(tǒng)資源。

3.? 逐個(gè)排查文件效率不高: 檢測(cè)哪些文件句柄可操作時(shí),采用的是輪詢遍歷所有的文件句柄,用FD_ISSET宏來判斷文件句柄是否可操作,然而實(shí)際情況,大部分文件句柄是不可操作的,這種逐個(gè)排查的方式效率太低。

實(shí)現(xiàn)方式三、poll技術(shù)

poll技術(shù)與select 技術(shù)本質(zhì)上是沒有區(qū)別的,只是文件句柄的存儲(chǔ)結(jié)構(gòu)變更了,變成了鏈表,所以沒有了文件句柄的上限,但是其他缺點(diǎn)依舊存在。

實(shí)現(xiàn)方式四、epoll技術(shù)

epoll技術(shù)整個(gè)流程其實(shí)和select、poll技術(shù)大體上是一樣的,主要是針對(duì)造成效率低下的點(diǎn)進(jìn)行優(yōu)化,可以說是將select和poll技術(shù)的缺點(diǎn)一一解決才達(dá)到現(xiàn)在的高效率,接下來我們一一道來:

1. 句柄上限

句柄上限的問題poll技術(shù)已經(jīng)解決,就不用多說了。

2. 重復(fù)初始化

這個(gè)問題就像中學(xué)時(shí)候讀書書包帶課本一樣(中學(xué)的課程數(shù)量和書本數(shù)量之多大家應(yīng)該都懂的),每天上學(xué)把所有幾十本課本從家里背到學(xué)校,放學(xué)了再?gòu)膶W(xué)校將所有書背回家,但你今天家庭作業(yè)實(shí)際需要帶的書可能就個(gè)別課程的個(gè)別幾本書而已。

所以為了減輕我們身體的負(fù)擔(dān),是不是放學(xué)的時(shí)候只帶幾本今天需要做家庭作業(yè)的幾本書就很輕松了,同樣的為了減少重復(fù)初始化過程中用戶空間和內(nèi)核空間發(fā)生不必要的拷貝帶來的資源浪費(fèi),epoll技術(shù)提供了epoll_ctl函數(shù),在用epoll_ctl函數(shù)進(jìn)行事件注冊(cè)的時(shí)候,會(huì)將文件句柄都復(fù)制到內(nèi)核中,所以不用每次都復(fù)制一遍,當(dāng)有新的文件句柄時(shí)采用的也是增量往內(nèi)核拷貝,確保了每個(gè)文件句柄只會(huì)被拷貝一次。

?

3. 逐個(gè)排查文件效率不高

epoll會(huì)用epoll_ctl為每個(gè)文件句柄注冊(cè)一個(gè)回調(diào)函數(shù),同時(shí)會(huì)在內(nèi)核中通過epoll_create創(chuàng)建一個(gè)專用鏈表(還有包含存儲(chǔ)fd的專用內(nèi)存空間),當(dāng)有文件句柄狀態(tài)發(fā)生變更,通過回調(diào)函數(shù)會(huì)將狀態(tài)發(fā)生變更的文件句柄加入該鏈表,epoll技術(shù)還提供了epoll_wait函數(shù),來查看鏈表中有沒有就緒的文件句柄,然后只將該鏈表中的就緒文件句柄從內(nèi)核空間拷貝到用戶空間,這樣一來就不用遍歷每個(gè)文件句柄,只處理狀態(tài)發(fā)生變更的,效率自然就提升上去了。

總結(jié)一下,epoll技術(shù)提供了三個(gè)系統(tǒng)調(diào)用函數(shù):

– epoll_create:用于創(chuàng)建和初始化一些內(nèi)部使用的數(shù)據(jù)結(jié)構(gòu)。

– epoll_crl: 用于注冊(cè)時(shí)間、添加、刪除和修改指定的df及其期待的事件。

– epoll_wait: 用于等待先前指定的fd事件,即就緒的fd。

通過以上三點(diǎn)解決方案,epoll技術(shù)的效率相比select、poll技術(shù)效率大大提升了,Tornado自然也采用了epoll技術(shù),通過這種技術(shù)也就解決了著名的C10k問題,實(shí)現(xiàn)了用一個(gè)進(jìn)程/線程來同時(shí)處理若干個(gè)連接的想法,減少了硬件資源的浪費(fèi)。

?

五、Tornado是如何發(fā)揮優(yōu)勢(shì)的(背后不為人知的處理邏輯)

我們先看一段簡(jiǎn)單代碼的demo:

4

如果你經(jīng)常用Tornado,那么對(duì)這段代碼一定非常熟悉了,那么我們今天的關(guān)注點(diǎn)就放在最后一句Torando.ioloop.IOLoop.current().start()代碼上,先簡(jiǎn)單的分析下這句代碼,前面一部分Torando.ioloop是Tornado的核心模塊ioloop模塊,IOLoop是ioloop模塊的一個(gè)類,current()是IOLoop類的一個(gè)方法,結(jié)果是返回一個(gè)當(dāng)前線程的IOLoop的實(shí)例,start()也是IOLoop的方法,調(diào)用后開啟循環(huán)。

?

先看一張流程圖:

5

?然后我們分析下Tornado這段代碼后的整個(gè)邏輯流程:

1.? 首先Tornado需要建立監(jiān)聽,會(huì)創(chuàng)建一個(gè)socket用于監(jiān)聽,如果有客戶端A請(qǐng)求建立連接之后,Tornado會(huì)基于原先的socket新創(chuàng)建一個(gè)包含客戶端A連接的有關(guān)信息的socket(分配新的監(jiān)聽端口),用于監(jiān)聽和客戶端A的請(qǐng)求。此時(shí)對(duì)Tornado來說就有兩個(gè)socket需要進(jìn)行監(jiān)控,原先的socket繼續(xù)用來監(jiān)聽建立新連接,新的socket用于和客戶端A進(jìn)行通信,假如沒有epoll技術(shù)的話,Tornado需要自己去循環(huán)詢問哪個(gè)socket有新的請(qǐng)求。

2.? ?有了epoll技術(shù),Tornado只需要把所有的socket丟給epoll,epoll作為管家?guī)兔ΡO(jiān)控,然后Torando.ioloop.IOLoop.current().start()開啟循環(huán),不斷的去詢問epoll是否有請(qǐng)求需要處理,這就是ioloop所做的工作,也是Tornado的核心部分。

3.? 當(dāng)有客戶端進(jìn)行請(qǐng)求,epoll就發(fā)現(xiàn)有socket可處理,當(dāng)ioloop再次詢問epoll時(shí),epoll就把需要處理的socket交由Tornado處理

4.? Tornado對(duì)請(qǐng)求進(jìn)行處理,取出報(bào)文,從報(bào)文中獲取請(qǐng)求路徑,然后從tornado.web.Applcation里配置的路由映射中把請(qǐng)求路徑映射成對(duì)應(yīng)的處理類,如上圖IndexHandler就是處理類。

5.? 處理類處理完成后,生成響應(yīng),將響應(yīng)內(nèi)容封裝成http報(bào)文,通過請(qǐng)求時(shí)建立的連接(尚未中斷)將響應(yīng)內(nèi)容返回給客戶端。

6.? 當(dāng)有多個(gè)請(qǐng)求同時(shí)發(fā)生,Tornado會(huì)按順序挨個(gè)處理。

看了上面的流程,假如Tornado在處理一個(gè)非常耗時(shí)的請(qǐng)求時(shí),后面的請(qǐng)求是不是就會(huì)被卡死呢?答案是肯定的,所以提到了Tornado的另一個(gè)特性—異步處理,當(dāng)一個(gè)請(qǐng)求特別耗時(shí),Tornado就把它丟在那處理,然后繼續(xù)處理下一個(gè)請(qǐng)求,確保后面的請(qǐng)求不會(huì)被卡死。

Tornado異步:原生Tornado框架提供異步網(wǎng)絡(luò)庫(kù)IOLoop和IOStream以及異步協(xié)程庫(kù)tornado.gen(必須使用Tornado的web框架和HTTP服務(wù)器,否則異步接口可能無法使用),方便用戶通過更直接的方法實(shí)現(xiàn)異步編程,而不是回調(diào)的方式,官方推薦yield協(xié)程方式完成異步。(異步是Tornado重要且核心部分,期待下篇技術(shù)好文重點(diǎn)介紹)。

?

通過上面所講,基本上已經(jīng)對(duì)Tornado的整個(gè)處理流程了解了,總結(jié)一下Tornado之所以能同時(shí)處理大量連接的原因:

1.? 利用高效的epoll技術(shù)處理請(qǐng)求,單線程/單進(jìn)程同時(shí)處理大量連接。

2.? 沒用使用傳統(tǒng)的wsgi協(xié)議,而是利用Tornado自己的web框架和http服務(wù)形成了一整套WSGI方案進(jìn)行處理。

3.? 異步處理方式,Tornado提供了異步接口可供調(diào)用。

六、Tornado的應(yīng)用場(chǎng)景
?

要性能,Tornado 首選;要開發(fā)速度,Django 和Flask 都行,區(qū)別是Flask 把許多功能交給第三方庫(kù)去完成了,因此Flask 更為靈活。Django適合初學(xué)者或者小團(tuán)隊(duì)的快速開發(fā),適合做管理類、博客類網(wǎng)站、或者功能十分復(fù)雜需求十分多的網(wǎng)站,Tornado適合高度定制,適合訪問量大,異步情況多的網(wǎng)站。

以上便是本文是本人學(xué)習(xí)收集整理后的文章,如有錯(cuò)誤,請(qǐng)多多留言指教。

A

BOUT

關(guān)于作者

吳俊杰:達(dá)觀數(shù)據(jù)后端開發(fā)工程師,負(fù)責(zé)達(dá)觀數(shù)據(jù)產(chǎn)品后端開發(fā)、產(chǎn)品落地、客戶定制化產(chǎn)品需求等設(shè)計(jì)。對(duì)后端開發(fā)使用到的web及服務(wù)器框架、http協(xié)議及相關(guān)應(yīng)用方面有比較深入的了解。