Самый быстрый надежный способ для приложений 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, чтобы ваш пробег мог меняться).