JMS微服務開發示例(六)安全退出程序
阿新 • • 發佈:2020-07-31
預設情況下,如果在linux,需要關閉微服務程序,請務必使用 kill -15 程序id 命令,其他命令可能會直接關閉程序,造成資料丟失。
例如,有個後臺任務,執行了一半,這時候程序突然關閉了,會形成一些無法預計的後果。
Kill -15 命令的安全性
預設情況下,當發出kill -15命令,微服務需要按順序,做完以下事情後,程序才會關閉:
1、執行IProcessExitHandler新增的任務
2、斷開閘道器連線
3、等待事務託管中心事務清零
4、等待定時任務執行完畢
5、等待客戶端請求數清零
所以,為了保證資料完整性,對於一些後臺執行的任務,如果不是使用MicroServiceHost.RegisterScheduleTask 開啟的定時任務,那麼,您需要手動寫一些程式碼保證你的任務執行完畢後,程序才會退出。
可以參考以下示例:
/// <summary> /// 單個使用者事件處理佇列 /// </summary> class UserActionQueue:IDisposable { System.Threading.AutoResetEvent _waitObj = new System.Threading.AutoResetEvent(false); ConcurrentQueue<Action> Actions { get; } public long UserId { get; } IProcessExitHandler _processExitHandler; bool _exited; public UserActionQueue(long userid) { this.UserId = userid; this.Actions = new ConcurrentQueue<Action>(); _processExitHandler = Global.ServiceProvider.GetService<JMS.IProcessExitHandler>();//當程序退出時,呼叫onProcessExit() _processExitHandler.AddHandler(onProcessExit); new Thread(run).Start(); } private void onProcessExit() { try { var obj = _waitObj; _waitObj = null; obj.Set(); obj.Dispose(); while(!_exited) //只有_exited = true時,才表示任務執行完畢,不會有任務執行了一半 { Thread.Sleep(100); } } catch { } } /// <summary> /// 新增一個任務到隊列當中 /// </summary> /// <param name="action"></param> public void AddAction(Action action) { this.Actions.Enqueue(action); //通知佇列馬上執行 _waitObj.Set(); } void run() { while (!_processExitHandler.ProcessExited) { try { _waitObj.WaitOne(); if (_waitObj == null) break; //執行佇列裡面的任務 if (this.Actions.TryDequeue(out Action o)) { o(); } } catch { } } _exited = true; } public void Dispose() { onProcessExit(); } }