简体   繁体   English

gRPC-web 如何处理来自服务器端流的字节数据?

[英]How gRPC-web handles bytes data from server-side streaming?

I want to transmit a sample video file from backend grpc service to the browser using grpc-web, I did some tweaks based on official hello world tutorial .我想使用 grpc-web 将一个示例视频文件从后端 grpc 服务传输到浏览器,我根据官方 hello world 教程做了一些调整。 Btw, nothing changed in the envoy configuration.顺便说一句,特使配置没有任何变化。 The video file is split into 17 chunks, I can receive 17 messages in browser, however there is nothing inside, what should do so I can get the data?视频文件被分成17个块,我在浏览器中可以接收到17条消息,但是里面什么都没有,我应该怎么做才能得到数据?

protobuf definition: protobuf 定义:

syntax = "proto3";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (stream HelloReply);
}

message HelloRequest {}

message HelloReply {
  bytes message = 1;
}

server.js: server.js:

var PROTO_PATH = __dirname + '/helloworld.proto';

var grpc = require('grpc');
var fs = require('fs');
var protoLoader = require('@grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(
    PROTO_PATH,
    {keepCase: true,
     longs: String,
     enums: String,
     defaults: true,
     oneofs: true
    });
var protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
var helloworld = protoDescriptor.helloworld;

function doSayHello(call) {
  let count = 0;
  let videoDataStream = fs.createReadStream('./sample.mp4');
  videoDataStream.on('data',function(chunk){
      console.log(chunk);
      console.log(++count);
      call.write({videoStream: chunk});
//      call.write(chunk);
  }).on('end',function(){
      call.end();
  });
}

function getServer() {
  var server = new grpc.Server();
  server.addService(helloworld.Greeter.service, {
    sayHello: doSayHello,
  });
  return server;
}

if (require.main === module) {
  var server = getServer();
  server.bind('0.0.0.0:9090', grpc.ServerCredentials.createInsecure());
  server.start();
}

exports.getServer = getServer;

client.js:客户端.js:

const {HelloRequest, HelloReply} = require('./helloworld_pb.js');
const {GreeterClient} = require('./helloworld_grpc_web_pb.js');

var client = new GreeterClient('http://localhost:8080');

var request = new HelloRequest();

client.sayHello(request).on('data', function(chunk){
  //console.log(chunk.getMessage());
  console.log(chunk);
});

Anyway, in case there is problem with proxy, below is my envoy.yaml:无论如何,如果代理有问题,下面是我的 envoy.yaml:

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address: { address: 0.0.0.0, port_value: 8080 }
    filter_chains:
    - filters:
      - name: envoy.http_connection_manager
        config:
          codec_type: auto
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match: { prefix: "/" }
                route:
                  cluster: greeter_service
                  max_grpc_timeout: 0s
              cors:
                allow_origin_string_match:
                - prefix: "*"
                allow_methods: GET, PUT, DELETE, POST, OPTIONS
                allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
                max_age: "1728000"
                expose_headers: custom-header-1,grpc-status,grpc-message
          http_filters:
          - name: envoy.grpc_web
          - name: envoy.cors
          - name: envoy.router
  clusters:
  - name: greeter_service
    connect_timeout: 0.25s
    type: logical_dns
    http2_protocol_options: {}
    lb_policy: round_robin
    hosts: [{ socket_address: { address: host.docker.internal, port_value: 9090 }}]

the bytes logged on server side:服务器端记录的字节数: 在此处输入图像描述

and below console output in browser:及以下浏览器中的控制台 output: 在此处输入图像描述

Have you tried testing with a gRPC (rather than gRPC Web) client to eliminate the possibility that the proxy is the problem?您是否尝试过使用 gRPC(而不是 gRPC Web)客户端进行测试以消除代理问题的可能性?

I'm not super familiar with the Node.JS implementation but...我对 Node.JS 的实现不是很熟悉,但是......

Should it not be server.addProtoService(...) ?它不应该是server.addProtoService(...)吗?

Also the message streamed by the server is:服务器流式传输的消息也是:

message HelloReply {
  bytes message = 1;
}

But you:但是你:

call.write({videoStream: chunk});

Should it not be:不应该是:

call.write({message: chunk});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM