Clojure(Java)和Ruby应用程序通信的最快可靠方式

Clojure(Java)和Ruby应用程序通信的最快可靠方式,java,ruby,clojure,messaging,network-protocols,Java,Ruby,Clojure,Messaging,Network Protocols,我们有云托管(RackSpace cloud)Ruby和Java应用程序,它们将按如下方式交互: Ruby应用程序向Java应用程序发送请求。请求由包含字符串、整数、其他映射和列表(类似于JSON)的映射结构组成 Java应用程序分析数据并向Ruby应用程序发送回复 我们对评估两种消息格式(JSON等)以及消息传输通道/技术(套接字、消息队列、RPC、REST、SOAP等)感兴趣 我们的标准: 往返时间短 低往返时间标准差。(我们知道垃圾收集暂停和网络使用高峰会影响此值) 高可用性 可伸缩性(我

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

  • Ruby应用程序向Java应用程序发送请求。请求由包含字符串、整数、其他映射和列表(类似于JSON)的映射结构组成
  • Java应用程序分析数据并向Ruby应用程序发送回复
  • 我们对评估两种消息格式(JSON等)以及消息传输通道/技术(套接字、消息队列、RPC、REST、SOAP等)感兴趣

    我们的标准:

  • 往返时间短
  • 低往返时间标准差。(我们知道垃圾收集暂停和网络使用高峰会影响此值)
  • 高可用性
  • 可伸缩性(我们可能希望将来有多个Ruby和Java应用程序实例交换点对点消息)
  • 易于调试和分析
  • 良好的文档和社区支持
  • Clojure支持的额外积分
  • 良好的动态语言支持
  • 您会推荐什么样的消息格式和传输方式组合?为什么?

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


    我相信协议缓冲区将比JSON快得多,效率也更高(上次我检查它的速度大约是JSON的40倍,我没有用ruby tho尝试它,所以您的里程数可能会有所不同)

    根据个人经验,我无法发言,但我知道Flightcaster正在使用JSON消息将其后端clojure分析引擎链接到前端Rails应用程序,而且似乎对他们有效。以下是文章(出现在结尾处):

    希望这有帮助。
    --迈克

    我在这方面没有经验。我将张贴这可能有帮助的猜测无论如何

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

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


    GitHub发明了用于快速RCP的BERT;BSON是由MongoDB(或10gen)出于同样的原因发明的;谷歌也同样如此。

    我们决定继续

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

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

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

    我们可能希望使用普通RPC方案,而不是使用消息队列,因为我们的消息传递风格本质上是同步的点对点

    谢谢大家的意见

    更新:这里是
    项目.clj
    核心.clj
    ,展示了如何将Clojure映射转换为BSON和BSON:

    ;;;; project.clj (defproject bson-demo "0.0.1" :description "BSON Demo" :dependencies [[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"]] :main core) ;;;; core.clj (ns core (:gen-class) (:import [org.bson BasicBSONObject BSONEncoder BSONDecoder])) (defonce *encoder* (BSONEncoder.)) (defonce *decoder* (BSONDecoder.)) ;; XXX Does not accept keyword arguments. Convert clojure.lang.Keyword in map to java.lang.String first. (defn map-to-bson [m] (->> m (BasicBSONObject.) (.encode *encoder*))) (defn bson-to-map [^BasicBSONObject b] (->> (.readObject *decoder* b) (.toMap) (into {}))) (defn -main [] (let [m {"foo" "bar"}] (prn (bson-to-map (map-to-bson m))))) ;;;; project.clj (defproject bson演示“0.0.1” :说明“BSON演示” :依赖项[[org.clojure/clojure“1.2.0”] [org.clojure/clojure-contrib“1.2.0”] [org.mongodb/mongo-java-driver“2.1”]] :开发依赖项[[swank clojure“1.3.0-SNAPSHOT”]] :主磁芯) ;;;; core.clj (ns核心 (:gen类) (:导入[org.bson basicbonobject bsonecoder BSONDecoder])) (defonce*编码器*(BSONECODER.)) (defonce*解码器*(BSONDecoder.)) ;; XXX不接受关键字参数。首先将映射中的clojure.lang.Keyword转换为java.lang.String。 (定义映射到bson[m] (>>m(基本对象)(.encode*encoder*)) (定义为映射[^BasicBonObject b] (>>(.readObject*解码器*b)(.toMap)(到{}))) (defn-main[] (让[m{“foo”“bar}]
    (prn(bson to map(map to bson m‘‘‘‘)’)编辑:protobuff vs JSON在我的例子中,但它当时没有使用Jackson(我想我使用的是jsonlib),protobuff java lib从那时起一定也在发展。网络RTT通常会占主导地位,负载大小才是真正重要的。Gzip JSON在大小上与协议缓冲区相当,所以我认为两者都可以。好文章。事实证明,我的队友已经非常熟悉该用例了^ ^我不确定这里描述的Ruby/Clojure互操作是否是关键速度敏感路径的一部分。你真的想要可靠性(从标题上看)?在您所讨论的消息传递类别的上下文中,这意味着消息永远不会丢失(也可能是按照发送顺序发送),这是非常昂贵的。当然,这里的可靠性指的是抵抗反铲攻击(即网络或电力基础设施的物理破坏)。我更喜欢及时交付,让应用程序更具抵抗力