1

我有一组不同方法的路线。我想让 expressjs 支持与 facebook、Facebook Batch Request非常相似的批处理请求。有人知道怎么做吗?而且我不想建立 3 个环回连接来处理批处理请求。

4

1 回答 1

7

如果您不想进行环回连接,那么最简单的解决方案是使用虚假请求手动调用您的服务器。

您必须重新实现IncomingMessage。您还应该使用Async#map等到所有请求都处理完毕。

这是基本思想:

// 您可能需要做更多工作来重新实现 http 基本 API。
功能假请求(请求){
  this.url = '/' + request.relative_url;
  this.method = request.method;
  this.headers = request.headers;
}

功能假响应(){
  Stream.call(this);

  this.statusCode = null;
  this.body = '';
}

FakeResponse.prototype.write = 函数(块){
  this.body += chunk.toString('utf8');

  返回真;
};

util.inherits(FakeResponse, Stream);

app.post('/', function (req, res) {
  var requests = JSON.parse(req.body.batch);

  async.map(requests, function (request, done) {
    var fakeReq = new FakeRequest(request),
        fakeRes = new FakeResponse();

    // 手动调用 Express' 中间件
    应用程序(fakeReq,fakeRes);

    // 这将在响应准备好时触发。
    fakeRes.once('end', function () {
      // 不要泄漏监听器
      fakeRes.removeAllListeners();
      完成(空,fakeRes);
    });

    fakeRes.once('error', function (err) {
      fakeRes.removeAllListeners();
      完成(错误);
    });
  },函数(错误,响应){
    如果(错误)
      返回 res.send(err);

    res.send(响应);
  });
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express 服务器监听端口' + app.get('port'));
});

更新

我实际上不确定您所说的环回是什么意思,但是您有两个选择:

  • 为批处理中的每个请求打开一个 HTTP 连接,这更容易实现但速度较慢。

  • 我上面概述的解决方案:直接调用 Express 中间件而不打开 HTTP 请求。

我的印象是您不想要第一个解决方案。但是,这就是我首先要尝试的方法,即使速度较慢:

  • 扩展时更容易将批处理连接分布在多个实例中。
  • 您不会绕过您可能拥有的任何负载限制机制(防止单个 Express 实例同时处理太多请求)。

但请务必禁用HTTP 代理

于 2013-07-30T11:28:04.777 回答