2010-12-17 10 views
14

Tenemos aplicaciones (RackSpace nube) Ruby y Java alojados en la nube que interactuarán de la siguiente manera:manera rápida y confiable para Clojure (Java) y Ruby aplicaciones para comunicarse

  1. Rubí aplicación envía una solicitud a Java aplicación. La solicitud consiste en una estructura de mapa que contiene cadenas, enteros, otros mapas y listas (análoga a JSON).
  2. La aplicación Java analiza los datos y envía una respuesta a la aplicación Ruby.

Estamos interesados ​​en la evaluación de ambos formatos de mensajería (JSON, Buffer Protocols, Thrift, etc.), así como canales de transmisión de mensajes/técnicas (enchufes, colas de mensajes, RPC, REST, SOAP, etc.)

Nuestros criterios:

  1. corto tiempo de ida y vuelta.
  2. Baja desviación estándar del tiempo de ida y vuelta. (Entendemos que las pausas de recolección de basura y los picos de uso de la red pueden afectar este valor).
  3. Alta disponibilidad.
  4. Escalabilidad (es posible que deseemos tener varias instancias de la aplicación Ruby y Java intercambiando mensajes punto a punto en el futuro).
  5. Facilidad de depuración y creación de perfiles.
  6. Buena documentación y apoyo de la comunidad.
  7. Puntos de bonificación para el soporte de Clojure.
  8. Soporte de buen lenguaje dinámico.

¿Qué combinación de formato de mensaje y método de transmisión recomendaría? ¿Por qué?

que he reunido aquí algunos materiales que ya hemos recogido para su revisión:

+0

Está seguro de querer fiabilidad (del título)? En el contexto de la clase de mensajes de la que está hablando, significa que los mensajes nunca se pierden (y posiblemente también que se entreguen en el orden en que se enviaron), lo cual es * muy * costoso. Por supuesto, la fiabilidad aquí se refiere a ser resistente incluso contra cosas como un ataque de retroexcavadora (es decir, la destrucción física de la red o la infraestructura de energía). En su mayoría prefiero tener una entrega oportuna y hacer que las aplicaciones sean resistentes a las fallas, porque eso es mucho más fácil ... –

+0

Hola, queremos una confiabilidad razonablemente buena y no nos importa la entrega en pedido. Nuestro sistema puede tolerar fallas ocasionales, aunque es importante mantener la tasa de fallas bastante baja. – jkndrkn

Respuesta

3

Hemos decidido ir con BSON sobre RabbitMQ.

Nos gusta el soporte de BSON para colecciones heterogéneas y la falta de la necesidad de especificar el formato de los mensajes por adelantado.No nos importa que tenga unas características de uso de espacio pobres y un rendimiento de serialización probablemente inferior al de otros formatos de mensaje, ya que no se prevé que la parte de mensajería de nuestra aplicación sea el cuello de botella. No parece que se haya escrito una buena interfaz Clojure para permitirle manipular objetos BSON directamente, pero espero que eso no sea un problema. Revisaré esta entrada si decidimos que BSON no funcionará para nosotros.

Elegimos RabbitMQ principalmente porque ya tenemos experiencia y lo estamos usando en un sistema que exige un alto rendimiento y disponibilidad.

Si los mensajes se convierten en un cuello de botella, primero buscaremos BERT (lo rechazamos porque actualmente no parece tener soporte de Java), luego a MessagePack (rechazado porque parece que no hay una gran comunidad de Desarrolladores de Java que lo usan), luego a Avro (rechazado porque requiere que defina su formato de mensaje por adelantado), luego Buffers de Protocolo (rechazados debido al paso de generación de código adicional y la falta de colecciones heterogéneas) y luego Thrift (rechazado por el razones mencionadas para los Protocolos de Protocolos).

Es posible que deseemos utilizar un esquema RPC simple en lugar de utilizar una cola de mensajes, ya que nuestro estilo de mensajería es esencialmente sincrónico punto a punto.

Gracias por su contribución a todos!

Actualización: Aquí es el project.clj y core.clj que muestra cómo convertir mapas de Clojure a BSON y Fondo:

;;;; 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)))))
1

creo Protocolo-buffers serían mucho más rápido y más eficiente que JSON (última vez que lo comprobé que era alrededor de 40 veces más rápido, Yo no probarlo con el rubí aunque por lo que su experiencia puede variar).

+0

40 veces más rápido que qué? – jkndrkn

+0

edited: ProtoBuffs vs JSON en mi caso, pero no estaba usando Jackson en aquel entonces (creo que usé jsonlib) y el protobuff java lib también debe haber evolucionado desde entonces. – mpenet

+0

RTT de red generalmente dominará y el tamaño de la carga es lo que realmente importa. Gzipped JSON es comparable en tamaño a los búferes de protocolo, por lo que creo que cualquiera está bien. – Kevin

2

No puedo hablar por experiencia personal, pero sé que Flightcaster está utilizando mensajes JSON para vincular su motor de análisis clojure de back-end a una aplicación front-end de Rails y parece funcionar para ellos. Aquí está (aparece cerca del final) del artículo:

Clojure and Rails - the Secret Sauce Behind FlightCaster

Espero que esto ayude. --Mike

+0

Hola Mike. Buen articulo. Resulta que mis compañeros de equipo ya están muy familiarizados con ese caso de uso^_^No estoy seguro si la interoperabilidad de Ruby/Clojure descrita allí es parte de un camino crítico sensible a la velocidad. – jkndrkn

2

No tengo experiencia en este sentido. Voy a publicar esta conjetura posiblemente útil de todos modos.

  • ZeroMQ ofrece mensajería punto a punto, incluso con varios tipos de topologías de red. Los mensajes consisten en valores binarios arbitrarios, por lo que solo necesitará un formato de serialización binario para sus mensajes estructurados.

  • BSON, ProtoBuffers y BERT oferta serialización de las estructuras arbitrarias de datos (números, cadenas, matrices secuenciales, arrays asociativos) en valores binarios.

GitHub inventó BERT para RCP rápido; BSON fue inventado por MongoDB (o 10gen) por la misma razón; y ProtoBuffers también por Google.

+0

Gracias, ya empleamos RabbitMQ en el sistema y podemos considerar simplemente usar eso en lugar de una solución RPC para enviar mensajes. Hasta ahora, parece que vamos a ir con Apache Thrift, Protocol Buffers o MessagePack para la serialización. Apache Avro es otra posibilidad. – jkndrkn

+0

Si ya tiene un bus de mensajes como RabbitMQ implementado, entonces podría tener sentido volver a usarlo cuando necesite mensajes. De lo contrario, ZeroMQ podría tener sentido porque podría ser más simple de implementar: es una biblioteca para mensajes directos que usted usa desde los componentes de su aplicación, y no requiere desplegar ninguna infraestructura separada. Estoy agregando este comentario en caso de que alguien más tenga la misma pregunta, pero no tiene implementado RabbitMQ. – yfeldblum

Cuestiones relacionadas