2011-07-04 10 views
5

Estoy desarrollando una aplicación multiproceso con Node.js. En esta aplicación, un proceso principal generará un proceso secundario y se comunicará con él utilizando un protocolo de mensajería basado en JSON sobre una tubería. Descubrí que los mensajes JSON grandes pueden "cortarse", de modo que un único "fragmento" emitido al oyente de datos en el conducto no contiene el mensaje JSON completo. Además, los pequeños mensajes JSON se pueden agrupar en el mismo fragmento. Cada mensaje JSON estará delimitado por un carácter de nueva línea, por lo que me pregunto si ya existe una utilidad que almacenará en búfer el flujo de lectura de canal de modo que emita una línea a la vez (y, por lo tanto, para mi aplicación, un documento JSON a la vez). Parece que sería un caso de uso bastante común, así que me pregunto si ya se hizo.Flujos orientados a la línea en Node.js

Agradecería cualquier orientación que cualquiera pueda ofrecer. Gracias.

+0

¿Ha pensado usar sólo buena HTTP de edad ? ¿Por qué estás inventando un nuevo protocolo IPC? El envío de mensajes JSON a través de HTTP es un problema resuelto, y el nodo es excelente en HTTP. –

+0

¿Podría describir cómo lo haría con HTTP?En este momento, no veo cómo esto cambiaría la naturaleza del problema, ya que creo que aún estaría leyendo fragmentos de una transmisión. – jbeard4

+0

Codifica el proceso hijo como un servidor HTTP node.js normal. La capacidad de aceptar y enviar mensajes JSON es proporcionada por el middleware bodyParser express.js/connect.js. https://github.com/senchalabs/connect/blob/master/lib/middleware/bodyParser.js. Esto maneja los fragmentos en el modo estándar node.js conducido por evento. No es necesario reinventar este mecanismo. –

Respuesta

4

¿Quizás Pedro carrier puede ayudarlo?

Carrier lo ayuda a implementar protocolos terminados de nueva línea en node.js.

El cliente puede enviarle trozos de líneas y la empresa de transporte solo le notificará en cada línea completa.

1

solución más simple es enviar longitud de datos JSON antes de cada mensaje como de longitud fija prefijo (4 bytes?) Y tienen un analizador simple un-encuadre que amortigua pequeños trozos o divide los más grandes.

Puede intentar node-binary para evitar escribir el analizador manualmente. Mire el ejemplo de documentación scan(key, buffer) - hace exactamente línea por línea leyendo.

2

Mi solución a este problema es enviar mensajes JSON cada uno terminado con algún carácter especial de Unicode. Un personaje que normalmente nunca obtendrías en la cadena JSON. Llámalo TERM.

Así que el remitente simplemente hace "JSON.stringify (mensaje) + TERM;" y lo escribe. El receptor divide los datos entrantes en TERM y analiza las partes con JSON.parse(), que es bastante rápido. El truco es que el último mensaje puede no analizarse, así que simplemente guardamos ese fragmento y lo agregamos al comienzo del siguiente mensaje cuando se trata. Recibiendo código es la siguiente:

 s.on("data", function (data) { 
     var info = data.toString().split(TERM); 
     info[0] = fragment + info[0]; 
     fragment = ''; 

     for (var index = 0; index < info.length; index++) { 
      if (info[index]) { 
       try { 
        var message = JSON.parse(info[index]); 
        self.emit('message', message); 
       } catch (error) { 
        fragment = info[index]; 
        continue; 
       } 
      } 
     } 
    }); 

Donde "fragmento" se define somwhere donde persistirá entre fragmentos de datos.

Pero, ¿qué es TERM? He usado el carácter de reemplazo Unicode '\ uFFFD'. También se podría usar la técnica utilizada por twitter donde los mensajes están separados por '\ r \ n' y los tweets usan '\ n' para las nuevas líneas y nunca contienen '\ r \ n'

Me parece mucho más simple que jugar con incluir longitudes y cosas por el estilo.

0

Mientras saltos de línea (o cualquier delimitador que usa) sólo delimitar los mensajes JSON y no estar incrustados en ellos, puede utilizar el siguiente patrón:

const buf = '' 
s.on('data', data => { 
    buf += data.toString() 
    const idx = buf.indexOf('\n') 
    if (idx < 0) { return } // No '\n', no full message 
    let lines = buf.split('\n') 
    buf = lines.pop() // if ends in '\n' then buf will be empty 
    for (let line of lines) { 
    // Handle the line 
    } 
}) 
Cuestiones relacionadas