Nginx 实现负载均衡的几种方式

网络相关系统参数优化心得

  • 优化总体方向

    • 内核级别
    • 进程级别
    • 应用程序
      • 应用程序架构有几层优化几层
        • nginx,php-fpm 的分别优化
        • mysql,Innodb的分别优化
  • 优化总体思路

    • 分析自己服务的调用链,一个请求是怎么进来,怎么处理,又是怎么出去的。
    • 谁是请求发起方,谁是主动关闭方,这里牵扯到time-wait/range_port的问题
    • 参数相关优化点非常多,需要根据木桶理论找出最短的系统制约
      • 比如一个系统最大qps到300的时候可能带宽就满了,那你还优化系统参数有必要吗?默认就够了。
      • 如果你做的系统正是7层负载均衡,单机qps高到一定程度,自然有必要优化
    • 系统不一样,优化的点也不一样,切莫生搬硬套,我下面讲述的是需要注意的点,并不是必须要修改的点
  • 系统问题常用定位手段,注意是非程序级别bug

    • dmesg,系统日志
    • strace 进程调试
    • gdb
    • tcpdump抓包及回放
    • ss/netstat/lsof等等,netstat -s|grep overflow
  • 修改方式

    • sysctl -w net.core.netdev_max_backlog=102400
  • 内核级别几个重要参数优化

    • backlog,连接队列
      • net.core.netdev_max_backlog
      • net.ipv4.tcp_max_syn_backlog
      • net.core.somaxconn
        • 小于等于tcp_max_syn_backlog即可,这是单个端口backlog的上限
    • tcp链接释放过程
      • net.ipv4.tcp_fin_timeout=30
        • fin-wait-2阶段的最大时间
          • ss -nat -o state fin-wait-2 ‘( sport = :http )’
    -  net.ipv4.tcp_max_tw_buckets 
       - time-wait状态的总个数,注意是系统tw总个数,并不是单个端口服务
       - ss -nat|grep -i time-wait |wc -l  或 netstat -nat|grep -i time_wait|wc -l
       - 溢出后会报bucket overflow
    
    
    
    -  time-wait阶段耗时时间修改不了,等于2MSL 
       -  linux下一般一个MSL=30s,定义在net/tcp.h
    

    #define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT
                                  \* state, about 60 seconds */
    #define TCP_FIN_TIMEOUT TCP_TIMEWAIT_LEN
                                   /* BSD style FIN_WAIT2 deadlock breaker.
                                     \* It used to be 3min, new value is 60sec,
                                     \* to combine FIN-WAIT-2 timeout with
                                   \* TIME-WAIT timer.
                                    */

    • net.ipv4.tcp_tw_recycle,4.10以后废掉这个参数
      • 开启需谨慎,对于nat/lb服务慎重考虑,本质上是基于timestamps的
      • man tcp 可以查看对这个参数的定义
      • ip-sysctl.txt
    • net.ipv4.tcp_tw_reuse
      • client端服务可以无脑开启

以上两个参数生效需要依赖 net.ipv4.tcp_timestamps = 1,这个参数linux默认开启
真实实验观察:http://linuxsyseng.blogspot.com/2017/03/the-difference-with-tcptwrecycle-and.html

  • net.ipv4.ip_local_port_range
    • 这个是随机端口范围,当你去连接别人服务的时候,本地要随机选择一个端口去连接别人服务
    • 任何一个链接都是5元组构成的,(协议,源端口,源ip,目的端口,目的ip
    • 默认是3w左右,如果time-wait是60s,一般链接别人服务只有源端口是变量,也就是上限就是500qps。(其他条件都没到阈值,就ip_local_port_range最低的情况下)
    • 注意你统计的时候一定要控制变量,要有5元组的概念。
      • ss -nat -o state time-wait
1
2
3
If tcp_tw_recycle is enabled, tw_timeout value is set to rto. tw_timeout value will be very small, so that TIME_WAIT state socket will be closed very fast. Especially in local server communication (just like between same datacenter servers), rto is very short, so TIME_WAIT state socket is closed very very fast.
If tcp_tw_recycle is disabled, tw_timeout value is set to TCP_TIMEWAIT_LEN (In linux, it's 60 seconds)
It looks like tcp_tw_recycle is very good because TIME_WAIT state socket will be closed very fast, but it has problems. If you tcp_tw_recycle is enabled, kernel remember timestamp of last sent packet from client. If a timestamp of next packet is smaller than a timestamp of last sent packet that kernel remember, kernel will drop that incoming packet. It's very dangerous especially in NAT environments. (many ISP use nat environment for their customers.)
  • net.ipv4.tcp_rmem/wrem

  • net.ipv4.tcp_slow_start_after_idle

  • fs.file-max

    • 系统打开最大总文件数
  • 进程级别

    • 单进程打开最大总文件数
      • ulimit -n
  • 应用程序

    • backlog,连接队列
      • ss -natl 查看
    • 绑核/各系统有特定的参数,多看看文档

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!