2016-05-15 7 views
1

Ich bin ein Neuling von gRPC, und hier ist mein Problem. Ich versuche, einen Dienst zu schreiben myOwnService in einen gRPC Dienst gemäß der folgenden Service-Methode zu entlarven:Wie kann ich einen Go gRPC auf der Serverseite mit Standard IO arbeiten lassen?

rpc HighFive (stream HighRequest) returns (stream HighReply) {} 

Der serverseitigen Code ist wie folgt:

func (s *server) HighFive(stream pb.Greeter_HighFiveServer) error {  
    // Oops, don't know how to do here ... 
    myOwnService(stdin io.ReadCloser, stdout io.WriteCloser) 
    return nil 
} 

func myOwnService(stdin io.ReadCloser, stdout io.WriteCloser) error {  
    // read input from stdin, do something, the write result to stdout 
    ... 
    return nil 
} 

Wie Sie oben sehen können, Ich habe keine Ahnung, wie man stream mit io.Reader und io.Writer in meinem ursprünglichen Dienst arbeiten, so dass der Anrufer des HighFive gRPC-Dienstes Daten lesen und schreiben kann, wie normalerweise myOwnService aufruft.

[Update] Meine aktuellen Meldungen wie diese sind, aber Sie können sie bei Bedarf ändern:

message HighRequest { 
    bytes content = 1; 
} 

message HighReply { 
    bytes content = 1; 
} 
+0

grpc Ströme sind Ströme von Protocol Buffer-Nachrichten, nicht roh Bytes (wie das, was 'myOwnService' erwartet). Damit dies funktioniert, müssen Sie definieren, wie HighRequest in ein Byte-Segment konvertiert wird und wie ein Byte-Segment in HighReply konvertiert wird. –

Antwort

1

Per the gRPC Basics tutorial section on Bidirectional streaming RPC, jeden Anruf auf Ihren streamRecv Methode des Parameters werden Sie eine dekodiert HighRequest Nachricht, nicht ein Byte-Stream, wie Sie für Ihre myOwnService Funktion erwarten.

Nun, wenn Ihre HighRequest Nachricht ein Feld von Typen bytes oder string enthält, können Sie möchten, dass Feld Inhalt in myOwnService als stdin Parameter füttern von dem rohen []byte Wert über bytes.NewReader wickeln.

Ich sehe jedoch, dass myOwnService fordert eine io.ReadCloser. Ich weiß nicht, warum Sie myOwnService erwarten, um seinen Eingabeparameter zu schließen, aber ich vertraue Ihnen gut genug, dass Sie es benötigen, um dann ioutil.NopCloser zu empfehlen, um diese Anforderung trivial zu erfüllen.

Sketching:

// Next tag: 2 
message HighRequest { 
    bytes content = 1; 
} 

func (s *server) HighFive(stream pb.Greeter_HighFiveServer) error { 
    for req, err := stream.Recv(); { 
    if err != nil { 
     if err == io.EOF { 
     return nil 
     } 
     return err 
    } 
    in := ioutil.NopCloser(bytes.NewReader(req.Content)) 
    out := /* ... */ 
    if err := myOwnService(in, out); err != nil { 
     return err 
    } 
    } 
} 
+0

Vielen Dank. Ich habe verstanden, wie Sie mit Eingaben umgehen. Aber wie wird die Ausgabe in den Stream umgeleitet, da es sich um einen Bio-Richtungs-RPC-Dienst handelt. – harryz

+0

Ich habe darüber nachgedacht, was Sie letzte Nacht versuchen könnten, und mir wurde klar, dass Sie vielleicht alle in Ihrem Nachrichtenstrom empfangenen Eingabefragmente verketten und sie als Eingabestream für Ihre 'myOwnService'-Funktion darstellen möchten . Das ist möglich, aber komplizierter als das, was ich oben gezeigt habe. – seh

+0

Für die Ausgabe könnten Sie einen benutzerdefinierten "io.Writer" an "myOwnService" liefern, der einige Bytes puffert und sie dann in einer "HighReply" -Nachricht ausgibt. Sie würden so viele "HighReply" -Nachrichten senden, bis keine weiteren gepufferten Daten mehr vorhanden waren, die 'myOwnService' geschrieben hat. Auch dies ist knifflig, aber sicherlich möglich. Wenn Sie herausfinden, wie Sie einen Nachrichtenstrom in einen 'io.Reader' oder 'io.Writer' in einen Nachrichtenstrom umwandeln können, müssen Sie hier separate Fragen stellen. – seh

Verwandte Themen