Pregunta

Mientras leía el tutorial Netty, he encontrado un simple descripción de cómo integrar a Netty y Buffers de protocolo de Google. Comencé a investigar su ejemplo (porque no hay más información en la documentación) y escribí una aplicación simple como la aplicación de hora local. Pero este ejemplo está utilizando la inicialización estática en la clase de factor de pipe, por ejemplo:

import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;

import static org.jboss.netty.channel.Channels.pipeline;

/**
 * @author sergiizagriichuk
 */
class ProtoCommunicationClientPipeFactory implements ChannelPipelineFactory {

    public ChannelPipeline getPipeline() throws Exception {
        ChannelPipeline p = pipeline();
        p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
        p.addLast("protobufDecoder", new ProtobufDecoder(Communication.DataMessage.getDefaultInstance()));

        p.addLast("frameEncoder", new ProtobufVarint32LengthFieldPrepender());
        p.addLast("protobufEncoder", new ProtobufEncoder());

        p.addLast("handler", new ProtoCommunicationClientHandler());
        return p;
    }

}

(Por favor, eche un vistazo a la línea p.addLast("protobufDecoder", new ProtobufDecoder(Communication.DataMessage.getDefaultInstance()));) y solo se puede crear una fábrica (como entiendo) para ClientBootstrap clase, quiero decir bootstrap.setPipelineFactory() método. Entonces, en esta situación puedo usar UNA mensaje para enviar al servidor y UNA mensaje para recibir del servidor y es malo para mí, y creo que no solo para mí :( ¿Cómo puedo usar diferentes mensajes hacia y desde una sola conexión? Quizás pueda crear algunos protobufDecoder como esto

p.addLast("protobufDecoder", new ProtobufDecoder(Communication.DataMessage.getDefaultInstance()));
p.addLast("protobufDecoder", new ProtobufDecoder(Communication.TestMessage.getDefaultInstance()));
p.addLast("protobufDecoder", new ProtobufDecoder(Communication.SrcMessage.getDefaultInstance()));

u otras técnicas? Muchas gracias.

¿Fue útil?

Solución

He encontrado hilo de autor de Netty en grupos de Google y entendí que tengo que cambiar mi arquitectura o escribir mi propio decodificador como escribí anteriormente, así que comience a pensar de qué manera será fácil y mejor.

Otros consejos

Si va a escribir sus propios códecs de todos modos, es posible que desee considerar la implementación de la interfaz externalizable para objetos de datos personalizados.

  • Serializable es un bajo esfuerzo, pero el peor rendimiento (serializa todo).
  • ProtoBuf es una buena compensación entre el esfuerzo y el rendimiento (requiere.
  • Externalizable es un alto esfuerzo, pero el mejor rendimiento (códecs mínimos personalizados)

Si ya sabe que su proyecto tendrá que escalar como una cabra de montaña, es posible que tenga que seguir el camino duro. ProtoBuf no es una bala de plata.

Teóricamente, esto se puede hacer modificando la tubería para cada mensaje entrante para adaptarse al mensaje entrante. Echa un vistazo al unificación de puerto Ejemplo en Netty.

La secuencia sería:
1) En el decodificador de cuadro u otro "decodermaping Decoder", verifica el tipo de mensaje del mensaje entrante
2) Modifique la tubería dinámicamente como se muestra en el ejemplo

Pero, ¿por qué no usar diferentes conexiones y seguir esta secuencia:
1) Agregue otros decodificadores en la tubería en función del mensaje entrante solo una vez.
2) Agregue el mismo Instancia del controlador aguas arriba del canal como el último controlador en la tubería, de esta manera, todos los mensajes se enrutan a la misma instancia, que es casi como tener una sola conexión.

El problema es que no hay forma de distintos dos mensajes de protobuf diferentes entre sí en formato binario. Pero hay una manera de resolverlo dentro del archivo ProtoBuf:

message AnyMessage {
    message DataMessage { [...] }
    optional DataMessage dataMessage = 1;
    message TestMessage { [...] }
    optional TestMessage testMessage = 2;
    message SrcMessage { [...] }
    optional SrcMessage srcMessage = 3;
}

Los campos opcionales que no están establecidos no producen sobrecarga. Además, puede agregar una enumación, pero es solo una ventaja.

El problema no es una limitación netty o una limitación de codificador/decodificador. El problema es que Google Protocol Buffers está ofreciendo una forma de serializar/deserializar objetos, pero no proporciona un protocolo. Tienen algún tipo de implementación de RPC como parte de la distribución estándar, pero si intentará implementar su protocolo RPC, terminará con 3 capas de indirección. Lo que he hecho en uno de los proyectos fue definir un mensaje que es básicamente una unión de mensajes. Este mensaje contiene un campo que es tipo y otro campo que es el mensaje real. Todavía terminará con 2 capas de indirección, pero no 3. De esta manera, el ejemplo de Netty funcionará para usted, pero como se mencionó en una publicación anterior, debe poner más lógica en el controlador de lógica de negocios.

Puede usar el túnel de mensajes para enviar varios tipos de mensajes como carga útil en un solo mensaje. Espero que ayude

Después de una larga investigación y sufrimiento ... se me ocurrió la idea de usar la composición de mensajes en un mensaje de envoltura. Dentro de ese mensaje que uso uno de clave para limitar el número de objetos permitidos a la sólo uno. Verifique el ejemplo:

message OneMessage {
    MessageType messageType = 1;

    oneof messageBody {
        Event event = 2;
        Request request  = 3;
        Response response = 4;
    }

    string messageCode = 5; //unique message code
    int64 timestamp = 6; //server time
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top