前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何做负载均衡的并发测试?

如何做负载均衡的并发测试?

原创
作者头像
路痴赵大宝
发布2021-02-03 16:14:26
3.5K0
发布2021-02-03 16:14:26
举报

本文的内容参考了InfoQ翻译的文章我们是如何优化 HAProxy 以让其支持 2,000,000 个并发 SSL 连接的?

负载均衡的并发测试,主要目标是测试负载均衡系统支持的最大并发连接数量。本文将介绍测试中应用的部署,测试的工具以及测试的过程。

压测负载均衡
压测负载均衡

一个TCP连接由一个五元组唯一确定:IP层协议、源IP地址、目的IP地址、源端口和目的端口。在负载均衡的测试过程中,有3个参数是不可变的:IP层协议、目的IP和目的端口,其中IP层协议是TCP,目的IP是负载均衡的IP地址,目的端口是负载均衡监听器的TCP端口。可变的参数只有源IP地址和源端口,而可用的源端口号通常只有1025~65534大约64k,所以为了达到更大的并发连接,我们就需要更多的源IP,也就是更多的客户端。

同样,我们也需要更多的应用服务器,负载均衡与应用服务器之间也需要建立TCP连接,应用服务器看到的源IP地址只是负载均衡的IP地址。

这里我们准备了20台压测客户端,20台应用服务器,理论上能够最大能够建立64k*20=1280k,大约128万。


首先介绍压力用到的两个工具。

工具一:pdsh

pdsh是一个并行登录远程主机执行命令的工具,我们需要同时从20台客户端机器发起压测,pdsh可以轻松的帮助完成。

pdsh的源码可以从github下载,按照文档编译安装

pdsh命令的使用举例如下:

# 需要配置SSH互信
# -w指定多个主机
pdsh -w 192.168.59.[1-10] -l root uptime
# -w使用逗号指定多个主机
pdsh -w 192.168.59.1,192.168.59.2 -l root uptime
# -x排除某个主机
pdsh -w 192.168.59.[1-10] -x 192.168.59.3 -l root uptime
# 使用主机组,把对应的主机写入到/etc/dsh/group/或~/.dsh/group/目录下的文件中即可
# 文件名就是对应组名
pdsh -g client-hosts -l root uptime
# 使用dshbak格式化输出
pdsh -g client-hosts -l root uptime | dshbak -c

工具二:vegeta

vegeta是一款优秀的HTTP压力测试工具,它本身的性能很好,保证了客户端不会成为测试中的瓶颈,同时它能以固定的频率发起连接,在并发测试中表现出众。

vegeta的源码可以从github下载,也可以直接下载编译好的二进制包

vegeta命令的使用举例如下:

# Usage: vegeta [global flags] <command> [command flags]
# 执行压测的命令是attack,查看报告的命令是report
echo "GET <https://192.168.60.246>" | vegeta -cpus=32 attack -duration=10m  \
  -rate=2000 -workers=500  | tee reports.bin | vegeta report

vegeta常用的选项:

  • -cpus:指定使用CPU的个数,默认使用所有的CPU
  • -body:指定request body文件
  • -duration:指定测试的时长,比如10m表示10分钟
  • -header:指定HTTP header
  • -insecure:忽略校验server的TLS证书
  • -keepalive:使用长连接(默认为true)
  • -rate:请求的频率,默认是50/1s
  • -workers:初始的worker个数,默认是10
  • -connection:每个target打开的最大的连接数,默认是10000
  • -timeout:请求的超时时间,默认是30s

接下来首先介绍如何部署测试的应用。

部署应用

最简单的方式是部署一个HTTP应用,只需要在应用服务器上安装httpd或者nginx等Web服务就好了,但是为了能够真正的测试出最大的并发连接,还需要一些额外的修饰。

假设目标是达到100万的并发连接,每个连接的平均处理时长是1秒,意味着每秒需要新建100万的连接,这对我们的模拟环境来说是一个很难达到的目标。另一方面,TCP连接断开之后的一段时间内,连接会处于time_wait/close_wait/fin_wait状态,为了保证TCP连接能够正确的释放,操作系统无法立即重用这些端口,就会出现可用端口不足的问题。

所以我们的目标就是延长每一个请求的处理时长,假设一个请求的处理时长是100秒,为了达到100万的目标,每秒只需要发起1万个连接,这对大多数压测工具不是问题。

这里提供两种部署方式,一种是用go实现一个简单的HTTP server,它收到请求之后会休眠100秒,然后返回5个字节,代码如下:

package main

import (
    "fmt"
    "log"
    "time"
    "net/http"
)

func response(w http.ResponseWriter, r *http.Request) {
    time.Sleep(time.Duration(100)*time.Second)
    fmt.Fprint(w, "ping\\n")
}

func main() {
    http.HandleFunc("/", response)
    err := http.ListenAndServe(":80", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

另一种是利用nginx的echo_sleep模块,nginx的配置文件如下:

# For more information on configuration, see:
#   * Official English Documentation: <http://nginx.org/en/docs/>
#   * Official Russian Documentation: <http://nginx.org/ru/docs/>

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
#include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1000000;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See <http://nginx.org/en/docs/ngx_core_module.html#include>
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        #include /etc/nginx/default.d/*.conf;

        location / {
        }

        location /sleep5 {
            echo_sleep 5;
            echo "sleep 5s";
        }

        location /sleep100 {
            echo_sleep 100;
            echo "sleep 100s";
        }

        location /sleep1200 {
            echo_sleep 1200;
            echo "sleep 1200s";
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
}

除了调整应用的处理时间,还需要调整一些Linux内核参数,让应用服务器能够接受大量的并发连接。

首先编辑文件/etc/security/limits.conf,增加以下两行:

* soft nofile 1000000
* hard nofile 1000000

然后编辑文件/etc/sysctl.conf,增加如下内容:

fs.file-max = 1000000
fs.nr_open = 1000000
net.ipv4.ip_local_port_range = 1025 65534
net.core.netdev_max_backlog = 100000
net.core.somaxconn = 65534
net.ipv4.tcp_max_orphans = 5800000
net.ipv4.tcp_max_syn_backlog = 100000
net.nf_conntrack_max = 2097152

另外需要注意,如果使用systemd启动nginx的话,为了使limits的配置生效,需要新建配置文件 /etc/systemd/system/nginx.service.d/override.conf,内容如下:

[Service]
LimitNOFILE=1000000

最后重启应用服务器使配置生效。

测试过程

1. 准备压测机器

准备20个压测机器client1~client20,作为压力测试的客户端,同样按照前面的说明调整内核参数。

将压测工具vegeta安装到压测虚拟机的/usr/local/bin目录。

登录到client1,作为工作机,安装pdsh,配置client1到其他client虚拟机的SSH互信:

# 这里假设client的IP地址是192.168.56.10~192.168.56.29
# 配置互信
ssh-copy-id 192.168.56.10
ssh-copy-id 192.168.56.11
ssh-copy-id 192.168.56.12
……

# 测试互信,
pdsh -w 192.168.56.[10-29] uptime

2. 准备负载均衡

部署好负载均衡,添加前面准备的应用服务器作为成员。

另外需要注意的是调整负载均衡监听器的超时时间,因为负载均衡通常会主动断开长时间没有响应的连接,以避免异常的连接占用资源。以HAProxy为例,需要修改以下三个参数:

  • timeout connect 3000
  • timeout client 120000
  • timeout server 120000

3. 测试

使用下面的命令测试:

# 登录到client1,执行下面的命令:
pdsh -w 192.168.56.[10-29] "echo 'GET <http://192.168.60.246:8080>' | \
  vegeta -cpus=10 attack -connections=1000000 -duration=20m -timeout=1h \
  -rate=500/s | tee report.bin | vegeta report"

下图显示了我们在虚拟机中部署HAProxy,最终达到100万并发连接。

HAProxy达到100万并发连接
HAProxy达到100万并发连接

因为每一个客户端连接在LB中对应两个TCP连接:从client到HAProxy和从HAProxy到应用服务器,所以图中established状态的连接有200万

如果测试过程中观察到总的socket与established状态的socket个数相差很多,可能就是某处的超时时间有问题,导致连接被异常中止造成的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 工具一:pdsh
  • 工具二:vegeta
  • 部署应用
  • 测试过程
    • 1. 准备压测机器
      • 2. 准备负载均衡
        • 3. 测试
        相关产品与服务
        负载均衡
        负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档