指定域名的IP地址

最近在用 artillery 做压测时遇到一个问题。我需要压测某一个通过域名访问的服务,而这个域名背后的机器地址需要随着压测用例变化的。通常这就是DNS要做的事情 - 把不变的域名和变化的地址关联起来 - 但我又没权限控制这个域名的解析地址。

另一个选择是跑到压测客户端的机器上,修改 /etc/hosts 让它指向不同的地址。不过压测客户端可不止一个,即使有办法批量下发 /etc/hosts 到每台机器上,事后我还需要把 /etc/hosts 给恢复回去,不然后面的人难免会踩坑。

还有一种选择,就是在客户端压测代码里根据不同的用例指定域名对应的IP。比如 curl 就有个 --resolve 参数可以指定域名和IP的对应关系,wrk 也可以通过 Lua 脚本设置。问题在于 artillery 并不支持这样的特性。

正在我一筹莫展之际,一个想法从脑海中蹦出来。我可以用 docker 封一层 artillery,然后通过 docker-compose 的 extra_hosts 配置设置映射关系。

version: '3'
services:
  benchmark:
    image: artillery:v1.6.0 # 我自己打了个 artillery v1.6.0 的镜像
    network_mode: "host"
    extra_hosts:
      # 映射关系在这里!
      - xxx.com:$XXX_HOST
    volumes:
      - .:/artillery
    command: artillery run xxx.yml

注意我这里使用了 $XXX_HOST 而不是直接在文件里写死 IP 地址。这样一来就能通过 docker-compose 的变量机制,在执行 docker-compose up 的时候通过环境变量注入真正的 IP 地址。就像这样:

$ XXX_HOST=192.168.0.123 docker-compose up

这下我只要根据测试用例的不同修改具体的命令行的值,就可以实现类似于 curl 的 --resolve 功能。

extra_hosts 的原理很简单,就是把配置文件里指定的映射关系写到容器的 /etc/hosts 文件,所以即使是 network_mode: "host" 下也能用。

指定 DNS

同样地,通过

dns:
  - 8.8.8.8

也能把 DNS 服务器地址写入到容器的 /etc/resolv.conf 文件,来自定义客户端用的DNS服务器。

利用多核

压测的过程中我们还发现一个问题:作为一个 node.js 应用,artillery 仅支持单核,而只跑一个 artillery 没办法充分利用客户端机器的性能。artillery 2.0 计划通过起多个worker的方式来用多个CPU,但远水解不了近渴,当前最新版本的 artillery 还不支持这一特性。好在我们已经套上了一个 docker 的壳,大可以通过 docker-compose 的方式起多个实例:

docker-compose up --scale benchmark=N

想一次性起多少个实例,就指定 N 为多少。当然这么做最后压测的结果需要自己计算各个实例的结果的总和。


spacewander
5.6k 声望1.5k 粉丝

make building blocks that people can understand and use easily, and people will work together to solve the very largest problems.