1、背景描述
最近在重寫對(duì)數(shù)據(jù)庫(kù)的探活,循環(huán)不斷對(duì)所有數(shù)據(jù)庫(kù)進(jìn)行select 1探活,但是發(fā)現(xiàn)當(dāng)數(shù)據(jù)庫(kù)出現(xiàn)假死的情況下,整個(gè)循環(huán)都卡主,連接hang死在假死的數(shù)據(jù)庫(kù),主要是這種異常無(wú)法通過(guò)connect_timeout超時(shí)來(lái)觸發(fā)異常,很難捕捉
2、目前解決辦法
目前解決辦法是通過(guò)裝飾器直接對(duì)函數(shù)進(jìn)行額外的超時(shí)判斷,將連接信息放到一個(gè)函數(shù)中,然后通過(guò)裝飾器對(duì)函數(shù)進(jìn)行額外的超時(shí)判斷,如果再遇到這種假死問題就可以通過(guò)裝飾器來(lái)拋出異常
裝飾器代碼
def function_timeout(seconds, err_msg='Function call timed out'):
"""
Timeout decorater.
Restrict function exec in special seconds or throw TimeoutError exception.
"""
def decorated(func):
def _handle_timeout(signum, frame):
raise Exception(err_msg)
def wrapper(*args, **kwargs):
signal.signal(signal.SIGALRM, _handle_timeout)
signal.alarm(seconds)
try:
result = func(*args, **kwargs)
finally:
signal.alarm(0)
return result
return functools.wraps(func)(wrapper)
return decorated
@function_timeout(5)
def connection():
xxx
3、案例展示
1、模擬數(shù)據(jù)庫(kù)假死,直接kill -19 pid即可模擬

image.png
2、首先不用裝飾器,在connect_timeout時(shí)間設(shè)置5s的情況下,程序hang死,手動(dòng)終止看時(shí)間超過(guò)5s

image.png
3、在使用裝飾器的情況下,在超時(shí)配置的超時(shí)時(shí)間后,會(huì)自動(dòng)拋出調(diào)用函數(shù)超時(shí)的異常用于捕捉

image.png
4、此方法問題
目前無(wú)法在多線程中使用,水平優(yōu)先,如果有大神有好的解決辦法辛苦分享下,感謝大佬們