Scala 无法从Akka群集客户端发送协议缓冲区消息
我正在尝试使用Play Framework(Scala)作为Akka群集客户端向另一个运行我的应用程序服务的Akka群集发送消息 以下是我所做的:Scala 无法从Akka群集客户端发送协议缓冲区消息,scala,akka,playframework-2.5,akka-cluster,Scala,Akka,Playframework 2.5,Akka Cluster,我正在尝试使用Play Framework(Scala)作为Akka群集客户端向另一个运行我的应用程序服务的Akka群集发送消息 以下是我所做的: 我使用协议缓冲区在不同的模块中定义了消息,并在运行项目的服务和Play app之间共享消息(使用git子模块) 已在端口2560启动服务 akka { remote.netty.tcp.port=${?AKKA_REMOTE_PORT} remote.netty.tcp.hostname=127.0.0.1 cluster {
akka {
remote.netty.tcp.port=${?AKKA_REMOTE_PORT}
remote.netty.tcp.hostname=127.0.0.1
cluster {
seed-nodes = [
"akka.tcp://ApiServiceActorSystem@127.0.0.1:2560"
]
auto-down-unreachable-after = 10s
}
extensions = ["akka.cluster.client.ClusterClientReceptionist"]
loglevel = DEBUG
actor {
serializer {
proto = "akka.remote.serialization.ProtobufSerializer"
}
serialization-bindings {
"com.myproject.api.common.messages.IsValidClientMessage$IsValidClient" = proto
}
serialize-messages = on
provider = "akka.cluster.ClusterActorRefProvider"
debug {
receive = on
}
}
}
akka {
remote.netty.tcp.port=2552
remote.netty.tcp.hostname=127.0.0.1
remote.enabled-transports = ["akka.remote.netty.tcp"]
cluster {
seed-nodes = [
"akka.tcp://Api@127.0.0.1:2552"
]
auto-down-unreachable-after = 10s
}
extensions = ["akka.cluster.client.ClusterClientReceptionist"]
loglevel = DEBUG
actor {
serializer {
proto = "akka.remote.serialization.ProtobufSerializer"
}
serialization-bindings {
"com.myproject.api.common.messages.IsValidClientMessage$IsValidClient" = proto
}
serialize-messages = on
provider = "akka.cluster.ClusterActorRefProvider"
debug {
receive = on
}
}
}
package com.myproject.api.akka.actors.socket
import ...
class ClientActor extends Actor with ActorLogging {
ClusterClientReceptionist(context.system).registerService(self)
val outActors: ArrayBuffer[ActorRef] = ArrayBuffer.empty
val apiServiceClient = context.system.actorOf(ClusterClient.props(
ClusterClientSettings(context.system).withInitialContacts(Set(ActorPath.fromString("akka.tcp://ApiServiceActorSystem@127.0.0.1:2560/system/receptionist")))
))
override def receive = {
case WatchOutActor(a) =>
context.watch(a)
outActors += a
case Terminated(a) =>
context.unwatch(a)
outActors.remove(outActors.indexOf(a))
case other =>
implicit val to: Timeout = 2 seconds
val isValidClient = IsValidClient.newBuilder() // Protocol Buffer Message
isValidClient.setClientId(1000)
isValidClient.setClientSecret("notsosecret")
(apiServiceClient ? ClusterClient.Send("/user/clientActor", isValidClient.build(), false)).mapTo[Future[Either[ServiceError, Boolean]]] map { f =>
f map {
case Left(e) =>
outActors foreach { a => a ! e.msg }
case Right(bool) =>
outActors foreach { a => a ! bool.toString }
}
} recover {
case e: Exception => println(s"-=> Exception ${e.getMessage}")
}
}
}
object ClientActor {
case class WatchOutActor(actorRef: ActorRef)
}
正如我从下面的日志中看到的,我的api已连接到运行服务的群集:
[DEBUG] [08/11/2016 10:11:05.936] [ApiServiceActorSystem-akka.remote.default-remote-dispatcher-24] [akka.remote.Remoting] Associated [akka.tcp://ApiServiceActorSystem@127.0.0.1:2560] <- [akka.tcp://Api@127.0.0.1:2552]
[DEBUG] [08/11/2016 10:11:05.998] [ApiServiceActorSystem-akka.remote.default-remote-dispatcher-24] [akka.serialization.Serialization(akka://ApiServiceActorSystem)] Using serializer[akka.cluster.client.protobuf.ClusterClientMessageSerializer] for message [akka.cluster.client.ClusterReceptionist$Internal$GetContacts$]
[DEBUG] [08/11/2016 10:11:06.000] [ApiServiceActorSystem-akka.actor.default-dispatcher-4] [akka.tcp://ApiServiceActorSystem@127.0.0.1:2560/system/receptionist] Client [akka.tcp://Api@127.0.0.1:2552/user/$a] gets contactPoints [akka.tcp://ApiServiceActorSystem@127.0.0.1:2560/system/receptionist] (all nodes)
[DEBUG] [08/11/2016 10:11:06.002] [ApiServiceActorSystem-akka.actor.default-dispatcher-4] [akka.tcp://ApiServiceActorSystem@127.0.0.1:2560/system/receptionist] Client [akka.tcp://Api@127.0.0.1:2552/user/$a] gets contactPoints [akka.tcp://ApiServiceActorSystem@127.0.0.1:2560/system/receptionist] (all nodes)
[DEBUG] [08/11/2016 10:11:06.002] [ApiServiceActorSystem-akka.actor.default-dispatcher-4] [akka.tcp://ApiServiceActorSystem@127.0.0.1:2560/system/receptionist] Client [akka.tcp://Api@127.0.0.1:2552/user/$a] gets contactPoints [akka.tcp://ApiServiceActorSystem@127.0.0.1:2560/system/receptionist] (all nodes)
[DEBUG] [08/11/2016 10:11:06.002] [ApiServiceActorSystem-akka.actor.default-dispatcher-4] [akka.tcp://ApiServiceActorSystem@127.0.0.1:2560/system/receptionist] Client [akka.tcp://Api@127.0.0.1:2552/user/$a] gets contactPoints [akka.tcp://ApiServiceActorSystem@127.0.0.1:2560/system/receptionist] (all nodes)
[DEBUG] [08/11/2016 10:11:06.004] [ApiServiceActorSystem-akka.remote.default-remote-dispatcher-76] [akka.serialization.Serialization(akka://ApiServiceActorSystem)] Using serializer[akka.cluster.client.protobuf.ClusterClientMessageSerializer] for message [akka.cluster.client.ClusterReceptionist$Internal$Contacts]
[DEBUG] [08/11/2016 10:11:06.033] [ApiServiceActorSystem-akka.remote.default-remote-dispatcher-76] [akka.serialization.Serialization(akka://ApiServiceActorSystem)] Using serializer[akka.serialization.JavaSerializer] for message [akka.actor.Identify]
[DEBUG] [08/11/2016 10:11:06.037] [ApiServiceActorSystem-akka.remote.default-remote-dispatcher-24] [akka.serialization.Serialization(akka://ApiServiceActorSystem)] Using serializer[akka.serialization.JavaSerializer] for message [akka.actor.ActorIdentity]
[DEBUG] [08/11/2016 10:11:06.126] [ApiServiceActorSystem-akka.remote.default-remote-dispatcher-76] [akka.serialization.Serialization(akka://ApiServiceActorSystem)] Using serializer[akka.serialization.JavaSerializer] for message [akka.remote.EndpointWriter$AckIdleCheckTimer$]
[DEBUG] [08/11/2016 10:11:07.749] [ApiServiceActorSystem-akka.remote.default-remote-dispatcher-76] [akka.serialization.Serialization(akka://ApiServiceActorSystem)] Using serializer[akka.cluster.client.protobuf.ClusterClientMessageSerializer] for message [akka.cluster.client.ClusterReceptionist$Internal$Heartbeat$]
如何序列化我的邮件?为什么运行时会发生
ClassNotFoundException
?任何帮助都将不胜感激akka remote和protobuf 3.x生成的类似乎存在类加载问题(即使您使用proto2
定义)。可以使用protobuf 2.5编译器istead 3.x解决此问题:
您必须自己编译它,因为没有预编译的二进制文件。只需转到下载的目录并运行以下命令:
./configure
make
make install
编译v2.5protoc
binary后,使用它重新构建java类并使用它们。将在akka发行proto 3支持版
澄清:它不是
protobuf java
版本,而是由protoc
binary 3.0生成的类。您需要将Lite和V3类显式绑定到您的proto序列化程序:
akka {
loglevel = "INFO"
actor {
provider = "akka.remote.RemoteActorRefProvider"
serializers {
proto = "akka.remote.serialization.ProtobufSerializer" # or use your own..
}
serialization-bindings {
"com.google.protobuf.Message" = proto
"com.google.protobuf.GeneratedMessageLite" = proto
"com.google.protobuf.GeneratedMessageV3" = proto
}
}
代码中可能有两个问题:1。已编译的protobuf不在客户端和服务器中,或者2。由于java scala互操作性非常棘手,您可能会发现protobuf无法正确解析定义消息协议的对象内的case类。您使用哪个protobuf java库版本?@frank_neff其2.6.1Akka 2.4.x在内部使用protobuf 2.5的着色版本,这不应干扰您自己的协议Protobuf3.x依赖项。您是否已将3.x运行时依赖项添加到项目中?我已将运行时依赖项添加到3.0.0。这不是java库,而是protoc编译器v2(works)v3(ClassNotFoundException)生成的类。我也遇到了同样的问题
./configure
make
make install
akka {
loglevel = "INFO"
actor {
provider = "akka.remote.RemoteActorRefProvider"
serializers {
proto = "akka.remote.serialization.ProtobufSerializer" # or use your own..
}
serialization-bindings {
"com.google.protobuf.Message" = proto
"com.google.protobuf.GeneratedMessageLite" = proto
"com.google.protobuf.GeneratedMessageV3" = proto
}
}