mean.io 堆栈角长运行操作与 http 请求
Posted
技术标签:
【中文标题】mean.io 堆栈角长运行操作与 http 请求【英文标题】:mean.io stack angular long running operations with http request 【发布时间】:2018-05-11 02:55:55 【问题描述】:我正在使用 mean stack 开发一个对多个 mongo db 集合执行多个操作的 Web 应用程序。
系统的总体意图是在多个系统之间执行数据同步。每个系统数据都存储在不同的集合中。不用说,这些集合的文档具有共同的属性。
在 nodeJS 或 API 级别,我创建了 get 和 post 请求,它们将异步循环主集合,并尝试将该集合中的文档与其他集合中的文档链接。这个过程自然需要几分钟。
可以链接的文档存储在不同的 mongodb 集合中。这些将在稍后在另一个节点 js API 调用中处理。
设置 API 后,我将创建一个控制器和一个带有 angular 的服务,以便连接到 api 并执行 api 获取和发布请求。
当我在 UI 中单击按钮执行此链接操作时,操作开始时不会阻塞浏览器,但最终浏览器会收到 ERR_EMPTY_RESPONSE,因为操作仍在所以我从来没有真正打电话给response.end()
。
我认为可能的解决方案:
-
操作开始后立即回复:问题 -> 我需要确保此操作完成,以便对结果集合进行其他调用。所以我完成了这个操作,以允许其他人对结果数据集进行操作。
如何避免浏览器在后台长时间运行操作完成之前关闭连接?
代码:
html-> 用户点击开始链接记录的按钮:
<div>
<md-button aria-label="link all records" ng-click="vm.linkRecords()">
<md-icon class="mdi mdi-plus"></md-icon>Link Records
</md-button>
</div>
控制器:canLink、canGrade 都是布尔变量,这样当服务器进行一项操作时,其他操作都无法执行。操作完成后,返回 true 并允许所有操作。
function linkRecords()
$state.go('app.records.link');
// END linkRecords page
$scope.$on('linkRecords', function(event, batchSize)
if ( canLink && canGrade)
showToast("Started linking records");
canLink = 0;
canGrade = 0;
recordService.linkRecords(batchSize).then(function(finished)
canLink = finished;
canGrade = finished;
);
else if ( !canLink )
showToast('Cannot link records: - Currently undergoing grading records');
else if ( !canGrade )
showToast('Cannot link records: - Currently undergoing linking records');
);//END linkingRecords
服务
function linkRecords(batchSize)
return $http.get(urlRoot+'/link/:'+batchSize);
//END linkRecords
节点js api:
routes.js:
//link all records
app.post('/link/:batchSize', function(req, res)
var batchSize = req.params.batchSize;
functions.linkRecords(batchSize, function(callback)
res.end(true);
);
);//END linkRecords
functions.js:
linkRecords : function(batchSize, callback)
//link all records in all collections a batchsize at a time
async.parallel([
function(callback)
...open cursor for collection1 and loops over the collections to stitch with other collections.
,
function(callback)
...open cursor for collection2 and loops over the collections to stitch with other collections.
], function done(err, result)
callback();
);
【问题讨论】:
你考虑使用 WebSockets/Socket.IO 吗? 【参考方案1】:我会借鉴 Mikelax 的答案,即使用队列系统进行管理。我一直在使用agenda 来处理我一直在从事的项目中的较长流程。
我认为值得一提(可能是您的 ERR_EMPTY_RESPONSE 错误的根源)Express 的默认超时时间为 2 分钟。因此,如果您的进程需要几分钟,您应该修改端点上的超时以处理请求。
您可以通过几种不同的方式修改超时,有中间件,例如connect-timeout。您还可以通过 env 对象或直接在 server.js 文件中设置超时。
【讨论】:
【参考方案2】:我不是 MEAN 堆栈方面的专家(目前),但我猜您设计服务的方式不正确。它会返回一个promise(结果未完成)并且你在promise完成之前调用ends。
尝试设计你的服务和 route.js 调用这样的东西。
服务
angular.module('rugCoPro').factory('appraisalSearch', ['$resource', 'RugSession', function($resource, RugSession)
return $resource("/:org/api/models/appraisals/:func/:value", org: "@org", func: "@func", value: "@value" ,
query:
method: 'GET',
isArray: true,
headers: 'Content-Type': 'application/json', 'X-Auth-Token': authToken
);
])
打电话
appraisalSearch(RugSession.getAuthToken()).query( org: org, func: "multi", value: orderNumber[0] ).$promise.then(function(data)
//success
, function(error)
//error
)
【讨论】:
【参考方案3】:听起来您需要更强大的后端基础架构来管理和跟踪这些长期运行的任务。如果您知道这些操作将花费“很长时间”,可能是几秒钟、几分钟或更长,那么您必须设置某种类型的队列服务来运行这些任务、跟踪它们并处理错误情况。
API 服务器的唯一职责应该是:
-
接收用户请求
验证请求中的数据,如果无效则立即返回错误
如果有效,则将新作业插入用于开始处理的队列中
然后,API 响应会向用户返回一条“正在处理的消息”,可能带有一些 ID,他们可以使用它们在单独的 API 请求中跟踪进程。
可以为此流程实现的一组可能的 API:
POST /api/links - create a new link process
GET /api/links - display all currently running link processes
GET /api/links/:id - display a single link process
DELETE /api/links/:id - delete (or cancel) a running link process, if needed
您可以使用多种不同的队列技术来管理长时间运行的任务。如果您在 AWS 环境中,则可以使用 SQS queues。如果您的流程涉及多个步骤,您可以查看处理数据(或流程)管道的系统。 Luigi(从 spotify 开源)是一个示例服务,可用于处理非常简单(即一步)的管道到具有大量步骤和依赖项的极其复杂的管道。
Here is a tutorial 分解了长时间运行的进程的问题,然后讨论了一些可能的实现。
【讨论】:
以上是关于mean.io 堆栈角长运行操作与 http 请求的主要内容,如果未能解决你的问题,请参考以下文章
为啥 MEAN 堆栈建议后端 Express 代码使用 MVC 目录结构?