日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
一文弄懂Gunicorn與PythonGIL

什么是 Python GIL,它是如何工作的,以及它如何影響 gunicorn。

成都創(chuàng)新互聯(lián)公司專注于蜀山企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,商城網(wǎng)站建設(shè)。蜀山網(wǎng)站建設(shè)公司,為蜀山等地區(qū)提供建站服務(wù)。全流程按需設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)

生產(chǎn)環(huán)境我應(yīng)該選擇哪種 Gunicorn worker類型?

Python 有一個(gè)全局鎖 (GIL),它只允許一個(gè)線程運(yùn)行(即解釋字節(jié)碼)。在我看來(lái),如果你想優(yōu)化你的 Python 服務(wù),理解 Python 如何處理并發(fā)是必不可少的。

Python 和 gunicorn 為您提供了處理并發(fā)的不同方法,并且由于沒(méi)有涵蓋所有用例的靈丹妙藥,因此最好了解每個(gè)選項(xiàng)的選項(xiàng)、權(quán)衡和優(yōu)勢(shì)。

Gunicorn worker類型

Gunicorn 以“workers types”的概念公開了這些不同的選項(xiàng)。每種類型都適用于一組特定的用例。

  • sync——將進(jìn)程分叉成 N 個(gè)并行運(yùn)行的進(jìn)程來(lái)處理請(qǐng)求。
  • gthread——產(chǎn)生 N 個(gè)線程來(lái)并發(fā)服務(wù)請(qǐng)求。
  • eventlet/gevent——產(chǎn)生綠色線程來(lái)并發(fā)服務(wù)請(qǐng)求。

Gunicorn sync worker

這是最簡(jiǎn)單的工作類型,其中唯一的并發(fā)選項(xiàng)是分叉N個(gè)進(jìn)程,它們將并行地服務(wù)請(qǐng)求。

它們可以很好地工作,但會(huì)招致大量開銷(例如內(nèi)存和CPU上下文切換),而且如果您的大部分請(qǐng)求時(shí)間都在等待I/O,那么伸縮性就不好。

Gunicorn gthread worker

gthread worker 通過(guò)允許您為每個(gè)進(jìn)程創(chuàng)建 N 個(gè)線程來(lái)改進(jìn)這一點(diǎn)。這提高了 I/O 性能,因?yàn)槟梢酝瑫r(shí)運(yùn)行更多代碼實(shí)例。這是受 GIL 影響的四個(gè)中唯一一個(gè)。

Gunicorn eventlet and gevent workers

eventlet/gevent workers試圖通過(guò)運(yùn)行輕量級(jí)用戶線程(又名綠色線程、greenlets 等)來(lái)進(jìn)一步改進(jìn) gthread 模型。

與系統(tǒng)線程相比,這允許您以很少的成本擁有數(shù)千個(gè)所述的greenlet。 另一個(gè)區(qū)別是它遵循協(xié)作工作模型而不是搶占式,允許不間斷工作,直到它們阻塞為止。我們將首先分析 gthread 工作線程在處理請(qǐng)求時(shí)的行為以及它如何受 GIL 影響。

與每個(gè)請(qǐng)求直接由一個(gè)進(jìn)程提供服務(wù)的sync不同,使用 gthread,每個(gè)進(jìn)程都有 N 個(gè)線程,以便更好地?cái)U(kuò)展,而無(wú)需產(chǎn)生多個(gè)進(jìn)程的開銷。由于您在同一個(gè)進(jìn)程中運(yùn)行多個(gè)線程,GIL 將阻止它們并行運(yùn)行。

GIL 不是進(jìn)程或特殊線程。它只是一個(gè)布爾變量,其訪問(wèn)受互斥鎖保護(hù),用于確保每個(gè)進(jìn)程內(nèi)只有一個(gè)線程在運(yùn)行。它的工作方式可以在上圖中看到。在這個(gè)例子中,我們可以看到我們有 2 個(gè)系統(tǒng)線程并發(fā)運(yùn)行,每個(gè)線程處理 1 個(gè)請(qǐng)求。流程是這樣的:

  • 線程 A 持有 GIL 開始服務(wù)請(qǐng)求。
  • 過(guò)了一會(huì)兒,線程 B 嘗試提供請(qǐng)求,但無(wú)法持有 GIL。
  • B 設(shè)置超時(shí)以強(qiáng)制釋放 GIL,如果在達(dá)到超時(shí)之前不會(huì)發(fā)生這種情況。
  • A 在達(dá)到超時(shí)之前不會(huì)釋放 GIL。
  • B 設(shè)置 gil_drop_request 標(biāo)志以強(qiáng)制 A 立即釋放 GIL。
  • A 釋放 GIL 并將等待直到另一個(gè)線程抓取 GIL,以避免出現(xiàn) A 會(huì)不斷釋放并抓取 GIL 而其他線程無(wú)法抓取它的情況。
  • B 開始運(yùn)行。
  • B 在阻塞 I/O 的同時(shí)釋放 GIL。
  • A 開始運(yùn)行。
  • B 嘗試再次運(yùn)行但被暫停。
  • A 在達(dá)到超時(shí)之前完成。
  • B 運(yùn)行完畢。

相同的場(chǎng)景,但使用 gevent

?

在不使用進(jìn)程的情況下增加并發(fā)性的另一個(gè)選擇是使用 greenlets。該worker產(chǎn)生“用戶線程”而不是“系統(tǒng)線程”以增加并發(fā)性。

盡管這意味著它們不受 GIL 的影響,但這也意味著您仍然無(wú)法增加并行度,因?yàn)樗鼈儫o(wú)法由 CPU 并行調(diào)度。

  • Greenlet A將開始運(yùn)行,直到發(fā)生I/O事件或執(zhí)行完畢。
  • Greenlet B將等待直到Greenlet A釋放事件循環(huán)。
  • A結(jié)束。
  • B開始。
  • B釋放事件循環(huán)以等待I/O。
  • B完成。

對(duì)于這種情況,很明顯,擁有一個(gè) greenlet 類型的worker并不理想。我們最終讓第二個(gè)請(qǐng)求等到第一個(gè)請(qǐng)求完成,然后再次空閑等待 I/O。

在這些場(chǎng)景中,greenlet 協(xié)作模型真的很出色,因?yàn)槟粫?huì)在上下文切換上浪費(fèi)時(shí)間并避免運(yùn)行多個(gè)系統(tǒng)線程的開銷。

我們將在本文末尾的基準(zhǔn)測(cè)試中見證這一點(diǎn)。現(xiàn)在,這引出了以下問(wèn)題:

  • 更改線程上下文切換超時(shí)是否會(huì)影響服務(wù)延遲和吞吐量?
  • 當(dāng)您混合使用 I/O 和 CPU 工作時(shí),如何在 gevent/eventlet 和 gthread 之間進(jìn)行選擇。
  • 如何使用 gthread worker 選擇線程數(shù)。
  • 我應(yīng)該只使用sync worker并增加分叉進(jìn)程的數(shù)量來(lái)避免 GIL 嗎?

要回答這些問(wèn)題,您需要進(jìn)行監(jiān)控以收集必要的指標(biāo),然后針對(duì)這些相同的指標(biāo)運(yùn)行量身定制的基準(zhǔn)測(cè)試。運(yùn)行與您的實(shí)際使用模式零相關(guān)性的綜合基準(zhǔn)測(cè)試是沒(méi)有用的 下圖顯示了不同場(chǎng)景的延遲和吞吐量指標(biāo),讓您了解這一切是如何協(xié)同工作的。

對(duì) GIL 切換間隔進(jìn)行基準(zhǔn)測(cè)試

在這里我們可以看到更改 GIL 線程切換間隔/超時(shí)如何影響請(qǐng)求延遲。正如預(yù)期的那樣,IO 延遲隨著切換間隔的降低而變得更好。發(fā)生這種情況是因?yàn)槭?CPU 限制的線程被迫更頻繁地釋放 GIL 并允許其他線程完成它們的工作。

但這不是靈丹妙藥。減少切換間隔將使 CPU 綁定線程需要更長(zhǎng)的時(shí)間才能完成。我們還可以看到總延遲增加,由于恒定線程切換的開銷增加,超時(shí)時(shí)間減少。如果您想自己嘗試,可以使用以下代碼更改切換間隔:

使用 CPU 綁定請(qǐng)求對(duì) gthread 與 gevent 延遲進(jìn)行基準(zhǔn)測(cè)試

總的來(lái)說(shuō),我們可以看到基準(zhǔn)測(cè)試反映了我們之前對(duì) GIL 綁定線程和 greenlet 如何工作的分析所產(chǎn)生的直覺。

由于切換間隔迫使長(zhǎng)時(shí)間運(yùn)行的線程釋放,gthread 對(duì)于 IO 綁定請(qǐng)求具有更好的平均延遲。

gevent CPU 綁定請(qǐng)求比 gthread 具有更好的延遲,因?yàn)樗鼈儾粫?huì)被中斷以服務(wù)其他請(qǐng)求。

使用 CPU 綁定請(qǐng)求對(duì) gthread 與 gevent 吞吐量進(jìn)行基準(zhǔn)測(cè)試

這里的結(jié)果也反映了我們之前對(duì) gevent 比 gthread 具有更好吞吐量的直覺。這些基準(zhǔn)高度依賴于完成的工作類型,不一定直接轉(zhuǎn)化為您的用例。

這些基準(zhǔn)測(cè)試的主要目標(biāo)是為您提供一些有關(guān)測(cè)試和測(cè)量?jī)?nèi)容的指南,以便最大限度地提高將服務(wù)于請(qǐng)求的每個(gè) CPU 內(nèi)核。

由于所有 gunicorn worker 都允許您指定將運(yùn)行的進(jìn)程數(shù),因此更改的是每個(gè)進(jìn)程如何處理并發(fā)連接。因此,請(qǐng)確保使用相同數(shù)量的worker以使測(cè)試公平?,F(xiàn)在讓我們嘗試使用從我們的基準(zhǔn)測(cè)試中收集的數(shù)據(jù)來(lái)回答前面的問(wèn)題。

更改線程上下文切換超時(shí)是否會(huì)影響服務(wù)延遲和吞吐量?

確實(shí)如此。然而,對(duì)于絕大多數(shù)工作負(fù)載來(lái)說(shuō),它并沒(méi)有改變游戲規(guī)則。

當(dāng)您混合使用 I/O 和 CPU 工作時(shí),如何在 gevent/eventlet 和 gthread 之間進(jìn)行選擇? 正如我們所看到的,當(dāng)您有更多 CPU 密集型工作時(shí),ghtread 往往允許更好的并發(fā)性。

如何選擇gthread worker的線程數(shù)?

只要您的基準(zhǔn)測(cè)試能夠模擬類似生產(chǎn)的行為,您就會(huì)清楚地看到峰值性能,然后它會(huì)因線程過(guò)多而開始下降。

我應(yīng)該只使用同步工作者并增加分叉進(jìn)程的數(shù)量來(lái)避免 GIL 嗎?

除非您的 I/O 幾乎為零,否則僅使用進(jìn)程進(jìn)行擴(kuò)展并不是最佳選擇。

結(jié)論

Coroutines/Greenlets 可以提高 CPU 效率,因?yàn)樗鼈儽苊饬司€程之間的中斷和上下文切換。協(xié)程用延遲換取吞吐量。

如果您混合使用 IO 和 CPU 綁定端點(diǎn),協(xié)程可能會(huì)導(dǎo)致更難以預(yù)測(cè)的延遲——CPU 綁定端點(diǎn)不會(huì)被中斷以服務(wù)其他傳入請(qǐng)求。如果您花時(shí)間正確配置 gunicorn,GIL 不是問(wèn)題。


當(dāng)前題目:一文弄懂Gunicorn與PythonGIL
URL鏈接:http://m.5511xx.com/article/djipjji.html