【问题标题】:Fastest reliable way for Clojure (Java) and Ruby apps to communicateClojure (Java) 和 Ruby 应用程序进行通信的最快可靠方式
【发布时间】:2011-05-27 07:00:00
【问题描述】:

我们有云托管(RackSpace 云)Ruby 和 Java 应用程序,它们的交互方式如下:

  1. Ruby 应用程序向 Java 应用程序发送请求。请求由包含字符串、整数、其他映射和列表(类似于 JSON)的映射结构组成。
  2. Java 应用分析数据并向 Ruby 应用发送回复。

我们有兴趣评估两种消息格式(JSON、Buffer ProtocolsThrift 等)以及消息传输通道/技术(套接字、消息队列、RPC、REST、SOAP 等)

我们的标准:

  1. 往返时间短。
  2. 低往返时间标准偏差。 (我们知道垃圾收集暂停和网络使用高峰会影响此值)。
  3. 高可用性。
  4. 可扩展性(我们可能希望将来有多个 Ruby 和 Java 应用程序实例交换点对点消息)。
  5. 易于调试和分析。
  6. 良好的文档和社区支持。
  7. Clojure 支持的奖励积分。
  8. 良好的动态语言支持。

您会推荐哪种消息格式和传输方式的组合?为什么?

我在这里收集了一些我们已经收集的材料以供审查:

【问题讨论】:

  • 你真的想要可靠性吗(从标题)?在您正在谈论的消息传递类的上下文中,这意味着消息永远不会丢失(并且可能还按照发送顺序传递),这是非常昂贵的。当然,这里的可靠性是指能够抵抗反铲攻击(即网络或电力基础设施的物理破坏)。我更喜欢及时交付并使应用程序能够抵抗故障,因为这更容易......
  • 您好,我们想要相当好的可靠性并且不关心按订单交付。我们的系统可以容忍偶尔的故障,但保持相当低的故障率很重要。

标签: java ruby clojure messaging network-protocols


【解决方案1】:

我们决定选择BSON 而不是RabbitMQ

我们喜欢 BSON 对异构集合的支持,并且不需要预先指定消息的格式。我们不介意它具有较差的空间使用特性,并且可能比其他消息格式更差的序列化性能,因为我们应用程序的消息传递部分预计不会成为瓶颈。它看起来不像是编写了一个很好的 Clojure 接口来让您直接操作 BSON 对象,但希望这不会成为问题。如果我们认为 BSON 不适合我们,我将修改此条目。

我们选择 RabbitMQ 主要是因为我们已经拥有使用它的经验,并且正在将它用于需要高吞吐量和可用性的系统中。

如果消息传递确实成为瓶颈,我们将首先关注 BERT(我们拒绝它,因为它目前似乎不支持 Java),然后是 MessagePack(拒绝,因为它似乎没有一个大型的 Java 社区开发人员使用它),然后是 Avro(被拒绝,因为它需要您预先定义消息格式),然后是 Protocol Buffers(因为额外的代码生成步骤和缺乏异构集合而被拒绝),然后是 Thrift(被拒绝的原因是提到了协议缓冲区)。

我们可能希望使用简单的 RPC 方案而不是使用消息队列,因为我们的消息传递方式本质上是同步的点对点。

感谢大家的意见!

更新:这里是 project.cljcore.clj,它们展示了如何将 Clojure 映射转换为 BSON 并返回:

;;;;项目.clj (defproject bson-demo "0.0.1" :description "BSON 演示" : 依赖 [[org.clojure/clojure "1.2.0"] [org.clojure/clojure-contrib “1.2.0”] [org.mongodb/mongo-java-driver "2.1"]] :dev-dependencies [[swank-clojure "1.3.0-SNAPSHOT"]] :主核心) ;;;;核心.clj (ns核心 (:gen-class) (:import [org.bson BasicBSONObject BSONEncoder BSONDecoder])) (defonce *encoder* (BSONEncoder.)) (defonce *decoder* (BSONDecoder.)) ;; XXX 不接受关键字参数。首先将map中的clojure.lang.Keyword转换为java.lang.String。 (defn map-to-bson [m] (->> m (BasicBSONObject.) (.encode *encoder*))) (defn bson-to-map [^BasicBSONObject b] (->> (.readObject *decoder* b) (.toMap) (into {}))) (定义-main [] (让 [m {"foo" "bar"}] (prn (bson-to-map (map-to-bson m)))))

【讨论】:

    【解决方案2】:

    我不能根据个人经验说话,但我知道 Flightcaster 正在使用 JSON 消息传递将他们的后端 clojure 分析引擎链接到前端 Rails 应用程序,而且它似乎对他们有用。这是文章(出现在结尾处):

    Clojure and Rails - the Secret Sauce Behind FlightCaster

    希望这会有所帮助。 --迈克

    【讨论】:

    • 嗨,迈克。不错的文章。原来我的队友已经非常熟悉这个用例了^_^我不确定所描述的 Ruby/Clojure 互操作是否是关键速度敏感路径的一部分。
    【解决方案3】:

    我没有这方面的经验。无论如何,我会发布这个可能有用的猜测。

    • ZeroMQ 提供点对点消息传递,包括各种类型的网络拓扑。消息由任意二进制值组成 - 因此您只需要结构化消息的二进制序列化格式。

    • BSONProtoBuffersBERT 提供将任意数据结构(数字、字符串、顺序数组、关联数组)序列化为二进制值。

    GitHub 为快速 RCP 发明了 BERT;出于同样的原因,BSON 是由 MongoDB(或 10gen)发明的;和 Google 的 ProtoBuffers。

    【讨论】:

    • 谢谢,我们已经在系统中使用了 RabbitMQ,并且可以考虑简单地使用它而不是 RPC 解决方案进行消息传递。到目前为止,看起来我们将使用 Apache Thrift、Protocol Buffers 或 MessagePack 进行序列化。 Apache Avro 是另一种可能性。
    • 如果您已经部署了像 RabbitMQ 这样的消息总线,那么在需要消息传递时重新使用它可能是有意义的。否则,ZeroMQ 可能有意义,因为它可能更易于部署:它是一个用于直接消息传递的库,您可以在应用程序的组件中使用它,并且不需要部署任何单独的基础架构。我添加此评论以防其他人有同样的问题,但没有部署 RabbitMQ。
    【解决方案4】:

    我相信 Protocol-buffers 会比 JSON 更快、更有效(上次我检查它的速度大约快 40 倍,但我没有用 ruby​​ 尝试它,所以你的里程可能会有所不同)。

    【讨论】:

    • 已编辑:就我而言,ProtoBuffs vs JSON,但当时并没有使用 Jackson(我想我使用了 jsonlib),并且从那时起 protobuff java lib 也必须发展。
    • 网络 RTT 通常占主导地位,有效负载大小才是真正重要的。 Gzipped JSON 在大小上与协议缓冲区相当,所以我认为两者都可以。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-17
    • 2015-09-03
    • 2013-05-15
    相关资源
    最近更新 更多