運維經驗分享作為一個專題,目前共7篇文章
====================================分割線======================================
chatterserver 之是以有如此多版和遇到這麼多問題,跟java程序還有很大的關系,此次面臨的問題和分析思路總結如下,歡迎各位補充。
停止java程序可能面臨的問題:
以kill pid的方式停止java程序,java程序在等待java程序内部結束,是以沒有立即結束,進而導緻原java程式監聽的端口可能沒有釋放,原java程序的pid也可能依然存在
在原java程序沒有立即結束的情況下,再重新啟動這個java程序就會産生錯誤,這些錯誤包括無法重新監聽端口,甚至是直接啟動失敗
啟動java程序可能面臨的問題:
用java指令啟動java程序,java程序傳回結果為成功,但實際不成功(需要注意确認“用java指令啟動java程序”傳回的執行結果是java自身傳回的,還是人工編寫的程式傳回的)
上面描述的一些進一步解釋、術語和例子:
java程序是指由人工編寫的一些java程式,其中不能保證程式裡面的異常全部捕獲并處理,例如如果無法監聽端口傳回正确的錯誤傳回值并退出
以kill pid的方式:kill `cat $pidfile`
用java指令啟動java程序:java -jar somename.jar $args
原有的啟動java程序的流程
啟動程序有兩種情況,第一次啟動(首次啟動),停止程序後再次啟動(重新啟動),是以可以考慮将這兩種情況綜合在一起考慮,即不區分之前是否啟動過或停止過,把這些情況都考慮進去
判斷目前系統中的特定目錄下是否存在pid檔案或者鎖
判斷目前系統中是否已經存在java程序,判斷的依據是從系統中檢測java程序pid是否存在,如ps,而不是根據pid檔案或者鎖判斷
判斷目前系統中是否已經監聽端口号,因為端口号可能由别的程式(如果pid不存在,則該端口号不會由它自己占用)占用
啟動java程序(大部分程式都會保證此處能啟動成功,可參考/etc/init.d/functions,行270,1-8),如果傳回結果為成功,則輸出成功并建立pid檔案和鎖,如果不成功,則輸出不成功,不再嘗試再次啟動
原有的停止java程序的流程
如果找到pid,先發送term信号,暫停100000微秒(usleep 100000),如果人工預先知道需要繼續延遲,則延遲自定義秒數,如果沒有殺死(即依然能檢測到系統中存在此pid)則再發送kill信号,再次暫停100000微秒
再次檢測到系統中是否存在此pid,如果不存在則輸出成功并移除pid檔案和鎖,如果存在則輸出不成功
如果找不到pid,則輸出程式沒有在運作
根據以上問題重新設計啟動java程序的流程(主要問題所在)
判斷目前系統中的特定目錄下是否存在pid檔案(原有設計中沒有鎖,故此處不使用鎖)
判斷目前系統中是否已經存在java程序,判斷的依據是從系統中檢測java程序pid是否存在,如test -d /proc/$pid,ps,而不是根據pid檔案或者鎖判斷
啟動java程序(大部分程式都會保證此處能啟動成功,可參考/etc/init.d/functions,行270,1-8),如果傳回結果為成功,從系統中檢測java程序pid是否存在,如果pid存在則輸出成功并建立pid檔案(原有設計中沒有鎖,故此處不使用鎖),如果pid不存在,則再次啟動java程序,移除“如果不成功,則輸出不成功,不再嘗試再次啟動”。
根據以上問題重新設計停止java程序的流程
針對java程序沒有殺死的可能性,現做出如此修改,如果找到pid,先發送term信号,暫停100000微秒(usleep 100000),已經預先知道需要繼續延遲,延遲5秒,如果沒有殺死(即依然能檢測到系統中存在此pid)則再發送kill信号,再次暫停100000微秒
再次檢測到系統中是否存在此pid,如果不存在則輸出成功并移除pid檔案(原有設計中沒有鎖,故此處不使用鎖),如果pid依然存在則再嘗試kill -9(the signals sigkill and sigstop cannot be caught, blocked, or ignored.目前假設認為-9比kill更加強制)
--end--