Go на основе grp c серверный поток продолжает составлять ответ на go клиент - PullRequest
0 голосов
/ 20 февраля 2020

Извините, если это вопрос noob, я новичок в потоковой передаче на стороне сервера grp c.

Что у меня есть сейчас в функции на сервере, которая транслируется на клиент

req, err := http.NewRequest("GET", actualURL, nil)

// пропуск некоторых строк // res, _: = http.DefaultClient.Do (req)

// closing body
defer res.Body.Close()

body, err := ioutil.ReadAll(res.Body)

// пропуск некоторых строк //

// unmarshaling the xml data received from the GET request done above
xmlDataErr := xml.Unmarshal(body, &ArrData)

// creating a variable of a custom type and creating object of specific struct Flight
var flightArrData ArrFlights
currArrData := flightArrData.Arr.Body.Flight

log.Println («Подсчет общего количества строк для отправки клиенту», len (currArrData))

// цикл по ответу и отправка потокового его клиенту

для i: = range currArrData {

    farr := &pb.FlightArrivalsResponse{
        ArrivalResponse: &pb.ArrivalFlightData{
            Hapt:     currArrData[i].HApt,
            Fltnr:    currArrData[i].Fltnr,
            Sdt:      currArrData[i].Sdt,
            Acreg:    currArrData[i].Acreg,
            Park:     currArrData[i].Park,
            EstD:     currArrData[i].EstD,
            Gate:     currArrData[i].Gate,
            AblkD:    currArrData[i].AblkD,
            ActD:     currArrData[i].ActD,
            Callsign: currArrData[i].Callsign,
        },
    }

    senderr := stream.Send(farr)

    // skipping some lines //
}

// возвращение nil после завершения return nil}

Проблема, с которой я сталкиваюсь На стороне клиента у меня есть функция, которая получает этот ответ, спит в течение n минут и снова запрашивает ответ.

Клиент получает ответ, как и ожидалось при первом вызове, однако для каждого последующего вызова происходит что-то странное, и это моя текущая проблема Я постараюсь проиллюстрировать в форме каждого последующего звонка ниже:

Звонок 1 из C lient to Server -> сервер возвращает 200 строк

клиент спит в течение n минут

вызов 2 от клиента к серверу -> сервер возвращает 400 строк !! (в основном в каждой строке дважды, как в 200 + 200)

клиент спит в течение n минут

Вызов 3 с клиента на сервер -> Сервер возвращает 600 строк !! (200 + 200 + 200)

Сводка

Я проверяю на наличие ошибок == io.EOF на стороне клиента и единственный способ остановить это наложение ответ от сервера к клиенту должен остановить сервер и перезапустить.

Я не уверен, что мне здесь не хватает, чтобы убедиться, что я отправляю только тот фактический и точный ответ, который я получил от запроса GET. Буду очень признателен за любую подсказку на этот счет.

Дополнительная информация

Часть из gRP C protobuffer def в файле proto

rpc GetFlightArrivals (FlightArrivalsRequestURL) returns (stream FlightArrivalsResponse) {
    };

Полный код для серверной части вышеупомянутого gRP C

func (s *Server) GetFlightArrivals(url *pb.FlightArrivalsRequestURL, stream pb.Flight_GetFlightArrivalsServer) error {

    cData := ch.ConfigProcessor() // fetches the initial part of the URL from config file

    if url.ArrivalURL == "" {
        actualURL = cData.FURL + "/arr/all" // adding the arrival endpoint

    } else {
        actualURL = url.ArrivalURL
    }

    // build new request to get arrival data
    req, err := http.NewRequest("GET", actualURL, nil)
    if err != nil {
        log.Fatalln("Recheck URL or connectivity, failed to make REST call")
    }
    req.Header.Add("Cache-Control", "no-cache")
    req.Header.Add("Accept", "text/plain")
    req.Header.Add("Connection", "keep-alive")
    req.Header.Add("app_id", cData.AppID)
    req.Header.Add("app_key", cData.AppKey)
    req.Header.Add("Content-Type", "application/xml")


    res, _ := http.DefaultClient.Do(req)

    // closing body
    defer res.Body.Close()

    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        log.Fatalln("Failed to get any response")
        return err
    }
    // unmarshaling the xml data
    xmlDataErr := xml.Unmarshal(body, &flightArrData)
    if xmlDataErr != nil {
        log.Fatalln("Failed to unmarshal arrival xml data see error, ", xmlDataErr)
        return xmlDataErr
    }

    currArrData := flightArrData.Arr.Body.Flight
    log.Println("Counting total arrivals in Finland", len(currArrData))
    log.Println("Starting FlightDeparturesResponse for client")
    for i := range currArrData {

        farr := &pb.FlightArrivalsResponse{
            ArrivalResponse: &pb.ArrivalFlightData{
                Hapt:     currArrData[i].HApt,
                Fltnr:    currArrData[i].Fltnr,
                Sdt:      currArrData[i].Sdt,
                Acreg:    currArrData[i].Acreg,
                Park:     currArrData[i].Park,
                EstD:     currArrData[i].EstD,
                Gate:     currArrData[i].Gate,
                AblkD:    currArrData[i].AblkD,
                ActD:     currArrData[i].ActD,
                Callsign: currArrData[i].Callsign,
            },
        }

        senderr := stream.Send(farr)

        if senderr != nil {
            log.Fatalln("Failed to stream arrival response to the client, see error ", senderr)
            return senderr
        }

    }
    currArrData = nil
    log.Println("Attempting to empty the arrival data")
    return nil
}

Контрольный пример для проверки вышеупомянутого значения gRP C

I просто запустите тестовый сервер GRP c и в этом тестовом случае вызовите этот GRP c. Реализация на клиенте аналогична получению данных.

func TestGetFlightArrivals(t *testing.T) {
    const addr = "localhost:50051"
    conn, err := grpc.Dial(addr, grpc.WithInsecure())
    if err != nil {
        t.Fatalf("Did not connect: #{err}")
    }
    defer conn.Close()
    f := pb.NewFlightClient(conn)

    t.Run("GetFlightArrivals", func(t *testing.T) {

        var res, err = f.GetFlightArrivals(context.Background(), &pb.FlightArrivalsRequestURL{ArrivalURL: ""})
        if err != nil {
            t.Error("Failed to make the REST call", err)
        }

        for {
            msg, err := res.Recv()
            if err == io.EOF {
                t.Log("Finished reading all the message")
                break
            }
            if err != nil {
                t.Error("Failed to receive response")
            }
            t.Log("Message from the server", msg.GetArrivalResponse())

        }
    })
}

1 Ответ

0 голосов
/ 04 марта 2020

На основе комментария от @ rubens21 я добавил следующие строки var emptyArrData ArrFlights, которые в основном являются полной структурой XML, и назначил эту emptyArrData структуре flightArrData = emptyArrData

...