提高Akka远程吞吐量

时间:2015-08-06 16:11:26

标签: akka netty throughput akka-remote-actor

我们正在考虑使用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"
    }
  }

}

更新:

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

2 个答案:

答案 0 :(得分:4)

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

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

您可以在此处了解如何在页面底部找到可用序列化程序的一些链接:http://doc.akka.io/docs/akka/current/scala/serialization.html

答案 1 :(得分:0)

好的,这是我们发现的:

使用我们的客户端服务器模型,我们能够得到< 3000毫秒/秒没有做任何事情,这对我们来说是不可接受的,但我们真的很困惑发生的事情,因为我们无法最大化cpu。

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

sample.remote.benchmark.Receiver

sample.remote.benchmark.Sender

这两个类使用akka远程从同一台机器上的两个jvms中ping出一堆消息。使用这个基准测试,我们可以在corei7上以24g获得大约10~15k msg / sec,使用大约50%的cpu。我们发现调整分配给netty的调度程序和线程有所不同,但只是略有不同。使用问题而不是告诉,使它有点慢,但不是很多。使用许多演员的平衡池发送和接收使它变得相当慢。

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

我们还攻击了Sender和Receivers,使用Akka zeromq扩展将消息从一个jvm直接传送到另一个jvm,同时绕过akka remote。在这个测试中,我们发现我们可以快速发送和接收,大约100k msg / sec,但性能很快降低。在进一步检查时,zeromq线程和akka actor切换不能很好地协同工作。我们可能通过更聪明地调整zeromq和akka如何相互作用来调整性能,但在那时我们认为最好使用原始的zeromq。

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