在 Node.js 中打开多个 UNIX 域套接字:为什么会出现 EAGAIN 错误?
Opening multiple UNIX domain sockets in Node.js: Why do I get EAGAIN errors?
我的用例(网络服务):
多个客户端 => Web 服务器 => 通过 UNIX 域套接字向 C 程序发送消息。
我一直在使用 Apache + PHP 作为网络服务器层,但我目前正在将其替换为 Node.js。
Web 服务达到 100 requests/sec,因此这是一个非常真实的场景,当一个新请求进来时,C 程序将很忙。PHP 处理得很好,但是 Node.js 经常因错误而失败:
{
"code": "EAGAIN",
"errno": "EAGAIN",
"syscall": "connect",
"address": "/tmp/service.sock"
}
我假设这是因为 PHP 执行某种消息 queue/retry 将确保所有消息都发送到 C 程序(Node.js 不会)。
是否有一种简单的方法可以在 Node.js 中执行相同的操作,或者我是否必须实现自定义消息队列?
C 套接字创建:
int listenSocket, newSocket;
struct sockaddr_un localAddress, remoteAddress;
// Create socket
if ((listenSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1){
printf("Error opening listener socket");
exit(1);
}
// Configure socket
localAddress.sun_family = AF_UNIX; // Set UNIX domain socket type
strcpy(localAddress.sun_path, "/tmp/service.sock");
unlink(localAddress.sun_path); // Remove any previous instances of the socket
// Open listener socket
int len = strlen(localAddress.sun_path) + sizeof(localAddress.sun_family);
if (bind(listenSocket, (struct sockaddr *)&localAddress, len) == -1){
printf("Error binding socket at %s", localAddress.sun_path);
exit(1);
}
chmod(localAddress.sun_path, 0777);
// Listen for new connections on the listener socket
if (listen(listenSocket, 5) == -1){
printf("Error listening on listener socket");
exit(1);
}
// Handle new connections
while(!shutdown){
printf("Waiting for a connection...\n");
// Accept new connection
int sizeofRemoteAddress = sizeof(remoteAddress);
if ((newSocket = accept(listenSocket, (struct sockaddr *)&remoteAddress, &sizeofRemoteAddress)) == -1){
printf("Error accepting new connection: %s\n", strerror(errno));
continue;
}
// Read and handle data from client...
}
正在连接到 PHP 中的套接字:
$socket = @socket_create(AF_UNIX, SOCK_STREAM, 0);
if (!$socket) return false;
$connected = @socket_connect($socket, "/tmp/service.sock");
if (!$connected) return false;
// Send message to server and read response...
正在连接到 Node.js 中的套接字:
new Promise(function(resolve, reject){
var socket = Net.connect("/tmp/service.sock");
socket.on("error", function(err){
reject(err);
});
socket.on("connect", function(){
socket.write(message);
});
socket.on("data", function(data){
socket.end();
resolve(data.toString("UTF-8"));
});
});
EAGAIN
是系统调用中断时的预期情况。当您收到 EAGAIN
错误代码时,您应该简单地重复相同的调用。在典型的 C 程序中,您会看到大量 while (returnCode == -1 && errno == EAGAIN)
风格的循环。
如果您期望有很多中断,您可以先禁用中断(不确定 node.js 中是如何完成的)进行系统调用,然后再次启用中断。
不确定这个答案是否适合 node.js
应用程序,但我想我还是提到了它。
我的用例(网络服务):
多个客户端 => Web 服务器 => 通过 UNIX 域套接字向 C 程序发送消息。
我一直在使用 Apache + PHP 作为网络服务器层,但我目前正在将其替换为 Node.js。
Web 服务达到 100 requests/sec,因此这是一个非常真实的场景,当一个新请求进来时,C 程序将很忙。PHP 处理得很好,但是 Node.js 经常因错误而失败:
{
"code": "EAGAIN",
"errno": "EAGAIN",
"syscall": "connect",
"address": "/tmp/service.sock"
}
我假设这是因为 PHP 执行某种消息 queue/retry 将确保所有消息都发送到 C 程序(Node.js 不会)。
是否有一种简单的方法可以在 Node.js 中执行相同的操作,或者我是否必须实现自定义消息队列?
C 套接字创建:
int listenSocket, newSocket;
struct sockaddr_un localAddress, remoteAddress;
// Create socket
if ((listenSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1){
printf("Error opening listener socket");
exit(1);
}
// Configure socket
localAddress.sun_family = AF_UNIX; // Set UNIX domain socket type
strcpy(localAddress.sun_path, "/tmp/service.sock");
unlink(localAddress.sun_path); // Remove any previous instances of the socket
// Open listener socket
int len = strlen(localAddress.sun_path) + sizeof(localAddress.sun_family);
if (bind(listenSocket, (struct sockaddr *)&localAddress, len) == -1){
printf("Error binding socket at %s", localAddress.sun_path);
exit(1);
}
chmod(localAddress.sun_path, 0777);
// Listen for new connections on the listener socket
if (listen(listenSocket, 5) == -1){
printf("Error listening on listener socket");
exit(1);
}
// Handle new connections
while(!shutdown){
printf("Waiting for a connection...\n");
// Accept new connection
int sizeofRemoteAddress = sizeof(remoteAddress);
if ((newSocket = accept(listenSocket, (struct sockaddr *)&remoteAddress, &sizeofRemoteAddress)) == -1){
printf("Error accepting new connection: %s\n", strerror(errno));
continue;
}
// Read and handle data from client...
}
正在连接到 PHP 中的套接字:
$socket = @socket_create(AF_UNIX, SOCK_STREAM, 0);
if (!$socket) return false;
$connected = @socket_connect($socket, "/tmp/service.sock");
if (!$connected) return false;
// Send message to server and read response...
正在连接到 Node.js 中的套接字:
new Promise(function(resolve, reject){
var socket = Net.connect("/tmp/service.sock");
socket.on("error", function(err){
reject(err);
});
socket.on("connect", function(){
socket.write(message);
});
socket.on("data", function(data){
socket.end();
resolve(data.toString("UTF-8"));
});
});
EAGAIN
是系统调用中断时的预期情况。当您收到 EAGAIN
错误代码时,您应该简单地重复相同的调用。在典型的 C 程序中,您会看到大量 while (returnCode == -1 && errno == EAGAIN)
风格的循环。
如果您期望有很多中断,您可以先禁用中断(不确定 node.js 中是如何完成的)进行系统调用,然后再次启用中断。
不确定这个答案是否适合 node.js
应用程序,但我想我还是提到了它。