为什么NodeJS / restify服务器*很less*报EPERM接受?

我正在NodeJS中运行restify服务器。 在非常罕见的情况下,按照HTTPS请求的0.05%的顺序导致net.js报告以下错误:

Error: accept EPERM at exports._errnoException (util.js:742:11) at TCP.onconnection (net.js:1280:24) 

HTTP请求没有什么特别之处。 在报告这个错误之前,服务器可能已经服务了数千个请求,甚至响应了几十个相同的请求。 我一直无法find任何有关为什么服务器可能会为已成功接受连接几个小时的套接字生成EPERM错误的任何信息。

顺便说一下,这个错误发生在我们源代码的任何执行上下文之外。 所以EPERM并不像我们的代码访问文件或执行其他系统调用。 当新的请求到达时,在我们的代码被调用之前,EPERM正在NodeJS TCP代码的深处发生。

起初,当发生错误时,会导致NodeJS终止。 那么我添加了代码来捕获应用程序级别的exception:

 process.on("uncaughtException", onUncaughtException ); 

但是因为我不知道这个错误是怎么发生的,所以还不清楚恢复过程是什么。

不知道它是否会影响,但这里是与启动restify服务相关的大部分代码:

 var restify = require("restify"); // skipping some other init code // configuration data is read from a JSON file var serverOptions = { name: configuration.server.name, version: configuration.server.version, formatters: { "application/json": jsonResponseFormatter, "text/html": textResponseFormatter }, serverOptions.key: fs.readFileSync(configuration.server.sslKey), serverOptions.cert: fs.readFileSync(configuration.server.sslCert) } var server = restify.createServer( serverOptions ); // skipping middleware inits and URL registrations server.listen( configuration.server.port, // using HTTPS 443 configuration.server.serverip ); 

顺便说一句,我们正在运行一个旧版本的NodeJS:v0.11.13。 我的长期计划是升级到最新的稳定版本,但我们可能无法更新几个月。

让我在这里留下我的解决scheme,以防其他人在将来遇到同样的问题。

从技术上讲,我没有发现为什么这个错误发生,但我确实发现如何成功地处理错误情况:陷阱和释放。 错误必须被困在应用程序级别,因为它是在我的源代码的任何try-catch上下文之外的net.js内部产生的。 所以如果我不抓住它,那么它会崩溃我的应用程序。 但是这个错误是非致命的,看来它可以被安全地忽略。 在testing中,即使发生这种错误,套接字也会继续接收新的连接。

 process.on("uncaughtException", onUncaughtException ); function onUncaughtException(error) { // put some code here to log the error occurrence, then ... if( error.code==="EPERM" && error.syscall==="accept" ) { // non-fatal error: do nothing; just ignore this error } else { // handle other application errors here } } 

因此,尽pipe知道为什么服务器套接字偶尔会出现EPERM错误仍然很有趣,但现在我很满意,知道处理错误的正确方法。

 $ man 2 accept ... In addition, Linux accept() may fail if: EPERM Firewall rules forbid connection. 

说实话,我并不完全确定什么types的防火墙规则会导致这个错误,我所能想到的是,您可能有一个规则,允许来自特定客户端的传入连接,但不允许传出数据到该客户端的IP /networking/港口/…