为什么要压测
俗话说 "知己知彼,百战不殆",当我们上线一个新的系统或应用的时候,至少要知道这个系统或应用的上线在哪里,做直接的数据可能就是【吞吐量】是多少,【延时】是多少,【瓶颈】是什么。更多关于压测的指导可参考CoolShell 的性能测试应该怎么做?
压测工具
rally es 官方提供的一款压测工具。同时官方也将 es 的实时压测结果放在了 https://elasticsearch-benchmarks.elastic.co/ , 你可以将你自己的结果与它进行对比,官方是使用 2 台服务器进行压测,一台运行 rally, 一台运行 es, 服务器的配置如下:
CPU: Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
RAM: 32 GB
SSD: Crucial MX200
OS: Linux Kernel version 4.8.0-53
JVM: Oracle JDK 1.8.0_131-b11
rally
安装
# 创建虚拟环境
virtualenv venv
pip3 install esrally
# 配置 rally,默认在 ~/.rally 目录中
esrally configure
rally 相关术语
rally 是汽车拉力赛的意思,所以关于它里面术语也是跟汽车的拉力赛有关。
-
track: 即赛道的意思,这里指压测用到的样本数据和压测策略,使用
esrally list tracks
列出。rally 自带的 track 可在 https://github.com/elastic/rally-tracks 中查看,每个 track 的文件名中都存在 README.md 对压测的数据类型和参数做了详细的说明。每个 track 都包含一个track.json
文件,track.json
中定义了样本数据的获取 url,具体的策略,我们来看一个具体的eventdata/track.json
:corpora
定义了 eventdata 数据从 AWS S3 中获取,这里获取样本数据比较坑爹,下载的速度很慢,国内基本就是无法下载,我是通过 AWS 新加坡上的一个 ECS 下载下来在通过公网拉取到国内的服务器上,新加坡到国内用公网的速度还不错,国内也有人将样本数据都放在百度云了:https://pan.baidu.com/s/123zgferlhWflOj7qJxFD1w{% import "rally.helpers" as rally with context %} { "version": 2, "description": "This benchmark indexes HTTP access logs generated based sample logs from the elastic.co website using the generator available in https://github.com/elastic/rally-eventdata-track", "indices": [ { "name": "eventdata", "body": "index.json" } ], "corpora": [ { "name": "eventdata", "base-url": "http://benchmarks.elasticsearch.org.s3.amazonaws.com/corpora/eventdata", "documents": [ { "source-file": "eventdata.json.bz2", "document-count": 20000000, "compressed-bytes": 791796014, "uncompressed-bytes": 16437108429 } ] } ], "operations": [ {{ rally.collect(parts="operations/*.json") }} ], "challenges": [ {{ rally.collect(parts="challenges/*.json") }} ] }
chanllenges
中定义了压测的策略,operations
中定义的策略可以被chellenges
中引用,我们来看 eventdata 的默认策略eventdata/challenges/default.json
:名字为
append-no-conflicts
的 challenge 在schedule
的operation
中定义了具体压测中包含的内容(delete-index,create-index, check-cluster-health 等),更多的可参考官方文档: https://esrally.readthedocs.io/en/latest/track.html{ "name": "append-no-conflicts", "description": "Indexes the whole document corpus using Elasticsearch default settings. We only adjust the number of replicas as we benchmark a single node cluster and Rally will only start the benchmark if the cluster turns green. Document ids are unique so all index operations are append only.", "default": true, "schedule": [ { "operation": "delete-index" }, { "operation": { "operation-type": "create-index", "settings": {{index_settings | default({}) | tojson}} } }, { "name": "check-cluster-health", "operation": { "operation-type": "cluster-health", "index": "eventdata", "request-params": { "wait_for_status": "{{cluster_health | default('green')}}", "wait_for_no_relocating_shards": "true" } } }, { "operation": "index-append", "warmup-time-period": 120, "clients": {{bulk_indexing_clients | default(8)}} }, { "operation": "force-merge", "clients": 1 } ] }
- car: 即赛车的意思,这里指被压测的不同类型的 es 实例 (包括 jvm 的大小,版本等),rally 能根据你指定的 es 类型,自动帮你下载并配置,如果你想对一个已存在的 es 实例进行测试,可以不使用这个选项,而是在后面的 Pipeline 中指定。
- Pipeline: 指一个压测流程,可以通过
esrally list pipeline
查看,其中有一个benchmark-only
的流程,就是将 es 的管理交给用户来操作,rally 只用来做压测,如果你想针对已有的 es 进行压测,则使用改模式。 - race: 即一次比赛的意思,这里是进行一次压测,如果没有指定 track, 则默认使用
geonames
track 进行测试。
如下实例,使用 pmc 样本数据对一个已存在的 es 实例进行压力测试,使用 track-params
对默认的压测参数进行覆盖,对这次测试以 version:5.5.0
进行 tag 标记。
esrally --track=pmc --target-hosts=10.10.102.35:9200 \
--pipeline=benchmark-only \
--track-params="number_of_shards:3,number_of_replicas=1" \
--user-tag="version:5.5.0"
被压测 ES 硬件资源
- OS:Ubuntu 16.04
- CPU: 12 core
- MEM: 24G
- DISK: 普通硬盘
- ES Version: 5.2
压测结果
以下所有的压测参数均使用默认值
压测数据类型: pmc (学术论文)
单节点,普通硬盘,副本数0
Task | Min Throughput | Median Throughput | Max Throughput | P99 latency |
---|---|---|---|---|
index-append | 853.79 docs/s | 889.94 docs/s | 909.67 docs/s | 19435.3ms |
单节点,4块普通硬盘组成 RAID0,副本数0
Task | Min Throughput | Median Throughput | Max Throughput | P99 latency |
---|---|---|---|---|
index-append | 1182.27 docs/s | 1259.22 docs/s | 1285.84 docs/s | 4811.05 ms |
压测数据类型: eventdata
单节点,普通硬盘,副本数0
Task | Min Throughput | Median Throughput | Max Throughput | P90 latency | P99 latency |
---|---|---|---|---|---|
index-append | 29751.8 docs/s | 34498.3 docs/s | 35366.3 docs/s | 1338.77 ms | 2337.83 ms |
单节点,4块普通硬盘组成 RAID0,副本数0
Task | Min Throughput | Median Throughput | Max Throughput | P90 latency | P99 latency |
---|---|---|---|---|---|
index-append | 39982.6 docs/s | 40951.4 docs/s | 41216.8 docs/s | 1177.72 ms | 1470.46 ms |
3节点,4块普通硬盘组成 RAID0,副本数0
Task | Min Throughput | Median Throughput | Max Throughput | P90 latency | P99 latency |
---|---|---|---|---|---|
index-append | 68381.3 docs/s | 70045.9 docs/s | 70533.6 docs/s | 654.343 ms | 800.628 ms |
3节点,4块普通硬盘组成 RAID0,副本数1
Task | Min Throughput | Median Throughput | Max Throughput | P90 latency | P99 latency |
---|---|---|---|---|---|
index-append | 37794.8 docs/s | 38637 docs/s | 39569.2 docs/s | 1232.43 ms | 1426.42 ms |
压测数据类型: geonames
单节点,普通硬盘,副本数0
Task | Min Throughput | Median Throughput | Max Throughput | P90 latency | P99 latency |
---|---|---|---|---|---|
index-append | 49641.4 docs/s | 50195.2 docs/s | 51236.1 docs/s | 1213.64ms | 2235.51ms |
单节点,4块普通硬盘组成 RAID0,副本数0
Task | Min Throughput | Median Throughput | Max Throughput | P90 latency | P99 latency |
---|---|---|---|---|---|
index-append | 54829.7 docs/s | 55663.9 docs/s | 56248.9 docs/s | 941.875 ms | 1327.69 ms |
3节点,4块普通硬盘组成 RAID0,副本数0
Task | Min Throughput | Median Throughput | Max Throughput | P90 latency | P99 latency |
---|---|---|---|---|---|
index-append | 88812.7 docs/s | 89132.5 docs/s | 89452.5 docs/s | 512.118 ms | 961.595 ms |
总结
- 在同样的硬件情况下,我通过 mdadm 将 4 块硬盘组成了 RAID0 来提升硬盘的 IO,可以看到针对不同的样本数据,PMC 类型 的样本性能提升最明显,geonames 类型的提升最少。可见,单条日志越大,硬盘的性能提升对 ES 的性能提升越明显。
- 比对单节点与集群(3节点)的数据,可见,通过新增节点的方式提升性能,性能的提升量并不等于
*
新增节点数据数量,增加一个节点性能提升 40% 左右。 - 对比开启副本数为1与不开启副本的结果,可见,副本数为1是,es 的写性能和延迟是原来的 1/2,所以生产环境中的副本数,还是需要在性能和稳定性上做一定的权衡。