zoukankan      html  css  js  c++  java
  • HAProxy压测及参数调优

    背景

    小米容器云平台,在构建云厂商集群时,需要通过HAProxy将云厂商LB流量从宿主机转到容器中,但对于HAProxy的性能没有把握。参考网上的一篇HAProxy压测文章,文章中提到HAProxy establish状态连接可以达到 400w,所以以此为目标,进行压测。

    参考文章:文章地址

    关键点

    TCP计数器ListenOverflows大量增加

    查看方法

    cat /proc/net/netstat | awk '/TcpExt/ { print $21,$22 }'

    原因

    系统调用listen函数(int listen(int sockfd, int backlog);)的队列长度由min(backlog ,内核参数 net.core.somaxconn ) 决定,对应socket的listen 队列已满的情况下,在新增一个连接时的情况,ListenOverflows计数器加 1 。

    解决方案

    调整系统参数 net.core.somaxconn = 65535 #默认为128

    HAProxy 耗尽cpu问题

    现象

    HAProxy绑定4核cpu、8核cpu、16核cpu,压测的时候,都会出现CPU 100%被使用的情况。

    追查过程

    1. 通过 mpstat  -P ALL 1 命令查看cpu 都用在哪里,可以看到cpu都绝大部分用在 sys态上。

    2. 通过 strace -p pid -c 查看HAProxy 进程那个系统调用占用cpu 最多,看到cpu 都用在了 connect系统调用上。

    3. HAProxy连接后端会使用connect系统调用,查看HAProxy配置,发现HAProxy连接后端就只有两个后端,即这种情况: vegeta(40台压测机器)-》HAProxy-》httptest(2台HAProxy后端),其中 HAProxy连接后端最多只能有63000个端口左右,大量的连接积压在HAProxy机器上,导致cpu被耗尽了。

     

    解决方案

    大量增加HAProxy的后端,解决HAProxy后端过少的瓶颈。

    网卡 drop 数据包

    现象

    压测的时候,ifconfig发现网卡eth0  RX 出现 droppped。

    解决方案

    1. 调大网卡Ring buffer

    查看:ethtool -g eth0

    设置Ring buffer到上限:ethtool -G eth0 rx 4096;ethtool -G eth0 tx 4096

    2. 调网卡队缓存队列

    net.core.netdev_max_backlog = 2000000  #默认为1000,内核参数配置时,有具体的解释

    最新稳定版HAProxy性能

    系统自带版本  1.5.18

    编译HAProxy 最新稳定版本(1.7.5 ) 

    wget http://www.haproxy.org/download/1.7/src/haproxy-1.7.5.tar.gz
    tar -xzvf haproxy-1.7.5.tar.gz
    cd haproxy-1.7.5/
    make  TARGET=linux2628  USE_CPU_AFFINITY=1

    压测时资源使用情况

    mem:

    最新新版:10G

    系统自带版本:102G,由于内存不够,使用了swap,

    引起cpu iowait占大量增加,导致cpu idle为0。

    cpu idle:

    最新新版:35%

    系统自带版本:0% 

    结论

    相同压力下,新版HAProxy使用内存大量减少。

    环境搭建

    HAProxy

    机器

    1台,24 cpu、128G内存的i1 机器

    系统版本

    centos 7.2

    安装系统自带HAProxy:yum install haproxy

    sysctl.conf 配置

    ### 系统中所允许的文件句柄的最大数目
    fs.file-max = 12553500
    ### 单个进程所允许的文件句柄的最大数目
    fs.nr_open = 12453500
    ### 内核允许使用的共享内存大 Controls the maximum number of shared memory segments, in pages
    kernel.shmall = 4294967296
    ###单个共享内存段的最大值 Controls the maximum shared segment size, in bytes
    kernel.shmmax = 68719476736
    ### 内核中消息队列中消息的最大值 Controls the maximum size of a message, in bytes
    kernel.msgmax = 65536
    ### 系统救援工具
    kernel.sysrq = 0
    ### 在每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到缓存队列的数据包的最大数目
    net.core.netdev_max_backlog = 2000000
    ### 默认的TCP数据接收窗口大小(字节)
    net.core.rmem_default = 699040
    ### 最大的TCP数据接收窗口(字节)
    net.core.rmem_max = 50331648
    ### 默认的TCP数据发送窗口大小(字节)
    net.core.wmem_default = 131072
    ### 最大的TCP数据发送窗口(字节)
    net.core.wmem_max = 33554432
    ### 定义了系统中每一个端口最大的监听队列的长度,这是个全局的参数
    net.core.somaxconn = 65535
    
    ### TCP/UDP协议允许使用的本地端口号
    net.ipv4.ip_local_port_range = 15000 65000
    net.ipv4.ip_nonlocal_bind = 1
    ### 对于本端断开的socket连接,TCP保持在FIN-WAIT-2状态的时间(秒)
    net.ipv4.tcp_fin_timeout = 7
    ### TCP发送keepalive探测消息的间隔时间(秒),用于确认TCP连接是否有效
    net.ipv4.tcp_keepalive_time = 300
    net.ipv4.tcp_max_orphans = 3276800
    ### 对于还未获得对方确认的连接请求,可保存在队列中的最大数目
    net.ipv4.tcp_max_syn_backlog = 655360
    net.ipv4.tcp_max_tw_buckets = 6000000
    ### 确定TCP栈应该如何反映内存使用,每个值的单位都是内存页(通常是4KB)
    ### 第一个值是内存使用的下限;第二个值是内存压力模式开始对缓冲区使用应用压力的上限;第三个值是内存使用的上限.
    net.ipv4.tcp_mem = 94500000 915000000 927000000
    ### 为自动调优定义socket使用的内存。
    ### 第一个值是为socket接收缓冲区分配的最少字节数;
    ### 第二个值是默认值(该值会被rmem_default覆盖),缓冲区在系统负载不重的情况下可以增长到这个值;
    ### 第三个值是接收缓冲区空间的最大字节数(该值会被rmem_max覆盖)
    net.ipv4.tcp_rmem = 32768 699040 50331648
    ### 为自动调优定义socket使用的内存。
    ### 第一个值是为socket发送缓冲区分配的最少字节数;
    ### 第二个值是默认值(该值会被wmem_default覆盖),缓冲区在系统负载不重的情况下可以增长到这个值;
    ### 第三个值是发送缓冲区空间的最大字节数(该值会被wmem_max覆盖)
    net.ipv4.tcp_wmem = 32768 131072 33554432
    net.ipv4.tcp_slow_start_after_idle = 0
    net.ipv4.tcp_synack_retries = 2
    ### 表示是否打开TCP同步标签(syncookie),同步标签可以防止一个套接字在有过多试图连接到达时引起过载
    ### 内核必须打开了CONFIG_SYN_COOKIES项进行编译,
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_syn_retries = 2
    ### 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
    net.ipv4.tcp_tw_recycle = 1
    ### 允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭
    net.ipv4.tcp_tw_reuse = 1
    ### 启用RFC 1323定义的window scaling,要支持超过64KB的TCP窗口,必须启用该值(1表示启用),
    ### TCP窗口最大至1GB,TCP连接双方都启用时才生效,默认为1
    net.ipv4.tcp_window_scaling = 1
    ### 最大限度使用物理内存
    vm.swappiness = 0

    HAProxy配置

    global
    log /dev/log local0
    log /dev/log local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 600s
    user haproxy
    group haproxy
    daemon
    #tune.ssl.default-dh-param 2048
    maxconn 4000000
    nbproc 23
    cpu-map 1 1
    cpu-map 2 2
    cpu-map 3 3
    cpu-map 4 4
    cpu-map 5 5
    cpu-map 6 6
    cpu-map 7 7
    cpu-map 8 8
    cpu-map 9 9
    cpu-map 10 10
    cpu-map 11 11
    cpu-map 12 12
    cpu-map 13 13
    cpu-map 14 14
    cpu-map 15 15
    cpu-map 16 16
    cpu-map 17 17
    cpu-map 18 18
    cpu-map 19 19
    cpu-map 20 20
    cpu-map 21 21
    cpu-map 22 22
    cpu-map 23 23
    stats bind-process 23
    defaults
    log global
    mode tcp
    option tcplog
    option dontlognull
    maxconn 4000000
    timeout connect 5000
    timeout client 60000
    timeout server 60000
    # Template Customization
    frontend http-in
    bind :8200
    stats enable
    mode http
    option httplog
    stats auth admin:admin
    stats uri /haproxy_stats
    
    listen port-30000
    bind :30000
    mode tcp
    option tcplog
    balance roundrobin
    server staging1 ……
    ……

    HAProxy后端服务

    机器

    10台,8 cpu、32G内存的3U8机器

    系统版本

    centos 7.2

    程序

    简写一个API server 

    压测机器

    机器

    80台,8/32 cpu,32/128G内存的机器,机器配置不好统一,所以用80台机器做压测,解决压测端性能、内核参数机器参差不齐的问题。

    程序

    vegeta   https://github.com/tsenart/vegeta

    总结

    压测效果复合预期

    压测效果基本符合预期,最终establish状态连接达到696W,占用10G内存,CPU使用66%(暂时没有ssl需求,所以没有压测ssl卸载),具体如图:

    关键知识点

    TCP连接, srcIp:srcPort -》 dstIp:dstPort    srcPort最多63k,并发流量超过63k的时候,应用进程会占用大量cpu。注意压测机器,同样受此限制。

    阅读原文

  • 相关阅读:
    马士兵讲jsp项目--BBS项目分析笔记
    ubuntu 14.04中安装phpmyadmin即mysql图形管理界面
    Xman冬令营writeup
    python--gevent协程及协程概念
    python--multiprocessing多进程总结
    python--threading多线程总结
    浅析Java中print、printf、println的区别
    内存泄漏与内存溢出
    Java中==和equals的区别,equals和hashCode的区别
    vue五十七:电影院售票项目案例之使用swiper实现轮播功能
  • 原文地址:https://www.cnblogs.com/276815076/p/8004039.html
Copyright © 2011-2022 走看看