【问题标题】:Can't reach max tcp connections for single server无法达到单个服务器的最大 tcp 连接数
【发布时间】:2019-09-07 07:42:43
【问题描述】:

我正在 CentOS7 中测试最大 tcp 连接。我将打开文件限制更改为 1000000(ulimit -n 1000000) 并编辑sysctl.conf,如下所示。然后我用 node.js 测试如下代码(单服务器):

var net = require('net');
var count = 0
//server
let server = net.createServer(function(conn){
    conn.on("close", function(code, reason){
        console.log("close", code, reason);
    })
    conn.on("error", function(code, reason){
        console.log("error close", code, reason);
    })
}).listen({port : 8080, host: "0.0.0.0", backlog: 100000}).on("connection", _=>{count++});

//client
setInterval(_=>{new Array(300).fill(1).map((_,index)=>index+1926).map(p=>{
    new net.Socket().connect(8080,'127.0.0.1')
        .on('error',function(e){
            console.log(count);
            console.log(e);
            process.exit()}
        );
    })&&console.log('connection count:',count)},10)

结果:

connection count: 64200
connection count: 64500
64500
{ Error: connect EADDRNOTAVAIL 127.0.0.1:8080 - Local (127.0.0.1:0)
    at internalConnect (net.js:872:16)
    at defaultTriggerAsyncIdScope (internal/async_hooks.js:294:19)
    at defaultTriggerAsyncIdScope (net.js:962:9)
    at process._tickCallback (internal/process/next_tick.js:61:11)
  errno: 'EADDRNOTAVAIL',
  code: 'EADDRNOTAVAIL',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 8080 }

当连接数达到 64500 时,它会抛出 EADDRNOTAVAIL。 然后我尝试了多个服务器如下:

var net = require('net');
var count = 0
//server
new Array(300).fill(1).map((_,index)=>index+1926).map(p=>{
    net.createServer().listen(p).on('connection',_=>count++)
    })

//client
setInterval(_=>{new Array(300).fill(1).map((_,index)=>index+1926).map(p=>{
    new net.Socket().connect(p,'127.0.0.1')
        .on('error',function(e){
            console.log(e);
            process.exit();
        })})&&console.log('connection count:',count);},10)

结果:

connection count: 392400
connection count: 392700
Aborted (core dumped)

为什么多服务器连接可以超过390000而单服务器连接只能达到64500并抛出EADDRNOTAVAIL错误?


/etc/sysctl.conf:

net.ipv4.tcp_tw_reuse = 1

net.ipv4.tcp_tw_recycle = 1

net.ipv4.tcp_fin_timeout = 10

net.ipv4.tcp_keepalive_time = 1200

net.ipv4.tcp_max_tw_buckets = 5000

fs.file-max = 1000000

net.ipv4.ip_local_port_range= 1024 65535

net.core.somaxconn = 65535

net.ipv4.tcp_syncookies = 1

net.ipv4.tcp_max_syn_backlog = 65535

net.ipv4.tcp_synack_retries = 2

net.ipv4.tcp_syn_retries = 2

【问题讨论】:

    标签: node.js linux sockets tcp centos7


    【解决方案1】:

    您没有绑定出站连接套接字。这会导致操作系统为它们分配本地源 IP 地址和端口。很可能它对所有这些都使用相同的本地源 IP 地址 (127.0.0.1),因此只有大约 65,000 个端口。将它自己绑定到环回范围内的本地 IP 地址和非特权范围内的端口的随机组合。如果您得到EADDRNOTAVAIL,请尝试不同的随机组合。

    【讨论】:

    • 但是多个服务器版本仍然使用相同的本地源IP地址,为什么可以连接超过65000?
    • 如果你绑定一个socket到本地IP地址,你还能用它连接远程IP吗?
    • @GapMAX 可以通过连接的服务器区分连接。
    • @peterh 否。如果您只有一个源 IP 地址可用于与侦听单个端口的单个远程服务器通信,那么您的连接数不能超过 65,000 个它。
    • @DavidSchwartz Afaik 你是对的。但我认为不应该这样 - 远程 ip:port 应该仍然可以用来区分套接字之间的数据包。 connect()bind() 只有在会导致 src_ip:src_port:dst_ip:dst_port 冲突时才应被拒绝。只有 src_ip:src_port 冲突应该不是问题。
    猜你喜欢
    • 2020-06-03
    • 2012-07-30
    • 1970-01-01
    • 2017-02-24
    • 2020-09-09
    • 1970-01-01
    • 1970-01-01
    • 2019-10-15
    • 1970-01-01
    相关资源
    最近更新 更多