91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何用Asyncio協程構建高并發應用

發布時間:2021-10-09 15:54:39 來源:億速云 閱讀:202 作者:iii 欄目:開發技術

這篇文章主要介紹“如何用Asyncio協程構建高并發應用”,在日常操作中,相信很多人在如何用Asyncio協程構建高并發應用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何用Asyncio協程構建高并發應用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

如何用Asyncio協程構建高并發應用

C10K問題

在互聯網尚未普及的早期,一臺服務器同時在線 100 個用戶已經算是非常大型的應用了,工程上沒有什么挑戰。

隨著 Web 2.0 時代的到來,用戶群體成幾何倍數增長,服務器需要更強的并發處理能力才能承載海量的用戶。這時,著名的 C10K  問題誕生了——如何讓單臺服務器同時支撐 1 萬個客戶端連接?

最初的服務器應用編程模型,是基于進程/線程的:當一個新的客戶端連接上來,服務器就分配一個進程或線程,來處理這個新連接。這意味著,想要解決 C10K  問題,操作系統需要同時運行 1 萬個進程或線程。

進程和線程是操作系統中,開銷最大的資源之一。每個新連接都新開進程/線程,將造成極大的資源浪費。況且,受硬件資源制約,系統同一時間能運行的進程/線程數存在上限。

換句話講,在進程/線程模型中,每臺服務器能處理的客戶端連接數是非常有限的。為支持海量的業務,只能通過堆服務器這種簡單粗暴的方式來實現。但這樣的人海戰術,既不穩定,也不經濟。

為了在單個進程/線程中同時處理多個網絡連接,select 、 poll 、epoll 等 IO多路復用  技術應運而生。在IO多路復用模型,進程/線程不再阻塞在某個連接上,而是同時監控多個連接,只處理那些有新數據達到的活躍連接。

為什么需要協程

單純的IO多路復用編程模型,不像阻塞式編程模型那樣直觀,這為工程項目帶來諸多不便。最典型的像 JavaScript 中的回調式編程模型,程序中各種  callback 函數滿天飛,這不是一種直觀的思維方式。

為實現阻塞式那樣直觀的編程模型,協程(用戶態線程)的概念被提出來。協程在進程/線程基礎之上,實現多個執行上下文。由 epoll  等IO多路復用技術實現的事件循環,則負責驅動協程的調度、執行。

協程可以看做是IO多路復用技術更高層次的封裝。雖然與原始IO多路復用相比有一定的性能開銷,但與進程/線程模型相比卻非常突出。協程占用資源比進程/線程少,而且切換成本比較低。因此,協程在高并發應用領域潛力無限。

然而,協程獨特的運行機制,讓初學者吃了不少虧,錯漏百出。

接下來,我們通過若干簡單例子,探索協程應用之道,從中體會協程的作用,并揭示高并發應用設計、部署中存在的常見誤區。由于 asyncio 是 Python  協程發展的主要趨勢,例子便以 asyncio 為講解對象。

第一個協程應用

協程應用由事件循環驅動,套接字必須是非阻塞模式,否則會阻塞事件循環。因此,一旦使用協程,就要跟很多類庫說拜拜了。以 MySQL  數據庫操作為例,如果我們使用 asyncio ,就要用 aiomysql 包來連數據庫。

而想要開發 Web 應用,則可以用 aiohttp 包,它可以通過 pip 命令安裝:

$ pip install aiohttp

這個例子實現一個完整 Web 服務器,雖然它只有返回當前時間的功能:

from aiohttp import web from datetime import datetime  async def handle(request):     return web.Response(text=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))  app = web.Application() app.add_routes([     web.get('/', handle), ])  if __name__ == '__main__':     web.run_app(app)

第 4 行,實現處理函數,獲取當前時間并返回;

第 7 行,創建應用對象,并將處理函數注冊到路由中;

第 13 行,將 Web 應用跑起來,默認端口是 8080 ;

當一個新的請求到達時,aiohttp 將創建一個新協程來處理該請求,它將負責執行對應的處理函數。因此,處理函數必須是合法的協程函數,以 async  關鍵字開頭。

將程序跑起來后,我們就可以通過它獲悉當前時間。在命令行中,可以用 curl 命令來發起請求:

$ curl http://127.0.0.1:8080/ 2020-08-06 15:50:34

壓力測試

研發高并發應用,需要評估應用的處理能力。我們可以在短時間內發起大量的請求,并測算應用的吞吐能力。然而,就算你手再快,一秒鐘也只能發起若干個請求呀。怎么辦呢?

我們需要借助一些壓力測試工具,例如 Apache 工具集中的 ab 。如何安裝使用 ab  不在本文的討論范圍,請參考這篇文章:Web壓力測試(https://network.fasionchan.com/zh_CN/latest/performance/web-pressure-test.html)  。

事不宜遲,我們先以 100 為并發數,壓 10000 個請求看看結果:

$ ab -n 10000 -c 100 http://127.0.0.1:8080/ This is ApacheBench, Version 2.3 <$Revision: 1706008 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/  Benchmarking 127.0.0.1 (be patient) Completed 1000 requests Completed 2000 requests Completed 3000 requests Completed 4000 requests Completed 5000 requests Completed 6000 requests Completed 7000 requests Completed 8000 requests Completed 9000 requests Completed 10000 requests Finished 10000 requests   Server Software:        Python/3.8 Server Hostname:        127.0.0.1 Server Port:            8080  Document Path:          / Document Length:        19 bytes  Concurrency Level:      100 Time taken for tests:   5.972 seconds Complete requests:      10000 Failed requests:        0 Total transferred:      1700000 bytes HTML transferred:       190000 bytes Requests per second:    1674.43 [#/sec] (mean) Time per request:       59.722 [ms] (mean) Time per request:       0.597 [ms] (mean, across all concurrent requests) Transfer rate:          277.98 [Kbytes/sec] received  Connection Times (ms)               min  mean[+/-sd] median   max Connect:        0    2   1.5      1      15 Processing:    43   58   5.0     57      89 Waiting:       29   47   6.3     47      85 Total:         43   60   4.8     58      90  Percentage of the requests served within a certain time (ms)   50%     58   66%     59   75%     60   80%     61   90%     65   95%     69   98%     72   99%     85  100%     90 (longest request)

-n 選項,指定總請求數,即總共發多少個請求;

-c 選項,指定并發數,即同時發多少個請求;

從 ab 輸出的報告中可以獲悉,10000 個請求全部成功,總共耗時 5.972 秒,處理速度可以達到 1674.43 個每秒。

現在,我們嘗試提供并發數,看處理速度有沒有提升:

$ ab -n 10000 -c 100 http://127.0.0.1:8080/

在 1000 并發數下,10000 個請求在 5.771 秒內完成,處理速度是 1732.87  ,略有提升但很不明顯。這一點也不意外,例子中的處理邏輯絕大部分都是計算型,虛增并發數幾乎沒有任何意義。

協程擅長做什么

協程擅長處理 IO  型的應用邏輯,舉個例子,當某個協程在等待數據庫響應時,事件循環將喚醒另一個就緒協程來執行,以此提高吞吐。為降低復雜性,我們通過在程序中睡眠來模擬等待數據庫的效果。

import asyncio  from aiohttp import web from datetime import datetime  async def handle(request):     # 睡眠一秒鐘     asyncio.sleep(1)     return web.Response(text=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))  app = web.Application() app.add_routes([     web.get('/', handle), ])  if __name__ == '__main__':     web.run_app(app)
并發數請求總數耗時(秒)處理速度(請求/秒)
10010000102.31097.74
5001000022.129451.89
10001000012.780782.50

可以看到,隨著并發數的增加,處理速度也有明顯的提升,趨勢接近線性。

到此,關于“如何用Asyncio協程構建高并發應用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節
推薦閱讀:
  1. lua 協程
  2. GO協程

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

遂昌县| 海丰县| 旬阳县| 茶陵县| 司法| 汪清县| 衡山县| 通化市| 苏州市| 磴口县| 旬邑县| 乐山市| 汝南县| 通化市| 潮州市| 土默特右旗| 尉犁县| 周口市| 商南县| 肥乡县| 乳山市| 海南省| 岑巩县| 通海县| 酉阳| 江华| 海原县| 白水县| 福贡县| 黎平县| 安福县| 公主岭市| 读书| 罗平县| 洛宁县| 大安市| 郎溪县| 乌恰县| 沂南县| 吴桥县| 钟祥市|