久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

day20.并發(fā)服務(wù)器&HTTP協(xié)議【Python教程】

 太極混元天尊 2018-05-28


一、單進(jìn)程服務(wù)器

1. 完成一個(gè)簡單的TCP服務(wù)器

2. 總結(jié)

  • 同一時(shí)刻只能為一個(gè)客戶進(jìn)行服務(wù),,不能同時(shí)為多個(gè)客戶服務(wù)

  • 類似于找一個(gè)“明星”簽字一樣,,客戶需要耐心等待才可以獲取到服務(wù)

  • 當(dāng)服務(wù)器為一個(gè)客戶端服務(wù)時(shí),而另外的客戶端發(fā)起了connect,,只要服務(wù)器listen的隊(duì)列有空閑的位置,,就會為這個(gè)新客戶端進(jìn)行連接,并且客戶端可以發(fā)送數(shù)據(jù),,但當(dāng)服務(wù)器為這個(gè)新客戶端服務(wù)時(shí),,可能一次性把所有數(shù)據(jù)接收完畢

  • 當(dāng)recv接收數(shù)據(jù)時(shí),返回值為空,,即沒有返回?cái)?shù)據(jù),,那么意味著客戶端已經(jīng)調(diào)用了close關(guān)閉了,;因此服務(wù)器通過判斷recv接收數(shù)據(jù)是否為空 來判斷客戶端是否已經(jīng)下線



二、多進(jìn)程服務(wù)器

1. 多進(jìn)程服務(wù)器

2. 總結(jié)

  • 通過為每個(gè)客戶端創(chuàng)建一個(gè)進(jìn)程的方式,,能夠同時(shí)為多個(gè)客戶端進(jìn)行服務(wù)

  • 當(dāng)客戶端不是特別多的時(shí)候,,這種方式還行,如果有幾百上千個(gè),,就不可取了,,因?yàn)槊看蝿?chuàng)建進(jìn)程等過程需要好較大的資源



三、多線程服務(wù)器



四,、單進(jìn)程服務(wù)器-非堵塞模式

服務(wù)器

客戶端



五,、select版-TCP服務(wù)器

1. select 原理

在多路復(fù)用的模型中,比較常用的有select模型和epoll模型,。這兩個(gè)都是系統(tǒng)接口,,由操作系統(tǒng)提供。當(dāng)然,,Python的select模塊進(jìn)行了更高級的封裝,。

網(wǎng)絡(luò)通信被Unix系統(tǒng)抽象為文件的讀寫,通常是一個(gè)設(shè)備,,由設(shè)備驅(qū)動程序提供,,驅(qū)動可以知道自身的數(shù)據(jù)是否可用。支持阻塞操作的設(shè)備驅(qū)動通常會實(shí)現(xiàn)一組自身的等待隊(duì)列,,如讀/寫等待隊(duì)列用于支持上層(用戶層)所需的block或non-block操作,。設(shè)備的文件的資源如果可用(可讀或者可寫)則會通知進(jìn)程,反之則會讓進(jìn)程睡眠,,等到數(shù)據(jù)到來可用的時(shí)候,,再喚醒進(jìn)程。

這些設(shè)備的文件描述符被放在一個(gè)數(shù)組中,,然后select調(diào)用的時(shí)候遍歷這個(gè)數(shù)組,,如果對于的文件描述符可讀則會返回改文件描述符。當(dāng)遍歷結(jié)束之后,,如果仍然沒有一個(gè)可用設(shè)備文件描述符,,select讓用戶進(jìn)程則會睡眠,直到等待資源可用的時(shí)候在喚醒,,遍歷之前那個(gè)監(jiān)視的數(shù)組,。每次遍歷都是依次進(jìn)行判斷的。

2. select 回顯服務(wù)器

使用python的select模塊很容易寫出下面一個(gè)echo(回顯)服務(wù)器:

在windows中,,使用‘網(wǎng)絡(luò)調(diào)試助手’,,進(jìn)行連接服務(wù)器即可測試

另外一個(gè)服務(wù)器(包含writeList):

3. 總結(jié)

優(yōu)點(diǎn)

select目前幾乎在所有的平臺上支持,其良好跨平臺支持也是它的一個(gè)優(yōu)點(diǎn),。

缺點(diǎn)

select的一個(gè)缺點(diǎn)在于單個(gè)進(jìn)程能夠監(jiān)視的文件描述符的數(shù)量存在最大限制,,在Linux上一般為1024,,可以通過修改宏定義甚至重新編譯內(nèi)核的方式提升這一限制,但是這樣也會造成效率的降低,。

一般來說這個(gè)數(shù)目和系統(tǒng)內(nèi)存關(guān)系很大,,具體數(shù)目可以cat /proc/sys/fs/file-max察看,。32位機(jī)默認(rèn)是1024個(gè),。64位機(jī)默認(rèn)是2048.

對socket進(jìn)行掃描時(shí)是依次掃描的,即采用輪詢的方法,,效率較低,。

當(dāng)套接字比較多的時(shí)候,每次select()都要通過遍歷FD_SETSIZE個(gè)Socket來完成調(diào)度,,不管哪個(gè)Socket是活躍的,,都遍歷一遍。這會浪費(fèi)很多CPU時(shí)間



六,、epoll版-TCP服務(wù)器

1. epoll的優(yōu)點(diǎn):

  1. 沒有最大并發(fā)連接的限制,,能打開的FD(指的是文件描述符,通俗的理解就是套接字對應(yīng)的數(shù)字編號)的上限遠(yuǎn)大于1024

  2. 效率提升,,不是輪詢的方式,,不會隨著FD數(shù)目的增加效率下降。只有活躍可用的FD才會調(diào)用callback函數(shù),;即epoll最大的優(yōu)點(diǎn)就在于它只管你“活躍”的連接,,而跟連接總數(shù)無關(guān),因此在實(shí)際的網(wǎng)絡(luò)環(huán)境中,,epoll的效率就會遠(yuǎn)遠(yuǎn)高于select和poll,。

2. epoll使用參考代碼

2. 說明

  • EPOLLIN (可讀)

  • EPOLLOUT (可寫)

  • EPOLLET (ET模式)

epoll對文件描述符的操作有兩種模式:LT(level trigger)和ET(edge trigger)。LT模式是默認(rèn)模式,,LT模式與ET模式的區(qū)別如下:

LT模式:當(dāng)epoll檢測到描述符事件發(fā)生并將此事件通知應(yīng)用程序,,應(yīng)用程序可以不立即處理該事件。下次調(diào)用epoll時(shí),,會再次響應(yīng)應(yīng)用程序并通知此事件,。

ET模式:當(dāng)epoll檢測到描述符事件發(fā)生并將此事件通知應(yīng)用程序,應(yīng)用程序必須立即處理該事件,。如果不處理,,下次調(diào)用epoll時(shí),不會再次響應(yīng)應(yīng)用程序并通知此事件,。


七,、協(xié)程

協(xié)程,又稱微線程,,纖程,。英文名Coroutine,。

協(xié)程是啥

首先我們得知道協(xié)程是啥?協(xié)程其實(shí)可以認(rèn)為是比線程更小的執(zhí)行單元,。 為啥說他是一個(gè)執(zhí)行單元,,因?yàn)樗詭PU上下文。這樣只要在合適的時(shí)機(jī),, 我們可以把一個(gè)協(xié)程 切換到另一個(gè)協(xié)程,。 只要這個(gè)過程中保存或恢復(fù) CPU上下文那么程序還是可以運(yùn)行的。

通俗的理解:在一個(gè)線程中的某個(gè)函數(shù),,可以在任何地方保存當(dāng)前函數(shù)的一些臨時(shí)變量等信息,,然后切換到另外一個(gè)函數(shù)中執(zhí)行,注意不是通過調(diào)用函數(shù)的方式做到的,,并且切換的次數(shù)以及什么時(shí)候再切換到原來的函數(shù)都由開發(fā)者自己確定

協(xié)程和線程差異

那么這個(gè)過程看起來比線程差不多,。其實(shí)不然, 線程切換從系統(tǒng)層面遠(yuǎn)不止保存和恢復(fù) CPU上下文這么簡單。 操作系統(tǒng)為了程序運(yùn)行的高效性每個(gè)線程都有自己緩存Cache等等數(shù)據(jù),,操作系統(tǒng)還會幫你做這些數(shù)據(jù)的恢復(fù)操作,。 所以線程的切換非常耗性能。但是協(xié)程的切換只是單純的操作CPU的上下文,,所以一秒鐘切換個(gè)上百萬次系統(tǒng)都抗的住,。

協(xié)程的問題

但是協(xié)程有一個(gè)問題,就是系統(tǒng)并不感知,,所以操作系統(tǒng)不會幫你做切換,。 那么誰來幫你做切換?讓需要執(zhí)行的協(xié)程更多的獲得CPU時(shí)間才是問題的關(guān)鍵,。

例子

目前的協(xié)程框架一般都是設(shè)計(jì)成 1:N 模式,。所謂 1:N 就是一個(gè)線程作為一個(gè)容器里面放置多個(gè)協(xié)程。 那么誰來適時(shí)的切換這些協(xié)程,?答案是有協(xié)程自己主動讓出CPU,,也就是每個(gè)協(xié)程池里面有一個(gè)調(diào)度器, 這個(gè)調(diào)度器是被動調(diào)度的,。意思就是他不會主動調(diào)度,。而且當(dāng)一個(gè)協(xié)程發(fā)現(xiàn)自己執(zhí)行不下去了(比如異步等待網(wǎng)絡(luò)的數(shù)據(jù)回來,但是當(dāng)前還沒有數(shù)據(jù)到),, 這個(gè)時(shí)候就可以由這個(gè)協(xié)程通知調(diào)度器,,這個(gè)時(shí)候執(zhí)行到調(diào)度器的代碼,調(diào)度器根據(jù)事先設(shè)計(jì)好的調(diào)度算法找到當(dāng)前最需要CPU的協(xié)程,。 切換這個(gè)協(xié)程的CPU上下文把CPU的運(yùn)行權(quán)交個(gè)這個(gè)協(xié)程,,直到這個(gè)協(xié)程出現(xiàn)執(zhí)行不下去需要等等的情況,或者它調(diào)用主動讓出CPU的API之類,,觸發(fā)下一次調(diào)度,。

那么這個(gè)實(shí)現(xiàn)有沒有問題,?

其實(shí)是有問題的,假設(shè)這個(gè)線程中有一個(gè)協(xié)程是CPU密集型的他沒有IO操作,, 也就是自己不會主動觸發(fā)調(diào)度器調(diào)度的過程,,那么就會出現(xiàn)其他協(xié)程得不到執(zhí)行的情況, 所以這種情況下需要程序員自己避免,。這是一個(gè)問題,,假設(shè)業(yè)務(wù)開發(fā)的人員并不懂這個(gè)原理的話就可能會出現(xiàn)問題。

協(xié)程的好處

在IO密集型的程序中由于IO操作遠(yuǎn)遠(yuǎn)慢于CPU的操作,,所以往往需要CPU去等IO操作,。 同步IO下系統(tǒng)需要切換線程,,讓操作系統(tǒng)可以在IO過程中執(zhí)行其他的東西,。 這樣雖然代碼是符合人類的思維習(xí)慣但是由于大量的線程切換帶來了大量的性能的浪費(fèi),尤其是IO密集型的程序,。

所以人們發(fā)明了異步IO,。就是當(dāng)數(shù)據(jù)到達(dá)的時(shí)候觸發(fā)我的回調(diào)。來減少線程切換帶來性能損失,。 但是這樣的壞處也是很大的,,主要的壞處就是操作被 “分片” 了,代碼寫的不是 “一氣呵成” 這種,。 而是每次來段數(shù)據(jù)就要判斷 數(shù)據(jù)夠不夠處理哇,,夠處理就處理吧,不夠處理就在等等吧,。這樣代碼的可讀性很低,,其實(shí)也不符合人類的習(xí)慣。

但是協(xié)程可以很好解決這個(gè)問題,。比如 把一個(gè)IO操作 寫成一個(gè)協(xié)程,。當(dāng)觸發(fā)IO操作的時(shí)候就自動讓出CPU給其他協(xié)程。要知道協(xié)程的切換很輕的,。 協(xié)程通過這種對異步IO的封裝 既保留了性能也保證了代碼的容易編寫和可讀性,。在高IO密集型的程序下很好。但是高CPU密集型的程序下沒啥好處,。

協(xié)程一個(gè)簡單實(shí)現(xiàn)

運(yùn)行結(jié)果:



八,、協(xié)程-greenlet版

為了更好使用協(xié)程來完成多任務(wù),python中的greenlet模塊對其封裝,,從而使得切換任務(wù)變的更加簡單

安裝方式

使用如下命令安裝greenlet模塊:

運(yùn)行效果



九,、gevent

greenlet已經(jīng)實(shí)現(xiàn)了協(xié)程,但是這個(gè)還的人工切換,,是不是覺得太麻煩了,,不要捉急,,python還有一個(gè)比greenlet更強(qiáng)大的并且能夠自動切換任務(wù)的模塊gevent

其原理是當(dāng)一個(gè)greenlet遇到IO(指的是input output 輸入輸出,比如網(wǎng)絡(luò),、文件操作等)操作時(shí),,比如訪問網(wǎng)絡(luò),就自動切換到其他的greenlet,,等到IO操作完成,,再在適當(dāng)?shù)臅r(shí)候切換回來繼續(xù)執(zhí)行。

由于IO操作非常耗時(shí),,經(jīng)常使程序處于等待狀態(tài),,有了gevent為我們自動切換協(xié)程,就保證總有g(shù)reenlet在運(yùn)行,,而不是等待IO

1. gevent的使用

運(yùn)行結(jié)果

可以看到,,3個(gè)greenlet是依次運(yùn)行而不是交替運(yùn)行

2. gevent切換執(zhí)行

運(yùn)行結(jié)果

3個(gè)greenlet交替運(yùn)行

3. gevent并發(fā)下載器

當(dāng)然,實(shí)際代碼里,,我們不會用gevent.sleep()去切換協(xié)程,,而是在執(zhí)行到IO操作時(shí),gevent自動切換,,代碼如下

運(yùn)行結(jié)果

從上能夠看到是先發(fā)送的獲取baidu的相關(guān)信息,,然后依次是itcast、itheima,,但是收到數(shù)據(jù)的先后順序不一定與發(fā)送順序相同,,這也就體現(xiàn)出了異步,即不確定什么時(shí)候會收到數(shù)據(jù),,順序不一定



十,、gevent版-TCP服務(wù)器



    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多