如何在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
相关产品推荐
相关产品推荐

