精华内容
下载资源
问答
  • ESRally性能测试步骤
    2021-08-19 16:55:12

    ES7.4.1搭建

    ES统一采用7.4.1版本

    ES的Docker镜像部署

    Docker的安装这里不再赘述

    单节点部署

    • vi docker-compose-es-single-node.yml

      version: "2"
      services:
        es-single-node:
      	image: elasticsearch:7.4.1
      	container_name: es-single-node
      	environment:
      	  - node.name=es-single-node
      	  - cluster.name=es-cluster
      	  - cluster.initial_master_nodes=es-single-node
      	  - discovery.seed_hosts=es-single-node
      	  - discovery.zen.minimum_master_nodes=1
      	  - node.master=true
      	  - node.data=true
      	  - http.port=9200
      	  - transport.tcp.port=9300
      	  - http.cors.enabled=true
      	  - http.cors.allow-origin="*"
      	  - "ES_JAVA_OPTS=-Xms128m -Xmx128m"
      	ports:
      	  - 9210:9200
      	  - 9310:9300
      
    • docker-compose -f docker-compose-es-single-node.yml up -d (这个步骤也可以用docker的界面管理工具portainer完成)

    多节点部署

    这里演示2个master2个data节点的配置,增加删除节点依葫芦画瓢即可

    • vi docker-compose-2master2data.yml

      version: "2"
      services:
        master01:
      	image: elasticsearch:7.4.1
      	container_name: master01
      	environment:
      	  - node.name=master01
      	  - cluster.name=es-cluster
      	  - cluster.initial_master_nodes=master01,master02
      	  - discovery.seed_hosts=master01,master02,data01,data02
      	  - discovery.zen.minimum_master_nodes=2
      	  - node.master=true
      	  - node.data=false
      	  - http.port=9200
      	  - transport.tcp.port=9300
      	  - http.cors.enabled=true
      	  - http.cors.allow-origin="*"
      	  - "ES_JAVA_OPTS=-Xms128m -Xmx128m"
      	ports:
      	  - 9200:9200
      	  - 9300:9300
        master02:
      	image: elasticsearch:7.4.1
      	container_name: master02
      	environment:
      	  - node.name=master02
      	  - cluster.name=es-cluster
      	  - cluster.initial_master_nodes=master01,master02
      	  - discovery.seed_hosts=master01,master02,data01,data02
      	  - discovery.zen.minimum_master_nodes=2
      	  - node.master=true
      	  - node.data=false
      	  - http.port=9200
      	  - transport.tcp.port=9300
      	  - http.cors.enabled=true
      	  - http.cors.allow-origin="*"
      	  - "ES_JAVA_OPTS=-Xms128m -Xmx128m"
      	ulimits:
      	  memlock:
      		soft: -1
      		hard: -1
      	ports:
      	  - 9201:9200
      	  - 9301:9300
        data01:
      	image: elasticsearch:7.4.1
      	container_name: data01
      	environment:
      	  - node.name=data01
      	  - cluster.name=es-cluster
      	  - cluster.initial_master_nodes=master01,master02
      	  - discovery.seed_hosts=master01,master02,data01,data02
      	  - discovery.zen.minimum_master_nodes=2
      	  - node.master=false
      	  - node.data=true
      	  - http.port=9200
      	  - transport.tcp.port=9300
      	  - http.cors.enabled=true
      	  - http.cors.allow-origin="*"
      	  - "ES_JAVA_OPTS=-Xms128m -Xmx128m"
      	ulimits:
      	  memlock:
      		soft: -1
      		hard: -1
      	ports:
      	  - 9202:9200
      	  - 9302:9300
        data02:
      	image: elasticsearch:7.4.1
      	container_name: data02
      	environment:
      	  - node.name=data02
      	  - cluster.name=es-cluster
      	  - cluster.initial_master_nodes=master01,master02
      	  - discovery.seed_hosts=master01,master02,data01,data02
      	  - discovery.zen.minimum_master_nodes=2
      	  - node.master=false
      	  - node.data=true
      	  - http.port=9200
      	  - transport.tcp.port=9300
      	  - http.cors.enabled=true
      	  - http.cors.allow-origin="*"
      	  - "ES_JAVA_OPTS=-Xms128m -Xmx128m"
      	ulimits:
      	  memlock:
      		soft: -1
      		hard: -1
      	ports:
      	  - 9203:9200
      	  - 9303:9300
        kibana:
      	image: kibana:7.4.1
      	environment:
      	  - ELASTICSEARCH_HOSTS=["http://master01:9200","http://master02:9200","http://data01:9200","http://data02:9200"]
      	ports:
      	  - 5601:5601
      
    • docker-compose -f docker-compose-2master2data.yml up -d

    Centos部署

    单节点部署

    1. 下载es7.4.1安装文件到服务器并解压到 /usr/share/elasticsearch 目录,然后已root用户执行:
      echo "* soft nofile 125536" >> /etc/security/limits.conf
      echo "* hard nofile 125536" >> /etc/security/limits.conf
      echo "* soft nproc 8096" >> /etc/security/limits.conf
      echo "* hard nproc 8096" >> /etc/security/limits.conf
      echo "* soft memlock unlimited" >> /etc/security/limits.conf
      echo "* hard memlock unlimited" >> /etc/security/limits.conf
      
      echo "vm.max_map_count=522144" >> /etc/sysctl.conf
      sysctl -p
      
      adduser elastic
      chown -R elastic:elastic /usr/share/elasticsearch
      
    2. 修改elasticsearch.yml,可参考下面的配置
      # 这两个配置都写master节点的ip
      cluster.initial_master_nodes: ["192.168.1.55"]
      discovery.seed_hosts: ["192.168.1.55"]
      
      # 节点名称,其余两个节点分别为node-ip
      # 节点名称以node-开头,以当前节点IP结尾
      node.name: master192.168.1.55
      
      discovery.zen.minimum_master_nodes: 1
      
      # 指定该节点是否有资格被选举成为master节点,默认是true,es是默认集群中的第一台机器为master,如果这台机挂了就会重新选举master
      node.master: true
      
      # 允许该节点存储数据(默认开启)
      node.data: true
      
      # 绑定的ip地址
      network.host: 0.0.0.0
      
      # 集群的名称
      cluster.name: xxxxx-dssa
      
      # 索引数据的存储路径
      path.data: data
      
      # 日志文件的存储路径
      path.logs: logs
      
      # 快照仓库路径
      path.repo: ["/opt/xxxxx/backups/es_repo","/opt/xxxxx/backups/rsyslog-audit","/opt/xxxxx/backups/rsyslog-firewall","/opt/xxxxx/backups/rsyslog-desens","/opt/xxxxx/backups/rsyslog-encrypt"]
      
      # 正式部署需要设置为true来锁住内存。因为内存交换到磁盘对服务器性能来说是致命的,当jvm开始swapping时es的效率会降低,所以要保证它不swap
      bootstrap.memory_lock: true
      
      # 设置对外服务的http端口,默认为9200
      http.port: 9200
      
      # 设置节点间交互的tcp端口,默认是9300
      transport.tcp.port: 9300
      
      # 如果没有足够大的内存,因为了elasticsearch引用文件,系统内存会大量用于系统cache(linux的内存管理机制)。
      # 由于系统cache释放缓慢,而导致这个过程非常长,这有可能使你的节点GC非常频繁,从而导致集群不稳定。
      # 建议把bootstrap.mlockall设为true
      # 这个参数在7.4.1无效
      # bootstrap.mlockall: true
      
      # 开启跨域访问
      http.cors.enabled: true
      http.cors.allow-origin: "*"
      
      
    3. 修改jvm.options,一般把Xms Xmx内存配置为可用内存的一半
    4. 尝试启动观察日志看看有没有问题
      su elastic
      cd /usr/share/elasticsearch
      bin/elasticsearch    前台执行
      bin/elasticsearch    后台执行,需要到配置的日志目录去看日志
      
    5. 开机启动
      • vi /usr/lib/systemd/system/elasticsearch.service 输入如下内容:
      [Unit]
      Description=elasticsearch service
      
      [Service]
      User=elastic
      ExecStart=/usr/share/elasticsearch/bin/elasticsearch
      
      [Install]
      WantedBy=multi-user.target
      
      • systemctl enable elasticsearch (开机启动)
      • systemctl restart elasticsearch (重启es)

    多节点部署

    多节点部署和单节点部署几乎一模一样,只需要根据自身要搭建的集群节点规划修改下配置文件即可

    一般修改如下几个配置:

    cluster.initial_master_nodes: ["master01","master02"]
    discovery.seed_hosts: ["master01","master02","data01","data02"]
    
    node.name: 节点的名字
    
    # 计算公式是这样的: master候选节点的个数/2 + 1,设置不恰当可能存在脑裂问题
    discovery.zen.minimum_master_nodes: 2
    
    # 指定该节点是否有资格被选举成为master节点,默认是true,es是默认集群中的第一台机器为master,如果这台机挂了就会重新选举master
    node.master: true
    
    # 允许该节点存储数据(默认开启)
    node.data: true
    

    ESRally部署与测试

    esrally是es官方提供的对es进行性能测试的工具
    官网:https://esrally.readthedocs.io/en/stable/quickstart.html

    esrally安装

    直接拉取docker镜像即可:
    
    1. 修改host文件,添加如下配置
    172.16.1.201 prod.docker
    172.16.1.201 dev.docker
    
    2. 修改docker配置文件,增加如下配置:
     { "insecure-registries": ["prod.docker:8085", "dev.docker:8085"] }
    
    3. 拉取docker esrally镜像
    docker pull dev.docker:8085/elastic/rally:2.0.0
    
    4. 执行测试
    docker run --rm -i -v /opt/esrally:/opt/esrally dev.docker:8085/elastic/rally:2.0.0  --pipeline=benchmark-only --track-path=/opt/esrally --target-hosts=192.168.1.55:9200
    
    

    enter description here

    准备es的索引模板

    在 tfs 中已经准备了几个我们生产环境使用的es索引模板,可根据自身情况自行修改

    enter description here

    由于索引模板是yml格式的,需要转换为json格式:通过修改index.sh中的相关参数并执行index.sh即可完成json转换。

    index.sh完成了两个动作(可根据自身情况自行删除):
    - yml转换为json
    - 连接es创建索引

    准备测试数据

    在tfs中也已经准备好了生成测试数据的工具

    enter description here

    只需要修改eslog_generator.sh中的三个参数即可根据索引模板生产测试数据

    编辑track.json文件

    这个文件是esrally需要使用的,可参考:

    {
        "version": 2,
        "description": "xxxxx logs",
        "indices": [
            {
                "name": "xxxxx_audit_bigdata"
            }
        ],
        "corpora": [
            {
                "name": "http_logs",
                "documents": [
                    {
                        "source-file": "xxxxx_audit_bigdata1200w.json.bz2",
                        "document-count": 12000000,
    					"uncompressed-bytes": 30760
                    }
                ]
            }
        ],
        "challenges": [
            {
                "name": "index-test",
                "default": true,
                "schedule": [
                	
                  	{
                        "operation": {
                            "name": "putdata_bulk",
                            "operation-type": "bulk",
                            "bulk-size": 1000
                        },
                        "clients": 5
                    },
                    {
                        "operation": {
                            "name": "search",
                            "operation-type": "search",
                            "body": {
                                "query":{
                                    "match_all": {}
                                }
                            }
                        },
                        "clients": 5
                    }
                ]
            }
        ]
    }
    
    

    enter description here

    执行

    track.json文件和生成的数据文件要放在同一个目录,假设为 /opt/esrally/track,则执行

    esrally race --pipeline=benchmark-only --track-path=/opt/esrally/track --target-hosts=esip:9200
    

    执行完成会有下面的一个结果输出

    enter description here

    更多相关内容
  • es压测esrally.docx

    2020-04-26 22:33:13
    es压测esrally 一、压测工具esrally安装 二、esrally工具介绍 三、配置参数说明 四、Race结果分析
  • 1.基础概念Rally 最初于 2016 年发布,直到 2018 年 7 月才发布 1.0 版本,Rally工具 是 Elasticsearch 开发团队用来运行夜间基准测试的工具。Ra...

    1.基础概念

    Rally 最初于 2016 年发布,直到 2018 年 7 月才发布 1.0 版本,Rally 工具 是 Elasticsearch 开发团队用来运行夜间基准测试的工具。

    Rally 的美妙之处在于它不仅可以充当负载生成器,还可以为构建、设置Elasticsearch 集群,从而帮助我们进行性能测试。

    我们可以使用 Rally 对现有的 Elasticsearch 集群进行基准测试、管理基准配置、运行和比较结果,并使用指标和报错(例如 JIT、GC、perf)发现潜在的性能问题。

    Rally 并发默认是配置多进程,基础进程数 8+1(client数量)。一台服务器只能运行一个 Rally 实例。

    Rally 的 git 地址:

    https://github.com/elastic/rally

    d000e6fba466fb2f6c2c1dbd4b0cc2e2.png

    下文中的:esrally 等价于 Rally 工具。

    1.1 相关概念与参数

    track:是赛道的意思,在这里是指压测用的数据和测试策略,track.json 便是压测策略的定义文件。

    525c519db096dfcb7fe2af87a91c9d99.png

    • track.json :track主要的操作定义,定义被操作的索引、执行的测试操作和被测试的数据文件。是必要文件。

    • 索引名.json:被测试的索引的mapping数据,也是必要文件。

    • documents.json(.bz2):被压测的索引数据,-1k的是用于test的部分数据。非必要文件。

    operations: 指定具体的操作,比如 index 索引数据的操作、force-merge 强制合并 segment 的操作、search 搜索的操作等等。

    schedule: 指定了 challenge 中按顺序执行的 task,其中每个 task 都指定了 一个 operation,除此之外还可以设定 clients (并发客户端数)、warmup-iterations(预热的循环次数)、iterations(operation 执行的循环次数)等。

    指定特定的 schedule 可以使用命令行参数--include-tasksexclude-tasks

    challenges: 通过组合 schedule 定义一系列 task ,再组合成一个压测的流程。

    指定 challenges 可以使用命令行参数--challenge

    pipeline:指的是压测的流程。在生产中,一般都是远端集群,因此主要选择 benchmark-only。

    1.2 关注指标

    在 Metric 一栏,是压测结果指标数据,一般要关注的数据有:

    • throughput 每个操作的吞吐量,比如 index、search等

    • latency 每个操作的响应时长数据

    • Heap used for x 记录堆栈的使用情况

    1.3 配置schedule

    • clients:(可选,默认为1):并发执行一个任务的客户端数量。

    • warmup-iterations(可选,默认为0):每个客户机应该执行的迭代数,以预热候选基准测试。热身迭代不会显示在测量结果中。

    • iterations (可选,默认为1):每个客户端执行的度量迭代的数量。命令行报告将根据这个数字自动调整百分位数(例如,如果您只运行5次迭代,您将不会得到99.9个百分位数,因为我们需要至少1000次迭代来精确地确定这个值)。

    • ramp-up-time-period(可选,默认为0):Rally将逐步启动客户端。在指定时间段结束时达到客户端指定的数量(以秒为单位)。此属性还需要设置预热时间周期,它必须大于或等于预热时间。有关更多细节,请参阅ramp-up一节。

    • warmup-time-period(可选,默认为0):Rally考虑的基准测试候选者预热的时间周期,以秒为单位。所有在热身过程中捕获的响应数据都不会显示在测量结果中。

    • time-period(可选):Rally考虑测量的以秒为单位的时间段。注意,对于批量索引,通常不应该定义此时间段。拉力将只是批量索引所有的文件,并考虑每个样本后的预热时间周期作为测量样本。

    • schedule(可选,默认为确定性的):为这个任务定义时间表,也就是说,它定义了在基准测试期间应该执行某个操作的时间点。例如,如果你指定了一个确定的调度和目标时间间隔为5(秒),Rally将尝试在秒0,5,10,15 ... .执行相应的操作Rally支持确定性和泊松,但您可以定义自己的自定义时间表。

    • target-throughput(可选):定义基准测试模式。如果没有定义,Rally将假设这是一个吞吐量基准,并将以尽可能快的速度运行任务。对于批处理风格的操作,这是最需要的,因为实现最佳吞吐量比获得可接受的延迟更重要。如果定义了它,它将指定所有客户端的每秒请求数。例如,如果你指定8个客户机的目标吞吐量为1000,这意味着每个客户机每秒将发出125(= 1000 / 8)个请求。总的来说,所有客户端每秒将发出1000个请求。如果Rally报告的吞吐量小于指定的吞吐量,那么Elasticsearch就无法到达它。

    • target-interval(可选):这仅仅是1 / target-throughput(以秒为单位),对于吞吐量小于每秒一个操作的情况可能更方便。

    • completed-by(可选):根据提供的任务名来结束并发的task,如果设置为any那么一旦有一个任务结束,整个schedule结束。假设有八个并发的相同任务,其中一个结束,另外7个结束。

    • ignore-response-error-level(可选):当基准测试运行时,控制是否忽略任务执行过程中遇到的错误。唯一允许的值是非致命的,它结合cli选项——on-error=abort,将在任务执行期间忽略非致命错误。

    注意:

    • 只能定义 target-intervaltarget-throughput的一个,但不能两者都定义(否则 Rally 将引发错误)。

    • iterationstime-period这两类的参数也不能同时定义。

    1.3.1 schedule examples

    基础配置

    {
      "schedule": [
        {
          "operation": {
            "operation-type": "search",
            "index": "_all",
            "body": {
              "query": {
                "match_all": {}
              }
            }
          },
          "warmup-iterations": 100,
          "iterations": 100,
          "target-throughput": 10
        }
      ]
    }
    • 使用一个 client 每秒10个操作

    • 并使用100个迭代作为热身,然后使用100个迭代来测量

    并发配置
    默认 rally 对每个 operation 分配一个 client 进行处理。

    在 parallel 和每个 task 都可以指定 clients。

    如果两者的clients参数出现冲突,则可参考以下示例:

    "schedule": [
      {
        "parallel": {
          "warmup-iterations": 50,
          "iterations": 100,
          "clients": 2,
          "tasks": [
            {
              "operation": "match-all",
              "target-throughput": 50
            },
            {
              "operation": "term",
              "target-throughput": 200
            },
            {
              "operation": "phrase",
              "target-throughput": 200
            }
          ]
        }
      }
    ]

    Rally 不会同时运行所有三个任务,Rally 将首先同时运行“match-all”和“term”(每个任务一个client)。在他们完成之后,Rally将与一个客户运行“phrase”。

    如果 parallel 指定比任务更多的 client,但这些 client 将是空闲的。

    {
      "parallel": {
        "clients": 3,
        "warmup-iterations": 50,
        "iterations": 100,
        "tasks": [
          {
            "operation": "default",
            "target-throughput": 50
          },
          {
            "operation": "term",
            "target-throughput": 200
          },
          {
            "operation": "phrase",
            "target-throughput": 200,
            "clients": 2
          }
        ]
      }
    }

    这种方式确保 phrase 由两个 client 执行,其他任务一个client执行。

    2 rally安装

    2.1 依赖工程以及相关版本

    1. 开发包:curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker libffi-devel bzip2-devel

    2. python:3.8以上

    3. jdk:1.8

    4. git:2.7.5

    2.2 离线安装esrally

    yum -y install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker libffi-devel bzip2-devel
     wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.7.5.tar.gz --no-check-certificate
     wget https://www.python.org/ftp/python/3.8.7/Python-3.8.7.tgz
     cd Python-3.8.7/
     ./configure prefix=/usr/local/python3
     make && make install
     echo 'export PYTHON3_HOME=/usr/local/python3' >> /etc/profile
     echo 'export PATH=$PATH:$PYTHON3_HOME/bin' >> /etc/profile
     source /etc/profile
     pip3.8 install sklearn
     tar -zxvf git-2.7.5.tar.gz
     cd git-2.7.5/
     make prefix=/usr/local/esrally/git all
     make prefix=/usr/local/esrally/git install
     rpm -qa | grep -w git
     rpm -e git-1.8.3.1-23.el7_8.x86_64 --nodeps
     echo 'export GIT2_HOME=/usr/local/esrally/git' >> /etc/profile
     echo 'export PATH=$PATH:$GIT2_HOME/bin' >> /etc/profile
     source /etc/profile
     wget https://github.com/elastic/rally/releases/esrally-dist-linux-2.3.1.tar.gz --no-check-certificate
     tar -zxf esrally-dist-linux-2.3.0.tar.gz 
     cd  esrally-dist-2.3.0/
     bash install.sh

    如果是已存在python3其他版本,后安装的python3.8,需要修改 install.sh中的python3修改成python3.8

    默认rally参数和压测文件路径:/root/.rally/

    使用 /root/.rally/benchmarks/tracks/default/download.sh 选择下载离线测试数据

    安装后测试

    esrally race  --track=metricbeat  --challenge=append-no-conflicts --target-hosts=127.0.0.1:9200 --client-options="use_ssl:false,verify_certs:false,basic_auth_user:'elastic',basic_auth_password:'passwd'"  --pipeline=benchmark-only --offline

    3 自定义测试

    这里分三个场景:

    1. 自定义查询压测:对当前索引进行自定义dsl查询压测。

    2. 重建索引测试:重建索引,修改分片数,并进行dsl查询测试。

    3. 使用challengs方式进行压测。

    其中查询的dsl为:

    {"query":{"term":{"meta.cloud.instance_id":{"value":"1983702708814995873"}}}}

    3.1 自定义简单查询压测

    创建track路径

    /usr/local/esrally/tracks/acms

    获取索引的mapping文件

    #命令格式
    curl -k --user 用户名:密码 -XGET http://<es域名>:9200/<索引名>/_mapping?pretty=true > <索引名>.json
    #实际命令
    curl -k --user elastic:abc123 -XGET http://127.0.0.1:9200/metricbeat/_mapping?pretty=true > metricbeat.json

    创建track.json

    {% import "rally.helpers" as rally with context %}
    {
      "version": 2,
      "description": "Tracker-generated track for test",
      "indices": [
        {
          "name": "metricbeat",      --------索引名
          "body": "metricbeat.json"  --------索引mapping文件名
        }
      ],
      "schedule": [
        {
          "operation": {
            "name": "query-dsl",
            "operation-type": "search",
            "body": {
              "query": {
                "term": {
                  "meta.cloud.instance_id": {
                    "value": "1983702708814995873"
                     }
                  }
                }
              }
              },
          "warmup-time-period": 10, ------warmup10s
          "time-period": 120,       ------实际测试120s
          "target-throughput": 4500,------目标吞吐量
          "clients": 5              ------启动的客户端数量
        }
      ]
    }

    运行自定义查询测试

    esrally race --track-path=/usr/local/esrally/tracks/acme  --pipeline=benchmark-only  --target-hosts=127.0.0.1:9200 --client-options="use_ssl:false,verify_certs:false,basic_auth_user:'elastic',basic_auth_password:'abc123'" --include-tasks="query-dsl" --report-file=/usr/local/esrally/report/20220128-5-10k.csv

    使用 --report-file 定义测试结果输出文件。

    3.2 重建索引测试

    创建 track ,获取压测数据,此处会生产索引数据文件,因此需要注意track路径的文件使用。

    esrally create-track --track=acme --target-hosts=127.0.0.1:9200 --client-options="use_ssl:false,verify_certs:false,basic_auth_user:'elastic',basic_auth_password:'passwd'" --indices="metricbeat" --output-path=/usr/local/esrally/tracks

    在 track.json 中添加 operation

    {% import "rally.helpers" as rally with context %}
    {
      "version": 2,
      "description": "Tracker-generated track for acme",
      "indices": [
        {
          "name": "metricbeat",
          "body": "metricbeat.json"
        }
      ],
      "corpora": [
        {
          "name": "metricbeat",
          "documents": [
            {
              "target-index": "metricbeat",
              "source-file": "metricbeat-documents.json.bz2",
              "document-count": 1079600,
              "compressed-bytes": 97535962,
              "uncompressed-bytes": 1249705758
            }
          ]
        }
      ],
      "schedule": [
        {
          "operation": "delete-index"
        },
        {
          "operation": {
            "operation-type": "create-index",
            "settings": {{index_settings | default({}) | tojson}}
          }
        },
        {
          "operation": {
            "operation-type": "cluster-health",
            "index": "metricbeat",
            "request-params": {
              "wait_for_status": "{{cluster_health | default('green')}}",
              "wait_for_no_relocating_shards": "true"
            },
            "retry-until-success": true
          }
        },
        {
          "operation": {
            "operation-type": "bulk",
            "bulk-size": {{bulk_size | default(5000)}},
            "ingest-percentage": {{ingest_percentage | default(100)}}
          },
          "clients": {{bulk_indexing_clients | default(8)}}
        },
     #### 此处新增
        {
       "operation": {
            "name": "query-dsl",
            "operation-type": "search",
            "body": {
              "query": {
                "term": {
                  "meta.cloud.instance_id": {
                    "value": "1983702708814995873"
                     }
                  }
                }
              }
       },
       "warmup-time-period": 60,
          "time-period": 120,
          "target-throughput": 450,
          "clients": 5
        }
      ]
    }

    修改索引 metricbeat 的分片数,即修改 metricbeat.json 文件中分片参数

    "number_of_shards": "12"

    重建索引

    esrally race --track-path=/usr/local/esrally/tracks/acme  --pipeline=benchmark-only  --target-hosts=127.0.0.1:9200 --client-options="use_ssl:false,verify_certs:false,basic_auth_user:'elastic',basic_auth_password:'passwd'" --exclude-tasks="type:search"

    测试自定义查询

    esrally race --track-path=/usr/local/esrally/tracks/acme  --pipeline=benchmark-only  --target-hosts=127.0.0.1:9200 --client-options="use_ssl:false,verify_certs:false,basic_auth_user:'elastic',basic_auth_password:'passwd'" --include-tasks="query-dsl" --report-file=/usr/local/esrally/report/20220128-5-10k.csv

    3.3 使用 challenges 定义压测内容

    创建track的方式与3.2一致。 以添加 challenges 文件的方式增加schedule;

    #####原来track.json
    {% import "rally.helpers" as rally with context %}
    {
      "version": 2,
      "description": "Tracker-generated track for acme",
      "indices": [
        {
          "name": "metricbeat",
          "body": "metricbeat.json"
        }
      ],
      "corpora": [
        {
          "name": "metricbeat",
          "documents": [
            {
              "target-index": "metricbeat",
              "source-file": "metricbeat-documents.json.bz2",
              "document-count": 1079600,
              "compressed-bytes": 97377230,
              "uncompressed-bytes": 1249705758
            }
          ]
        }
      ],
      "schedule": [
        {
          "operation": "delete-index"
        },
        {
          "operation": {
            "operation-type": "create-index",
            "settings": {{index_settings | default({}) | tojson}}
          }
        },
        {
          "operation": {
            "operation-type": "cluster-health",
            "index": "metricbeat",
            "request-params": {
              "wait_for_status": "{{cluster_health | default('green')}}",
              "wait_for_no_relocating_shards": "true"
            },
            "retry-until-success": true
          }
        },
        {
          "operation": {
            "operation-type": "bulk",
            "bulk-size": {{bulk_size | default(5000)}},
            "ingest-percentage": {{ingest_percentage | default(100)}}
          },
          "clients": {{bulk_indexing_clients | default(8)}}
        }
      ]
    }
    #####修改后
    {% import "rally.helpers" as rally with context %}
    {
      "version": 2,
      "description": "Tracker-generated track for acme",
      "indices": [
        {
          "name": "metricbeat",
          "body": "metricbeat.json"
        }
      ],
      "corpora": [
        {
          "name": "metricbeat",
          "documents": [
            {
              "target-index": "metricbeat",
              "source-file": "metricbeat-documents.json.bz2",
              "document-count": 1079600,
              "compressed-bytes": 97377230,
              "uncompressed-bytes": 1249705758
            }
          ]
        }
      ],
      "challenges": [   #####此处添加
        {{ rally.collect(parts="challenges/*.json") }}
      ]
    }

    在/usr/local/esrally/tracks/acme路径下添加 challenges 路径,在其中新建query-dsl.json。

    {
      "name": "query-dsl",
      "default": false,
      "schedule": [{
        "operation": {
          "name": "query-dsl",
          "operation-type": "search",
          "body": {
            "query": {
              "term": {
                "meta.cloud.instance_id": {
                  "value": "1983702708814995873"
          }
        }
      }
       }
     },
     "warmup-time-period": 60,
        "time-period": 120,
        "target-throughput": 450,
        "clients": 5
      }]
    }

    将原来的 operations 迁移到default.json,设置 "default": true 使其成为默认的 challenges。

    {
     "name": "default",
     "default": true,
     "schedule": [
        {
          "operation": "delete-index"
        },
        {
          "operation": {
            "operation-type": "create-index",
            "settings": {{index_settings | default({}) | tojson}}
          }
        },
        {
          "operation": {
            "operation-type": "cluster-health",
            "index": "metricbeat",
            "request-params": {
              "wait_for_status": "{{cluster_health | default('green')}}",
              "wait_for_no_relocating_shards": "true"
            },
            "retry-until-success": true
          }
        },
        {
          "operation": {
            "operation-type": "bulk",
            "bulk-size": {{bulk_size | default(5000)}},
            "ingest-percentage": {{ingest_percentage | default(100)}}
          },
          "clients": {{bulk_indexing_clients | default(8)}}
        }
     ]
    }

    修改索引 metricbeat 的分片数,即修改 metricbeat.json 文件中分片参数

    "number_of_shards": "12"

    重建索引

    esrally race --track-path=/usr/local/esrally/tracks/acme  --pipeline=benchmark-only  --target-hosts=127.0.0.1:9200 --client-options="use_ssl:false,verify_certs:false,basic_auth_user:'elastic',basic_auth_password:'passwd'"

    测试自定义查询:

    esrally race --track-path=/usr/local/esrally/tracks/acme --challenge=query-dsl --pipeline=benchmark-only  --target-hosts=127.0.0.1:9200 --client-options="use_ssl:false,verify_certs:false,basic_auth_user:'elastic',basic_auth_password:'passwd'" --report-file=/usr/local/esrally/report/20220128-5-10k.csv

    使用 --report-file 定义测试结果输出文件。

    4. 总结

    1. 在使用 track进行测试内容定义的时候,如果仅仅是对查询内容的qps测试,则不需要create-track这个命令项创建track,直接创建track.json文件来减少测试的时间和存储成本。

    2. 面对比较复杂的测试场景,比如有多次bulksearch的流程,建议定义不同的challenges进行区分。

    3. 在实际测试(16c32g的虚机)中,esrally单 client 的 bulk 写入性能不到2w docs/s,如果需增加压力则需要加 client。

    4. rally 的报告中,latency 减去 service_time 即为 rally 等待 Elasticsearch 的响应时间。

    参考文档

    • rally 详解:

      https://elasticsearch.cn/article/275

    • 部署参考文档: https://cloud.tencent.com/developer/article/1892344

    • 压测结果指标: https://esrally.readthedocs.io/en/stable/metrics.html

    • 测试数据源地址: http://benchmarks.elasticsearch.org.s3.amazonaws.com/

    作者介绍

    作者:金多安,Elastic 认证工程师、Elastic 中文社区日报编辑、运维工程师。

    审稿人:铭毅天下,Elastic 认证工程师,Elastic 中国合作培训讲师,阿里云 MVP,Elastic Stack 技术博文全网累计阅读量 1000万+。

    说明

    ddb673b882f285f58523d43889ca90d0.png

    上个月,死磕 Elasticsearch 知识星球搞了:“群智涌现”杯输出倒逼输入——Elastic干货输出活动。

    后续会不定期逐步推出系列文章,目的:以文会友,“输出倒逼输入”。

    推荐

    1、重磅 | 死磕 Elasticsearch 方法论认知清单(2021年国庆更新版)

    2Elasticsearch 7.X 进阶实战私训课(口碑不错)

    3、如何系统的学习 Elasticsearch ?

    30ffd8d79c6930a23b5e107b882a4336.png

    更短时间更快习得更多干货!

    已带领88位球友通过 Elastic 官方认证!

    a91bab115468b6e3beddcf5617251ba3.gif

    比同事抢先一步学习进阶干货!

    展开全文
  • esrally是elastic search官方用于对ES集群进行压力测试的工具,使用esrally可以为我们构建不同版本集群,构造不同的参数和数据来进行压力测试,并且可以对产生的压测结果进行比较,rally顾名思义是拉力赛的意思,es...

    微信公众号:运维开发故事,作者:wanger

    ESrally介绍

    esrally是elastic search官方用于对ES集群进行压力测试的工具,使用esrally可以为我们构建不同版本集群,构造不同的参数和数据来进行压力测试,并且可以对产生的压测结果进行比较,rally顾名思义是拉力赛的意思,esrally的一些名词也都与拉力赛有关。
    github地址:https://github.com/elastic/rally

    ESrally安装

    环境要求

    python3.8 pip3
    jdk8
    git 1.9+
    
    

    python3.8安装

    yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gcc make libffi-devel 
    wget https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz
    tar -xvJf Python-3.8.2.tar.xz
    mkdir /usr/local/python3
    cd Python-3.8.2/
    ./configure --prefix=/usr/local/python3
    make && make install
    ln -s /usr/local/python3/bin/python3 /usr/local/bin/python3
    ln -s /usr/local/python3/bin/pip3 /usr/local/bin/pip3
    
    

    git 2.22安装

    由于yum安装的git版本默认为1.8,因此我需要编译安装较新版本的git,如果已通过yum安装过git,可以使用yum remove git卸载

    yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker
    cd /tmp
    wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.22.0.tar.gz
    tar xzf git-2.22.0.tar.gz
    cd git-2.22.0
    make prefix=/usr/local/git all
    make prefix=/usr/local/git install
    echo "export PATH=$PATH:/usr/local/git/bin" >> /etc/bashrc
    source /etc/bashrc
    
    

    👉jdk安装

    rpm -ivh jdk-8u221-linux-x64.rpm
    
    

    👉esrally安装

    python3 -m pip install esrally
    vim /etc/profile
    JAVA_HOME=/usr/java/jdk1.8.0_221-amd64/jre
    export PATH=$PATH:/usr/local/python3/bin/:/usr/local/git/bin JAVA_HOME
    source /etc/profile
    
    

    👉配置ESrally

    用于定义一些数据的配置,可以选择把结果存储到已有的ES中进行分析
    esrally configure
    配置完成后,将会覆写ESrally的配置文件/root/.rally/rally.ini
    图片👉ESrally名词解释

    👉track

    赛道的意思,用于构建不同的数据和策略进行压测,track.json定义压测的数据集,以geonames/track.json为例

    {% import "rally.helpers" as rally with context %}
    {
      "version": 2,
      "description": "POIs from Geonames",
      "data-url": "http://benchmarks.elasticsearch.org.s3.amazonaws.com/corpora/geonames",
      "indices": [
        {
          "name": "geonames",
          "body": "index.json"
        }
      ],
      "corpora": [
        {
          "name": "geonames",
          "base-url": "http://benchmarks.elasticsearch.org.s3.amazonaws.com/corpora/geonames",
          "documents": [
            {
              "source-file": "documents-2.json.bz2",
              "document-count": 11396503,
              "compressed-bytes": 265208777,
              "uncompressed-bytes": 3547613828
            }
          ]
        }
      ],
      "operations": [
        {{ rally.collect(parts="operations/*.json") }}
      ],
      "challenges": [
        {{ rally.collect(parts="challenges/*.json") }}
      ]
    }
    
    

    当我们开始用esrally开始比赛的时候,会先根据base-url和source-files构建链接从亚马逊下载数据,下载测试数据的速度很慢,我们可以提前下好离线数据来进行测试,测试数据存放在/home/elk/.rally/benchmarks/data/geonames目录下,indices定义了索引名和索引的具体设置,通过index.json文件可以查看

    {
      "settings": {
        "index.number_of_shards": {{number_of_shards | default(5)}},
        "index.number_of_replicas": {{number_of_replicas | default(0)}},
        "index.store.type": "{{store_type | default('fs')}}",
        "index.requests.cache.enable": false
      },
      "mappings": {
        "dynamic": "strict",
        "_source": {
          "enabled": {{ source_enabled | default(true) | tojson }}
        },
        "properties": {
          "elevation": {
            "type": "integer"
          },
          "name": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "geonameid": {
            "type": "long"
          },
          "feature_class": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "location": {
            "type": "geo_point"
          },
          "cc2": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "timezone": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "dem": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "country_code": {
            "type": "text",
            "fielddata": true,
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "admin1_code": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "admin2_code": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "admin3_code": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "admin4_code": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "feature_code": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "alternatenames": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "asciiname": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            }
          },
          "population": {
            "type": "long"
          }
        }
      }
    }
    
    

    operations目录下定义了压测的具体操作,包括索引的写入、更新、段合并、各种查询,每个操作都可以构建不同的参数,

    {
          "name": "index-append",
          "operation-type": "bulk",
          "bulk-size": {{bulk_size | default(5000)}},
          "ingest-percentage": {{ingest_percentage | default(100)}}
        },
        {
          "name": "index-update",
          "operation-type": "bulk",
          "bulk-size": {{bulk_size | default(5000)}},
          "ingest-percentage": {{ingest_percentage | default(100)}},
          "conflicts": "{{conflicts | default('random')}}",
          "on-conflict": "{{on_conflict | default('index')}}",
          "conflict-probability": {{conflict_probability | default(25)}},
          "recency": {{recency | default(0)}}
        },
        {
          "name": "default",
          "operation-type": "search",
          "body": {
            "query": {
              "match_all": {}
            }
          }
        },
        {
          "name": "term",
          "operation-type": "search",
          "body": {
            "query": {
              "term": {
                "country_code.raw": "AT"
              }
            }
          }
        },
        {
          "name": "phrase",
          "operation-type": "search",
          "body": {
            "query": {
              "match_phrase": {
                "name": "Sankt Georgen"
              }
            }
          }
        },
        {
          "name": "country_agg_uncached",
          "operation-type": "search",
          "body": {
            "size": 0,
            "aggs": {
              "country_population": {
                "terms": {
                  "field": "country_code.raw"
                },
                "aggs": {
                  "sum_population": {
                    "sum": {
                      "field": "population"
                    }
                  }
                }
              }
            }
          }
        },
        {
          "name": "country_agg_cached",
          "operation-type": "search",
          "cache": true,
          "body": {
            "size": 0,
            "aggs": {
              "country_population": {
                "terms": {
                  "field": "country_code.raw"
                },
                "aggs": {
                  "sum_population": {
                    "sum": {
                      "field": "population"
                    }
                  }
                }
              }
            }
          }
        },
        {
          "name": "scroll",
          "operation-type": "search",
          "pages": 25,
          "results-per-page": 1000,
          "body": {
            "query": {
              "match_all": {}
            }
          }
        },
        {
          "name": "expression",
          "operation-type": "search",
          "body": {
            "query": {
              "function_score": {
                "query": {
                  "match_all": {}
                },
                "functions": [
                  {
                    "script_score": {
                      "script": {
                        "source": "abs(ln(abs(doc['population']) + 1) + doc['location'].lon + doc['location'].lat) * _score",
                        "lang": "expression"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "name": "painless_dynamic",
          "operation-type": "search",
          "body": {
            "query": {
              "function_score": {
                "query": {
                  "match_all": {}
                },
                "functions": [
                  {
                    "script_score": {
                      "script": {
                        "source": "Math.abs(Math.log(Math.abs(doc['population'].value) + 1) + doc['location'].lon * doc['location'].lat)/_score",
                        "lang": "painless"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        {
          "name": "decay_geo_gauss_function_score",
          "operation-type": "search",
          "body": {
            "query": {
              "function_score": {
                "query": {
                  "match_all": {}
                },  
                "gauss": {
                  "location": {
                    "origin": "52.37, 4.8951",
                    "scale": "500km",
                    "offset": "0km",
                    "decay" : 0.1
                  }
                }     
              }
            }
          }
        },
       {
          "name": "decay_geo_gauss_script_score",
          "operation-type": "search",
          "body": {
            "query": {
              "script_score": {
                "query": {
                  "match_all": {}
                },
                "script": {
                  "source": "decayGeoGauss(params.origin, params.scale, params.offset, params.decay, doc['location'].value)",
                  "params": {
                     "origin": "52.37, 4.8951",
                      "scale": "500km",
                      "offset": "0km",
                      "decay" : 0.1 
                  }
                }
              }
            }
          }
        },
        {
          "name": "random_script_score",
          "operation-type": "search",
          "body": {
            "query": {
              "script_score": {
                "query": {
                  "match_all": {}
                },
                "script": {
                  "source": "randomScore(100, '_seq_no')"
                }
              }
            }
          }
        },     
        {
          "name": "large_terms",
          "operation-type": "search",
          "param-source": "pure-terms-query-source"
        },
        {
          "name": "desc_sort_population",
          "operation-type": "search",
          "body": {
            "query": {
              "match_all": {}
            },
            "sort" : [
              {"population" : "desc"}
            ]
          }
        },
        {
          "name": "asc_sort_population",
          "operation-type": "search",
          "body": {
            "query": {
              "match_all": {}
            },
            "sort" : [
              {"population" : "asc"}
            ]
          }
        },
        {
          "name": "desc_sort_geonameid",
          "operation-type": "search",
          "body": {
            "query": {
              "match_all": {}
            },
            "sort" : [
              {"geonameid" : "desc"}
            ]
          }
        },
        {
          "name": "asc_sort_geonameid",
          "operation-type": "search",
          "body": {
            "query": {
              "match_all": {}
            },
            "sort" : [
              {"geonameid" : "asc"}
            ]
          }
        }
    
    

    challenge指定了压测时执行的task,不同的track包含一个或多个challenge,“name”: "append-no-conflicts"表示默认的challenge为append-no-conflicts,执行esrally list tracks可以查看不同track支持的challenge,default为true时,为默认执行的challenge,schedule定义了执行的任务列表

    {
          "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. After that a couple of queries are run.",
          "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": "geonames",
                "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)}}
            },
            {
              "name": "refresh-after-index",
              "operation": "refresh"
            },
            {
              "operation": {
                "operation-type": "force-merge",
                "request-timeout": 7200
              }
            },
            {
              "name": "refresh-after-force-merge",
              "operation": "refresh"
            },
            {
              "name": "wait-until-merges-finish",
              "operation": {
                "operation-type": "index-stats",
                "index": "_all",
                "condition": {
                  "path": "_all.total.merges.current",
                  "expected-value": 0
                },
                "retry-until-success": true,
                "include-in-reporting": false
              }
            },
            {
              "operation": "index-stats",
              "warmup-iterations": 500,
              "iterations": 1000,
              "target-throughput": 90
            },
            {
              "operation": "node-stats",
              "warmup-iterations": 100,
              "iterations": 1000,
              "target-throughput": 90
            },
            {
              "operation": "default",
              "warmup-iterations": 500,
              "iterations": 1000,
              "target-throughput": 50
            },
            {
              "operation": "term",
              "warmup-iterations": 500,
              "iterations": 1000,
              "target-throughput": 150
            },
            {
              "operation": "country_agg_uncached",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 3.6
            },
            {
              "operation": "country_agg_cached",
              "warmup-iterations": 1000,
              "iterations": 1000,
              "target-throughput": 100
            },
            {
              "operation": "scroll",
              "warmup-iterations": 200,
              "iterations": 100,
              "#COMMENT": "Throughput is considered per request. So we issue one scroll request per second which will retrieve 25 pages",
              "target-throughput": 0.8
            },
            {
              "operation": "expression",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 2
            },
            {
              "operation": "painless_static",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 1.5
            },
            {
              "operation": "painless_dynamic",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 1.5
            },
            {
              "operation": "decay_geo_gauss_function_score",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 1
            },
            {
              "operation": "decay_geo_gauss_script_score",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 1
            },
            {
              "operation": "field_value_function_score",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 1.5
            },
            {
              "operation": "field_value_script_score",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 1.5
            },
            {
              "operation": "random_function_score",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 1.5
            },
            {
              "operation": "large_filtered_terms",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 1.1
            },
            {
              "operation": "large_prohibited_terms",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 1.1
            },
            {
              "operation": "desc_sort_geonameid",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 6
            },
            {
              "operation": "asc_sort_geonameid",
              "warmup-iterations": 200,
              "iterations": 100,
              "target-throughput": 6
            }
          ]
        },
        {
          "name": "append-fast-with-conflicts",
          "description": "Indexes the whole document corpus using a setup that will lead to a larger indexing throughput than the default settings. Rally will produce duplicate ids in 25% of all documents (not configurable) so we can simulate a scenario with appends most of the time and some updates in between.",
          "schedule": [
            {
              "operation": "delete-index"
            },
            {
              "operation": {
                "operation-type": "create-index",
                "settings": {%- if index_settings is defined %} {{index_settings | tojson}} {%- else %} {
                  "index.refresh_interval": "30s",
                  "index.number_of_shards": {{number_of_shards | default(6)}},
                  "index.translog.flush_threshold_size": "4g"
                }{%- endif %}
              }
            },
            {
              "name": "check-cluster-health",
              "operation": {
                "operation-type": "cluster-health",
                "index": "geonames",
                "request-params": {
                  "wait_for_status": "{{cluster_health | default('green')}}",
                  "wait_for_no_relocating_shards": "true"
                }
              }
            },
            {
              "operation": "index-update",
              "warmup-time-period": 45,
              "clients": {{bulk_indexing_clients | default(8)}}
            },
            {
              "operation": {
                "operation-type": "force-merge",
                "request-timeout": 7200
              }
            },
            {
              "name": "wait-until-merges-finish",
              "operation": {
                "operation-type": "index-stats",
                "index": "_all",
                "condition": {
                  "path": "_all.total.merges.current",
                  "expected-value": 0
                },
                "retry-until-success": true,
                "include-in-reporting": false
              }
            }
          ]
        }
    
    

    👉car

    用于定义不同配置的ES实例,我们可以定义堆内存大小,垃圾回收器,既然是赛车,那就可以改装,我们可以自定义不同配置的car,执行命令esrally list car可查看所有的赛车,配置在/home/elk/.rally/benchmarks/teams/default/cars/v1目录下
    图片👉race

    表示某一次的压测,并且可以指定赛道和赛车配置,不指定则使用默认配置,race结果存储在/home/elk/.rally/benchmarks/races目录下,执行命令esrally list races可查看以往比赛结果
    图片并且可以对不同的race进行比较

    esrally compare --baseline=d1be27e5-c459-4a40-ab7b-f3576cda7144 --contender=694f5c89-2ed1-4a82-8524-98a8e59778d4
    
    

    图片👉pipeline

    就是定义以何种方式来构建这个集群,通过esrally list pipelines可查看所有的pipeline
    图片

    • from-sources-complete :表示从源代码构建ES, --revision参数可以指定一个ES的修订版本,默认为最新版本、

    • from-sources-skip-build :表示如果之前已经通过源码构建过一次相同版本的ES了,那么本次将不再进行构建,这样可以节省测试的时间

    • from-distribution:esrally将下载正式的ES发行版来进行测试, --distribution-version 参数可以指定ES版本,最低支持1.7.5

    • benchmark-only :将对已有的ES集群进行压测,–target-hosts参数可以指定ES集群地址

    ESrally压测实例

    👉测试5.4.3、6.4.3与7.8.1版本之间的写入性能差异

    使用非root用户运行,并且保证内存够用,这里我是用geonames赛道进行测试,使用默认的car为1gb堆内存,为了快速测试,可以将测试数据和ES二进制包提前下到指定的目录下,ES二进制包存储在/home/elk/.rally/benchmarks/distributions目录下,测试数据存放在/home/elk/.rally/benchmarks/data/geonames目录下

    esrally race --distribution-version=5.4.3 --track=geonames  --user-tag="version:5.4.3" --include-tasks="type:bulk"
    esrally race --distribution-version=6.4.3 --track=geonames  --user-tag="version:6.4.3" --include-tasks="type:bulk"
    esrally race --distribution-version=7.8.1 --track=geonames  --user-tag="version:7.8.1"  --include-tasks="type:bulk"
    
    

    压测过程可以通过/home/elk/.rally/logs.log查看
    图片👉对压测结果进行比较

    比较7.8.1与5.4.3的写入差异

    esrally compare --baseline=27265e6e-566a-4a47-a0d9-1fd2f8830041 --contender=66086ef0-5834-4743-a870-fd9c0bb41688
    
    

    图片可以看到5.4版本的写入性能差别还是很大的
    图片再看一下6.4.3与7.8.1的差异,写入性能差别不是很大

    esrally compare --baseline=27265e6e-566a-4a47-a0d9-1fd2f8830041 --contender=b02fb6fe-824f-48ee-beb5-ab2ca2ad4bbc
    
    

    图片👉测试x86_64平台与arm平台的性能差异

    👉环境

    阿里云2v4g 志强Platinum 8269CY CPU 2.50GHz x86_64
    华为云2v4g 鲲鹏920 CPU 2.6GHz arm平台
    两台云主机的ES配置均相同,2G堆内存,系统参数相同

    开始测试

    还是要提前下好测试数据,这个测试周日跑了一天,结果截图没保存,可能配置太低了,结果差别不是很大,而且不是在同一台机器上跑的,没法使用esrally compare进行比较

    esrally race --pipeline=benchmark-only --target-hosts=172.16.0.95:9200 --track=http_logs --offline
    esrally race --pipeline=benchmark-only --target-hosts=172.26.214.32:9200 --track=http_logs --offline
    
    

    👉中间遇到的问题

    开始压测之后,报不能进入比赛,pid文件不可用
    图片之后查看了相关race的日志,发现内存不够用了,因为之前已经跑了一个ES实例了,导致了我内存不足,把之前的ES实例关掉即可解决
    图片参考链接:https://esrally.readthedocs.io/en/stable/quickstart.html

    - END -

    公众号:运维开发故事

    github:https://github.com/orgs/sunsharing-note/dashboard

    爱生活,爱运维

    如果你觉得文章还不错,就请点击右上角选择发送给朋友或者转发到朋友圈。您的支持和鼓励是我最大的动力。喜欢就请关注我吧~

    图片

    扫码二维码

    关注我,不定期维护优质内容

    温馨提示

    如果你喜欢本文,请分享到朋友圈,想要获得更多信息,请关注我。

                                              ........................
    
    展开全文
  • es官方压测工具,当前最新版本!
  • Elasticsearch 压测方案— esrally 简介

    千次阅读 2019-05-31 20:05:32
    然而在引入新的解决方案前,不免要做一番调研和测试,本文便是介绍官方的一个 es 压测工具 esrally,希望能为大家带来帮助。 为什么要压测? 关于压测,我们先来看下百度百科上的一个定义。 压测,即压力测试,...

    由于 Elasticsearch(后文简称es) 的简单易用及其在大数据处理方面的良好性能,越来越多的公司选用 es 作为自己的业务解决方案。然而在引入新的解决方案前,不免要做一番调研和测试,本文便是介绍官方的一个 es 压测工具 esrally,希望能为大家带来帮助。

    为什么要压测?

    关于压测,我们先来看下百度百科上的一个定义。

    压测,即压力测试,是确立系统稳定性的一种测试方法,通常在系统正常运作范围之外进行,以考察其功能极限和隐患。

    从定义不难看出压测的目的,是要测出一个系统的极限,提早发现隐患,早作打算。那么对于 es 来讲,我认为压测一般有以下几个目的:

    1. 验证 es 的性能,尽管网上把 es 的性能夸上天了,还是自己跑一下才放心。
    2. 针对 es 的某些配置做试验性测试,比如关闭索引的 _all 特性,是否能提高写性能,具体能提高多少。
    3. 对比 es 新版本和旧版本的性能差异。众所周知,es 的版本升级非常快,用着 2.x 的同学们还没来得及升级 5.x ,眼看 6.x 都要发布了。此时,你到底要不要升级呢?答案虽然是肯定的,但是你怎么说服你的 leader 呢?很简单:压测新版本,和旧版本做对比,用表格、图表指明新版本在写性能、读性能方面的改善等等,搞定。
    4. 对 es 集群做容量规划。俗话说“人无远虑,必有近忧”,容量规划就是“远虑”。简单讲就是你线上的 es 集群一共需要多少节点?每个节点的配置如何?这个集群的写性能极限是多少?读性能呢?如果你回答不了这些问题,那就说明你没有做过容量规划,只是两眼一抹黑,说干就干,上了再说,好在有惊无险,没有碰到性能问题。至于什么时候会遇到问题,你也说不准,感觉是个概率和人品问题……对面的老板已经黑脸了…… 对于这个问题我们在最后再来详细讨论。

    如何进行压测?

    现在我们知道压测的目的了,接下来该如何进行压测呢?一般有以下几个方案:

    1. 自己写代码。无需多言,想怎么写怎么写,难点在于如果确保测试代码的专业性。这里有一些开源项目,留给大家自己探索:esperf 和 elasticsearch-stress-test
    2. http压测工具。es 对外暴露了 Restful API,因此所有的针对 http 协议的压测工具都可以用来测试 es,比如 JMeter、httpload等等。
    3. elastic 官方工具 esrally。

    各个压测方案各有优劣,大家可以根据自己的需求和工具熟悉度来选择自己的压测工具。接下来我们就来具体了解下 esrally。

    入门

    简介

    esrally 是 elastic 官方开源的一款基于 python3 实现的针对 es 的压测工具,源码地址为https://github.com/elastic/rally,相关博客介绍在这里。esrally主要功能如下:

    • 自动创建、压测和销毁 es 集群
    • 可分 es 版本管理压测数据和方案
    • 完善的压测数据展示,支持不同压测之间的数据对比分析,也可以将数据存储到指定的es中进行二次分析
    • 支持收集 JVM 详细信息,比如内存、GC等数据来定位性能问题

    elastic 官方也是基于 esrally 进行 es 的性能测试,并将结果实时发布到 https://elasticsearch-benchmarks.elastic.co/ ,大家可以从该网站上直接查看 es 的性能。官方使用两台服务器进行压测,一台运行 esrally ,一台运行 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

    网站顶部的 Geonames、Geopoint、Percolator等都是针对不同的数据集做的压测,比如下面这些图展示了 logging 日志类数据的压测结果。

    快速入门

    esrally 的文档在这里,这里简单说下安装与运行。
    esrally 对于软件环境的要求如下:

    • Python 3.4+ 和 pip3
    • JDK 8
    • git 1.9+

    安装方法为:

    pip3 install esrally

    Tips: 
    可以使用国内的pip源,比如豆瓣或者阿里的,这样安装会快很多。

    安装完毕后执行如下的配置命令,确认一些数据存放的路径即可。

    esrally configure

    接下来就可以开跑了,比如下面这条命令是针对 es 5.0.0 版本进行压力测试。

    esrally --distribution-version=5.0.0

    运行结束后,会得到如下的结果。

    对于第一次见到压测结果的同学来说可能有些晕,这么多数据,该怎么看?!别急,一步步来!

    Tips:
    由于 esrally 的测试数据存储在国外 aws 上,导致下载很慢甚至会超时失败,从而导致整个压测无法进行。后面我会把这些测试数据的压缩包放到国内,大家可以下载后直接放到 esrally 的数据文件夹下面,保证压测的正常进行。另外由于数据量过大,压测的时间一般会很久,可能在1个小时左右,所以大家要有耐心哦~
    如果你只是想体验下,可以加上 --test-mode 的参数,此时只会下载1000条文档进行测试。

    相关术语

    rally 是汽车拉力赛的意思,也就是说 esrally 是将压测比作了汽车拉力赛,因此其中的很多术语都是从汽车拉力赛中借鉴来的。

    track

    track 是赛道的意思,在这里是指压测用的数据和测试策略,详细文档在这里。esrally 自带的track都在 github 上,地址在这里 https://github.com/elastic/rally-tracks。在该 repository 中,有很多测试数据,比如 geonames geopoint logging nested 等,每个数据文件夹中的 README.md 中有详细的数据介绍,而 track.json 便是压测策略的定义文件。
    我们来看下 loggins/track.json 文件

    {% import "rally.helpers" as rally with context %}
    
    {
      "short-description": "Logging benchmark",
      "description": "This benchmark indexes HTTP server log data from the 1998 world cup.",
      "data-url": "http://benchmarks.elasticsearch.org.s3.amazonaws.com/corpora/logging",
      "indices": [
        {
          "name": "logs-181998",
          "types": [
            {
              "name": "type",
              "mapping": "mappings.json",
              "documents": "documents-181998.json.bz2",
              "document-count": 2708746,
              "compressed-bytes": 13815456,
              "uncompressed-bytes": 363512754
            }
          ]
        },
        {
          "name": "logs-191998",
          "types": [
            {
              "name": "type",
              "mapping": "mappings.json",
              "documents": "documents-191998.json.bz2",
              "document-count": 9697882,
              "compressed-bytes": 49439633,
              "uncompressed-bytes": 1301732149
            }
          ]
        }
      ],
      "operations": [
        {{ rally.collect(parts="operations/*.json") }}
      ],
      "challenges": [
        {{ rally.collect(parts="challenges/*.json") }}
      ]
    }
    

    该 json 文件主要包含下面几个部分:

    • description 和 short-description: track 的描述文字
    • data-url: 一个url地址,指明测试数据的下载根路径,与下方 indices 中的 documents 结合,可得到数据的下载地址。
    • indices: 指定该track可以操作的索引,包括创建、更新、删除等操作。详细信息可以参见这里
    • operations: 指定具体的操作,比如 index 索引数据的操作、force-merge 强制合并segment的操作、search 搜索的操作等等。具体例子可以看下面的示例。详细信息可以参见这里
    • challenges: 通过组合 operations 定义一系列 task ,再组合成一个压测的流程,请参照下方的 例子。详细信息参见这里

    operations/default.json 中的一个定义如下:

    {
          "name": "index-append",
          "operation-type": "index",
          "bulk-size": 5000
    }

    其中 operation-type 包含 index、force-merge、index-stats、node-stats、search等,每一个operation-type都有自己的可定义参数,比如 index 中可以通过指定 bulk-size 来决定批量写入的文档数。

    challenges/default.json 中的一个定义如下:

     {
          "name": "append-no-conflicts",
          "description": "",
          "default": true,
          "index-settings": {
            "index.number_of_replicas": 0
          },
          "schedule": [
            {
              "operation": "index-append",
              "warmup-time-period": 240,
              "clients": 8
            },
            {
              "operation": "force-merge",
              "clients": 1
            },
            {
              "operation": "index-stats",
              "clients": 1,
              "warmup-iterations": 100,
              "iterations": 100,
              "target-throughput": 50
            },
            {
              "operation": "node-stats",
              "clients": 1,
              "warmup-iterations": 100,
              "iterations": 100,
              "target-throughput": 50
            },
            {
              "operation": "default",
              "clients": 1,
              "warmup-iterations": 100,
              "iterations": 500,
              "target-throughput": 10
            },
            {
              "operation": "term",
              "clients": 1,
              "warmup-iterations": 100,
              "iterations": 500,
              "target-throughput": 60
            },
            {
              "operation": "range",
              "clients": 1,
              "warmup-iterations": 100,
              "iterations": 200,
              "target-throughput": 2
            },
            {
              "operation": "hourly_agg",
              "clients": 1,
              "warmup-iterations": 100,
              "iterations": 100,
              "target-throughput": 0.2
            },
            {
              "operation": "scroll",
              "clients": 1,
              "warmup-iterations": 100,
              "iterations": 200,
              "target-throughput": 10
            }
          ]
        }

    这里定义了一个名为 append-no-conflicts 的 challenge。由于每次压测只能运行一个challenge,这里的 default 参数是指当压测未指定时默认运行的 challenge。schedule 中指定了该 challenge 中按顺序执行 index-append、force-merge、index-stats、node-stats、default、term、range、hourly_agg、scroll 等 9 个task,其中每个 task 都指定了 一个 operation,除此之外还可以设定 clients (并发客户端数)、warmup-iterations(预热的循环次数)、iterations(operation 执行的循环次数)等,详情请参见此处

    通过下面的命令可以查看当前 esrally 可用使用的track。

    esrally list tracks

    esrally 的 track 数据位于 rally 目录(mac默认是 ~/.rally)中 benchmarks/tracks/ 下面。

    car

    car 是赛车的意思,这里是指不同配置的 es 实例。通过下面的命令可以查看 esrally 当前可用的 car。

    esrally list cars

    Name
    ----------
    16gheap
    1gheap
    2gheap
    4gheap
    8gheap
    defaults
    ea
    verbose_iw

    cars 的配置位于 rally 目录(mac默认是 ~/.rally)中 benchmarks/teams/default/cars/ 下面。具体配置可以参见 cars 的文档,除了 heap 的配置,所有的 es 配置都可以修改。

    race

    race 是一次比赛的意思,这里是指某一次压测。要比赛,就要有赛道和赛车,如果不指定赛车,就用 default 配置,如果不指定赛道,则默认使用 geonames track。通过下面的命令来执行一次 race。

    esrally race --track=logging --challenge=append-no-conflicts --car="4gheap"

    上面的命令便是执行一次压测,并指定使用 logging 的track,运行该 track 中的 append-no-conflicts 的 challenge,指定的 car 为 4gheap 的 es 实例。详情可以查看 race 相关文档

    Tournament

    tournament 是锦标赛的意思,是由多个 race 组成的。通过下面的命令可以查看所有的 race。

    esrally list races

    Recent races:
    
    Race Timestamp    Track    Challenge            Car       User Tag
    ----------------  -------  -------------------  --------  ------------------------------
    20160518T122341Z  pmc      append-no-conflicts  defaults  intention:reduce_alloc_1234
    20160518T112057Z  pmc      append-no-conflicts  defaults  intention:baseline_github_1234
    20160518T101957Z  pmc      append-no-conflicts  defaults

    当有了多个 race 后,可以通过下面的命令方便地比较不同 race 之间的数据。

    esrally compare --baseline=20160518T112057Z --contender=20160518T112341Z

     

    详细信息可以参见 tournament 的文档

    Pipeline

    Pipeline 在这里是指压测的一个流程,通过下面的命令可以查看已有的pipeline。

    esrally list pipeline

    Name                     Description
    -----------------------  ---------------------------------------------------------------------------------------------
    from-sources-complete    Builds and provisions Elasticsearch, runs a benchmark and reports results.
    from-sources-skip-build  Provisions Elasticsearch (skips the build), runs a benchmark and reports results.
    from-distribution        Downloads an Elasticsearch distribution, provisions it, runs a benchmark and reports results.
    benchmark-only           Assumes an already running Elasticsearch instance, runs a benchmark and reports results
    
    • from-sources-complete 是从源代码编译 es 后再运行,可以通过 --revision 参数指明要编译的commit hash ,这样就可以针对某一个提交版本就行测试了。
    • from-sources-skip-build 如果已经编译好了,使用该 pipeline,可以跳过编译的流程,节省测试时间
    • from-distribution 通过 --distribution-version 指定 es 版本,esrally 会从官网直接下载该版本的可执行文件,然后进行测试。
    • benchmark-only 此 pipeline 将 es 集群的管理交由用户来处理, esrally 只做压测。如果你想针对已有集群进行测试,那么要将pipeline设定为该模式。

    详细信息请参见 pipeline 的文档

    压测流程

    esrally 的压测流程主要分为以下三个步骤:

    1. 根据参数设定自行编译或者下载 es 可执行实例,然后根据 car 的约定,创建并启动 es 集群。如果使用 benchmark-only 的pipeline,则该步骤省略。
    2. 根据指定 track 去下载数据,然后按照指定的 challenge 进行操作。
    3. 记录并输出压测结果数据。

    压测结果分析

    压测结束后,esrally 会将结果输出到终端和结果文件(位于 esrally 目录logs 和 benchmarks/races)中,如下图所示:

     

    在 Metric 一栏,有非常多的指标数据,详细的解释可以参见该文档。一般要关注的数据有:

    • throughput 每个操作的吞吐量,比如 index、search等
    • latency 每个操作的响应时长数据
    • Heap used for x 记录堆栈的使用情况

    先搞懂每个 metric 的含义,然后根据自己的需求去确认自己要关注的指标。

    每一次压测都会以压测时的时间命名,比如 logs/rally_out_20170822T082858Z.log ,这个日志便是记录的 2017年8月22日 8:28:58开始的压测日志。而在 benchmarks/races/2017-08-22-08-28-58 中记录着最终的结果和 es 的运行日志。

    另外对于 benchmark-only 模式的测试,即针对已有集群的压力测试,也可以通过安装 X-Pack Basic 版本进行监控(Monitoring),在压测的过程中就能查看相关指标。

     

    esrally 可以在配置的时候指定将所有的 race 压测结果数据存入一个指定的 es 实例中,配置如下(在 esrally 目录中 rally.ini 文件中):

    [reporting]
    datastore.type = elasticsearch
    datastore.host = localhost
    datastore.port = 9200
    datastore.secure = False
    datastore.user =
    datastore.password =

    esrally 会将数据存储在如下 3 个index中,下面 * 代指月份,即按月存储结果数据。

    • rally-metrics-* 该索引分指标记录每次 race 的结果,如下图所示为某一次race的所有 metric 数据。

     

    第一列时间是指某一次压测的时间,第二列时间是指标采集的时间,第三列 operation 指具体执行的操作,operation 为空的指标都是总计类的,比如indexing total time 记录的是总索引数据的时间、segments_count 是总段数等等。其他的 operation 都记录了每一个操作的数据。需要注意的是,这里记录的是 operation 的所有采样数据,不是一个最终的汇总数据。上面截图中也可以看出同一个 hour_agg 的operation 有多项名为 service_time 的指标数据,但他们的采集时间是不同的。基于这些数据,我们可以做出某一次 race 中某个指标的可视化图表,比如你想观察本次 race 中 index-log 这个 task 的 throughput 指标数据,便可以通过如下图的方式实现。

     

    • rally-result-* 该索引分指标记录了每次 race 的最终汇总结果,比如下面这条数据。

      {
         "user-tag": "shardSizeTest:size6",
         "distribution-major-version": 5,
         "environment": "local",
         "car": "external",
         "plugins": [
           "x-pack"
         ],
         "track": "logging",
         "active": true,
         "distribution-version": "5.5.2",
         "node-count": 1,
         "value": {
           "50_0": 19.147876358032228,
           "90_0": 21.03116340637207,
           "99_0": 41.644479789733886,
           "100_0": 47.20634460449219
         },
         "operation": "term",
         "challenge": "default-index",
         "trial-timestamp": "20170831T063724Z",
         "name": "latency"
       }

    这个记录了 term operation 的 latency 指标数据,汇总值以 percentile(百分位数) 的形式展示。基于该数据,我们可以绘制针对某个指标的多race对比,比如下图便是对比多 race 之间 hourly_agg(按小时做聚合)、default(match_all 查询)、term(term查询)、range(range查询)的latency(延迟时间)对比。

    • rally-races-* 该索引记录了所有 race 的最终结果,即命令行执行的输出结果。

    除了es相关指标数据外,esrally 还会同时记录测试的一些环境信息,比如操作系统、JVM等等,你可以方便的查看本次测试的软硬件环境。

    实战

    终于到了开赛的时候,下面我们采用问答的形式来进行,希望大家看到问题后先自己思考下再看答案。

    问题一

    提问:如何对比 5.5.0 相比 2.4.6 的性能改进?

    回答:

    分别针对 5.5.0 和 2.4.6 做一次压测,然后比较两者两者的相关指标即可,这里我们的 track 和 challenge 如下:

    • track: nyc_taxis
    • challenge: append-no-conflicts

    测试步骤如下:

    1. 测试 2.4.6 的性能

    esrally race --distribution-version=2.4.6 --track=nyc_taxis --challenge=append-no-conflicts --user-tag="version:2.4.6"

    1. 测试 5.5.0 的性能

    esrally race --distribution-version=5.5.0 --track=nyc_taxis --challenge=append-no-conflicts --user-tag="version:5.5.0"

    1. 对比两次 race 的结果

    esrally list races

    esrally compare --baseline=[2.4.6 race] --contender=[5.5.0 race]

    Tips:
    --user-tag 用于为 race 打标签,方便后续查找
    如果只是试一下,可以加上 --test-mode ,用测试数据来跑,很快。

    问题二

    提问:如何测试 _all 关闭后对于写性能的影响?

    回答:

    针对 5.5.0 版本的 es 做两次测试,第一次开启 _all,第二次关闭 _all,对比两次的结果,由于只测试写性能,所以我们只需要 index 类型的 operation执行。这里我们的 track 和 challenge 如下:

    • track: nyc_taxis
    • challenge: append-no-conflicts

    测试步骤如下:

    1. 默认 nyc_taxis 的 mapping 设置是将 _all 关闭的,直接测试 _all 关闭时的性能。

    esrally race --distribution-version=5.5.0 --track=nyc_taxis --challenge=append-no-conflicts --user-tag="enableAll:false" --include-tasks="type:index"

    1. 修改 nyc_taxis 的 mapping 设置,打开 _all。mapping 文件位于 rally 主目录 benchmarks/tracks/default/nyc_taxis/mappings.json,修改 _all.enabled 为 true。

    esrally race --distribution-version=5.5.0 --track=nyc_taxis --challenge=append-no-conflicts --user-tag="enableAll:true" --include-tasks="type:index"

    1. 对比两次 race 的结果

    esrally list races

    esrally compare --baseline=[enableAll race] --contender=[disableAll race]

    下图是我在 --test-mode 模式下运行的对比结果,也可以看出关闭 _all 可以提升写性能。

    Tips:
    --include-tasks 用于只运行 challenge 中的部分 task

    问题三

    提问:如何测试已有集群的性能?

    回答:

    使用 benchmark-only 的 pipeline 即可,这里我们的 track 和 challenge 如下:

    • track: nyc_taxis
    • challenge: append-no-conflicts

    测试步骤如下:

    1. 执行下方命令即可测试已有集群

    esrally race --pipeline=benchmark-only --target-hosts=127.0.0.1:9200 --cluster-health=yellow --track=nyc_taxis --challenge=append-no-conflicts

    Tips:
    --cluster-health=yellow 默认 esrally 会检查集群状态,非 green 状态会直接退出。添加该参数可以避免该情况

    希望这三个问答可以帮助到大家快速掌握 esrally 的用法。

    进阶

    自定义 car

    前面讲解 car 的时候,我们提到 esrally 已经自带了一些可用的 es 配置,但是如果这些还不能满足你的时候,可以通过下面两个方案解决。

    1. 定制自己的car
      car 的配置文件位于 esrally 目录 benchmarks/teams/default/cars,在这里新增一个自己的 car 配置文件就可以了。这里就不赘述了,感兴趣的可以查阅 car 的文档
    2. 自己搭建集群
      最简单的方式是脱离 esrally 的管理,自行搭建集群,这样想怎么配置就怎么配置了。

    自定义 track

    虽然 esrally 自带了很多 track,而且这些数据本身也不小,简单列在下面:

    Track压缩数据大小解压数据大小文档数
    geonames252 MB3.3 GB11396505
    geopoint482 MB2.3 GB60844404
    logging1.2 GB31 GB247249096
    nested663 MB3.3 GB11203029
    noaa947 MB9 GB33659481
    nyc_taxis4.5 GB74 GB165346692
    percolator103KB105 MB2000000
    pmc5.5 GB22 GB574199

    这些数据文件位于 esrally 目录 benchmarks/data 下面。不同的 Track 有不同的测试目的,详情可以去该 github repo 下面去查看。

    当我们做定向测试的时候,还是希望针对自己的数据进行压测,此时可以自定义 track。操作也很简单,详情可以参考官方文档。这里简单列一下操作步骤。

    1. 在 上文提到的 data 目录中创建自己的数据目录。
    2. 准备压测数据文件。 esrally 使用的是一个json文件,其实是一个一个 json object。
    3. 将准备好的数据文件压缩成 bz2 格式,然后复制到步骤 1 创建的目录中去。
    4. 新增自定义的track。可以直接复制 geoname 目录,然后修改相关的配置文件,将测试数据与 track 绑定。
    5. 添加完后,通过 esrally list rack 就可以看到自定义的 track。

    分布式压测

    esrally 还支持分布式压测,即如果一个节点的 esrally 无法达到要求的并发数、请求数,那么可以将 esrally 分布到多台机器上去同时执行。分布式压测文档在这里,此处用到了 esrally dameon,对应命令是 esrallyd 。简单讲就是 esrally 通过 esrallyd 将多台机器组合成一个集群,然后 esrally 在执行测试任务的时候通过制定 --load-driver-hosts 便可以将测试任务分发到对应的机器上执行。这里便不赘述了,感兴趣的去看前面提到的文档。

    最后一个问题

    让我们回到开头提到的容量规划的问题吧!

    提问:一个 index 的 shard 数该如何确认?

    回答:

    其实针对这个提问,还可以再问下面两个问题。

    1. shard 设置过少是否有问题?比如一直都采用默认的 5个分片
    2. shard 设置过多是否有问题?比如直接设置为100个分片

    要回到这两个问题,我们得先知道 shard 的作用。shard 是 es 实现分布式特性的基石,文档在索引进 es 时,es 会根据一个路由算法,将每一个文档分配到对应的 shard 上。每个 shard 实际对应一个 lucene index。那么每个 shard 能存储的文档数是否有上限呢?答案是有!每个shard最多存储 2^31 个文档,即 20亿。这是 lucene 设计决定的。那是不是只要我的文档数没有超过20亿,就可以只用一个或者很少的shard 呢?不尽然。因为随着 shard 体积的增大,其查询效率会下降,而且数据迁移和恢复的成本也会增高。官方建议单个 shard 大小不要超过 50GB,可以参见讨论一讨论二

    现在回答上面的两个问题。
    shard数过小不一定好,如果数据量很大,导致每个 shard 体积过大,会影响查询性能。
    shard数过大也不一定好,因为 es 的每次查询是要分发给所有的 shard 来查询,然后再对结果做聚合处理,如果 shard 数过多也会影响查询性能。因此 shard 的数量需要根据自己的情况测出来。

    官方文档有一节关于容量规划的章节,建议大家去看一下,链接在这里,其给出的步骤如下:

    1. 使用生产环境的硬件配置创建单节点集群
    2. 创建一个只有一个主分片无副本的索引,设置相关的mapping信息
    3. 将真实的文档导入到步骤 2 的索引中
    4. 测试实际会用到的查询语句

    测试的过程中,关注相关指标数据,比如索引性能、查询性能,如果在某一个点相关性能数据超出了你的预期值,那么此时的 shard size大小便是符合你预期的单个 shard size的大小。接下来通过下面这个简单的计算公式便大致能确定一个 index 需要设定的 shard 数了。

    shard数 = index 的数据总大小/单个shard size的极限值

    比如你测出单个 shard size 最大为 20 GB,而你预测该索引数据最大量在1年或者2年内不会超过 200GB,那么你的 shard 数就可以设置为10。

    接下来要做的事情也很明确,我们要用 esrally 完成上面的压测步骤:

    1. 自行维护 es 节点的创建和运行,esrally 运行的时候采用 benchmark-only 模式.
    2. 自定义 track,这里有以下两个重点:

      • 生成真实数据。如果你的数据无法生成很多,那么可以在 track 的 schedule 中设置 iterations 参数,即循环进行同一个操作,这样也可以测试大数据量的写性能。
      • 定义自己的查询任务。在 track 的 operations 中是可以定义自己的查询语句的,比如下面这个
      {
        "name": "hourly_agg",
        "operation-type": "search",
        "index": "logs-*",
        "type": "type",
        "body": {
          "size": 0,
          "aggs": {
            "by_hour": {
              "date_histogram": {
                "field": "@timestamp",
                "interval": "hour"
              }
            }
          }
        }
      }

      其中的 body 便是自定义的查询语句,所以你可以通过自己的需求来设定查询语句,以贴近实际使用的情况。

    3. 还要记得设置索引的 mapping 与线上一致,比如是否启用 _all 等设置。
    4. 基于自定义的track来进行压测即可。要注意的是运行 esrally 的机器要和 es 机器分开,防止对 es 性能产生干扰。

    Tips:
    esrally 默认在每次压测是会删除已有的索引后再重新创建索引,如果你不想这样,可以在每个 index 的配置中设置 auto-managed 为 false,具体文档在这里
    通过这个参数,你就可以单独压测查询性能了,而不用每次都要先经过漫长的导入数据的过程。

    总结

    esrally 针对 es 的压测设计了一套完备的基于配置文件的测试流程,极大地简化了操作难度,并且提供了可重复验证的方式。对国内用户来讲,我认为最大的难处还是在于 esrally 自带的 track 文件太大,从 国外 aws 下载很慢。好在可以自定义 track,不必完全依赖自带的 track。

    其他没啥好说的,esrally 棒棒哒,大家赶紧去试试吧,如果有问题欢迎来讨论!

    参考资料

    1. esrally 官方文档
    2. Using Rally to benchmark Elasticsearch queries
    3. esrally 作者的演讲视频
    4. Benchmarking Elasticsearch for your use case with Rally

    转载:https://segmentfault.com/a/1190000011174694

    展开全文
  • Elasticsearch压测工具esrally使用笔记

    千次阅读 2021-01-31 22:48:40
    Elasticsearch压测工具esrally使用笔记 一、环境配置 方法一 使用docker docker pull elastic/rally docker run elastic/rally list tracks docker run elastic/rally --track=nested --test-mode --pipeline=...
  • 1.真正的离线安装esrally 2.术语介绍,官方数据集、track介绍 3.官方数据集下载 4.离线使用esrally测试现有ES测试集群 5.对比两次race(测试)的结果 6.测试时间太长怎么办? 7.报告分析 全文: 【离线】...
  • ELK esrally 压测工具安装使用

    千次阅读 2019-06-26 10:07:02
    ES 是近乎线性扩展的分布式系统,所以可以总结成同一个测试模式: 1.使用和线上集群相同硬件配置的服务器搭建一个单节点集群。 2.使用和线上集群相同的映射创建一个 0 副本,1 分片的测试索引。 3.使用和线上集群...
  • 一、esrally工具介绍 esrally是基于python的针对ES(Elasticsearch)实现压测的工具 rally的定义是the macrobenchmarking framework for Elasticsearch,是基于用户视角的系统测试,不仅可以使用命令行,同时也...
  • 一、针对ES版本压测数据对比 针对ES2.4.6与ES5.6.0进行性能对比,前提是在同一压测数据集和压测方案条件下进行 1、针对ES2.4.6版本进行压测(~/.rally/benchmarks/tracks/MyTracks/demo...esrally --distribution-...
  • ES压测工具(二):esrally进阶实战

    千次阅读 2019-11-13 13:37:51
    一、esrally压测执行步骤回顾 通过上图可以得知,esrally执行命令的步骤如下: 先判断本地有没有ES6.0.0的实例,如果没有就去下载ES6.0.0的实例 判断本地有没有http_logs的track压测数据集,如果没有就去下载...
  • ES性能测试-esrally

    千次阅读 2020-04-21 14:35:50
    es存储结构: 我们从es存储一个数据来分析es的结构: index相当于我们的mysql中的数据库的database _type相当于我们数据的表名 id:相当于我们表中的某一...esrally 对于软件环境的要求如下: Python 3.4+ 和 pip3 ...
  • esrally 是 elastic 官方开源的一款基于 python3 实现的针对 es 的压测工具,esrally主要功能如下: 自动创建、压测和销毁 es 集群 可分 es 版本管理压测数据和方案 完善的压测数据展示,支持不同压测之间的数据...
  • ESrally离线测试环境搭建

    千次阅读 2017-09-28 15:20:05
    由于公司网络原因没法从esrally默认下载源下载数据,另外我的linux也没法从github上下载esrally,因此整个配置过程需要 纯手动配置了。下面介绍下整个流程。整个配置过程可以参考官网http://esrally .readthedocs ....
  • rally文档:http://esrally.readthedocs.io/en/latest/quickstart.html...然而在引入新的解决方案前,不免要做一番调研和测试,本文便是介绍官方的一个 es 压测工具 esrally,希望能为大家带来帮助。为什...
  • 文章目录为什么要压测?如何进行压测?入门简介快速入门相关术语...然而在引入新的解决方案前,不免要做一番调研和测试,本文便是介绍官方的一个 es 压测工具 esrally,希望能为大家带来帮助。 为什么
  • Elasticsearch压测工具esrally详解

    千次阅读 2019-01-12 23:24:35
    rally 工具是 Elastic 官方开源的针对性...对自己在做 ES 源码修改,或者ES 应用调优的人来说 ,通过 rally 验证自己的修改效果,是一件很需要且容易的事情。 环境:python3.4+ ;pip3;JDK8;git 1.9+;gradle 2...
  • es官方自带的压测工具后会生成一个结果json,有没有对这块详细描述的文档或者介绍
  • 压力测试elasticsearch,使用官方推荐工具 esrally 依赖环境: python3.5+ 、 pip3+ 、 git1.9+ 先安装 git ,版本要大于 1.9 yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc-c++ ...
  • ESRally基准测试工具离线使用简介

    千次阅读 2019-12-10 14:56:25
    ESRally安装 运行ESRally需要依赖Python3,Git。本篇是针对Centos7系统。 安装依赖 安装Python3 yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel 解压Python-3.5.0...
  • esrally-dist-1.0.4.tar.gz

    2021-04-19 13:57:49
    esrally-dist-1.0.4.tar.gz
  • esrally性能分析结果图形化展示深入详解
  • 然而在引入新的解决方案前,不免要做一番调研和测试,本文便是介绍官方的一个 es 压测工具 esrally,希望能为大家带来帮助。 为什么要压测? 关于压测,我们先来看下百度百科上的一个定义。 压测,...
  • esrally安装运行测试

    2019-09-12 17:30:13
    esrally安装 安装过程,在《ElasticSearch 性能测试工具 rally esrally 【译】》这篇文章里面,进行了描述。期间也遇到了一个小问题,解决并不难,主要是因为还不熟悉python导致的《ImportError: No module named ...
  • ES压测工具(三):esrally报告指标介绍

    千次阅读 2019-11-14 21:09:50
    ------------------------------------------------------ _______ __ _____ / ____(_)___ ____ _/ / / ___/_________ ________ / /_ / / __ \/ __ `/ / \__ \/ ___/ __ \/ ___/ _ \ ...
  • ES 5.5.3 esrally压测过程及对比

    千次阅读 2018-05-21 17:01:40
    前言:所有操作在mac下操作(在linux上操作相同命令有差异)======安装homebrew=======ruby -e "$(curl -fsSL ... ==&gt; This script will install:/usr/local/bin/brew/usr...
  • 我们采用官方压测工具ESRally来进行压测 二.测试 我们安装好esrally后,先启动它的测试用例 esrally --distribution-version=6.4.1 --test-mode 结果: 三.步骤 1. 定义压测目标 1) 本次压测在于考察ES三...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 522
精华内容 208
关键字:

esrally