Node.js 在网络库节点JS中获取请求的客户端ip
我在nginx后面的nodejs中使用粘性会话。 Sticky会话通过检查连接的remoteAddress来实现负载平衡。 现在的问题是它总是占用nginx服务器的ipNode.js 在网络库节点JS中获取请求的客户端ip,node.js,nginx,socket.io,Node.js,Nginx,Socket.io,我在nginx后面的nodejs中使用粘性会话。 Sticky会话通过检查连接的remoteAddress来实现负载平衡。 现在的问题是它总是占用nginx服务器的ip server = net.createServer({ pauseOnConnect: true },function(c) { // Get int31 hash of ip var worker, ipHash = hash((c.remoteAddress || '').split(/\./g),
server = net.createServer({ pauseOnConnect: true },function(c) {
// Get int31 hash of ip
var worker,
ipHash = hash((c.remoteAddress || '').split(/\./g), seed);
// Pass connection to worker
worker = workers[ipHash % workers.length];
worker.send('sticky-session:connection', c);
});
我们可以使用网络库获取客户端ip吗
Nginx配置:
server {
listen 80 default_server;
server_name localhost;
root /usr/share/nginx/html;
#auth_basic "Restricted";
#auth_basic_user_file /etc/nginx/.htpasswd;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://socket_nodes;
proxy_read_timeout 3000;
您正在使用的模块似乎还不支持使用反向代理源
看一看,一些pull请求似乎可以解决您的问题,因此您可以通过使用模块的fork(您可以)找到解决方案。您正在使用的模块似乎还不支持反向代理源
看一看,一些pull请求似乎可以解决您的问题,因此您可以通过使用模块的fork(您可以)找到解决方案。您正在使用的模块似乎还不支持反向代理源
看一看,一些pull请求似乎可以解决您的问题,因此您可以通过使用模块的fork(您可以)找到解决方案。您正在使用的模块似乎还不支持反向代理源
看一看,一些pull请求似乎可以解决您的问题,因此您可以通过使用模块的fork(您可以)找到解决方案。正如mef所指出的,目前,sticky session在反向代理之后不起作用,其中remoteAddress总是相同的。 上面提到的问题中的问题,以及之前的问题,可能确实解决了这个问题,尽管我还没有测试过自己 然而,这些修复依赖于部分解析数据包,在更高级别上查看报头的同时执行低级路由。。。正如pull请求上的注释所示,它们不稳定,依赖于未记录的行为,存在兼容性问题,可能会降低性能,等等 如果您不想依赖这样的实验性实现,另一种选择是将负载平衡完全留给nginx,nginx可以看到客户端的真实IP,从而保持会话的粘性。您所需要的只是nginx的内置ip_散列负载平衡 您的nginx配置可能如下所示:
upstream socket_nodes {
ip_hash;
server 127.0.0.1:8000;
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
server 127.0.0.1:8004;
server 127.0.0.1:8005;
server 127.0.0.1:8006;
server 127.0.0.1:8007;
}
server {
listen 80 default_server;
server_name localhost;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
# Note: Trusting all addresses like this means anyone
# can pretend to have any address they want.
# Only do this if you're absolutely certain only trusted
# sources can reach nginx with requests to begin with.
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://socket_nodes;
proxy_read_timeout 3000;
}
}
现在,要使其正常工作,还需要对服务器代码进行一些修改:
if (cluster.isMaster) {
var STARTING_PORT = 8000;
var NUMBER_OF_WORKERS = 8;
for (var i = 0; i < NUMBER_OF_WORKERS; i++) {
// Passing each worker its port number as an environment variable.
cluster.fork({ port: STARTING_PORT + i });
}
cluster.on('exit', function(worker, code, signal) {
// Create a new worker, log, or do whatever else you want.
});
}
else {
server = http.createServer(app);
// Socket.io initialization would go here.
// process.env.port is the port passed to this worker by the master.
server.listen(process.env.port, function(err) {
if (err) { /* Error handling. */ }
console.log("Server started on port", process.env.port);
});
}
if(cluster.isMaster){
var起始端口=8000;
工人的var数量=8;
对于(var i=0;i<工人数量;i++){
//将每个辅助进程的端口号作为环境变量传递。
fork({port:STARTING_port+i});
}
集群打开('exit',功能(工作者、代码、信号){
//创建一个新的工作程序、日志或执行任何您想要的操作。
});
}
否则{
server=http.createServer(app);
//Socket.io初始化将转到此处。
//process.env.port是主机传递给此辅助进程的端口。
侦听(process.env.port,函数(err){
if(err){/*错误处理。*/}
log(“服务器在端口上启动”,process.env.port);
});
}
不同之处在于,不是使用集群让所有工作进程共享一个端口(由集群本身平衡负载),而是每个工作进程都有自己的端口,nginx可以在不同的端口之间分配负载,以到达不同的工作进程
由于nginx根据它从客户机(或您的情况下的X-Forwarded-For报头)获得的IP选择要转到哪个端口,因此同一会话中的所有请求将始终以相同的进程结束
当然,这种方法的一个主要缺点是,工人数量的动态性大大降低。如果端口在nginx配置中是“硬编码”的,那么节点服务器必须确保始终严格侦听这些端口,不少于也不多于。如果没有一个好的系统来同步nginx配置和节点服务器,这就引入了错误的可能性,并使得动态扩展到环境中的核心数量变得更加困难
然后,我再次设想,可以通过编程方式生成/更新nginx配置来克服这个问题,因此它总是反映所需的进程数,或者可能通过为nginx配置大量端口,然后根据需要让每个节点工作线程侦听多个端口(因此,您仍然可以拥有与内核数量相同的工作人员)。然而,到目前为止,我还没有亲自验证或尝试实施这两种方法
关于代理后面的nginx服务器的说明 在您提供的nginx配置中,您似乎使用了ngx_http_realip_模块。虽然您在问题中没有明确提及这一点,但请注意,在nginx本身位于某种代理(例如ELB)后面的情况下,这实际上可能是必要的 然后需要使用
real\u ip\u header
指令来确保散列以选择要转到哪个端口的是真正的客户端ip(例如X-Forwarded-For),而不是其他代理
在这种情况下,nginx实际上提供了一个与sticky session的pull请求试图实现的目的非常相似的目的:使用头来做出负载平衡决策,特别是确保相同的真实客户端IP始终指向相同的进程
当然,关键的区别在于,nginx作为一个专用的web服务器、负载均衡器和反向代理,被设计来完成这类操作。解析和操作协议栈的不同层是它的主要任务。更重要的是,尽管还不清楚有多少人实际使用了这些pull-requ在EST、nginx中,它是稳定的、维护良好的,几乎在任何地方都可以使用。正如mef所指出的,sticky session目前不能在反向代理之后工作,因为在反向代理中,remoteAddress总是相同的。 上面提到的问题中的问题,以及之前的问题,可能确实解决了这个问题,尽管我还没有测试过自己 然而,这些修复依赖于