热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

locust+boomer+docker+prometheus+grafana性能测试(二)

locust的报告展示无法固化存储,有没有可以把报告数据存储起来的方式?

locust的报告展示无法固化存储,有没有可以把报告数据存储起来的方式?


boomer项目中

prometheus_exporter.py文件实现了prometheus的node_exporter

https://github.com/myzhan/boomer




一、环境搭建(mac为例)

A.docker环境搭建

    请参考官网https://docs.docker.com/desktop/mac/install/


    B.prometheus环境搭建

    prometheus.yml

      global:
      scrape_interval: 15s
      evaluation_interval: 15s

      scrape_configs:
      - job_name: prometheus
      static_configs:
      - targets: ['localhost:9090']
      labels:
      instance: prometheus

      - job_name: locust
      metrics_path: '/export/prometheus'
      static_configs:
            - targets: ['localhost:8089']
      labels:
      instance: locust

      启动prometheus

        docker pull bitnami/prometheus
        docker run -d --name prometheus -p 9090:9090 -v $PWD/prometheus.yml:/etc/prometheus/prometheus.yml bitnami/prometheus


        C.grafana环境搭建

          docker pull grafana/grafana
          docker run -d --name grafana -p 3000:3000 grafana/grafana


          二、代码编写

          见花献佛
          https://github.com/myzhan/boomer/blob/master/prometheus_exporter.py

            import six
            from itertools import chain


            from flask import request, Response
            from locust import stats as locust_stats, runners as locust_runners
            from locust import User, task, events
            from prometheus_client import Metric, REGISTRY, exposition




            # This locustfile adds an external web endpoint to the locust master, and makes it serve as a prometheus exporter.
            # Runs it as a normal locustfile, then points prometheus to it.
            # locust -f prometheus_exporter.py --master
            # Lots of code taken from [mbolek's locust_exporter](https://github.com/mbolek/locust_exporter), thx mbolek!
            class LocustCollector(object):
            registry = REGISTRY


            def __init__(self, environment, runner):
            self.envirOnment= environment
            self.runner = runner


            def collect(self):
            # collect metrics only when locust runner is spawning or running.
            runner = self.runner


            if runner and runner.state in (locust_runners.STATE_SPAWNING, locust_runners.STATE_RUNNING):
            stats = []
            for s in chain(locust_stats.sort_stats(runner.stats.entries), [runner.stats.total]):
            stats.append({
            "method": s.method,
            "name": s.name,
            "num_requests": s.num_requests,
            "num_failures": s.num_failures,
            "avg_response_time": s.avg_response_time,
            "min_response_time": s.min_response_time or 0,
            "max_response_time": s.max_response_time,
            "current_rps": s.current_rps,
            "median_response_time": s.median_response_time,
            "ninetieth_response_time": s.get_response_time_percentile(0.9),
            # only total stats can use current_response_time, so sad.
            # "current_response_time_percentile_95": s.get_current_response_time_percentile(0.95),
            "avg_content_length": s.avg_content_length,
            "current_fail_per_sec": s.current_fail_per_sec
            })


            # perhaps StatsError.parse_error in e.to_dict only works in python slave, take notices!
            errors = [e.to_dict() for e in six.itervalues(runner.stats.errors)]


            metric = Metric('locust_user_count', 'Swarmed users', 'gauge')
            metric.add_sample('locust_user_count', value=runner.user_count, labels={})
            yield metric


            metric = Metric('locust_errors', 'Locust requests errors', 'gauge')
            for err in errors:
            metric.add_sample('locust_errors', value=err['occurrences'],
            labels={'path': err['name'], 'method': err['method'],
            'error': err['error']})
            yield metric


            is_distributed = isinstance(runner, locust_runners.MasterRunner)
            if is_distributed:
            metric = Metric('locust_slave_count', 'Locust number of slaves', 'gauge')
            metric.add_sample('locust_slave_count', value=len(runner.clients.values()), labels={})
            yield metric


            metric = Metric('locust_fail_ratio', 'Locust failure ratio', 'gauge')
            metric.add_sample('locust_fail_ratio', value=runner.stats.total.fail_ratio, labels={})
            yield metric


            metric = Metric('locust_state', 'State of the locust swarm', 'gauge')
            metric.add_sample('locust_state', value=1, labels={'state': runner.state})
            yield metric


            stats_metrics = ['avg_content_length', 'avg_response_time', 'current_rps', 'current_fail_per_sec',
            'max_response_time', 'ninetieth_response_time', 'median_response_time',
            'min_response_time',
            'num_failures', 'num_requests']


            for mtr in stats_metrics:
            mtype = 'gauge'
            if mtr in ['num_requests', 'num_failures']:
            mtype = 'counter'
            metric = Metric('locust_stats_' + mtr, 'Locust stats ' + mtr, mtype)
            for stat in stats:
            # Aggregated stat's method label is None, so name it as Aggregated
            # locust has changed name Total to Aggregated since 0.12.1
            if 'Aggregated' != stat['name']:
            metric.add_sample('locust_stats_' + mtr, value=stat[mtr],
            labels={'path': stat['name'], 'method': stat['method']})
            else:
            metric.add_sample('locust_stats_' + mtr, value=stat[mtr],
            labels={'path': stat['name'], 'method': 'Aggregated'})
            yield metric




            @events.init.add_listener
            def locust_init(environment, runner, **kwargs):
            print("locust init event received")
            if environment.web_ui and runner:
            @environment.web_ui.app.route("/export/prometheus")
            def prometheus_exporter():
            registry = REGISTRY
            encoder, content_type = exposition.choose_encoder(request.headers.get('Accept'))
            if 'name[]' in request.args:
            registry = REGISTRY.restricted_registry(request.args.get('name[]'))
            body = encoder(registry)
            return Response(body, content_type=content_type)


            REGISTRY.register(LocustCollector(environment, runner))




            class Dummy(User):
            @task(20)
            def hello(self):
            pass


            三、查看结果

            启动命令:

              locust --master -f prometheus_exporter.py
              go run slave.go  --master-host=127.0.0.1 --master-port=5557 --max-rps 10000

              查看结果:

              访问http://127.0.0.1:8089/,如图,说明脚本执行成功

              访问

              http://127.0.0.1:8089/export/prometheus,如图,说明启动成功

              访问http://127.0.0.1:9090/targets,如果数据已写入prometheus中

              访问

              http://127.0.0.1:3000/d/VvJxUgCWk/locust-for-prometheus?orgId=1

              ,如图数据已在Grafana中展示


              四、未来规划

              1.boomer对taf协议的压测

              2.使用boomer需要熟悉Go语言,有学习成本,做成平台省去Go的学习成本

              3.施压机迁移到k8s平台上






              推荐阅读
              • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
              • Jupyter Notebook多语言环境搭建指南
                本文详细介绍了如何在Linux环境下为Jupyter Notebook配置Python、Python3、R及Go四种编程语言的环境,包括必要的软件安装和配置步骤。 ... [详细]
              • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
                本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
              • 本文详细介绍了如何在Oracle VM VirtualBox中实现主机与虚拟机之间的数据交换,包括安装Guest Additions增强功能,以及如何利用这些功能进行文件传输、屏幕调整等操作。 ... [详细]
              • 如何在Django框架中实现对象关系映射(ORM)
                本文介绍了Django框架中对象关系映射(ORM)的实现方式,通过ORM,开发者可以通过定义模型类来间接操作数据库表,从而简化数据库操作流程,提高开发效率。 ... [详细]
              • 利用 Calcurse 在 Linux 终端高效管理日程与任务
                对于喜爱使用 Linux 终端进行日常操作的系统管理员来说,Calcurse 提供了一种强大的方式来管理日程安排、待办事项及会议。本文将详细介绍如何在 Linux 上安装和使用 Calcurse,帮助用户更有效地组织工作。 ... [详细]
              • Requests库的基本使用方法
                本文介绍了Python中Requests库的基础用法,包括如何安装、GET和POST请求的实现、如何处理Cookies和Headers,以及如何解析JSON响应。相比urllib库,Requests库提供了更为简洁高效的接口来处理HTTP请求。 ... [详细]
              • 本文详细介绍了如何正确设置Shadowsocks公共代理,包括调整超时设置、检查系统限制、防止滥用及遵守DMCA法规等关键步骤。 ... [详细]
              • 本文详细介绍了如何搭建一个高可用的MongoDB集群,包括环境准备、用户配置、目录创建、MongoDB安装、配置文件设置、集群组件部署等步骤。特别关注分片、读写分离及负载均衡的实现。 ... [详细]
              • 本文介绍了如何在不同操作系统上安装Git,以及一些基本和高级的Git操作,包括项目初始化、文件状态检查、版本控制、分支管理、标签处理、版本回退等,并简要提及了开源许可协议的选择。 ... [详细]
              • FL Studio 20.8 中文版进阶教程及安装指南
                FL Studio 20.8 是目前最新版本的音乐制作软件,它能够将您的电脑转变为全面的音乐工作室,配备先进的制作工具,使您的音乐创作超越想象。本文将详细介绍FL Studio 20.8的安装步骤及中文语言切换方法。 ... [详细]
              • 通过网上的资料我自己的实际内核编译,我把对Linux内核编译的过程写在这里,也许对其他的Linux爱好者的编译学习有些帮助,其中很大部分是 ... [详细]
              • 在 Ubuntu 22.04 LTS 上部署 Jira 敏捷项目管理工具
                Jira 敏捷项目管理工具专为软件开发团队设计,旨在以高效、有序的方式管理项目、问题和任务。该工具提供了灵活且可定制的工作流程,能够根据项目需求进行调整。本文将详细介绍如何在 Ubuntu 22.04 LTS 上安装和配置 Jira。 ... [详细]
              • 在Ubuntu 18.04上使用Nginx搭建RTMP流媒体服务器
                本文详细介绍了如何在Ubuntu 18.04上使用Nginx和nginx-rtmp-module模块搭建RTMP流媒体服务器,包括环境搭建、配置文件修改和推流拉流操作。适用于需要搭建流媒体服务器的技术人员。 ... [详细]
              • 所在位置|室友_Python+OpenCv实现图像边缘检测(滑动调节阈值)
                所在位置|室友_Python+OpenCv实现图像边缘检测(滑动调节阈值) ... [详细]
              author-avatar
              凯瑞德医药科技发展有限公司_997
              这个家伙很懒,什么也没留下!
              PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
              Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有