SMS、電子メール、およびプッシュ通知用の Akka クラスター インフラストラクチャを作成しました。システムには、クライアント、送信者、灯台の 3 種類のノードが存在します。クライアント ロールは、Web アプリケーションと API アプリケーションによって使用されています (Web と API は IIS でホストされています)。Lighthouse と Sender の役割は、Windows サービスとしてホストされています。IIS によって Web アプリと API アプリの AppPools がリサイクルされることを考慮して、global.asax.cs の Start および Stop イベントで、Client ロールでアクター システムをシャットダウンし、再度開始します。ログから、システムが正常にシャットダウンしてクラスターに参加したことを確認できます。
しかし、AppPool がリサイクルされると、クライアントの ActorSystem は起動しますが、クラスターに参加できず、通知が機能しなくなることがあります (これは私たちにとって大きな問題です)。ActorSystem を手動で停止し、再度手動で動作させると、クラスターに参加します。この状況は、約 2 日ごとに発生します。
クライアントがエラーの前にクラスターに参加していることを確認できます。
ノード [akka.tcp://NotificationSystem@ . . . :41350] は JOINING、ロール [クライアント]
リーダーはノード [akka.tcp://NotificationSystem@ を移動中です。. . :41350] から [上へ]
ログを見ると、クライアントがクラスターに参加した後に次のエラーが表示されます。
シャットダウン アドレス: akka.tcp://NotificationSystem@ 。. . :41350Akka.Remote.ShutDownAssociation: シャットダウンアドレス: akka.tcp://NotificationSystem@ . . .:41350 ---> Akka.Remote.Transport.InvalidAssociationException: シャットダウン中のため、リモート システムがアソシエーションを終了しました。--- 内部例外スタック トレースの終了 --- Akka.Remote.EndpointWriter.PublishAndThrow(例外の理由、LogLevel レベル) で Akka.Remote.EndpointWriter.b__20_0(例外の例) で Akka.Actor.LocalOnlyDecider.Decide(例外の原因) で) at Akka.Actor.OneForOneStrategy.Handle(IActorRef child, Exception x) at Akka.Actor.SupervisorStrategy.HandleFailure(ActorCell actorCell, Exception cause, ChildRestartStats failedChildStats, IReadOnlyCollection1 allChildren) at Akka.Actor.ActorCell.HandleFailed(Failed f) at Akka.Actor.ActorCell.SystemInvoke(エンベロープ エンベロープ)--- 例外がスローされた前の場所からのスタック トレースの終わり --- Akka.Actor で Akka.Actor.ActorCell.HandleFailed(Failed f) で。. . .:41350 ---> Akka.Remote.Transport.InvalidAssociationException: シャットダウン中のため、リモート システムがアソシエーションを終了しました。--- 内部例外スタック トレースの終了 --- Akka.Remote.EndpointWriter.PublishAndThrow(例外の理由、LogLevel レベル) で Akka.Remote.EndpointWriter.b__20_0(例外の例) で Akka.Actor.LocalOnlyDecider.Decide(例外の原因) で) at Akka.Actor.OneForOneStrategy.Handle(IActorRef child, Exception x) at Akka.Actor.SupervisorStrategy.HandleFailure(ActorCell actorCell, Exception cause, ChildRestartStats failedChildStats, IReadOnlyCollection`1 allChildren) at Akka.Actor.ActorCell.HandleFailed(Failed f) ) Akka.Actor.ActorCell.SystemInvoke(エンベロープ エンベロープ) で --- 例外がスローされた前の場所からのスタック トレースの終わり --- Akka.Actor で Akka.Actor.ActorCell.HandleFailed(Failed f) で。
エラーの後、次のエラー メッセージが表示されます。
[akka.tcp://NotificationSystem@ への関連付け。. . :41350] が UID [226948907] を持つことは回復不能に失敗しました。UID は隔離され、この UID へのすべてのメッセージはデッド レターに配信されます。この状況から回復するには、リモート アクター システムを再起動する必要があります。
クライアント アクターを再起動しないと、システムはそれ自体を修正しません。
クライアント ロールの構成は次のとおりです。
<akka>
<hocon>
<![CDATA[
akka{
loglevel = DEBUG
actor{
provider = "Akka.Cluster.ClusterActorRefProvider, Akka.Cluster"
deployment {
/coordinatorRouter {
router = round-robin-group
routees.paths = ["/user/NotificationCoordinator"]
cluster {
enabled = on
max-nr-of-instances-per-node = 1
allow-local-routees = off
use-role = sender
}
}
}
serializers {
wire = "Akka.Serialization.WireSerializer, Akka.Serialization.Wire"
}
serialization-bindings {
"System.Object" = wire
}
debug{
receive = on
autoreceive = on
lifecycle = on
event-stream = on
unhandled = on
}
}
remote {
helios.tcp {
transport-class = "Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote"
applied-adapters = []
transport-protocol = tcp
hostname = "***.***.**.**"
port = 0
}
}
cluster {
seed-nodes = ["akka.tcp://NotificationSystem@***.***.**.**:5053", "akka.tcp://NotificationSystem@***.***.**.**:5073"]
roles = [client]
}
}
]]>
</hocon>
送信者の役割の構成は次のとおりです。
<akka>
<hocon><![CDATA[
akka{
loglevel = INFO
loggers = ["Akka.Logger.NLog.NLogLogger, Akka.Logger.NLog"]
actor{
debug {
# receive = on
# autoreceive = on
# lifecycle = on
# event-stream = on
# unhandled = on
}
provider = "Akka.Cluster.ClusterActorRefProvider, Akka.Cluster"
serializers {
wire = "Akka.Serialization.WireSerializer, Akka.Serialization.Wire"
}
serialization-bindings {
"System.Object" = wire
}
deployment{
/NotificationCoordinator/ApplePushNotificationActor{
router = round-robin-pool
resizer{
enabled = on
lower-bound = 3
upper-bound = 5
}
}
/NotificationCoordinator/AndroidPushNotificationActor{
router = round-robin-pool
resizer{
enabled = on
lower-bound = 3
upper-bound = 5
}
}
/NotificationCoordinator/EmailActor{
router = round-robin-pool
resizer{
enabled = on
lower-bound = 3
upper-bound = 5
}
}
/NotificationCoordinator/SmsActor{
router = round-robin-pool
resizer{
enabled = on
lower-bound = 3
upper-bound = 5
}
}
/NotificationCoordinator/LoggingCoordinator/ResponseLoggerActor{
router = round-robin-pool
resizer{
enabled = on
lower-bound = 3
upper-bound = 5
}
}
}
}
remote{
log-remote-lifecycle-events = DEBUG
log-received-messages = on
helios.tcp{
transport-class = "Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote"
applied-adapters = []
transport-protocol = tcp
#will be populated with a dynamic host-name at runtime if left uncommented
#public-hostname = "POPULATE STATIC IP HERE"
hostname = "***.***.**.**"
port = 0
}
}
cluster {
seed-nodes = ["akka.tcp://NotificationSystem@***.***.**.**:5053", "akka.tcp://NotificationSystem@***.***.**.**:5073"]
roles = [sender]
}
}
]]></hocon>
どうすればこの問題を解決できますか? ありがとうございました。