背景 最近在使用calibre-web管理電子書(shū),不過(guò)很多時(shí)候還是需要用到Calibre桌面版軟件,批量管理,編輯電子書(shū)等功能,因此需要使用calibre-douban元數(shù)據(jù)...

背景 最近在使用calibre-web管理電子書(shū),不過(guò)很多時(shí)候還是需要用到Calibre桌面版軟件,批量管理,編輯電子書(shū)等功能,因此需要使用calibre-douban元數(shù)據(jù)...
多路復(fù)用I/O 部分第2個(gè)異步的代碼沒(méi)有實(shí)現(xiàn)完整,主要是 Stream.write() 生成器的問(wèn)題。
Server._handle() 和 Stream.read() 都是監(jiān)聽(tīng) select.POLLIN 事件,通過(guò)棧組合到一起。
先處理?xiàng)m數(shù)?Stream.read(),讀取完成后的數(shù)據(jù) send 回 Server._handle(),繼而傳遞給
Stream.write(). 而 Stream.write() 需要監(jiān)聽(tīng) select.POLLOUT,這部分更新監(jiān)聽(tīng)事件有問(wèn)題:
- IOLoop.add_handler() 為同一 fd 多次注冊(cè)會(huì)報(bào)錯(cuò),引入的 IOLoop.modify() 可能是為了解決這個(gè)問(wèn)題,但并沒(méi)有被調(diào)用
- 修改注冊(cè)事件寫(xiě)在了 Stream.write() 內(nèi)部,這樣會(huì)出現(xiàn)反復(fù)修改注冊(cè)事件。沒(méi)有重用原來(lái) stack handler 策略
另外,這里棧結(jié)構(gòu)實(shí)現(xiàn)利用 list 就足夠了,沒(méi)必要 collections.deque。
最后,非常感謝作者的分享,很有啟發(fā)。
簡(jiǎn)明網(wǎng)絡(luò)I/O與并發(fā) --- I/O簡(jiǎn)明網(wǎng)絡(luò)I/O與并發(fā) --- I/O簡(jiǎn)明網(wǎng)絡(luò)I/O與并發(fā) --- 并發(fā) 計(jì)算機(jī)的基本組成其實(shí)很簡(jiǎn)單,處理器,存儲(chǔ)器加上輸入輸出設(shè)備,就能構(gòu)成計(jì)算機(jī)。大至超級(jí)計(jì)算機(jī),小到手機(jī)等...
簡(jiǎn)明網(wǎng)絡(luò)I/O與并發(fā) --- I/O簡(jiǎn)明網(wǎng)絡(luò)I/O與并發(fā) --- 并發(fā) 計(jì)算機(jī)的基本組成其實(shí)很簡(jiǎn)單,處理器,存儲(chǔ)器加上輸入輸出設(shè)備,就能構(gòu)成計(jì)算機(jī)。大至超級(jí)計(jì)算機(jī),小到手機(jī)等...
Worker.notify() 用于 Worker.tmp ctime 訪(fǎng)問(wèn)時(shí)間,而 Worker.tmp ctime 被用在 Arbiter.run() 循環(huán)下 `Arbiter.murder_workers()` 中,murder_workers() 負(fù)責(zé)清理 idle workers。(超時(shí)受 timeout 參數(shù)控制)
當(dāng)接收到 TERM 信號(hào)時(shí),信號(hào)從 Arbiter 下發(fā)到 Worker,TERM 信號(hào)下 Worker 并不直接殺死自己(QUIT,INT除外),而是 `Worker.alive = False` 控制請(qǐng)求循環(huán)停止接受新請(qǐng)求。
上面我介紹的這種情況對(duì)應(yīng) `Arbiter.handle_term()` 信號(hào)處理,實(shí)際調(diào)用 `Arbiter.stop()`,第一次 Arbiter 下發(fā) TERM 信號(hào)讓 worker 停止接受新請(qǐng)求,graceful_timeout 后直接 SIGKILL 殺死 worker。(據(jù)我所搜索到的,SIGKILL 并不能捕捉掛載自定義處理函數(shù))
還有一點(diǎn),timeout 和 graceful_timeout 不是一碼事。timeout 用于控制請(qǐng)求超時(shí),graceful_timeout 則是殺死 worker 前的等待時(shí)間(等待正在處理的請(qǐng)求處理完)。前者相關(guān)代碼在 SyncWorker.run(), Arbiter.murder_workers() 中,后者相關(guān)代碼在 Arbiter.stop() 中。
Gunicorn源碼分析(二)Worker進(jìn)程Gunicorn.worker實(shí)現(xiàn)了不同類(lèi)型的work進(jìn)程,有單進(jìn)程、多線(xiàn)程、多協(xié)程等形式。 gunicorn.worker目錄結(jié)構(gòu): 主要看以下幾個(gè)源碼文件 base.py...
最近使用Gunicorn+Flask部署了一套服務(wù),順便研究下Gunicorn的源碼,看看Python 的Prefork模型是如何實(shí)現(xiàn)的。具體Gunicorn的用法可以看官方...
沒(méi)有源碼模式就是難用,導(dǎo)入外部的md筆記代碼都不自動(dòng)換行,自己造車(chē)。。
第二張圖中查看代碼行數(shù)的工具是什么,Pycharm 中插件?
FastAPI 源碼閱讀 (一) ASGI應(yīng)用本章開(kāi)啟FastAPI的源碼閱讀,F(xiàn)astAPI是當(dāng)下python web中一顆新星,是一個(gè)劃時(shí)代的框架。從誕生便是以快速和簡(jiǎn)潔為核心理念。它繼承于Starlette,是在其...
本章開(kāi)啟FastAPI的源碼閱讀,F(xiàn)astAPI是當(dāng)下python web中一顆新星,是一個(gè)劃時(shí)代的框架。從誕生便是以快速和簡(jiǎn)潔為核心理念。它繼承于Starlette,是在其...
Gunicorn.worker實(shí)現(xiàn)了不同類(lèi)型的work進(jìn)程,有單進(jìn)程、多線(xiàn)程、多協(xié)程等形式。 gunicorn.worker目錄結(jié)構(gòu): 主要看以下幾個(gè)源碼文件 base.py...
有在B站直播(看動(dòng)漫/電影吐槽,玩游戲,敲代碼)的想法很久了,但是一直沒(méi)有付諸實(shí)踐。我有舞臺(tái)恐懼癥,在直播場(chǎng)景下說(shuō)話(huà)也會(huì)說(shuō)不利索。不過(guò)兵馬未動(dòng),糧草先行,我們今天記錄一下怎么...
@Gascognya 那也蠻厲害了。我是用了一段時(shí)間 Web 框架,文檔翻過(guò)一遍才開(kāi)始讀源碼。不知道是你運(yùn)氣好還是有人指點(diǎn),starlette 已經(jīng)是非常優(yōu)雅的框架了,簡(jiǎn)直藝術(shù)品。
Starlette 源碼閱讀 (階段總結(jié)一)在前五篇中,筆者對(duì)applications.py,routing.py,requests.py,responses.py進(jìn)行了解讀。了解到了從app進(jìn)入,到endpoint返...
這里提一下 _TemplateResponse 中不直接發(fā)送渲染好的HTML內(nèi)容,而先發(fā)送一個(gè) "type": "http.response.template" 響應(yīng)的原因。scope["extensions"] 是不是 ASGI 規(guī)范指定的字段不是很確定,但這里的 "http.response.template" 類(lèi)型響應(yīng)從邏輯上不是必要的(只要直接給客戶(hù)端返回HTML內(nèi)容就可以了,沒(méi)必要把 template, context 先返回)。在代碼中全文搜索,猜測(cè)這可能是配合 testclient.py 做出的響應(yīng)。
Starlette 源碼閱讀 (十四) 配置文件與模板config.py 配置文件的方式很多,starlette提供了一種.env文件的配置方式,實(shí)際像py,json,xml都是非常合適的配置文件。 Environ環(huán)境變量對(duì)象 ...
這里值得一提的是 BackgroundTask 中 run_in_threadpool().
BackgroundTask 是把一個(gè)函數(shù)封裝,通過(guò)非阻塞方式去調(diào)用它。
如果函數(shù)時(shí)一個(gè)協(xié)程函數(shù),通過(guò) await 執(zhí)行,當(dāng)前事件循環(huán) loop 會(huì)控制其切換。
如果函數(shù)不是一個(gè)協(xié)程,則調(diào)用 await run_in_threadpool() 執(zhí)行此函數(shù)。乍一看名字好像是放到一個(gè)線(xiàn)程池里執(zhí)行,實(shí)際是通過(guò) loop.run_in_executor() 把函數(shù)交給當(dāng)前事件循環(huán)的 executor 執(zhí)行,其實(shí)還是在當(dāng)前 loop 中控制切換。
至于 loop 中 Executor 是什么,我也不是很理解。
Starlette 源碼閱讀 (十) 異步與后臺(tái)任務(wù)background.py & concurrency.py 實(shí)際上筆者對(duì)于異步的深層原理了解并不透徹,還只停留在勉強(qiáng)會(huì)用的水平。日后會(huì)對(duì)這方面只是進(jìn)行系統(tǒng)性自下而上的學(xué)習(xí)。...
我覺(jué)得作者可能有點(diǎn)把順序搞反了。應(yīng)該先去理解 ASGI 規(guī)范再來(lái)看 ASGI 的實(shí)現(xiàn)(也就是這里的 Starlette)。
Starlette 源碼閱讀 (階段總結(jié)一)在前五篇中,筆者對(duì)applications.py,routing.py,requests.py,responses.py進(jìn)行了解讀。了解到了從app進(jìn)入,到endpoint返...
ASGI 是一套通信標(biāo)準(zhǔn),方便遵循 ASGI 標(biāo)準(zhǔn)的服務(wù)器和應(yīng)用之間通信。Starlette 算是實(shí)現(xiàn)了 ASGI 的應(yīng)用或者工具集、框架。ASGI 應(yīng)用這邊要給出一個(gè)可調(diào)用對(duì)象,對(duì)應(yīng) Starlette 中 app 對(duì)象 :Starlette 實(shí)例,其調(diào)用方式為 func(self, scope: Scope, receive: Receive, send: Send). 由實(shí)現(xiàn)了 ASGI 的 Web 服務(wù)器發(fā)起調(diào)用,故而調(diào)用參數(shù) scope, receive, send 都是 Web 服務(wù)器提供。
目前常用的 ASGI 服務(wù)器有 Uvicorn, Hypercorn, Daphne.
在部署時(shí)還會(huì)用到 Nginx, Apache 等服務(wù)器。Uvicorn 和 Nginx 都屬于 Web 服務(wù)器,但 Uvicorn 是專(zhuān)一型的:實(shí)現(xiàn)了 ASGI 規(guī)范,只講 HTTP, WebSockets。而 Nginx 屬于通用性服務(wù)器(并發(fā)能力強(qiáng)、反代靈活等)。Uvicorn 與 Nginx 通過(guò) HTTP 協(xié)議通信。
對(duì)于不同請(qǐng)求的分發(fā),Starlette 可以通過(guò)處理不同路徑的請(qǐng)求,Host 處理不同域名的請(qǐng)求,傳遞給不同的 Route 或者說(shuō) request handler。Nginx 也可以針對(duì)路徑、域名分發(fā)請(qǐng)求,只不過(guò)是轉(zhuǎn)發(fā)給不同的 app。
Starlette 源碼閱讀 (階段總結(jié)一)在前五篇中,筆者對(duì)applications.py,routing.py,requests.py,responses.py進(jìn)行了解讀。了解到了從app進(jìn)入,到endpoint返...