akka系統中停止運行任務的問題

   上週的工作中遇到了一個停止運行任務時的問題,就是在一個任務運行到一半時需要停止的問題。正常的需求是一按停止按鈕,就要立即停止,但現在都要等程序運行完才能停止,現在是一個bug。由於之前寫任務運行邏輯的不是我,因此我先花一個小時苦讀大神們的代碼,瞭解了他們對於任務運行那塊的邏輯,發現是首先前端發消息給一個Actor,然後這個Actor用actorOf方法創建許多子Actor,然後再對這些Actor調用ActorSelection創建運行這個任務的Actor。

   之前以爲通過獲取Actor的地址,終止這個Actor,然後自動終止其所有子Actor應該就能停止任務了,後來發現根本停不下來。

   第一次嘗試是在狀態機FSM中不僅在whenUnhandled方式下停止Actor,而且在其他每一種狀態下都調用停止Actor操作,直接終止運行該線程的Actor。

   這裏順便普及一下停止Actor的時候,是給該Actor發送兩種消息,Kill或者PoisonPill。使用Kill消息可以在不損失緩衝區中消息的情況下重啓Actor對象,但是不會停止Actor對象,僅僅是重啓,而且會拋出異常,使用PoisonPill消息可以停止Actor對象,但允許Actor對象處理完收到PoisonPill消息之前存儲在緩衝區中的消息。然後我又嘗試了context.stop(actorRef)去直接停止某Actor,同樣無濟於事,線程依舊瀟灑地運行結束。

   這個時候我發現問題應該轉移到線程級別,既然終止Actor是不起作用的,我就乾脆把這個線程終止掉。一開始我們採用給運行線程的Actor發送消息的方式終止該線程,發現能停止,但還是在任務運行完之後停止。後來我意識到,Actor處理消息應該是按照發送順序來的,首先發送的消息是處理這個任務,所以只有處理完任務纔會處理停止線程這個消息,此時線程已經不是運行狀態了。因此我乾脆定義了一個線程安全的HashMap,保存了id和Process對象的映射關係,可以通過這個數據結構搜索到線程對象,當父Actor收到終止任務命令時,不再向運行該任務的子Actor發送消息,而是在父Actor中直接調用運行任務的線程的Process對象裏的destroy方法,直接終止這個線程,終於成功了。

   得出結論就是,akka系統對於線程粒度的啓停控制可能還是有一定缺陷,需要我們根據線程的Process對象自己來做停止操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章