正如标題所說的,這篇文章主要說下,在解決這個問題的時候所遇到的問題
先說下背景:
1,一個請求,啟動多個actor去執行任務,當任務執行過程中,又請求的一次,進行了重複請求
這種情況下,會出現異常InvalidActorNameException,也就是說actor的名字重複了
首先想到将正在執行的actor關閉,actor的關閉我這裡說一種,actorSysm.stop(actor);
actorSystem類型是ActorSystem,如果不知道這個是怎麼來的,去搜尋下怎麼建立actor,自然就有了
但是這裡有個問題,stop的指令不會立即終止actor,不像linux的kill一樣,直接殺死,而是要發送讓其
死亡的消息,但是我們不可能等到這個actor徹底死了,才去建立新的actor
這期間試了幾種方法,都不能滿足需求
最後,隻能曲線救國
那就是每次請求進來,重建立立actorSystem
ActorSystem systemo = system.apply("AkkaVehicleReport");
然後将之前的actorSystem關閉
system.shutdown();
最後将之前的actorSystem的引用指向建立的actorSystem
system = systemo;
這樣做的效果就是每次都是新的actorSystem去建立actor執行任務,不會出現名字重複的問題
同時關閉了之前的actorSystem,之前建立的actor會逐層被殺死,解決了不會因為重複送出而造成
一直建立actor的問題,
因為我的actor執行的完成之後會将資料儲存到一個地方,這麼操作還有一個意外收獲
那就是之前的actor未被殺死之前執行完的資料會被儲存下來,建立的actor不需要再次執行
提高了資料使用率
下面把相對完整的代碼貼出來,歡迎大家指導
注入部分:
@Autowired
private ActorSystem system;
這裡說下,如果你無法注入這個actorSystem,需要增加一部分代碼,這裡不做解釋,可以自己搜下,找不到可以找我-469798404
方法内部:
ActorSystem systemo = system.apply("AkkaVehicleReport");
system.shutdown();
system = systemo;
for (int i = 1; i <= 20; i++) {
ReportMessage msg = new ReportMessage();
String actorName = session.getId() + "pageActor" + i;
try {
actorList.add(actorName);
ActorRef pageActor = system.actorOf(SpringExtProvider.get(system).props(PageActor.class), actorName);
System.out.println("---" + actorName + "-----------create");
pageActor.tell(msg, ActorRef.noSender());
} catch (InvalidActorNameException e) {
e.printStackTrace();
}
}
建立了20個actor,去執行任務
@Override
public void onReceive(Object msg) throws Exception {
if(msg instanceof ReportMessage){
//查詢資料,處理資料
ReportMessage remsg = (ReportMessage)msg;
//判斷該部分資料是否處理完成
if(//處理完成){
System.out.println("----------重複---done---" + this.self().path().name());
}else{//未處理完成
//重新處理
System.out.println("-------------done---" + this.self().path().name());
}
getContext().stop(this.getSelf());
}
else{
unhandled(msg);
}
}
整體的結構就是這樣,删掉了一些業務代碼
整體思路就是這樣
重複送出時,建立actor的動作和停止正在執行的actor的動作時同時操作的,這樣又可以節省一部分時間
隻是可能要多消耗一些性能