小編寫這篇文章的目的,主要是給大家講解一下,關于實現(xiàn)配置熱加載的方法,具體是怎么操作呢?下面就給大家詳細的解答下。
背景
由于最近有相關的工作需求,需要進行增添相關的新功能,實現(xiàn)配置熱加載的功能。所謂的配置熱加載,也就是說當服務收到配置更新消息之后,我們不用重啟服務就可以使用最新的配置去執(zhí)行任務。
如何實現(xiàn)
下面我分別采用多進程、多線程、協(xié)程的方式去實現(xiàn)配置熱加載。
使用多進程實現(xiàn)配置熱加載
如果我們代碼實現(xiàn)上使用多進程,主進程1來更新配置并發(fā)送指令,任務的調(diào)用是進程2,如何實現(xiàn)配置熱加載呢?
使用signal信號量來實現(xiàn)熱加載
當主進程收到配置更新的消息之后(配置讀取是如何收到配置更新的消息的?這里我們暫不討論),主進程就向進子程1發(fā)送kill信號,子進程1收到kill的信號就退出,之后由信號處理函數(shù)來啟動一個新的進程,使用最新的配置文件來繼續(xù)執(zhí)行任務。
main函數(shù)
def main(): #啟動一個進程執(zhí)行任務 p1=Process(target=run,args=("p1",)) p1.start() monitor(p1,run)#注冊信號 processes["case100"]=p1#將進程pid保存 num=0 while True:#模擬獲取配置更新 print( f"{multiprocessing.active_children()=},count={len(multiprocessing.active_children())}\n") print(f"{processes=}\n") sleep(2) if num==4: kill_process(processes["case100"])#kill當前進程 if num==8: kill_process(processes["case100"])#kill當前進程 if num==12: kill_process(processes["case100"])#kill當前進程 num+=1
signal_handler函數(shù)
def signal_handler(process:Process,func,signum,frame): #print(f"{signum=}") global counts if signum==17:#17 is SIGCHILD #這個循環(huán)是為了忽略SIGTERM發(fā)出的信號,避免搶占了主進程發(fā)出的SIGCHILD for signame in[SIGTERM,SIGCHLD,SIGQUIT]: signal.signal(signame,SIG_DFL) print("Launch a new process") p=multiprocessing.Process(target=func,args=(f"p{counts}",)) p.start() monitor(p,run) processes["case100"]=p counts+=1 if signum==2: if process.is_alive(): print(f"Kill{process}process") process.terminate() signal.signal(SIGCHLD,SIG_IGN) sys.exit("kill parent process")
完整代碼如下
#!/usr/local/bin/python3.8 from multiprocessing import Process from typing import Dict import signal from signal import SIGCHLD,SIGTERM,SIGINT,SIGQUIT,SIG_DFL,SIG_IGN import multiprocessing from multiprocessing import Process from typing import Callable from data import processes import sys from functools import partial import time processes:Dict[str,Process]={} counts=2 def run(process:Process): while True: print(f"{process}running...") time.sleep(1) def kill_process(process:Process): print(f"kill{process}") process.terminate() def monitor(process:Process,func:Callable): for signame in[SIGTERM,SIGCHLD,SIGINT,SIGQUIT]: #SIGTERM is kill signal. #No SIGCHILD is not trigger singnal_handler, #No SIGINT is not handler ctrl+c, #No SIGQUIT is RuntimeError:reentrant call inside<_io.BufferedWriter name='<stdout>'> signal.signal(signame,partial(signal_handler,process,func)) def signal_handler(process:Process,func,signum,frame): print(f"{signum=}") global counts if signum==17:#17 is SIGTERM for signame in[SIGTERM,SIGCHLD,SIGQUIT]: signal.signal(signame,SIG_DFL) print("Launch a new process") p=multiprocessing.Process(target=func,args=(f"p{counts}",)) p.start() monitor(p,run) processes["case100"]=p counts+=1 if signum==2: if process.is_alive(): print(f"Kill{process}process") process.terminate() signal.signal(SIGCHLD,SIG_IGN) sys.exit("kill parent process") def main(): p1=Process(target=run,args=("p1",)) p1.start() monitor(p1,run) processes["case100"]=p1 num=0 while True: print( f"{multiprocessing.active_children()=},count={len(multiprocessing.active_children())}\n") print(f"{processes=}\n") time.sleep(2) if num==4: kill_process(processes["case100"]) if num==8: kill_process(processes["case100"]) if num==12: kill_process(processes["case100"]) num+=1 if __name__=='__main__': main()
執(zhí)行結果如下
multiprocessing.active_children()=[<Process name='Process-1'pid=2533 parent=2532 started>],count=1 processes={'case100':<Process name='Process-1'pid=2533 parent=2532 started>} p1 running... p1 running... kill<Process name='Process-1'pid=2533 parent=2532 started> multiprocessing.active_children()=[<Process name='Process-1'pid=2533 parent=2532 started>],count=1 processes={'case100':<Process name='Process-1'pid=2533 parent=2532 started>} signum=17 Launch a new process p2 running... p2 running... multiprocessing.active_children()=[<Process name='Process-2'pid=2577 parent=2532 started>],count=1 processes={'case100':<Process name='Process-2'pid=2577 parent=2532 started>} p2 running... p2 running... multiprocessing.active_children()=[<Process name='Process-2'pid=2577 parent=2532 started>],count=1 processes={'case100':<Process name='Process-2'pid=2577 parent=2532 started>} p2 running... p2 running... multiprocessing.active_children()=[<Process name='Process-2'pid=2577 parent=2532 started>],count=1 processes={'case100':<Process name='Process-2'pid=2577 parent=2532 started>} p2 running... p2 running... kill<Process name='Process-2'pid=2577 parent=2532 started> signum=17 Launch a new process multiprocessing.active_children()=[<Process name='Process-2'pid=2577 parent=2532 stopped exitcode=-SIGTERM>],count=1 processes={'case100':<Process name='Process-3'pid=2675 parent=2532 started>} p3 running... p3 running... multiprocessing.active_children()=[<Process name='Process-3'pid=2675 parent=2532 started>],count=1
總結
好處:使用信號量可以處理多進程之間通信的問題。
自媒體培訓
壞處:代碼不好寫,寫出來代碼不好理解。信號量使用必須要很熟悉,不然很容易自己給自己寫了一個bug.(所有初學者慎用,老司機除外。)
還有一點不是特別理解的就是process.terminate()發(fā)送出信號是SIGTERM number是15,但是第一次signal_handler收到信號卻是number=17,如果我要去處理15的信號,就會導致前一個進程不能kill掉的問題。歡迎有對信號量比較熟悉的大佬,前來指點迷津,不甚感謝。
采用multiprocessing.Event來實現(xiàn)配置熱加載
實現(xiàn)邏輯是主進程1更新配置并發(fā)送指令。進程2啟動調(diào)度任務。
這時候當主進程1更新好配置之后,發(fā)送指令給進程2,這時候的指令就是用Event一個異步事件通知。
直接上代碼
scheduler函數(shù) def scheduler(): while True: print('wait message...') case_configurations=scheduler_notify_queue.get() print(f"Got case configurations{case_configurations=}...") task_schedule_event.set()#設置set之后,is_set為True print(f"Schedule will start...") while task_schedule_event.is_set():#is_set為True的話,那么任務就會一直執(zhí)行 run(case_configurations) print("Clearing all scheduling job...") event_scheduler函數(shù) def event_scheduler(case_config): scheduler_notify_queue.put(case_config) print(f"Put cases config to the Queue...") task_schedule_event.clear()#clear之后,is_set為False print(f"Clear scheduler jobs...") print(f"Schedule job...") 完整代碼如下 import multiprocessing import time scheduler_notify_queue=multiprocessing.Queue() task_schedule_event=multiprocessing.Event() def run(case_configurations:str): print(f'{case_configurations}running...') time.sleep(3) def scheduler(): while True: print('wait message...') case_configurations=scheduler_notify_queue.get() print(f"Got case configurations{case_configurations=}...") task_schedule_event.set() print(f"Schedule will start...") while task_schedule_event.is_set(): run(case_configurations) print("Clearing all scheduling job...") def event_scheduler(case_config:str): scheduler_notify_queue.put(case_config) print(f"Put cases config to the Queue...") task_schedule_event.clear() print(f"Clear scheduler jobs...") print(f"Schedule job...") def main(): scheduler_notify_queue.put('1') p=multiprocessing.Process(target=scheduler) p.start() count=1 print(f'{count=}') while True: if count==5: event_scheduler('100') if count==10: event_scheduler('200') count+=1 time.sleep(1) if __name__=='__main__': main() 執(zhí)行結果如下 wait message... Got case configurations case_configurations='1'... Schedule will start... 1 running... 1 running... Put cases config to the Queue... Clear scheduler jobs... Schedule job... Clearing all scheduling job... wait message... Got case configurations case_configurations='100'... Schedule will start... 100 running... Put cases config to the Queue... Clear scheduler jobs... Schedule job... Clearing all scheduling job... wait message... Got case configurations case_configurations='200'... Schedule will start... 200 running... 200 running...
總結
使用Event事件通知,代碼不易出錯,代碼編寫少,易讀。相比之前信號量的方法,推薦大家多使用這種方式。
使用多線程或協(xié)程的方式,其實和上述實現(xiàn)方式一致。唯一區(qū)別就是調(diào)用了不同庫中,queue和event.
#threading scheduler_notify_queue=queue.Queue() task_schedule_event=threading.Event() #async scheduler_notify_queue=asyncio.Queue() task_schedule_event=asyncio.Event()
綜上所述,就是小編給大家總結的,關于python方面的一些知識了,希望可以給大家?guī)韼椭?/p>
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/128005.html
摘要:而熱部署技術能夠幫助開發(fā)人員減少重新部署的等待時間。本文的目的為調(diào)研熱部署的技術現(xiàn)狀及其對開發(fā)效率的幫助,并簡單梳理其技術實現(xiàn)的難點。熱部署技術總結熱部署目前有多種技術實現(xiàn)官方開源商業(yè)。 開發(fā)、自測、聯(lián)調(diào)期間代碼可能會被頻繁地修改,通常即使只增加了一行代碼,都需要重啟容器以檢查執(zhí)行效果。而熱部署技術能夠幫助開發(fā)人員減少重新部署的等待時間。本文的目的為調(diào)研熱部署的技術現(xiàn)狀及其對開發(fā)效率的...
時間:2017年12月01日星期五說明:本文部分內(nèi)容均來自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com 教學源碼:無 學習源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 課程介紹 熱部署的使用場景 本地調(diào)式 線上發(fā)布 熱部署的使用優(yōu)點 無論本地還是線上,都適用 無需重啟服務器:提高開發(fā)、調(diào)式效率、提升發(fā)布、運維效率、降低運維成本 前置...
摘要:在項目根目錄下創(chuàng)建,通過這個文件來起服務。到這里為止,自動刷新的內(nèi)容基本講完了。注意到一點,目前自動刷新都是刷新整個頁面。其中表示熱加載模塊,表示。后續(xù)我還會進行更深入的學習,希望和大家共同進步。 本文主要介紹以下兩方面的內(nèi)容: webpack-dev-server自動刷新 熱加載(Hot Module Replacement) 自動刷新 webpack-dev-server提供了...
摘要:熱加載代表的是我們不需要重啟服務器,就能夠類檢測得到,重新生成類的字節(jié)碼文件無論是熱部署或者是熱加載都是基于類加載器來完成的。驗證階段字節(jié)碼文件不會對造成危害準備階段是會賦初始值,并不是程序中的值。 一、SpringBoot入門 今天在慕課網(wǎng)中看見了Spring Boot這么一個教程,這個Spring Boot作為JavaWeb的學習者肯定至少會聽過,但我是不知道他是什么玩意。 只是大...
閱讀 1069·2023-01-14 11:38
閱讀 1067·2023-01-14 11:04
閱讀 906·2023-01-14 10:48
閱讀 2384·2023-01-14 10:34
閱讀 1152·2023-01-14 10:24
閱讀 1029·2023-01-14 10:18
閱讀 657·2023-01-14 10:09
閱讀 736·2023-01-14 10:02