1. 程式人生 > >python執行緒卡死問題解決

python執行緒卡死問題解決

1. top命令和日誌方式判定卡死的位置python程式碼忽然卡死,日誌不輸出,通過如下方式可以確定執行緒確實已經死掉了:# top 命令top命令可以看到機器上所有執行緒的執行情況,%CPU和%MEM可以看出執行緒消耗的資源情況由於機器上執行緒數量太多,可能要檢視的執行緒的資訊在top命令當前螢幕上顯示不出來可以通過如下方式檢視在top命令下輸入:u 接下來會提示輸入使用者名稱,就可以檢視該使用者所執行的所有執行緒Which user (blank for all): denglinjie這樣就可以看到degnlinjie使用者的所有執行緒可以看到那幾個卡死執行緒的%CPU和%MEM都為0,說明執行緒根本沒有消耗資源,那麼可以看出執行緒已經卡死了接下來通過打日誌的方式來確定執行緒究竟是卡死在哪裡了,執行緒卡死的地方大多數都是在io或者http請求那,所以以後遇到執行緒卡死的情況,就通過打日誌的方式來確定卡死的位置,最終定位到問題確實是一個http服務掛掉了,而且此時requests.get()我雖然設定了超時,但是竟然無效

2 . 服務程序數量不足導致的客戶端程序卡死

服務端程式碼:

handler = SimilarityService()
transport = TSocket.TServerSocket('10.134.113.75', 1234)
factory = TBinaryProtocol.TBinaryProtocolFactory()
processor = Processor(handler)
server = TProcessPoolServer.TProcessPoolServer(processor, transport)
server.setNumWorkers(10)
server.serve()

客戶端程式碼

docQue = queues.Queue(maxsize=1000)
pCount = 15


class ParseSaveEsProcess(multiprocessing.Process):

    def __init__(self, threadId):
        self.threadId = threadId
        multiprocessing.Process.__init__(self)

    def run(self):
        global docQue
        f = open('recall_match_file_all_simi.lst.%s' % self.threadId, 'w')
        try:
            transport = TSocket.TSocket('10.134.113.75', 1234)
            transport = TTransport.TBufferedTransport(transport)
            protocol = TBinaryProtocol.TBinaryProtocol(transport)
            client = Client(protocol)
            transport.open()
while True: line = docQue.get(block=True) if not line: print 'thread%d run over' % self.threadId break p = line.split('\t') if len(p) >= 6 and p[5] == 'simi_high': simi_str = client.calculate_similarity_by_itemurl(p[0]) f.write(line + '\t' + simi_str + '\n') else: f.write(line + '\n') transport.close() except Thrift.TException as e: print str(e) pass class PutUrlProcess(multiprocessing.Process): def __init__(self): multiprocessing.Process.__init__(self) def run(self): global docQue for line in open('recall_match_file.lst', 'r'): baikeid = line.strip() docQue.put(baikeid, block=True) for i in range(pCount): docQue.put(None, block=True) if __name__ == '__main__': putProcess = PutUrlProcess() putProcess.start() for i in range(pCount): parseProcess = ParseSaveEsProcess(i) parseProcess.start()

可以看到,程序ParseSaveEsProcess程序總共開啟了15個,每個程序會開啟一個thrift連線,開啟後一直髮送請求,並將處理的結果寫檔案,全部執行完成後才關閉thrift連線。

可是,發現從啟動到執行了很長時間後,只有10個檔案裡面有內容寫入,其中5個一直沒有寫入:

111965 recall_match_file_all_simi.lst.0
   111878 recall_match_file_all_simi.lst.1
        0 recall_match_file_all_simi.lst.10
        0 recall_match_file_all_simi.lst.11
        0 recall_match_file_all_simi.lst.12
        0 recall_match_file_all_simi.lst.13
        0 recall_match_file_all_simi.lst.14
   113429 recall_match_file_all_simi.lst.2
   110720 recall_match_file_all_simi.lst.3
   111993 recall_match_file_all_simi.lst.4
   113691 recall_match_file_all_simi.lst.5
   113360 recall_match_file_all_simi.lst.6
   113953 recall_match_file_all_simi.lst.7
   112007 recall_match_file_all_simi.lst.8
   113818 recall_match_file_all_simi.lst.9
原因是因為thrift服務端只啟動了10個服務程序,所以只能同時處理10個請求,而我客戶端開啟的thrift連線一直沒有關閉,所以10個服務程序被10個客戶端連線霸佔了,另外5個程序獲取不到連線,自然就一直卡住了