Frage

Beim Lesen des Netty -Tutorials habe ich ein einfaches gefunden Bezeichnung wie man Netty integriert und Google Protocol Puffer. Ich habe angefangen, sein Beispiel zu untersuchen (da in der Dokumentation keine weiteren Informationen vorhanden sind) und eine einfache Anwendung wie die Beispiel für die lokale Zeit für die lokale Zeit geschrieben. Dieses Beispiel verwendet jedoch die statische Initialisierung in der PipeFactory -Klasse, z. B.:

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;
    }

}

(Bitte schauen Sie sich die Zeile an p.addLast("protobufDecoder", new ProtobufDecoder(Communication.DataMessage.getDefaultInstance()));) und nur eine Fabrik kann erstellt werden (wie ich verstehe) für ClientBootstrap Klasse, ich meine bootstrap.setPipelineFactory() Methode. In dieser Situation kann ich also verwenden EINES Nachricht zum Senden an Server und EINES Nachricht zum Empfangen vom Server und es ist schlecht für mich, und ich denke nicht nur für mich :( Wie kann ich verschiedene Nachrichten für und von nur für eine Verbindung verwenden? Vielleicht kann ich ein paar erstellen protobufDecoder so was

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

oder andere Techniken? Danke vielmals.

War es hilfreich?

Lösung

Ich habe Faden des Autors von Netty in gefunden Google -Gruppen Und verstanden, dass ich meine Architektur ändern oder meinen eigenen Decoder schreiben muss, wie ich oben geschrieben habe.

Andere Tipps

Wenn Sie sowieso Ihre eigenen Codecs schreiben möchten, möchten Sie möglicherweise die Implementierung der externalisierbaren Schnittstelle für benutzerdefinierte Datenobjekte implementieren.

  • Serialisierbar ist niedrig, aber die schlimmste Leistung (serialisiert alles).
  • Protobuf ist ein guter Kompromiss zwischen Aufwand und Leistung (erfordert .Proto-Wartung)
  • Externalisierbar ist ein hoher Aufwand, aber die beste Leistung (benutzerdefinierte minimale Codecs)

Wenn Sie bereits wissen, dass Ihr Projekt wie eine Bergziege skalieren muss, müssen Sie möglicherweise die harte Straße gehen. Protobuf ist keine Silberkugel.

Theoretisch kann dies erfolgen, indem die Pipeline für jede eingehende Nachricht geändert wird, um die eingehende Nachricht zu entsprechen. Schauen Sie sich das an die Hafeneinigung Beispiel in Netty.

Sequenz wäre:
1) In Frame Decoder oder einem anderen "DecodermapingDeCoder" überprüfen Sie den Nachrichtentyp der eingehenden Nachricht
2) Ändern Sie die Pipeline dynamisch, wie im Beispiel gezeigt

Aber warum nicht unterschiedliche Verbindungen verwenden und dieser Sequenz folgen:
1) Fügen Sie andere Decoder in Pipeline nur einmal auf der eingehenden Nachricht hinzu.
2) Fügen Sie die hinzu gleich Instanz von Channel Upstream -Handler als letzter Handler in der Pipeline. Auf diese Weise werden alle Nachrichten in die gleiche Instanz weitergeleitet, was fast so ähnlich ist, wie eine einzelne Verbindung.

Das Problem ist, dass es in binärem Format keine Möglichkeit gibt, zwei verschiedene Protobuf -Nachrichten voneinander zu unterscheiden. Aber es gibt eine Möglichkeit, es in der Protobuf -Datei zu lösen:

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

Optionale Felder, die nicht eingestellt sind, erzeugen keinen Overhead. Außerdem können Sie eine Aufzählung hinzufügen, aber es ist nur ein Bonus.

Das Problem ist keine Netto -Einschränkung oder Encoder-/Decoder -Einschränkung. Das Problem ist, dass Google Protocol -Puffer nur eine Möglichkeit bieten, Objekte zu serialisieren/zu deserialisieren, aber kein Protokoll bereitstellt. Im Rahmen der Standardverteilung verfügen sie über eine RPC -Implementierung. Wenn Sie jedoch versuchen, ihr RPC -Protokoll zu implementieren, werden Sie 3 Lagen von Indirektion haben. Was ich in einem der Projekte getan habe, war es, eine Nachricht zu definieren, die im Grunde genommen eine Vereinigung von Nachrichten ist. Diese Nachricht enthält ein Feld, das Typ und ein anderes Feld ist, das die tatsächliche Nachricht ist. Sie werden immer noch mit 2 Indirektionsstichen enden, aber nicht 3. Auf diese Weise funktioniert das Beispiel von Netty für Sie, aber wie in einem früheren Beitrag erwähnt, müssen Sie den Geschäftslogik-Handler mehr Logik aufnehmen.

Sie können das Meldung Tunneling verwenden, um verschiedene Arten von Nachrichten als Nutzlast in einer einzelnen Nachricht zu senden. Ich hoffe, das hilft

Nach langer Forschung und Leiden ... hatte ich die Idee, die Zusammensetzung von Nachrichten in eine Wrapper -Nachricht zu verwenden. In dieser Nachricht verwende ich einer von Schlüssel, um die Anzahl der erlaubten Objekte auf zu begrenzen das einziger. Checkout des Beispiels:

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
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top