Envoy GRPC 反向桥接 - 收到代码 0 的 RST_STREAM

发布于 2025-01-17 05:12:53 字数 3702 浏览 4 评论 0原文

我正在尝试通过 GRPC 客户端通过 Envoy GRPC 反向桥访问 HTTP1.1 REST API。但是当我测试它时,我收到以下错误。任何帮助或示例代码片段将不胜感激。谢谢!

Error: 13 INTERNAL: Received RST_STREAM with code 0
    at Object.callErrorFromStatus (/Users/meiyappan/grpc-node/grpc/examples/node/node_modules/@grpc/grpc-js/build/src/call.js:31:26)
    at Object.onReceiveStatus (/Users/meiyappan/grpc-node/grpc/examples/node/node_modules/@grpc/grpc-js/build/src/client.js:176:52)
    

我的 Envoy 代理配置 XML

admin:
  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: 50051
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          access_log:
          - name: envoy.access_loggers.stdout
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: grpc
                  timeout: 50.00s
                # per_filter_config disables the filter for this route
                typed_per_filter_config:
                  envoy.filters.http.grpc_http1_reverse_bridge:
                    "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfigPerRoute
                    disabled: true
          http_filters:
          - name: envoy.filters.http.grpc_http1_reverse_bridge
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfig
              content_type: application/grpc
              withhold_grpc_frames: true
          - name: envoy.filters.http.router
  clusters:
  - name: grpc
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: grpc
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: localhost
                port_value: 80

这是 Proto 文件

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

我的 HTTP Rest API,

app.post('/helloworld.greeter/SayHello', async (req, res) => {
    console.log(req)
const root = await protobuf.load(PROTO_PATH);

  const HelloReply = root.lookupType('helloworld.HelloReply');
  const buf = HelloReply.encode({ message: 'Hello Bill'}).finish();
  res.send(buf)
  res.end();
})

在 Node js 中使用 Node-Express GRPC 客户端代码

function main() {
  
  var  target = 'localhost:50051';
  
  var client = new hello_proto.Greeter(target,
                                       grpc.credentials.createInsecure());
  var user = 'world';
  
  var metadata = new grpc.Metadata();
  metadata.add('Content-Type', 'application/grpc')
  client.sayHello({name: user},metadata, function(err, response) {
    console.log(err)
    console.log('Greeting:', response);
  });
}

I am trying to access HTTP1.1 rest API via GRPC client, through Envoy GRPC Reverse bridge. But when I test it I get the below error. Any help or sample code snippet would be much appreciated. Thanks!

Error: 13 INTERNAL: Received RST_STREAM with code 0
    at Object.callErrorFromStatus (/Users/meiyappan/grpc-node/grpc/examples/node/node_modules/@grpc/grpc-js/build/src/call.js:31:26)
    at Object.onReceiveStatus (/Users/meiyappan/grpc-node/grpc/examples/node/node_modules/@grpc/grpc-js/build/src/client.js:176:52)
    

My Envoy proxy configuration XML

admin:
  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: 50051
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          access_log:
          - name: envoy.access_loggers.stdout
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: grpc
                  timeout: 50.00s
                # per_filter_config disables the filter for this route
                typed_per_filter_config:
                  envoy.filters.http.grpc_http1_reverse_bridge:
                    "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfigPerRoute
                    disabled: true
          http_filters:
          - name: envoy.filters.http.grpc_http1_reverse_bridge
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.grpc_http1_reverse_bridge.v3.FilterConfig
              content_type: application/grpc
              withhold_grpc_frames: true
          - name: envoy.filters.http.router
  clusters:
  - name: grpc
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: grpc
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: localhost
                port_value: 80

This is the Proto File

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

My HTTP Rest API, using Node-Express

app.post('/helloworld.greeter/SayHello', async (req, res) => {
    console.log(req)
const root = await protobuf.load(PROTO_PATH);

  const HelloReply = root.lookupType('helloworld.HelloReply');
  const buf = HelloReply.encode({ message: 'Hello Bill'}).finish();
  res.send(buf)
  res.end();
})

GRPC Client Code in node js

function main() {
  
  var  target = 'localhost:50051';
  
  var client = new hello_proto.Greeter(target,
                                       grpc.credentials.createInsecure());
  var user = 'world';
  
  var metadata = new grpc.Metadata();
  metadata.add('Content-Type', 'application/grpc')
  client.sayHello({name: user},metadata, function(err, response) {
    console.log(err)
    console.log('Greeting:', response);
  });
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蓝眼泪 2025-01-24 05:12:53

我已成功重现您的问题。有两处错误:

在您的 Envoy 配置中,删除 typed_per_filter_config,因为这里您说不要将 grpc_http1_reverse_bridge 用于 / 但您应该使用它。

在您的服务器实现中,

res.header("Content-Type", "application/grpc");

res.send(buf) 之前

添加:然后,在您的客户端中,如果您编写:

console.log('Greeting:', response.getMessage());

您应该看到:Greeting: Hello Bill

检索请求属性

另外,如果你想检索请求正文,你应该在服务器中使用原始的 Express 中间件:

app.use(express.raw({type: "application/grpc"}));

然后:

const root = await protobuf.load(PROTO_PATH);

app.post('/helloworld.greeter/SayHello', (req, res) => {
    var message = "Hello";

    // if there is a body, transform it to HelloRequest and retrieve name
    if (req.body !== undefined && req.body instanceof Buffer && req.body.length != 0) {
        const HelloRequest = root.lookupType('helloworld.HelloRequest');
        const helloReq = HelloRequest.decode(req.body);
        message += " " + helloReq.name;
    }

    res.header("Content-Type", "application/grpc");

    const HelloReply = root.lookupType('helloworld.HelloReply');
    res.send(HelloReply.encode({ message: message }).finish());
});

客户端,你可以像这样传递名称:

var request = new HelloRequest();
request.setName("World");

通过执行客户端,你现在应该得到: <代码>问候:你好世界。

I have successfully reproduced your issue. There are two things wrong:

In your Envoy config, remove the typed_per_filter_config, because here you are saying to not use the grpc_http1_reverse_bridge for / but you should use it.

In your server implementation, add:

res.header("Content-Type", "application/grpc");

just before res.send(buf).

Then, in your client, if you write:

console.log('Greeting:', response.getMessage());

You should see: Greeting: Hello Bill.

Retrieve request attributes

Also, if you want to retrieve the request body, you should use the raw express middleware in the server:

app.use(express.raw({type: "application/grpc"}));

And then:

const root = await protobuf.load(PROTO_PATH);

app.post('/helloworld.greeter/SayHello', (req, res) => {
    var message = "Hello";

    // if there is a body, transform it to HelloRequest and retrieve name
    if (req.body !== undefined && req.body instanceof Buffer && req.body.length != 0) {
        const HelloRequest = root.lookupType('helloworld.HelloRequest');
        const helloReq = HelloRequest.decode(req.body);
        message += " " + helloReq.name;
    }

    res.header("Content-Type", "application/grpc");

    const HelloReply = root.lookupType('helloworld.HelloReply');
    res.send(HelloReply.encode({ message: message }).finish());
});

Client side, you can pass the name like this:

var request = new HelloRequest();
request.setName("World");

By executing the client, you should now get: Greeting: Hello World.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文