EggJS 异步获取流时可能导致进程堵塞
在 eggjs
中异步向其它服务请求文件流时,出现异步始终等待,导致请求阻塞问题。通过排查,发现是由于
await
请求后,流无法被消费,流没有消费完,请求会继续等待,从而陷入了逻辑循环。
源代码
1 | const { PassThrough,pipeline } = require('stream') |
其中, this.curlPython
是对 this.curl
的封装,在此处可以直接理解成 this.curl
。
该方法的作用是请求 python 服务将 html 转换成
pdf,对方返回一个文件流。代码中使用 PassThrough
中转流到其它地方进行消费。
问题分析
上述代码在本机环境表现一切正常,但是在生产环境总是发生阻塞。
通过查看 eggjs 的 curl 的参数介绍,发现其中提到:
1 | export interface RequestOptions { |
当流结束之后,才会以一个 null data 进行回调
所以这就导致在本文开头所讲的情况:
await
请求后,流无法被消费,流没有消费完,请求会继续等待,从而陷入了逻辑循环。
所以,遇到这种情况时,只需要去掉 await
直接返回
PassThrough
让程序对流进行消费即可,即代码为:
1 | await this.curlPython(`/api/html/pdf-stream`, { |
残留问题
为什么在本机测试时是正常,但是到生产环境总是发生阻塞呢?这个问题我也一直没想明白。
通过问 AI,猜测可能原因是:python
服务器的响应是流式的,但没有正确发送结束信号(EOF),writeStream
可能不会触发 'close'
事件,导致 Promise 永不 resolve,从而
await
阻塞,无法执行后续代码。
欢迎大家在下面留言讨论,提前为大家的解惑致以感谢!