在服務(wù)器端實(shí)現(xiàn)無間斷部署Python應(yīng)用的教程
當(dāng)你開始著手部署應(yīng)用時,最簡單的方式莫過于使用管理員身份重啟my_app或者所有服務(wù),使產(chǎn)品升級至當(dāng)前版本。開始的時候一切都很好,但是最終你會發(fā)現(xiàn)一旦應(yīng)用啟動以后,在重啟期間去嘗試連接會得到眾多HTTP 503 錯誤。
最后你可能發(fā)現(xiàn)Gunicorn和uWSGI可以在不關(guān)閉套接字的情況下重新加載你的應(yīng)用,這樣在你的應(yīng)用啟動時,網(wǎng)絡(luò)請求僅僅是被延時了一點(diǎn)點(diǎn)。只要你的應(yīng)用不會花費(fèi)很長時間在啟動上,它就會工作的很好。不幸的是,現(xiàn)有的許多應(yīng)用可能會花費(fèi)1分鐘的時間在啟動上,對于等待在套接字上的鏈接來說,這太長了。
Gunicorn使用kill -HUP $PID,通過關(guān)閉所有工作進(jìn)程,然后再啟動它們來重新加載。但是工作進(jìn)程緩慢的初始化過程往往會導(dǎo)致問題的產(chǎn)生。uWSGI使用鏈?zhǔn)街剌d,它每次只會啟動一個工作進(jìn)程。我需要對Tornado的支持,它當(dāng)前并不十分適合uWSGI。
使用負(fù)載均衡器
一種常見的技術(shù)是從負(fù)載均衡器中移除單個服務(wù)器,升級/重啟應(yīng)用,然后再把它加載回來。我們正在使用負(fù)載均衡器,但是為了調(diào)度整個過程,在配置節(jié)點(diǎn)的時候需要協(xié)調(diào)使用HAProxy來管理套接字。我們當(dāng)前的部署方案是同時部署到所有節(jié)點(diǎn),而不是一個接一個的來,一個相當(dāng)大的變化。在等待LBs(譯注:負(fù)載均衡器)將節(jié)點(diǎn)移出池期間,可以使用404'ing狀態(tài)頁來欺騙healthcheck。這比我想要的時間要多一點(diǎn),對于每個服務(wù)器來說,兩次healthcheck失敗間隔5秒鐘,這包括了升級完成后web進(jìn)程恢復(fù)的時間。
Gunicorn 重載 ++
Gunicorn會自動重啟失敗的web進(jìn)程,所以它可能會殺掉每個進(jìn)程,在其間休眠,直到所有的子進(jìn)程執(zhí)行完畢。這很有效,不過如果應(yīng)用啟動的次數(shù)變動顯著的話,我們要么會為重啟等待過長時間,要么會等待不長的時間并承擔(dān)一些故障宕機(jī)的風(fēng)險。
因?yàn)镚unicorn包含了指向應(yīng)用的Python鉤子,所以完全可能寫出一小段代碼,在工作進(jìn)程準(zhǔn)備就緒的時候通知重啟進(jìn)程。Gunicorn并不包含需要的鉤子,但做出改變非常簡單。在新版本發(fā)布前它需要一些修改。
現(xiàn)在重啟進(jìn)程發(fā)揮了這樣的事實(shí)優(yōu)勢,就是說單個的soket具有接受連接的多個進(jìn)程。重啟只會極微弱的減少服務(wù)能力(1/N),但我們因此可以繼續(xù)處理流量而無需讓連接等待過長時間。
這種進(jìn)程一般是這樣的
for child_pid of gunicorn-master: kill child_pid wait for app startup
我的第一個版本使用shell和nc來監(jiān)聽?wèi)?yīng)用啟動的UDP數(shù)據(jù)包。盡管將我們的進(jìn)程管理器集成到shell環(huán)境比我預(yù)想的要麻煩一點(diǎn),但它工作的很好。
重啟腳本被調(diào)用的時候應(yīng)該帶上Gunicorn的PID,就是masterrestart.sh的 $PID
echo 'Killing children of ' $1; children=$(pgrep -P $1) for child in $children do echo 'Killing' $child kill $child response=$(timeout 60 nc -w 0 -ul 4012) if [ "$response" != '200 OK' ]; then echo 'BROKEN' exit 1; fi done
在串聯(lián)上post_worker_init腳本,以便app運(yùn)行的時候通知重啟腳本。
import socket
import time
def post_worker_init(worker):
_send_udp('200 OK\n')
def _send_udp(message):
udp_ip = "127.0.0.1"
udp_port = 4012
sock = socket.socket(socket.AF_INET, # Internet
socket.SOCK_DGRAM) # UDP
sock.sendto(message, (udp_ip, udp_port))
如果我們有這樣一個WSGI( Python Web Server Gateway Interface)應(yīng)用:
from werkzeug.wrappers import Request, Response
@Request.application
def application(request):
resp = Response('Hello World!')
if request.path == '/_status':
resp.status = '200 OK'
else:
resp.status ='404 Not Found'
return resp
我們甚至可以去做檢查/_status頁面之類的事情,以此來驗(yàn)證應(yīng)用是否已運(yùn)行。
def post_worker_init(worker):
env = {
'REQUEST_METHOD': 'GET',
'PATH_INFO': '/_status',
}
def start_response(*args, **kwargs):
_send_udp(args[0])
worker.wsgi(env, start_response)
注意不要試圖在這個健康檢測中運(yùn)行太多的應(yīng)用,如果不管什么原因你的post_worker_init產(chǎn)生了一個錯誤,那么工作進(jìn)程將會退出,并阻止應(yīng)用的啟動。在你檢查可能失效的DB鏈接的時候這會是一個問題,即使你的應(yīng)用可以工作,它也無法再次啟動。
現(xiàn)在通過一分鐘的應(yīng)用啟動,我們實(shí)現(xiàn)了滾動重啟,而無需停止應(yīng)用或者丟棄任何鏈接!
- 如何把python項目部署到linux服務(wù)器
- Django+python服務(wù)器部署與環(huán)境部署教程詳解
- python+selenium定時爬取丁香園的新型冠狀病毒數(shù)據(jù)并制作出類似的地圖(部署到云服務(wù)器)
- 基于騰訊云服務(wù)器部署微信小程序后臺服務(wù)(Python+Django)
- Python Web程序部署到Ubuntu服務(wù)器上的方法
- Linux下將Python的Django項目部署到Apache服務(wù)器
- Python實(shí)現(xiàn)根據(jù)指定端口探測服務(wù)器/模塊部署的方法
- 淺談Python項目的服務(wù)器部署
相關(guān)文章
python虛擬機(jī)之描述器實(shí)現(xiàn)原理與源碼分析
在本篇文章當(dāng)中主要給大家介紹描述器背后的實(shí)現(xiàn)原理,通過分析?cpython對應(yīng)的源代碼了解與描述器相關(guān)的字節(jié)碼的指令,我們就可以真正了解到描述器背后的原理,需要的朋友可以參考下2023-05-05
為python爬蟲docker鏡像添加nodejs環(huán)境實(shí)現(xiàn)方法
這篇文章主要為大家介紹了為python爬蟲docker鏡像添加nodejs環(huán)境實(shí)現(xiàn)方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
python用plotly實(shí)現(xiàn)繪制局部放大圖
大家好,本篇文章主要講的是python用plotly實(shí)現(xiàn)繪制局部放大圖,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下2022-02-02
詳解Pandas的三大利器(map,apply,applymap)
這篇文章主要為大家介紹了pandas中的三大利器: map、apply、applymap,他們經(jīng)常在進(jìn)行數(shù)據(jù)處理的時候用到,需要的可以參考一下2022-02-02
使用Python docx修改word關(guān)鍵詞顏色的操作
這篇文章主要介紹了使用Python docx修改word關(guān)鍵詞顏色的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03
python+opencv實(shí)現(xiàn)霍夫變換檢測直線
這篇文章主要為大家詳細(xì)介紹了python+opencv實(shí)現(xiàn)霍夫變換檢測直線,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12
Python超有趣實(shí)例通過冒泡排序來實(shí)現(xiàn)LOL厄斐琉斯控槍
冒泡排序是一種簡單的排序算法,它也是一種穩(wěn)定排序算法。其實(shí)現(xiàn)原理是重復(fù)掃描待排序序列,并比較每一對相鄰的元素,當(dāng)該對元素順序不正確時進(jìn)行交換。一直重復(fù)這個過程,直到?jīng)]有任何兩個相鄰元素可以交換,就表明完成了排序2022-05-05

