Самый быстрый надежный способ для приложений Clojure (Java) и Ruby для связи

У нас есть облачные (RackSpace cloud) приложения Ruby и Java, которые будут взаимодействовать следующим образом:

  • Приложение Ruby отправляет запрос в приложение Java. Запрос состоит из структуры карты, содержащей строки, целые числа, другие карты и списки (аналогичные JSON).
  • Java-приложение анализирует данные и отправляет ответ в приложение Ruby.

Мы заинтересованы в оценке как форматов обмена сообщениями (JSON, Буферные протоколы, Thrift и т.д.), а также каналы/методы передачи сообщений (сокеты, очереди сообщений, RPC, REST, SOAP и т.д.)

Наши критерии:

  • Короткое время прохождения в оба конца.
  • Стандартное отклонение с минимальным временем прохождения в оба конца. (Мы понимаем, что паузы в сборке мусора и всплески использования сети могут повлиять на это значение).
  • Высокая доступность.
  • Масштабируемость (мы можем захотеть, чтобы в будущем несколько экземпляров приложения Ruby и Java заменяли сообщения "точка-точка" ).
  • Простота отладки и профилирования.
  • Хорошая документация и поддержка сообщества.
  • Бонусные баллы для поддержки Clojure.
  • Хорошая поддержка динамического языка.

Какую комбинацию формата сообщения и метода передачи вы бы порекомендовали? Почему?

Я собрал здесь некоторые материалы, которые мы уже собрали для обзора:

Ответы

Ответ 1

Мы решили перейти BSON через RabbitMQ.

Нам нравится поддержка BSON для гетерогенных коллекций и отсутствие необходимости указывать формат сообщений вверх. Мы не против, что у этого есть плохие характеристики использования пространства и, вероятно, более низкая производительность сериализации, чем другие форматы сообщений, так как часть сообщений в нашем приложении не является узким местом. Не похоже, что хороший интерфейс Clojure был написан, чтобы вы могли напрямую манипулировать объектами BSON, но, надеюсь, это не будет проблемой. Я пересмотрю эту запись, если мы определим, что BSON не сработает для нас.

Мы выбрали RabbitMQ главным образом потому, что у нас уже есть опыт работы с ним и используем его в системе, которая требует высокой пропускной способности и доступности.

Если обмен сообщениями становится узким местом, мы сначала посмотрим на BERT (мы его отвергли, потому что в настоящее время он не поддерживает Java), а затем MessagePack (отклонено, поскольку, похоже, не существует большого сообщества Java разработчики используют его), затем в Avro (отклоняется, потому что для этого требуется, чтобы вы определили формат своего сообщения вперед), затем Буферы протокола (отклоненные из-за дополнительного этапа генерации кода и отсутствия гетерогенных коллекций), а затем Thrift (отклонено по причинам для протокольных буферов).

Мы можем пойти с простой схемой RPC, а не с помощью очереди сообщений, так как наш стиль обмена сообщениями по существу является синхронным двухточечным.

Спасибо за ваш вклад!

Обновление: здесь project.clj и core.clj, который показывает, как преобразовать карты Clojure в 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)))))

Ответ 2

Я не могу говорить из личного опыта, но я знаю, что Flightcaster использует обмен сообщениями JSON для связывания своего back-end механизма clojure analytics с внешним интерфейсом Rails и, похоже, работает для них. Здесь статья (появляется ближе к концу):

Clojure и Rails - секретный соус за FlightCaster

Надеюсь, это поможет. --Mike

Ответ 3

У меня нет опыта в этом отношении. В любом случае я опубликую эту полезную догадку.

  • ZeroMQ предлагает двухточечную передачу сообщений, в том числе с различными типами сетевых топологий. Сообщения состоят из произвольных двоичных значений, поэтому для ваших структурированных сообщений вам понадобится формат двоичной сериализации.

  • BSON, ProtoBuffers, и BERT предлагают сериализацию произвольных структур данных (числа, строки, последовательные массивы, ассоциативные массивы) в двоичные значения.

GitHub изобрел BERT для быстрого RCP; BSON была изобретена MongoDB (или 10gen) по той же причине; и ProtoBuffers аналогично Google.

Ответ 4

Я считаю, что протокольные буферы будут намного быстрее и эффективнее, чем JSON (последний раз, когда я проверял, он был примерно в 40 раз быстрее, я не пытался его использовать ruby ​​tho, чтобы ваш пробег мог меняться).