Scala 无法从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 {

我正在尝试使用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 {
    
        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配置运行Play应用程序:

    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
        }
      }
    }
    
  • 这是我一直试图向ApiServiceSystem发送消息的代码:

    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.5
    protoc
    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
        }
      }