3

我们正在考虑使用 Akka 进行客户端服务器通信,并尝试对数据传输进行基准测试。目前我们正在尝试发送一百万条消息,其中每条消息都是一个包含 8 个字符串字段的案例类。

在这一点上,我们正在努力获得可接受的性能。我们在客户端和服务器上看到大约 600KB/s 的传输速率和空闲 CPU,所以出现了问题。也许这是我们的网络配置。

这是我们的 akka 配置

Server {
  akka {
    extensions = ["akka.contrib.pattern.ClusterReceptionistExtension"]
    loggers = ["akka.event.slf4j.Slf4jLogger"]
    loglevel = "DEBUG"
    logging-filter = "akka.event.slf4j.Slf4jLoggingFilter"
    log-dead-letters = 10
    log-dead-letters-during-shutdown = on
    actor {
      provider = "akka.cluster.ClusterActorRefProvider"
    }
    remote {
      enabled-transports = ["akka.remote.netty.tcp"]
      netty.tcp {
        hostname = "instance.myserver.com"
        port = 2553
        maximum-frame-size = 1000 MiB
        send-buffer-size = 2000 MiB
        receive-buffer-size = 2000 MiB
      }
    }
    cluster {
      seed-nodes = ["akka.tcp://server@instance.myserver.com:2553"]

      roles = [master]
    }
    contrib.cluster.receptionist {
      name = receptionist
      role = "master"
      number-of-contacts = 3
      response-tunnel-receive-timeout = 300s
    }
  }

}

Client {
  akka {
    loggers = ["akka.event.slf4j.Slf4jLogger"]
    loglevel = "DEBUG"
    logging-filter = "akka.event.slf4j.Slf4jLoggingFilter"
    actor {
      provider = "akka.remote.RemoteActorRefProvider"
    }
    remote {
      enabled-transports = ["akka.remote.netty.tcp"]
      netty.tcp {
        hostname = "127.0.0.1"
        port = 0
        maximum-frame-size = 1000 MiB
        send-buffer-size = 2000 MiB
        receive-buffer-size = 2000 MiB
      }
    }
    cluster-client {
      initial-contacts = ["akka.tcp://server@instance.myserver.com:2553/user/receptionist"]
      establishing-get-contacts-interval = "10s"
      refresh-contacts-interval = "10s"
    }
  }

}

更新:

最后,尽管讨论了序列化(见下文),但我们只是将有效负载转换为使用字节数组,这样序列化不会影响测试。我们发现在核心 i7 上使用 jeroMQ(即 zeroMQ 在 java 中重新实现 - 所以仍然不是最快的),在原始 akka 上我们始终看到大约 200k msgs/sec 或大约 20 MB/sec(即没有 zeroMQ 插件)我们看到大约 10k 消息/秒或略低于 1MB/秒。尝试使用 akka + zeroMQ 会使性能变差。

4

2 回答 2

4

为了使远程处理更容易,akka 使用 Java 序列化进行消息序列化,这不是您通常在生产中使用的,因为它不是很快并且不能很好地处理消息版本控制。

您应该做的是使用 kryo 或 protobuf 进行序列化,您应该能够获得更好的数字。

您可以在此处阅读有关如何使用的信息,页面底部还有一些指向可用序列化程序的链接:http: //doc.akka.io/docs/akka/current/scala/serialization.html

于 2015-08-18T08:02:42.167 回答
0

好的,这是我们发现的:

使用我们的客户端服务器模型,我们能够在不做任何事情的情况下获得大约 < 3000 msg/sec,这对我们来说是无法接受的,但我们真的对正在发生的事情感到困惑,因为我们无法最大化 CPU。

因此,我们回到 akka 源代码并在那里找到了一个基准测试示例:

sample.remote.benchmark.Receiver

sample.remote.benchmark.Sender

这两个类使用akka remote 来ping自己一堆来自同一台机器上的两个jvm的消息。使用这个基准,我们能够在 24g 的 corei7 上获得大约 10~15k msg/sec,使用大约 50% 的 cpu。我们发现调整分配给 netty 的调度程序和线程会有所不同,但只是很小。使用询问而不是告诉,让它变慢了一点,但不是很多。使用由许多参与者组成的平衡池来发送和接收会大大降低速度。

为了进行比较,我们使用 jeromq 进行了类似的测试,我们设法使用 100% CPU(相同的有效负载,相同的机器)获得了大约 100k msg/sec。

我们还破解了 Sender 和 Receivers 以使用 Akka zeromq 扩展将消息直接从一个 jvm 传递到另一个绕过 akka 远程。在这个测试中,我们发现我们可以开始快速发送和接收,大约 100k msg/sec,但性能很快下降。在进一步检查中,zeromq 线程和 akka actor 切换不能很好地结合在一起。我们可能可以通过更智能地处理 zeromq 和 akka 的交互方式来调整性能,但那时我们决定使用 raw zeromq 会更好。

结论:如果您关心通过网络快速序列化大量数据,请不要使用 akka。

于 2015-08-17T10:06:35.847 回答