python實現異步的幾種方式_終于搞明白了,異步Python比同步Python究竟快在哪里?...

大家好,你是否聽人們說過,異步 Python 代碼比“普通(或同步)Python 代碼更快? 果真是那樣嗎?

同步和異步是什么意思?

Web 應用程序通常要處理許多請求,這些請求在短時間內來自不同的客戶端。為避免處理延遲,必須考慮并行處理多個請求,這通常稱為“并發”。

在本文中,我將繼續使用 Web 應用程序作為例子,但還有其它類型的應用程序也從并發中獲益。因此,這個討論并不僅僅是針對 Web 應用程序的。

術語“同步”和“異步”指的是編寫并發應用程序的兩種方式。所謂的“同步”服務器使用底層操作系統支持的線程和進程來實現這種并發性。下面是同步部署的一個示意圖:

461277a4fff649c7e5f9e1f63b4249e3.png

在這種情況下,我們有 5 臺客戶端,都向應用程序發送請求。這個應用程序的訪問入口是一個 Web 服務器,通過將服務分配給一個服務器 worker 池來充當負載均衡器,這些 worker 可以實現為進程、線程或者兩者的結合。這些 worker 執行負載均衡器分配給他們的請求。你使用 Web 應用程序框架(例如 Flask 或 Django)編寫的應用程序邏輯運行在這些 worker 中。

這種類型的方案對于有多個 CPU 的服務器比較好,因為你可以將 worker 的數量設置為 CPU 的數量,這樣你就能均衡地利用你的處理器核心,而單個 Python 進程由于全局解釋器鎖(GIL)的限制無法實現這一點。

在缺點上,上面的示意圖也清楚展示了這種方案的主要局限。我們有 5 個客戶端,卻只有 4 個 worker。如果這 5 個客戶端在同一時間都發送請求,那么負載均衡器會將某一個客戶端之外的所有請求發送到 worker 池,而剩下的請求不得不保留在一個隊列中,等待有 worker 變得可用。

因此,五分之四的請求會立即響應,而剩下的五分之一需要等一會兒。服務器優化的一個關鍵就在于選擇適當數量的 worker 來防止或最小化給定預期負載的請求阻塞。

一個異步服務器的配置很難畫,但是我盡力而為:

89c28f2d26f14baf799ebe93786aad38.png

這種類型的服務器運行在單個進程中,通過循環控制。這個循環是一個非常有效率的任務管理器和調度器,創建任務來執行由客戶端發送的請求。與長期存在的服務器 worker 不同,異步任務是由循環創建,用來處理某個特定的請求,當那個請求完成時,該任務也會被銷毀。任何時候,一臺異步服務器都會有上百或上千個活躍的任務,它們都在循環的管理下執行自己的工作。

你可能想知道異步任務之間的并行是如何實現的。這就是有趣的部分,因為一個異步應用程序通過唯一的協同多任務處理來實現這點。這意味著什么?

當一個任務需要等待一個外部事件(例如,一個數據庫服務器的響應)時,不會像一個同步的 worker 那樣等待,而是會告訴循環,它需要等待什么,然后將控制權返回給它。循環就能夠在這個任務被數據庫阻塞的時候發現另外一個準備就緒的任務。最終,數據庫將發送一個響應,而那時循環會認為第一個的任務已經準備好再次運行,并將盡快恢復它。

異步任務暫停和恢復執行的這種能力可能在抽象上很難理解。為了幫你應用到你已經知道的東西,可以考慮在 Python 中使用await或yield關鍵字這一方法來實現,但你之后會發現,這并不是唯一實現異步任務的方法。

一個異步應用程序完全運行在單個進程或線程中,這可以說是令人吃驚的。當然,這種類型的并發需要遵循一些規則,因此,你不能讓一個任務占用 CPU 太長時間,否則,剩余的任務會被阻塞。為了異步執行,所有的任務需要定時主動暫停并將控制權返還給循環。

為了從異步方式獲益,一個應用程序需要有經常被 I/O 阻塞的任務,并且沒有太多 CPU 工作。Web 應用程序通常非常適合,特別是當它們需要處理大量客戶端請求時。

在使用一個異步服務器時,為了最大化多 CPU 的利用率,通常需要創建一個混合方案,增加一個負載均衡器并在每個 CPU 上運行一個異步服務器,如下圖所示:

73fb0fb0dae4eeaa6702ea873b91e6af.png

Python異步的2種方法

我敢肯定,你知道要在 Python 中寫一個異步應用程序,你可以使用 asyncio package,這個包是在協程的基礎上實現了所有異步應用程序都需要的暫停和恢復特性。其中yield關鍵字,以及更新的async和await都是asyncio構建異步能力的基礎。

https://docs.python.org/3/library/asyncio.html

Python 生態系統中還有其它基于協程的異步方案,例如 Trio 和 Curio。還有 Twisted,它是所有協程框架中最古老的,甚至出現得比asyncio都要早。

如果你對編寫異步 Web 應用程序感興趣,有許多基于協程的異步框架可以選擇,包括 aiohttp、sanic、FastAPI 和 Tornado。

很多人不知道的是,協程只是 Python 中編寫異步代碼的兩種方法之一。第二種方法是基于一個叫做 greenlet 的庫,你可以用 pip 安裝它。Greenlets 和協程類似,它們也允許一個 Python 函數暫停執行并稍后恢復,但是它們實現這點的方式完全不同,這意味著 Python 中的異步生態系統分成兩大類。

協程與 greenlets 之間針對異步開發最有意思的區別是,前者需要 Python 語言特定的關鍵字和特性才能工作,而后者并不需要。我的意思是,基于協程的應用程序需要使用一種特定的語法來書寫,而基于 greenlet 的應用程序看起來幾乎和普通 Python 代碼一樣。這非常酷,因為在某些情況下,這讓同步代碼可以被異步執行,這是諸如asyncio之類的基于協程的方案做不到的。

那么在 greenlet 方面,跟asyncio對等的庫有哪些?我知道 3 個基于 greenlet 的異步包:Gevent、Eventlet 和 Meinheld,盡管最后一個更像是一個 Web 服務器而不是一個通用的異步庫。它們都有自己的異步循環實現,而且它們都提供了一個有趣的“monkey-patching”功能,取代了 Python 標準庫中的阻塞函數,例如那些執行網絡和線程的函數,并基于 greenlets 實現了等效的非阻塞版本。如果你有一些同步代碼想要異步運行,這些包會對你有所幫助。

據我所知,唯一明確支持greenlet 的 Web 框架只有 Flask。這個框架會自動監測,當你想要運行在一個 greenlet Web 服務器上時,它會自我進行相應調整,而無需進行任何配置。這么做時,你需要注意不要調用阻塞函數,或者,如果你要調用阻塞函數,最好用猴子補丁來“修復”那些阻塞函數。

但是,Flask 并不是唯一受益于 greenlets 的框架。其它 Web 框架,例如 Django 和 Bottle,雖然沒有 greenlets,但也可以通過結合一個 greenlet Web 服務器并使用 monkey-patching修復阻塞函數的方式來異步運行。

異步比同步更快嗎?

對于同步和異步應用程序的性能,存在著一個廣泛的誤解——異步應用程序比同步應用程序快得多。

對此,我需要澄清一下。無論是用同步方式寫,還是用異步方式寫,Python 代碼運行速度是幾乎相同的。除了代碼,有兩個因素能夠影響一個并發應用程序的性能:上下文切換和可擴展性。

上下文切換

在所有運行的任務間公平地共享 CPU 所需的工作,稱為上下文切換,能夠影響應用程序的性能。對同步應用程序來說,這項工作是由操作系統完成的,而且基本上是一個黑箱,不需要配置或微調選項。對異步應用程序來說,上下文切換是由循環完成的。

默認的循環實現由asyncio提供,是用 Python 編寫的,效率不是很高。而 uvloop 包提供了一個備選的循環方案,其中部分代碼是用 C 編寫的來實現更好的性能。Gevent 和 Meinheld 所使用的事件循環也是用 C 編寫的。Eventlet 用的是 Python 編寫的循環。

高度優化的異步循環比操作系統在進行上下文切換方面更有效率,但根據我的經驗,要想看到實際的效率提升,你運行的并發量必須非常大。對于大部分應用程序,我不認為同步和異步上下文切換之間的性能差距有多明顯。

擴展性

我認為異步更快這個神話的來源是,異步應用程序通常會更有效地使用 CPU、能更好地進行擴展并且擴展方式比同步更靈活。

如果上面示意圖中的同步服務器同時收到 100 個請求,想一下會發生什么。這個服務器同時最多只能處理 4 個請求,因此大部分請求會停留在一個隊列中等待,直到它們被分配一個 worker。

與之形成對比的是,異步服務器會立即創建 100 個任務(或者使用混合模式的話,在 4 個異步 worker 上每個創建 25 個任務)。使用異步服務器,所有請求都會立即開始處理而不用等待(盡管公平地說,這種方案也還會有其它瓶頸會減慢速度,例如對活躍的數據庫連接的限制)。

如果這 100 個任務主要使用 CPU,那么同步和異步方案會有相似的性能,因為每個 CPU 運行的速度是固定的,Python 執行代碼的速度總是相同的,應用程序要完成的工作也是相同的。但是,如果這些任務需要做很多 I/O 操作,那么同步服務器只能處理 4 個并發請求而不能實現 CPU 的高利用率。而另一方面,異步服務器會更好地保持 CPU 繁忙,因為它是并行地運行所有這 100 個請求。

你可能會想,為什么你不能運行 100 個同步 worker,那樣,這兩個服務器就會有相同的并發能力。要注意,每個 worker 需要自己的 Python 解釋器以及與之相關聯的所有資源,再加上一份單獨的應用程序拷貝及其資源。你的服務器和應用程序的大小將決定你可以運行多少個 worker 實例,但通常這個數字不會很大。另一方面,異步任務非常輕量,都運行在單個 worker 進程的上下文中,因此具有明顯優勢。

綜上所述,只有如下場景時,我們可以說異步可能比同步快:

存在高負載(沒有高負載,訪問的高并發性就沒有優勢)

任務是 I/O 綁定的(如果任務是 CPU 綁定的,那么超過 CPU 數目的并發并沒有幫助)

你查看單位時間內的平均請求處理數。如果你查看單個請求的處理時間,你不會看到有很大差別,

甚至異步可能更慢,因為異步有更多并發的任務在爭奪 CPU。

結論

希望本文能解答異步代碼的一些困惑和誤解。我希望你能記住以下兩個關鍵點:

異步應用程序只有在高負載下才會比同步應用程序做得更好

多虧了 greenlets,即使你用一般方式寫代碼并使用 Flask 或 Django 之類的傳統框架,也能從異步中受益。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279218.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279218.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279218.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

您可能沒有注意到的7個Ubuntu File Manager功能

The Nautilus file manager included with Ubuntu includes some useful features you may not notice unless you go looking for them. You can create saved searches, mount remote file systems, use tabs in your file manager, and more. Ubuntu隨附的Nautilus文件管理器…

P3174 [HAOI2009]毛毛蟲(樹形dp)

P3174 [HAOI2009]毛毛蟲 題目描述 對于一棵樹,我們可以將某條鏈和與該鏈相連的邊抽出來,看上去就象成一個毛毛蟲,點數越多,毛毛蟲就越大。例如下圖左邊的樹(圖 1 )抽出一部分就變成了右邊的一個毛毛蟲了&am…

wdcp mysql密碼_WDCP提示無法連接mysql及創建站點提示mysql密碼不正確

一、wdcp系統訪問提示無法連接mysql1、可能是mysql服務沒啟動,首先ssh登陸服務器,然后執行service mysqld restart重啟mysql再訪問試下,如果無法啟動,先用df -lh查看下home分區有沒有掛載,如果沒有掛載嘗試先重啟&…

applecare多少錢?_否,AppleCare +無法覆蓋丟失或被盜的iPhone

applecare多少錢?Losing your iPhone or getting it stolen is pretty common these days, but it’s important to know that while AppleCare covers accidental damage, it doesn’t cover a lost or stolen iPhone. 如今,丟失iPhone或使其被盜很普遍&#xff0…

10以內數的組成分解圖_大班數學教案《10以內數的組成》

大班數學教案《10以內數的組成》作為一名教學工作者,時常需要編寫教案,借助教案可以讓教學工作更科學化。那么什么樣的教案才是好的呢?以下是小編收集整理的大班數學教案《10以內數的組成》,希望能夠幫助到大家。大班數學教案《10…

HDFS文件目錄操作代碼

分布式文件系統HDFS中對文件/目錄的相關操作代碼,整理了一下,大概包括以下部分: 文件夾的新建、刪除、重命名文件夾中子文件和目錄的統計文件的新建及顯示文件內容文件在local和remote間的相互復制定位文件在HDFS中的位置,以及副本…

craigslist_如何設置Craigslist警報(用于電子郵件或SMS)

craigslistWhether you’re looking for apartments or used gadgets on Craigslist, you don’t have to keep checking the website. You can stay on top of things by getting notified when new posts go up that match your searches. 無論您是在Craigslist上尋找公寓還是…

merge r語言daframe_R語言總結

R語言總結數據框操作(plyr包)輔助小函數1 splat函數:作用:把原函數中多個參數打包為一個list作為參數,然后輸出新的函數。也就是說本來某個函數需要輸入多個參數,現在套上splat后,只要輸入一個參數list就可以了&#x…

Django模板語言中的自定義方法filter過濾器實現web網頁的瀑布流

模板語言自定義方法介紹 自定義方法注意事項 Django中有simple_tag 和 filter 兩種自定義方法,之前也提到過,需要注意的是 擴展目錄名稱必須是templatetagstemplatetags中的自定義標簽和過濾器必須依賴于一個django app,也就是說,自定義標簽和過濾器是綁…

dsp怪胎_2012年6月最佳怪胎文章

dsp怪胎This past month we covered topics such as why you only have to wipe a disk once to erase it, what RSS is and how you can benefit from using it, how websites are tracking you online, and more. Join us as we look back at the best articles for June. 在…

mysql 回退查詢_MYSQL數據庫表排序規則不一致導致聯表查詢,索引不起作用問題...

Mysql數據庫表排序規則不一致導致聯表查詢,索引不起作用問題表更描述: 將mysql數據庫中的worktask表添加ishaspic字段。具體操作:(1)數據庫worktask表新添是否有圖片字段ishaspic;新添字段時,報錯[SQL] alter table WorkTask add …

如何在Ubuntu上查看和寫入系統日志文件

Linux logs a large amount of events to the disk, where they’re mostly stored in the /var/log directory in plain text. Most log entries go through the system logging daemon, syslogd, and are written to the system log. Linux將大量事件記錄到磁盤上&#xff0c…

[轉]table中設置tr行間距

原文地址:https://blog.csdn.net/itmyhome1990/article/details/50475616 CSS border-collapse 屬性設置表格的邊框是否被合并為一個單一的邊框 值描述separate默認值。邊框會被分開。不會忽略 border-spacing 和 empty-cells 屬性。collapse如果可能,邊框會合并為一…

向Ubuntu提供反饋的5種方法

Ubuntu, like many other Linux distributions, is a community-developed operating system. In addition to getting involved and submitting patches, there are a variety of ways you can provide useful feedback and suggest features to Ubuntu. 與許多其他Linux發行版…

Tomcat 發布項目 conf/Catalina/localhost 配置 及數據源配置

本文介紹通過在tomcat的conf/Catalina/localhost目錄下添加配置文件,來發布項目。因為這樣對 tomcat 的入侵性最小,只需要新增一個配置文件,不需要修改原有配置;而且支持動態解析,修改完代碼直接生效(修改配置除外)。在…

Centos7 中文亂碼

1. 安裝中文庫 yum groupinstall "fonts" 2. 檢查是否有中文語言包 locale -a 3. 查看當前系統語言環境 locale 解析如下 LANG:當前系統的語言LC_CTYPE:語言符號及其分類LC_NUMERIC:數字LC_COLLATE:比較和排序習慣LC_TIME&#xff…

pkpm板按彈性計算還是塑性_雙向板按彈性方法還是按塑性方法計算

雙向板按彈性方法還是按塑性方法計算茅老師您好!想請教您個問題,PKPM計算雙向板時一般都是按彈性算吧,可我去年剛進設計院的時候有一個項目是按塑性算的,這樣影響大不大啊,支座與跨中彎矩比值系數取得默認的1.8&#x…

chrome自動退出的原因_Chrome 70將讓用戶選擇退出新的自動登錄功能

chrome自動退出的原因An upcoming Chrome option allows users to log into Google accounts without logging into the browser. The change was prompted by a backlash among users and privacy advocates. 即將推出的Chrome選項允許用戶無需登錄瀏覽器即可登錄Google帳戶。…

學習筆記DL007:Moore-Penrose偽逆,跡運算,行列式,主成分分析PCA

2019獨角獸企業重金招聘Python工程師標準>>> Moore-Penrose偽逆(pseudoinverse)。 非方矩陣,逆矩陣沒有定義。矩陣A的左逆B求解線性方程Axy。兩邊左乘左逆B,xBy。可能無法設計唯一映射將A映射到B。矩陣A行數大于列數,方程無解。矩…

mysql40題_mysql40題

一、表關系請創建如下表,并創建相關約束導入現有數據庫數據:/*Navicat Premium Data TransferSource Server : localhostSource Server Type : MySQLSource Server Version :50624Source Host : localhostSource Database : sqlexamTarget Server Type :…