[英]Trouble Connecting to Custom Akka.NET Transport
我正在嘗試實現自定義 Akka.NET Transport
。 目前我有以下內容:
客戶端程序(基於https://getakka.net/articles/remoting/messaging.html ):
using Akka.Actor;
using Akka.Configuration;
using AkkaTest.Messages;
namespace AkkaTest;
static class Program
{
static void Main()
{
var config = ConfigurationFactory.ParseString(@"
akka {
actor {
provider = remote
}
remote {
enabled-transports = [""akka.remote.myproto""]
myproto {
transport-class = ""AkkaTest.Messages.MyTransport, AkkaTest.Messages""
applied-adapters = []
transport-protocol = myproto
port = 0 # bound to a dynamic port assigned by the OS
hostname = localhost
}
}
}");
var system = ActorSystem.Create("MyActorSystem", config);
var myActor = system.ActorOf<SendActor>();
myActor.Tell(new StartRemoting());
while (true)
{
// null task
}
}
}
// Initiates remote contact
public class SendActor : ReceiveActor
{
public SendActor()
{
Receive<StartRemoting>(s => {
Context.ActorSelection("akka.myproto://RemoteSys@localhost:8081/user/Echo")
.Tell(new Msg("hi!"));
});
Receive<Msg>(msg => {
Console.WriteLine("Received {0} from {1}", msg.Content, Sender);
});
}
}
服務器:
using Akka.Actor;
using Akka.Configuration;
using AkkaTest.Messages;
namespace AkkaTest.Server;
static class Program
{
static void Main()
{
var config = ConfigurationFactory.ParseString(@"
akka {
actor {
provider = remote
}
remote {
enabled-transports = [""akka.remote.myproto""]
myproto {
transport-class = ""AkkaTest.Messages.MyTransport, AkkaTest.Messages""
applied-adapters = []
transport-protocol = myproto
port = 8081 #bound to a specific port
hostname = localhost
}
}
}");
var system = ActorSystem.Create("RemoteSys", config);
system.ActorOf<EchoActor>("Echo");
while (true)
{
// null task
}
}
}
// Runs in a separate process from SendActor
public class EchoActor : ReceiveActor
{
public EchoActor()
{
Receive<Msg>(msg => {
// echo message back to sender
Sender.Tell(msg);
});
}
}
留言:
namespace AkkaTest.Messages;
// Written into a shared library
public class Msg
{
public Msg(string content)
{
this.Content = content;
}
public string Content { get; set; }
}
public class StartRemoting { }
存根關聯事件偵聽器:
namespace AkkaTest.Messages
{
using Akka.Remote.Transport;
public class MyAel : IAssociationEventListener
{
public void Notify(IAssociationEvent ev)
{
throw new NotImplementedException();
}
}
}
最后,被截斷的傳輸:
namespace AkkaTest.Messages
{
using Akka.Actor;
using Akka.Configuration;
using Akka.Remote.Transport;
using System;
using System.Threading.Tasks;
public class MyTransport : Transport
{
public MyTransport(ActorSystem system, Config config)
{
this.System = system;
this.Config = config;
}
public override Task<AssociationHandle> Associate(Address remoteAddress)
{
throw new NotImplementedException();
}
public override bool IsResponsibleFor(Address remote)
{
return remote.Protocol.ToUpper() == this.Config.GetString("transport-protocol").ToUpper();
}
public override Task<(Address, TaskCompletionSource<IAssociationEventListener>)> Listen()
{
var tcs = new TaskCompletionSource<IAssociationEventListener>();
tcs.TrySetResult(new MyAel());
var protocol = this.Config.GetString("transport-protocol");
var host = this.Config.GetString("hostname");
var port = this.Config.GetInt("port");
if (port == 0)
{
port = 62978;
}
return Task.FromResult((
new Address(
protocol,
this.System.Name,
host,
port),
tcs));
}
public override Task<bool> Shutdown()
{
throw new NotImplementedException();
}
}
}
以前,我嘗試過使用 TCP 而不是我的自定義傳輸的非常相似的客戶端/服務器設置。 這是服務器 output:
[INFO][9/27/2022 2:29:15 PM][Thread 0001][remoting (akka://RemoteSys)] Starting remoting
[INFO][9/27/2022 2:29:15 PM][Thread 0001][remoting (akka://RemoteSys)] Remoting started; listening on addresses : [akka.tcp://RemoteSys@localhost:8081]
[INFO][9/27/2022 2:29:15 PM][Thread 0001][remoting (akka://RemoteSys)] Remoting now listens on addresses: [akka.tcp://RemoteSys@localhost:8081]
和客戶:
[INFO][9/27/2022 2:29:29 PM][Thread 0001][remoting (akka://MyActorSystem)] Starting remoting
[INFO][9/27/2022 2:29:30 PM][Thread 0001][remoting (akka://MyActorSystem)] Remoting started; listening on addresses : [akka.tcp://MyActorSystem@localhost:62978]
[INFO][9/27/2022 2:29:30 PM][Thread 0001][remoting (akka://MyActorSystem)] Remoting now listens on addresses: [akka.tcp://MyActorSystem@localhost:62978]
Received hi! from [akka.tcp://RemoteSys@localhost:8081/user/Echo#2122916400]
所以這是我的預期行為。 當我使用自定義傳輸啟動服務器項目時,我得到以下控制台 output:
[INFO][9/27/2022 3:49:50 PM][Thread 0001][remoting (akka://RemoteSys)] Starting remoting
[INFO][9/27/2022 3:49:50 PM][Thread 0001][remoting (akka://RemoteSys)] Remoting started; listening on addresses : [akka.myproto://RemoteSys@localhost:8081]
[INFO][9/27/2022 3:49:50 PM][Thread 0001][remoting (akka://RemoteSys)] Remoting now listens on addresses: [akka.myproto://RemoteSys@localhost:8081]
這是我所期望的。 與我在使用 TCP 嘗試相同設置時得到的 output 非常相似。 但是,當我嘗試啟動客戶端時,出現以下錯誤:
[INFO][9/27/2022 3:50:48 PM][Thread 0001][remoting (akka://MyActorSystem)] Starting remoting
[INFO][9/27/2022 3:50:48 PM][Thread 0001][remoting (akka://MyActorSystem)] Remoting started; listening on addresses : [akka.myproto://MyActorSystem@localhost:62978]
[INFO][9/27/2022 3:50:48 PM][Thread 0001][remoting (akka://MyActorSystem)] Remoting now listens on addresses: [akka.myproto://MyActorSystem@localhost:62978]
[ERROR][9/27/2022 3:50:49 PM][Thread 0009][akka://MyActorSystem/user/$a] No transport is loaded for protocol: [akka.myproto], available protocols: [akka.]
Cause: Akka.Remote.RemoteTransportException: No transport is loaded for protocol: [akka.myproto], available protocols: [akka.]
at Akka.Remote.Remoting.LocalAddressForRemote(IDictionary`2 transportMapping, Address remote)
at Akka.Remote.RemoteActorRefProvider.RootGuardianAt(Address address)
at Akka.Actor.ActorRefFactoryShared.ActorSelection(String path, ActorSystem system, IActorRef lookupRoot)
at AkkaTest.SendActor.<>c.<.ctor>b__0_0(StartRemoting s) in ...\AkkaTest\AkkaTest\Program.cs:line 44
at lambda_method7(Closure , Object , Action`1 , Action`1 )
at Akka.Actor.ReceiveActor.OnReceive(Object message)
at Akka.Actor.UntypedActor.Receive(Object message)
at Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
at Akka.Actor.ActorCell.ReceiveMessage(Object message)
at Akka.Actor.ActorCell.Invoke(Envelope envelope)
無論我是否啟動了服務器,我都會遇到同樣的問題,所以它幾乎就好像它甚至沒有嘗試建立關聯一樣。 我懷疑問題可能是我現在有太多的存根(我特別想知道問題是否與tcs.TrySetResult(new MyAel());
線有關),但我沒有很多到 go 上要填寫什么; 文檔有點稀疏。 據我所知,沒有任何NotImplementedExceptions
被命中,也沒有任何先前的斷點。 那么我在這個階段缺少什么?
找到(當前)問題。 檢查DotnettyTransport
的元數據,我注意到它覆蓋了虛擬SchemeIdentifier
。 我在我的ctor中設置了SchemeIdentifier
:
public MyTransport(ActorSystem system, Config config)
{
this.System = system;
this.Config = config;
this.SchemeIdentifier = this.Config.GetString("transport-protocol");
}
在我這樣做之后,我的IsResponsibleFor
實現被調用了。 這導致了我的下一個問題,傳入的remote.Protocol
屬性沒有像我預期的那樣返回myproto
,而是返回akka.myproto
。 很容易修復:
public override bool IsResponsibleFor(Address remote)
{
return remote.Protocol.ToUpper() == $"AKKA.{this.SchemeIdentifier.ToUpper()}";
}
以后可能會整理一下。 現在它正在工作,我的Associate
覆蓋被調用,當然會拋出它的NotImplemented
[yet] Exception
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.