ExpressJS 后端挂起太多请求
Posted
技术标签:
【中文标题】ExpressJS 后端挂起太多请求【英文标题】:ExpressJS backend hanging with too much requests 【发布时间】:2012-03-31 00:37:01 【问题描述】:我有一个使用 Sequelize.js 作为 ORM 运行的快速应用程序。我的 express 应用从我的主 Rails 应用接收请求,并且由于跨域策略,这些请求是使用 getJSON 执行的。
在客户端,当用户点击一个键时,请求被触发。 一切都很顺利,并且每次用户点击键时都会记录正在执行的查询(以及正在服务的 json)。即使试图快速击中它也表现良好。但是,每当我按下键(或者可能有几个客户端非常快速地按下键)时,当它开始触发大量请求时,服务器有时会挂起,从那时起的所有请求都处于待处理状态(我看到在 Chrome 开发工具的网络选项卡中),它们慢慢开始超时。我必须重新启动服务器才能让它再次响应。
我的请求的服务器代码是:
models.Comment.findAllPublic(req.params.pId, req.params.sId, function(comments)
var json = comments.map(function(comment)
var com = ;
['user_id','user_avatar', 'user_slug', 'user_name', 'created_at', 'text', 'private', 'is_speaker_note'].forEach(function(key)
com[key]=comment[key];
);
return com;
);
res.json(comments: json);
);
Comment 模型(这是一个 Sequelize 模型)中的 findAllPublic 方法是:
findAllPublicAndMyNotes: function(current_user, presentationId, slideId, cb)
db.query("SELECT * FROM `comments` WHERE commentable_type='Slide' AND commentable_id=(SELECT id from `slides` where `order_in_presentation`="+slideId+" AND `presentation_id`="+presentationId+") AND (`private` IS FALSE OR (`private` IS TRUE AND `user_id`="+current_user+" AND `is_speaker_note` IS FALSE))",self.Comment).on('success', cb).on('failure',function(err)console.log(err););
如何避免服务器卡死?我是否在请求中留下了一些阻塞代码,这些代码可能会在发出新请求时缓慢挂起服务器?
起初我认为这可能是因为“forEach”在从 Sequelize 模型中组合 json 对象时出现问题,但我也尝试将 mysql 查询的回调留空,只响应空 json 并且它也被冻结.
可能是mysql连接器的问题?当服务器卡住时,我可以正常运行 mysql 控制台并在我的数据库上执行查询,它也会响应,所以我不知道这是不是问题。
我知道我可以控制按键事件以防止它在长时间按下按键时触发过多的请求,但是当多个客户端反复同时按键时似乎也会出现问题。
有什么想法吗?提前感谢您的帮助:D
【问题讨论】:
你在创建类似自动提示的东西吗? 【参考方案1】:两件事:
-
您似乎有一些路径没有调用
res.render
。可能是您正在连接的数据库在请求数量荒谬之后断开与您的 Express 服务器的连接,并且从未触发回调(并且没有 database.on('close', function() // Handle disconnect from DB, perhaps auto-restarting )
代码可以捕获它。
您的客户端代码应该检测到按键上的 AJAX 请求何时仍在等待启动新请求时,并取消旧请求。我猜getJSON
是一个 jQuery 方法?假设它是 jQuery 的,那么你需要类似下面的东西
.
var currKeyRequest = null;
function callOnKeyUp()
var searchText = $('#myInputBox').value;
if(currKeyRequest)
currKeyRequest.reject();
currKeyRequest = null;
currKeyRequest = $.getJSON('path/to/server', function(json)
currKeyRequest = null;
// Use JSON code
);
通过这种方式,您可以减少客户端的负载、自动完成功能的延迟(但是,如果您想要这样做,为什么不使用 jQuery UI 自动完成功能呢?),并且您可以节省服务器的一些负载以及如果按键比与服务器握手更快(可能在几个小时的飞行路程之外有一个好的触摸打字员)。
【讨论】:
您好,感谢您的回答,这使我找到了一些我认为可能与此问题有关的信息。我正在开发的是一个实时演示系统,当用户点击前进/后退键时,幻灯片被加载并且幻灯片上的用户的 cmets 也被加载。所以它不是自动完成:)。感谢您的评论,我发现 sequelize.js 目前使用 node-mysql 连接器,我们可以在其中找到 opened issue。你认为这可能相关吗? sequelize 作者还说要换连接器。 除此之外,我已经尝试了在客户端控制挂起请求的解决方案,不幸的是,jquery的getJSON方法返回的对象似乎没有实现reject,尽管它实现了一些其他Deferred 元素的方法。对此有任何线索吗?感谢您的帮助。 @scumah:不要诋毁 felixge 的工作,但我认为他把自己分散得太少了。我之前不得不 fork 他的一个库,因为他根本不想查看我提交给一个相对简单的库(node-dateformat)的补丁。这个问题听起来很可能是问题的原因——如果它断开连接,它不会在该故障上触发任何事件,也不会尝试重新连接。关于 getJSON 不提供“正确”对象,您使用的是什么版本的 jQuery?旧版本只提供XMLHttpRequest
对象,您可以只提供.abort()
以上是关于ExpressJS 后端挂起太多请求的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 express js 处理 fetch API 请求