You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NestJS中实现gRPC ServerWritableStream?

如何在NestJS中实现gRPC ServerWritableStream?

我完全懂你现在的困扰——在纯TypeScript里写的gRPC ServerWritableStream逻辑跑起来顺得很,结果移植到NestJS的gRPC控制器里就失效了,偏偏普通的一元gRPC调用还都正常,Envoy配置也没毛病,这确实让人摸不着头脑。

先帮你揪出核心问题:你在NestJS的onAdded方法上加了async关键字,但ServerWritableStream是基于事件驱动的流式处理,不需要用异步函数包裹。NestJS会默认把async方法的返回值当作Promise来处理,这会干扰gRPC流的正常生命周期,导致你的call.write()调用无法正确推送给客户端。

解决方案:去掉async关键字

把你的NestJS控制器方法里的async去掉,让方法直接处理流逻辑就行。修改后的代码如下:

@GrpcMethod('TodoService', 'OnAdded')
onAdded(
  request: todo.OnAddedTodoRequest,
  metadata: Metadata,
  call: ServerWritableStream<todo.OnAddedTodoRequest, todo.ServerMessage>,
) {
  const interval = setInterval(() => {
    const myTodo = JSON.stringify({
      id: 'b779cb10-72c8-416f-9399-273eab8e3421',
      title: 'Fix the server streaming',
      completed: false,
    });
    console.log('Sending streaming data', myTodo);
    const message = new todo.ServerMessage({ message: myTodo });
    call.write(message);
  }, 5000);

  call.on('end', () => {
    console.log('end');
    clearInterval(interval); // 记得清理定时器,避免内存泄漏
  });

  setTimeout(() => {
    call.end();
  }, 30000);
}

额外注意点

  • 清理资源:我在call.on('end')里加了clearInterval(interval),避免客户端提前断开连接后定时器还在运行,造成内存泄漏。
  • Protobuf定义验证:你的proto文件是没问题的,OnAdded方法明确定义了“一元请求→流式响应”的模式,符合ServerWritableStream的使用场景:
syntax = "proto3";

package todo;

service TodoService {
  rpc OnAdded (OnAddedTodoRequest) returns (stream ServerMessage);
}

message OnAddedTodoRequest {}

message ServerMessage {
  string message = 1;
}
  • NestJS gRPC配置:确保你在app.module.ts里正确配置了gRPC客户端/服务端,比如指定了proto文件路径、package名称等,不过既然一元调用正常,这部分应该没问题。

为什么纯TS代码能正常工作?因为你写的是普通的回调函数,没有async/await的干扰,gRPC的流生命周期能正常推进。而NestJS的async方法会让框架误以为这是一个需要等待结果的异步操作,从而提前结束请求上下文,导致流数据无法正确发送。

备注:内容来源于stack exchange,提问作者Va5ili5

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 10:59:05