我目前正在 nginx 后面运行一系列 Node.js express 应用程序。但是,尽管我的应用程序运行良好,但我现在在某些情况下会遇到间歇性 502 Bad Gateway 错误。
主要实例是用户尝试登录的地方。通常,第一次登录尝试会返回 502 错误(并且此错误将是瞬时的,而不是在延迟后发生),而随后的第二次尝试将正常处理,请求标头没有变化。
我检查了 nginx 和 express 的日志,似乎在第一个实例中,尽管细节相同,但第一次尝试返回 500 错误(正如在登录尝试错误的情况下所计划的那样)。然后这会在 nginx 中触发 502 错误。
Nginx 错误日志:
2013/10/21 19:32:57 [error] 8178#0: *32101 upstream prematurely closed connection while reading response header from upstream, client: 82.40.77.228, server: instok.net, request: "POST /login HTTP/1.1", upstream: "https://127.0.0.1:5001/login", host: "instok.net", referrer: "https://instok.net/"
Nginx 访问日志:
- [21/Oct/2013:19:32:57 +0000] "POST /login HTTP/1.1" 502 172 "https://instok.net/" "Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0" "-"82.40.77.228 -
- [21/Oct/2013:19:32:59 +0000] "POST /login HTTP/1.1" 200 5 "https://instok.net/" "Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0" "-"82.40.77.228 -
快速访问日志:
- [Mon, 21 Oct 2013 19:32:57 GMT] \"POST /login HTTP/1.0\" 500 69 \"https://instok.net/\"
- [Mon, 21 Oct 2013 19:32:59 GMT] \"POST /login HTTP/1.0\" 200 - \"https://instok.net/\"
服务器端认证
function authenticate(name, pass, fn) {
User.findOne({_id: name}, function(err, user) {
if (!user) { return fn(new Error("Cannot find user"))};
bcrypt.compare(pass, user.hash, function(err, res){
if (err || !res) { return fn(err) }
else {
return fn(null, user);
}
})
})
}
exports.logIn = function(req, res){
authenticate(req.body.username, req.body.password, function(err, user){
if (user){
req.session.regenerate(function(){
req.session.user = user;
res.status(200).send();
})
}
else {
res.status(500).send({message: "Error with username or password - please try again"})
}
});
}
我的 nginx.conf 文件的相关部分位于https://gist.github.com/grabbeh/6721046,我还使用同一文件运行其他几个 node.js 应用程序。
在客户端,我使用 Angular.js 和 $http.post 将登录详细信息发送到服务器,并根据服务器发回的 200 或 500 错误进行条件处理。
我还使用 routeChangeError 事件来重定向来自服务器的 500 错误,以重定向到尝试在登录之外访问路由的登录页面。但是我不认为客户端处理是相关的,因为错误是在任何客户端处理之前返回的。
很可能有一种更好的方法来处理身份验证,这当然可以解决上述问题,但是目前我想深入了解间歇性 502 错误。
该错误似乎确实源于 Express 返回 500,而它应该返回 200,但尽管使用了代码,但我无法确定问题所在。任何意见将不胜感激。应用程序本身运行在https://instok.net
可以查看所有客户端代码的位置。
出于兴趣,502 和有效请求的详细信息如下:
编辑
我缺少的一点是我使用https://github.com/nodejitsu/forever来保持应用程序在发生崩溃时运行。检查 Forever 日志后,很明显问题是连接到 MongoDB 数据库失败导致应用程序崩溃。此错误未在应用程序中捕获,因此据我了解,Express 日志中未引用此错误。现在已经解决了这个问题,而且我已经切换到另一个 MongoDB 实例,我希望它能解决问题。