高并发 TCP 的 time_wait 问题。为什么服务器资源会被占满 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Moonkin
V2EX    问与答

高并发 TCP 的 time_wait 问题。为什么服务器资源会被占满

  •  2  
  •   Moonkin 2020-06-10 09:36:51 +08:00 4351 次点击
    这是一个创建于 1951 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一个端口可以建立 2^16 个 TCP 链接吧,为什么讲解 time_wait 的博客大多都是说服务器端口被占满,难道一般情况下设计的服务器是为每一个 TCP 链接单独占用一个端口吗?

    所有空闲端口*每个端口 2^16 个链接,差不多可以有 2^30 个链接,这样的话,不会发生 time_wait 过多的问题吧?

    所以 time_wait 到底是占用了什么导致后续客户端访问被拒绝的?

    第 1 条附言    2020-06-10 10:41:26 +08:00
    EDIT:比如这个面试题,“问若客户端和服务器之间,1s 会发生 5000 到 6000 次短链接,会发生什么问题”,如果只有持续了一两秒,是不是没什么问题?如果几分钟时间内每秒都是这么多链接,是不是才会有 fd 资源占用过多的问题?
    27 条回复    2020-06-13 19:25:58 +08:00
    soulzz
        1
    soulzz  
       2020-06-10 10:02:05 +08:00
    他们可能不知道 nio
    time_wait 基本都是卡在数据库那里了
    如果请求方做了超时处理,这时候就成了 close_wait 了
    zjj19950716
        2
    zjj19950716  
       2020-06-10 10:02:59 +08:00 via iPhone
    cpu fd 内核参数 ?
    hopingtop
        3
    hopingtop  
       2020-06-10 10:16:33 +08:00
    如果服务是短链接,例如 HTTP 这种,高并发情况下,会创建很多新的 TCP 新链接。当服务器主动发起 FIN 包关闭链接时,会出现 2 个 MSL 的等待时间(此时的 fd 资源是没有释放的),这都是为了安全关闭 TCP 链接所做的机制。可以修改系统参数,适当的缓解 time_wait 这种情况。
    fxxkgw
        4
    fxxkgw  
       2020-06-10 10:19:42 +08:00
    我记得看过的 time_wait 都是基本上说是占用系统资源,没有特别强调说把端口占满这种问题。。。正常端口范围是 1024-65535 之间

    不过 time_wait 状态最好的办法就是扩容机器,盲目把 tcp_tw_recycle=1,在 NAT 环境下因为服务器间系统时间不一致,导致包时间戳不一致而产生丢包这种问题能折腾死人。
    rrfeng
        5
    rrfeng  
       2020-06-10 10:22:26 +08:00
    fd 也是一种资源,一般是受限的( ulimit )
    @fxxkgw
    Moonkin
        6
    Moonkin  
    OP
       2020-06-10 10:45:47 +08:00
    @soulzz nio time_wait 过多的问题有哪方面帮助啊? nio 是高并发的时候不需要每个为 socket new 一个处理线程吧。。
    Moonkin
        7
    Moonkin  
    OP
       2020-06-10 10:48:04 +08:00
    @zjj19950716
    @hopingtop
    @fxxkgw
    @rrfeng
    我看这个 StackOverflow 上面的回答也是说 TCP 链接数目没有限制,是 fd 限制。。。可能我之前看的博客比较水吧。。。
    https://stackoverflow.com/questions/2332741/what-is-the-theoretical-maximum-number-of-open-tcp-connections-that-a-modern-lin
    liuminghao233
        8
    liuminghao233  
       2020-06-10 10:57:46 +08:00 via iPhone
    你要是没用 reuseaddr
    timewait 的时候用那个端口是不可用的
    如果你几秒钟内把 2^16 个端口都用了
    timewait 还没到时间
    那么就没有端口用了
    Moonkin
        9
    Moonkin  
    OP
       2020-06-10 11:05:46 +08:00
    @liuminghao233 也就是说,没有 reuseaddr 的话,每个端口只能有一个 TCP 链接吗?
    raynor2011
        10
    raynor2011  
       2020-06-10 11:07:36 +08:00
    是发起短连接的客户端会有 time_wait 占用端口问题, 服务器不会有这个问题
    SAIKAII
        11
    SAIKAII  
       2020-06-10 11:17:28 +08:00 via iPhone
    1. 首先,每次来一个连接都对应一个套接字,套接字由(local_ip, local_port, remote_ip, remote_port)标志,然后每个新的连接套接字的本地 ip 和 port 不变,变的是 remote 的 ip 和 port 。
    2,每个套接字对应一个文件描述符 fd,fd 用完就无法再创建了。wait_time 导致的资源耗尽是 fd 的耗尽,这个资源大小可以修改。
    misaka19000
        12
    misaka19000  
       2020-06-10 11:17:28 +08:00
    time_wait 一般是短连接太多导致的吧,解决办法是尽量复用 TCP 连接
    misaka19000
        13
    misaka19000  
       2020-06-10 11:20:49 +08:00
    楼上的一些文字真是让我很诧异,time_wati 和 nio 没关系,和 fd 也没关系

    我估计楼主想问的是另一个问题:一个端口可以对应多个 TCP 链接吗?
    答案是可以的,因为 client_host:client_port -- server_host:server_port 为一个连接,可见服务器端是可以维护多个连接的,一个连接会占用一个 fd,fd 由操作系统限制并且可以修改
    sagaxu
        14
    sagaxu  
       2020-06-10 11:32:14 +08:00 via Android
    time_wait 的时候,fd 已经 close 掉了,怎么个占用法呢?
    Moonkin
        15
    Moonkin  
    OP
       2020-06-10 11:53:11 +08:00
    @misaka19000 那 time_wait 的危害是什么呢?为什么要减少 time_wait 。。。
    Moonkin
        16
    Moonkin  
    OP
       2020-06-10 11:56:24 +08:00
    @raynor2011 也就是说客户端一个端口只能发起一个 tcp 链接吗?我看 StackOverflow 说“一个端口可以有 64K 个 tcp 链接”,这是说端口在服务器被监听的情况下才可以吗?发起方不能发起 64K 个?
    gravitybox
        17
    gravitybox  
       2020-06-10 12:21:37 +08:00
    @Moonkin time_wait 会占着端口不放,如果有大量的连接处于 time_wait,那么可能后续无法分配端口了。
    misaka19000
        18
    misaka19000  
       2020-06-10 13:11:32 +08:00
    @Moonkin #14 一个 time_wait 代表了一个未被释放的 TCP 连接,总归是会占用一些内存的,如果出现了大量的 time_wait 需要考虑是不是系统被攻击了或者有什么可以优化的地方
    Moonkin
        19
    Moonkin  
    OP
       2020-06-10 16:32:22 +08:00
    @gravitybox 只有一个服务器而且只有一个客户端 才会出现端口占满的情况吧,因为这种情况只能客户端改变端口标识唯一 tcp
    liuminghao233
        20
    liuminghao233  
       2020-06-10 16:56:52 +08:00 via iPhone
    @Moonkin
    假设你有个 tcp
    10.10.10.10:6666远程 8.8.8.8:80 timewait 了
    你就暂时不能用
    [10.10.10.10:66668.8.8.8:80]
    但是有 reuseort 的话
    虽然[10.10.10.10:66668.8.8.8:80]还是用不了
    但是你可以用[10.10.10.10:66668.8.8.8:83]
    或者是[10.10.10.10:66668.8.8.2:80]
    liuminghao233
        21
    liuminghao233  
       2020-06-10 16:58:37 +08:00 via iPhone
    打错了 是 reuseaddr
    Moonkin
        22
    Moonkin  
    OP
       2020-06-10 17:21:28 +08:00
    @liuminghao233 #20 嗯,懂啦,谢谢大佬。查了查 so_reuseaddr 和 so_reuseport,感觉我这个问题还是得事先说清楚是不是 reuse
    https://stackoverflow.com/questions/14388706/how-do-so-reuseaddr-and-so-reuseport-differ
    akira
        23
    akira  
       2020-06-10 18:11:33 +08:00
    @fxxkgw 对的,之前我们有遇到过这个情况,他们查了一个多月都没查到问题
    catror
        24
    catror  
       2020-06-10 18:20:58 +08:00 via Android
    time_wait 是客户端的状态……占用的我是客户端的资源
    julyclyde
        25
    julyclyde  
       2020-06-11 10:36:08 +08:00
    “讲解 time_wait 的博客大多都是说服务器端口被占满”的主要原因是文盲
    wanguorui123
        26
    wanguorui123  
       2020-06-12 08:48:40 +08:00 via iPhone
    修改 Linux 的参数,time_wait 都杀掉
    gravitybox
        27
    gravitybox  
       2020-06-13 19:25:58 +08:00
    “一个端口可以建立 2^16 个 TCP 链接吧”
    答:一个端口可以建立不只 2^16 个 TCP 连接。标识一个 tcp 套接字是四元组,你现在只限定了源 ip 和源端口。
    你这里的语境应该是:
    1 、有一组固定的客户端 A 和服务端 B,即源 ip 和目的 ip 是固定的
    2 、有服务端端口 6379,例如 B 上运行着 Redis 服务,绑定端口 6379

    那么客户端 A 最多能和服务端 B 同时建立 65535-1024 个 tcp 连接。


    “为什么讲解 time_wait 的博客大多都是说服务器端口被占满”
    答:time_wait 是最先发 FIN 包的那一端才会有的状态,一般服务端不会主动断连,大多是客户端主动挥手,断开连接。


    “难道一般情况下设计的服务器是为每一个 CP 链接单独占用一个端口吗?”
    答:服务端不会为每个 tcp 连接再分配端口。服务端为每个新的 tcp 连接会创建一个套接字,tcp 套接字是以四元组标识的,新的 tcp 连接,即对应不同的客户端 ip 或客户端端口。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     972 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 53ms UTC 19:00 PVG 03:00 LAX 12:00 JFK 15:00
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86