使用WebApp& amp;时为什么流星会挂起发送npm包来提供自定义文件?

时间:2014-10-09 11:38:37

标签: google-chrome meteor npm send

我已经创建了一个自定义上传/服务机制来管理流星应用的媒体文件。

问题

整个应用程序在~800 - 4000(因系统而异)文件被提供给浏览器后挂起

简化服务代码

var idx = 0;
var send = Meteor.npmRequire('send');

WebApp.connectHandlers.use(function(req, res /*, next*/ ) {
    sendFile(req, res, '/penken.jpg');
});

var sendFile = function(req, res, urlPath) {
    var lidx = idx++;
    console.log(lidx, 'requesting', urlPath);

    send(req, urlPath, {
        root: process.env.PWD + '/.uploads',
        maxAge: 20 * 60 * 1000
    }).pipe(res);
};

备注

  • 我不知道这是一个特定的meteor问题,还是sendWebApp等。
  • 我无法查明问题 - 因为很难重现并且节点检查员无法调试挂起的应用程序
  • 有趣的是,如果我使用以下bash行运行wget 10000次:

    for i in `seq 10000`; do wget http://localhost:3000/uploads/penken.jpg -qO /dev/null; sleep 0.01; done
    

    问题不会表现出来

示例问题的示例项目

https://github.com/albertmatyi/meteor-hangs

找到它

试一试

  1. 克隆项目     git clone https://github.com/albertmatyi/meteor-hangs.git
  2. 输入其文件夹     cd meteor-hangs
  3. 运行服务器     meteor
  4. 打开chrome并导航到(你应该看到一张图片)     http://localhost:3000/
  5. 打开Inspector并禁用缓存 Disable cache
  6. 刷新页面~810-4500次(可能会有所不同) - 只需将手指放在refesh按钮上(F5Ctrl + RCmd + R)  控制台将显示请求和提供资源的时间
  7. 结果:Meteor挂起,不会为任何其他客户提供服务
  8. GitHub meteor issue ref

1 个答案:

答案 0 :(得分:1)

这个可能发生是因为您使用的是具有阻塞文件I / O操作的中间件。对于每个页面加载,Meteor最初必须通过每个中间件处理程序并在可以提供页面之前运行它。

您可能遇到此问题的原因是您正在执行的操作是I / O密集型,并且在等待上一个任务完成时阻止其他中间件运行。 (请记住,javascript是异步的,但文件I / O是阻塞的。)

通过这种方式并不容易。想到的直接想法是以某种方式使用内存缓冲区或其他东西,或确保它只针对特定路径运行(例如/upload而不是所有路径。这样你就不会感到不方便了得多。

wget操作的原因是没有其他调用的javascript。对于每个页面加载meteor,它拥有浏览器将调用的每个模块的几十个javascript文件(反过来每个文件请求也会调用middlware)。它将在页面提供之前等待js。

为了简单起见,我建议的是,如果路线与特定模式(例如sendFile)匹配,则仅执行/upload操作。这样,如果您使用http://localhost:3000,则无法运行。

有点像这样(只适用于/upload

var url = Npm.require('url');

WebApp.connectHandlers.use(function(req, res, next) {
    var path = url.parse(req.url).pathname;
    if(path != '/upload') next()

    sendFile(req, res, '/penken.jpg');
});