超详细的搭建压测平台笔记

news2024/11/18 21:46:23

0、前言

最近重新回来学习熊哥的极客教程,结合自己学习的shell编程和Docker的指令学习,对熊哥的一些操作做bash脚本自动化,将搭建压测平台的步骤做记录,目的是分享搭建过程。

过程中会安装docker,mysql,redis,influxdb,grafana,promethues,jmeter,node-exporter等内容。

中间用于压测应用的服务Jar包属于课程的内容,这里不便提供,请原谅。

可以将应用程序jar换成自己标准的spring boot项目。

1、前置条件

  • 首先需要在阿里云创建四台按量计费,4C8G,25Mbps的机器
  • 账户充值至少100RMB
  • 自己机器下载FinalShel软件类似的连接云端服务器的软件,以便进行连接阿里云服务器。

1.1 搭建结构

服务架构如下:
image.png
搭建的监控架构如下所示:
image.png

1.2 云主机选择

选择阿里云 ecs.c7a.xlarge 类型,选择这个类型的原因是相对便宜,而且熊哥当初展示是也是使用这个规格类型,避免发生问题。
image.png
版本选择 CentOs 7.6 64位,硬盘选择默认即可。
image.png
选择分配公网地址,且流量为25Mbpsimage.png

定义自己的实例名称和主机名称。 image.png

目前定义四台机器,实例名称如下列表所示:

实例名主机名密码
hero01-ci-nginx-JMeterhero01A9405kk@01
hero02-mysql-redishero02A9405kk@02
hero03-applicationhero03A9405kk@03
hero04-grafana-influxDB-Prometheushero04A9405kk@04

实例创建完后如下所示:

image.png
为了节省资源消耗,首先先搭建hero02,先把基础中间件搭建完毕。

1.2 搭建环境步骤

1.2.1 搭建hero02-mysql-redis

这里安装Mysql和Redis,采用Docker安装的方式。

1.2.1.1 公网绑定

由于是数据库连接,建议采取弹性公网绑定的方式,以便外部访问。
image.png

image.png

image.png

接下来打开Final-Shell,进行后续操作。
image.png
image.png
image.png

1.2.1.1 安装Docker

创建一个脚本,install-docker.sh,内容如下所示:

#!/bin/bash

# 该脚本用于在CentOS 7.6上自动安装Docker并设置为开机自启

# 更新YUM包索引
sudo yum check-update

# 卸载旧版本的Docker(如果安装了)
sudo yum remove docker \
                docker-client \
                docker-client-latest \
                docker-common \
                docker-latest \
                docker-latest-logrotate \
                docker-logrotate \
                docker-engine

# 安装必要的YUM依赖项
sudo yum install -y yum-utils

# 设置Docker的稳定版仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 安装Docker Engine(社区版)
sudo yum install -y docker-ce docker-ce-cli containerd.io

# 启动Docker服务
sudo systemctl start docker

# 将当前用户加入docker组,避免每次调用docker命令都需要sudo(需要重新登录以生效)
sudo usermod -aG docker $(whoami)

# 设置Docker服务开机自启
sudo systemctl enable docker

sudo yum install -y docker-compose

# 验证Docker是否安装成功
sudo docker run hello-world

# 脚本结束
echo "Docker has been installed and set to start on boot."

然后执行下面命令:

[root@hero02 ~]# vim install-docker.sh
[root@hero02 ~]# bash install-docker.sh 

image.png

1.2.1.2 安装Mysql+Redis+Adminer

建议参考博客:
Mysql: 【Docker-Dev】Mac M2 搭建docker mysql-CSDN博客
Redis: 【Docker-Dev】Mac M2 搭建docker的redis环境-CSDN博客

执行下面脚本,这个会设置docker启动后,会自动启动这两个中间件,而且脚本会帮忙创建对应的一些文件和目录。

创建一个脚本,名称为 install-mysql-redis-adminer.sh,内容如下所示:

#!/bin/bash

# 创建MySQL和Redis的数据存储与日志文件夹和配置文件,并启动服务

# 定义MySQL和Redis的数据和日志目录路径
MYSQL_DATA_DIR="./mysql/data"
MYSQL_CONF_DIR="./mysql/conf"
MYSQL_LOG_DIR="./mysql/logs"
REDIS_DATA_DIR="./redis/data"
REDIS_CONF_DIR="./redis/conf"

# 为MySQL和Redis创建数据和日志目录以及配置文件
mkdir -p "${MYSQL_DATA_DIR}" "${MYSQL_CONF_DIR}" "${MYSQL_LOG_DIR}"
mkdir -p "${REDIS_DATA_DIR}" "${REDIS_CONF_DIR}"


# 创建MySQL配置文件
cat > "${MYSQL_CONF_DIR}/my.cnf" << EOF
[mysqld]
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
datadir = /var/lib/mysql
socket = /var/run/mysqld/mysqld.sock
log-error = /var/log/mysql/mysql_error.log
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
EOF

# 创建Redis配置文件
cat > "${REDIS_CONF_DIR}/redis.conf" << EOF
bind 0.0.0.0
protected-mode no
port 6379
timeout 0
tcp-keepalive 300
daemonize no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /data/redis.log
databases 16
always-show-logo no
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /data
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
slave-priority 100
requirepass rootpassword
appendonly no
EOF

# 创建docker-compose.yml文件
cat > docker-compose.yml << EOF
version: '3.1'

services:
  mysql:
    image: mysql:5.7
    container_name: mysql
    restart: always
    environment:
      MYSQL_DATABASE: 'db'
      MYSQL_USER: 'user'
      MYSQL_PASSWORD: 'password'
      MYSQL_ROOT_PASSWORD: 'root'
    volumes:
      - ${MYSQL_DATA_DIR}:/var/lib/mysql
      - ${MYSQL_CONF_DIR}:/etc/mysql/conf.d
      - ${MYSQL_LOG_DIR}:/var/log/mysql
    ports:
      - "3306:3306"

  redis:
    image: redis:5.0
    container_name: redis
    restart: always
    command: redis-server /usr/local/etc/redis/redis.conf
    volumes:
      - ${REDIS_DATA_DIR}:/data
      - ${REDIS_CONF_DIR}:/usr/local/etc/redis
    ports:
      - "6379:6379"

  adminer:
    image: adminer
    container_name: adminer
    restart: always
    ports:
      - "8901:8080"
    environment:
      ADMINER_DEFAULT_SERVER: mysql
    depends_on:
      - mysql
EOF

# 启动服务
docker-compose up -d

# 输出成功消息
echo "MySQL, Redis, and Adminer services have been started."

image.png
执行完毕后,可以看见服务启动成功。
image.png
为了确保服务重启后,能重新启动,需要重启云服务实例,然后查看是否OK。
目前测试过重启是OK的。

1.2.1.3 设置安全组

为了能够外部访问端口,需要设置安全组策略。
新建安全组并创建者几个规则
image.png
image.png

image.png

接下来,让实例绑定刚刚创建的安全组。
image.png

1.2.1.4 验证是否完成

接下来输入如下地址,下面ip地址,是这台服务器的弹性公网ip地址。

http://<yourIpAddress>:8901

image.png
可以发现是可以打开成功的。
接下来进行登录。
image.png
操作也是正常的。
然后打开redis客户端进行访问。
image.png

ip地址敏感,进行了模糊化

image.png

直到现在为止,redis和mysql已经搭建完成。

1.2.1.5 安装node_exporter

这里我不是采用熊哥的逐步脚本操作,采用docker 文件运行。
创建目录文件 node-export,然后在这个目录下,创建docker-compose.yaml文件,内容如下所示:

这里尤其注意, hostname,和当前你机器的hostname或者你实例的名称一致,否则在后续搭建grafana+promethues面板看见的只是容器的id。看不出是啥。

version: '3.1'

services:
  node-exporter:
    image: prom/node-exporter:latest
    hostname: hero02-mysql-redis
    ports:
      - '9100:9100'
    volumes:
      - '/proc:/host/proc:ro'
      - '/sys:/host/sys:ro'
      - '/:/rootfs:ro'
    command:
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.ignored-mount-points'
      - '^/(sys|proc|dev|host|etc)($$|/)'
    restart: always

然后开放安全组9100端口。
image.png
然后访问

http://<yourIpAddress>:9100/metrics

image.png
然后服务重启后,发现重启后,服务都可以重新恢复。
在这里插入图片描述

1.2.1.6 数据导入

为了验证后续1.2.2的应用程序运行后,可以验证性能效果。这里需要导入sql的初始化脚本。
这里决定采用Adminer进行导入,这里数据库导入的方式因人而已,可以采用自己本身机器连接去导入,我这里只是图省事,后续我还把这个hero_all删掉,再试了一遍sql文件的导入,完全是ok的。只是验证过程。
image.png
首先需要先创建一个数据库,这里命名为hero_all
image.png
否则脚本中存在乱码而导致导入异常。
接下来用导入的方式进行导入。
image.png
导入可能需要较长时间,需要等待一段时间。

1.2.2 搭建hero03-application

因为保密性,应用的jar包不会提供,可以部署自己应用的jar包去进行后续操作。

1.2.2.1 创建JDK环境

用FinalShell登录对应的hero03-application服务器,然后上传jar包到对应目录文件中。

编写下面脚本,以便执行JDK安装,下面脚本可以在任意处执行,会计算上传的jdk文件路径,如果确定自己在哪个路径了,可以修改find命令,改成自己的上传jar包路径地址。

下面的脚本的jdk-8u261-linux-x64.tar.gz,事实上是提前下好了的。Oracle并没有提供不进行用户鉴权后的下载url

#!/bin/bash

# JDK包名称
JDK_TAR_GZ_FILENAME='jdk-8u261-linux-x64.tar.gz'
# JDK版本信息
JDK_VERSION="1.8.0_261"
# 安装目录
JAVA_INSTALL_DIR='/usr/local/java'

# 在整个文件系统中搜索JDK包
echo "正在搜索JDK安装包 ${JDK_TAR_GZ_FILENAME} ..."
JDK_TAR_GZ_PATH=$(find / -type f -name "$JDK_TAR_GZ_FILENAME" 2>/dev/null | head -n 1)

# 如果JDK包不存在,则退出脚本
if [[ -z "$JDK_TAR_GZ_PATH" ]]; then
    echo "错误:未在系统中找到JDK安装包 ${JDK_TAR_GZ_FILENAME}."
    exit 1
fi
echo "找到JDK安装包:${JDK_TAR_GZ_PATH}"

# 检查是否已安装了JDK
if type -p java; then
    JAVA_VERSION=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}')
    if [[ "$JAVA_VERSION" == "$JDK_VERSION" ]]; then
        echo "JDK $JDK_VERSION 已安装."
        exit 0
    else
        echo "发现其他版本的JDK:$JAVA_VERSION"
        exit 1
    fi
else
    echo "未发现JDK安装,继续..."
fi

# 检查Java安装目录是否存在,若不存在则创建
if [[ ! -d "$JAVA_INSTALL_DIR" ]]; then
    echo "创建安装目录..."
    sudo mkdir -p $JAVA_INSTALL_DIR
fi

# 解压JDK包到安装目录
echo "解压JDK到 ${JAVA_INSTALL_DIR}..."
sudo tar -xzf "$JDK_TAR_GZ_PATH" -C "$JAVA_INSTALL_DIR"

# 设置环境变量
JAVA_HOME_DIR=$(tar -tzf "$JDK_TAR_GZ_PATH" | grep "/$" | head -n 1 | tr -d '/')
echo "JAVA_HOME_DIR: ${JAVA_HOME_DIR}"
# 写入环境变量到/etc/profile
echo "设置环境变量..."
echo "export JAVA_HOME=${JAVA_INSTALL_DIR}/${JAVA_HOME_DIR}" | sudo tee -a /etc/profile
echo 'export PATH=$PATH:$JAVA_HOME/bin' | sudo tee -a /etc/profile

# 更新环境变量
source /etc/profile

# 验证安装
echo "验证安装..."
java -version
# 完成
echo "Oracle JDK 安装完成。"

执行完毕后,在command界面还是得输入 source /etc/profile,否则最终还是没生效,我认为可能是脚本的bash执行,terminal的状态并没有变更。
image.png

1.2.2.2 上传应用jar和执行脚本

返回上级目录,并创建子目录,hero_default,由于课程会有多次不同的hero,以及后续还需要测JVM的GC不同会有不同的。
然后在hero_default文件夹下,创建一个conf文件夹。
将熊哥的jar和两个启动脚本都上传上去。
原始的jar提供的start.sh的执行脚本如下所示:

#!/bin/sh
# Copyright 1999-2022 Geek NB Group Holding Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

export JAVA_HOME=/usr/local/hero/jdk1.8.0_261
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

#===========================================================================================
# init
#===========================================================================================

export SERVER="hero_web"
export JAVA_HOME
export JAVA="$JAVA_HOME/bin/java"
# 获取当前目录
export BASE_DIR=`cd $(dirname $0)/.; pwd`
# 默认加载路径
export DEFAULT_SEARCH_LOCATIONS="classpath:/,classpath:/config/,file:./,file:./config/"
# 自定义默认加载配置文件路径
export CUSTOM_SEARCH_LOCATIONS=${DEFAULT_SEARCH_LOCATIONS},file:${BASE_DIR}/conf/


#===========================================================================================
# JVM Configuration
#===========================================================================================
JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${BASE_DIR}/logs/java_heapdump.hprof"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages"
JAVA_OPT="${JAVA_OPT} -jar ${BASE_DIR}/${SERVER}-*.jar"
JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}"
JAVA_OPT="${JAVA_OPT} --spring.config.location=${CUSTOM_SEARCH_LOCATIONS}"
# 创建日志文件目录
if [ ! -d "${BASE_DIR}/logs" ]; then
  mkdir ${BASE_DIR}/logs
fi

# 输出变量
echo "$JAVA ${JAVA_OPT}"
# 检查start.out日志输出文件
if [ ! -f "${BASE_DIR}/logs/${SERVER}.out" ]; then
  touch "${BASE_DIR}/logs/${SERVER}.out"
fi
#===========================================================================================
# 启动服务
#===========================================================================================
# 启动服务
echo "$JAVA ${JAVA_OPT}" > ${BASE_DIR}/logs/${SERVER}.out 2>&1 &
nohup $JAVA ${JAVA_OPT} hero_web.hero_web >> ${BASE_DIR}/logs/${SERVER}.out 2>&1 &
echo "server is starting,you can check the ${BASE_DIR}/logs/${SERVER}.out"

我需要对文件路径进行修改,变动点如下所示:

# 修改JAVA_HOME地址
export JAVA_HOME=/usr/local/java/jdk1.8.0_261
# 修改CUSTOM_SEARCH_LOCATIONS路径
export CUSTOM_SEARCH_LOCATIONS=file:${BASE_DIR}/conf/

因为是标准的spring boot项目,所以执行下面命令,提取出jar包中的config文件。

jar xf hero_web-1.0-SNAPSHOT-default.jar BOOT-INF/classes/application.yml
jar xf hero_web-1.0-SNAPSHOT-default.jar BOOT-INF/classes/application-dev.yml

然后把这两个文件copy所创建的conf目录下

cp BOOT-INF/classes/* conf/

修改application-dev.yml文件做的mysql的ip地址172.17.187.78:3307,改成自己机器的内网地址:3306(需要确定能连通,用户名和密码是正确的):

server:
  port: 9001
spring:
  thymeleaf:
    cache: false
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://<your mysql ip>:3306/hero_all?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    username: root
    password: root

# Tomcat的maxConnections、maxThreads、acceptCount三大配置,分别表示最大连接数,最大线程数、最大的等待数,可以通过application.yml配置文件来改变这个三个值,一个标准的示例如下:
server.tomcat.uri-encoding: UTF-8

由于熊哥提供的脚本文件是windows下的,需要进行windows的换行符变成linux换行符。
这里需要安装一个工具,然后执行命令,将脚本转换格式:

sudo yum install -y  dos2unix
dos2unix startup.sh 
dos2unix stop.sh

image.png
image.png
然后查看一下java进程,是否启动成功
image.png
然后对接口进行访问,测试一下是否成功?

curl http://localhost:9001/spu/goods/10000005620800

image.png

到现在项目jar包已经启动完成。
然后在安全组需要开放9001端口,否则无法外部访问。
image.png

1.2.2.3 启动jmeter的ServiceAgent

回到用户目录,创建serviceAgent文件夹,并cd进去。

为了让压测的时候,jmeter能够监听当前服务器的状态,所以需要下载配置服务端的ServerAgent。

关于ServerAgent的描述请点击这里,下载地址为https://github.com/undera/perfmon-agent/releases/download/2.2.3/ServerAgent-2.2.3.zip。

服务器硬件资源的监控,必须在服务端安装serverAgent代理服务,jmeter才能实现监控服务端的cpu、内存、io的使用情况

通过研究知道,这个下载解压后,内部会有个startAgent.sh的脚本,脚本的原始内容如下所示:

java -jar $(dirname $0)/CMDRunner.jar --tool PerfMonAgent "$@"

按照熊哥说法,为了让能正常对外开放,这里需要把脚本设置端口。

服务启动默认4444端口,根本连接不上,因此自己创建一个部署脚本文件对此进行部署,且把端口修改为7879

所以脚本需要变更如下所示:

nohup java -jar $(dirname $0)/CMDRunner.jar --tool PerfMonAgent --udp-port 7879 --tcp-port 7879 > log.log 2>&1 &

同时还需要赋予脚本可执行权限。

chmod 755 startAgent.sh

因此为了这个目的,我编写如下脚本:

#!/bin/bash

# 定义需要的文件和下载链接
FILE="ServerAgent-2.2.3.zip"
URL="https://github.com/undera/perfmon-agent/releases/download/2.2.3/ServerAgent-2.2.3.zip"
DIR="ServerAgent-2.2.3"
BASE_DIR=$(dirname $(realpath $0))/$DIR
echo "BASE DIR: $BASE_DIR"
# 检查文件是否存在
if [ ! -f "$FILE" ]; then
    echo "$FILE does not exist. Downloading..."
    wget "$URL"
else
    echo "$FILE already exists."
fi

# 检查unzip命令是否存在,如果不存在,则使用yum安装它
if ! command -v unzip &> /dev/null; then
    echo "Unzip not found. Installing it using yum..."
    sudo yum install unzip -y
fi

# 解压zip文件
unzip -o "$FILE"

# 删除旧的startAgent.sh文件(如果存在)
rm -f startAgent.sh

# 创建新的startAgent.sh文件,并添加shebang以及指定的命令
{
echo '#!/bin/bash'
echo ''
echo 'export JAVA_HOME=/usr/local/java/jdk1.8.0_261'
echo 'export JRE_HOME=${JAVA_HOME}/jre'
echo 'export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib'
echo 'export PATH=${JAVA_HOME}/bin:$PATH'
echo 'export JAVA_HOME'
echo 'export JAVA="$JAVA_HOME/bin/java"'
echo 'BASE_DIR=$(dirname $(realpath $0))'
echo 'nohup java -jar $BASE_DIR/CMDRunner.jar --tool PerfMonAgent --udp-port 7879 --tcp-port 7879 > $BASE_DIR/log.log 2>&1 &'
} > $BASE_DIR/startAgent.sh

# 给新的startAgent.sh文件添加执行权限
chmod 755 "$BASE_DIR/startAgent.sh"

# 检查/etc/rc.local是否已包含startAgent.sh启动命令
if ! grep -q "$BASE_DIR/startAgent.sh" /etc/rc.local; then
    echo "Adding startAgent.sh to /etc/rc.local"
    echo "$BASE_DIR/startAgent.sh" | sudo tee -a /etc/rc.local > /dev/null
else
    echo "startAgent.sh already added to /etc/rc.local"
fi

chmod +x /etc/rc.d/rc.local

然后重启服务,执行下面命令:

ps -ef|grep CMDRunner

同时前往ServerAgent-2.2.3的文件夹下,查看log.log输出。
image.png
现在为止已经说明可以执行成功。

然后还需要开放端口。
image.png

1.2.2.4 初步压测验证

打开jmeter工具,运行一下看效果
image.png
主要是看CPU/内存/磁盘读写的效果。
注意测试前需要运行应用程序。
image.png
然后结果如下所示:
image.png
可以看出来,目前是安装成功的,且可以被jmeter收集。

1.2.2.5 安装node_exporter

这台机器也需要安装node exporter,以便监控。
需要先参照 1.2.1.1 安装Docker。
然后再安装 1.2.1.5 安装node_exporter。
这里过程不再演示,只展示最终结果。
访问 http://< yourIpAddress >:9100/metrics
image.png
到现在,hero-application的机器环境已经完全搭建完成。

1.2.3 搭建hero01-ci-nginx-JMeter

这个是为了后续课程学习nginx所需要的。
为了安装OpenResty,推荐采用Docker-Compose的做法,熊哥写的脚本操作最后服务重启还得写脚本,相对麻烦,这里是其官方的Docker Hub链接。

1.2.3.1 安装docker和docker-compose

参照 1.2.1.1 安装Docker

1.2.3.2 下载安装OpenResty

首先,创建一个目录,名称为openResty,创建nginx.conf文件,内容所示:

events {
    # worker_connections 768;
    # 其他事件配置...
}

http {
    server {
        listen 80;
        server_name localhost;

        location / {
            root   /usr/local/openresty/nginx/html;
            index  index.html index.htm;
        }

        # 其他 location、upstream、等配置...
    }

    # 其他 http 配置...
}


然后创建docker-compose.yaml文件,内容如下所示:

version: '3.1'

services:
  openresty:
    image: openresty/openresty
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf
    command: ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"]

在这个docker-compose文件中,我使用command

command: ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"]

这个命令的含义拆解如下:

  • /usr/local/openresty/bin/openresty”:这是在容器内部调用 OpenResty 可执行文件的完整路径。OpenResty 是建立在 Nginx 和 LuaJIT 上的一个全功能的 web 平台,通过该命令启动它。
  • -g”:这是一个指示 OpenResty 接下来的参数是全局指令的标志。
  • "daemon off;":这是一个 Nginx 的全局指令,告诉 Nginx 以前台模式运行而不是默认的守护进程模式。在 Docker 容器中运行服务时,通常希望主进程在前台运行。如果主进程作为守护进程在后台运行,那么 Docker 容器在启动后会立即退出,因为 Docker 认为主进程已经结束。

将整个命令合在一起,就是告诉 Docker 启动 OpenResty 并保持它在前台运行。这样,Docker 就可以管理 OpenResty 服务,如果服务终止,Docker 将能够检测到这一点,并根据容器的重启策略做出相应的操作。

编写完毕后,我选择执行docker compose up -d
image.png
然后将实例加入之前设置好的安全组,使用公网看看能不能访问。
image.png
访问地址是

http://<ip-address>

image.png

1.2.3.3 安装jmeter

这个部分是为了后续搭建分布式压测做准备。
和nginx不同,jmeter不是一个需要实时启动的应用程序,所以jmeter不采用docker方式部署,采用脚本方式。
根据熊哥描述,采用5.4.1的版本方式进行。
为了安装JMeter,首先需要安装JDK,需要按照 1.2.2.1我写的操作步骤安装JDK环境,这里不再重复撰写。

然后把熊哥提供的插件就就绪版的jmeter上传。所谓的插件就绪,是在plugin页面对应插件。然后把下载的文件放入/lib/ext目录下,然后打开测试计划,jui会提示要下哪些插件。下完后压缩上传到linux服务端。

image.png
这里创建/usr/local/apache-jmeter-5.4.1目录,然后把上传的zip。

这里注意,因为原文件zip包包含中文,需要去掉中文,目前我把“插件就绪版"几个字去掉了。

解压放到对应目录下,解压前,需要安装unzip。

yum install -y unzip

然后执行下面脚本:

#!/bin/bash

# 要解压的zip文件
ZIP_FILE="apache-jmeter-5.4.1.zip"

# 目标目录,解压后的文件将放在这里
TARGET_DIR="/usr/local/apache-jmeter-5.4.1"

# 临时目录,用于中转解压内容
TEMP_DIR=$(mktemp -d)

# 解压ZIP文件到临时目录
unzip -q "$ZIP_FILE" -d "$TEMP_DIR"

# 找到临时目录中的第一层目录(假设只有一个目录)
FIRST_DIR=$(find "$TEMP_DIR" -mindepth 1 -maxdepth 1 -type d)
echo "first DIR : $FIRST_DIR"
# 将第一层目录中的内容移动到目标目录
if [ -d "$FIRST_DIR" ]; then
    # 如果目标目录不存在,创建它
    mkdir -p "$TARGET_DIR"
    # 将文件复制到目标目录
    mv "$FIRST_DIR"/* "$TARGET_DIR"
fi

# 删除临时目录
rm -rf "$TEMP_DIR"


# 设置环境变量
echo "Setting environment variables..."

JMETER_HOME_VAR="JMETER_HOME=/usr/local/apache-jmeter-5.4.1"
PATH_VAR='PATH=$JMETER_HOME/bin:$PATH'

# 添加 JMETER_HOME 到 /etc/profile,如果它还没被添加
if ! grep -q "export $JMETER_HOME_VAR" /etc/profile; then
    echo "Adding JMETER_HOME to /etc/profile"
    echo "export $JMETER_HOME_VAR" | sudo tee -a /etc/profile
else
    echo "JMETER_HOME already added to /etc/profile"
fi

# 添加 JMETER_HOME/bin 到 PATH,在 /etc/profile,如果它还没被添加
if ! grep -q "export $PATH_VAR" /etc/profile; then
    echo "Adding JMETER_HOME/bin to PATH in /etc/profile"
    echo "export $PATH_VAR" | sudo tee -a /etc/profile
else
    echo "JMETER_HOME/bin already added to PATH in /etc/profile"
fi

# 提示
echo "Please log out and log back in to apply the environment variable changes, or open a new terminal session."
sudo chmod -R 755 /usr/local/apache-jmeter-5.4.1

为了验证这个是ok的,打算使用一个测试计划去验证。
通过熊哥给的文件,需要把测试计划修改一下,把ip地址切换成内网地址。

jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]
# 参数说明
-h 帮助:打印出有用的信息并退出
-n 非 GUI 模式:在非 GUI 模式下运行 JMeter
-t 测试文件:要运行的 JMeter 测试脚本文件
-l 日志文件:记录结果的文件
-r 远程执行:启动远程服务
-H 代理主机:设置 JMeter 使用的代理主机
-P 代理端口:设置 JMeter 使用的代理主机的端口号
-e:测试结束后,生成测试报告
-o:指定测试报告的存放位置

所以目前我们执行命令:

jmeter -n -t 01-stress-testing-example.jmx -l 01-stress-testing-example.jtl -e -o ./01-stress-testing-example-html

image.png

1.2.3.4 安装node exporter

这台机器也需要安装node exporter,以便监控。
按照1.2.1.5 安装node_exporter。
这里过程不再演示,只展示最终结果。
值得注意的是,记得修改docker-compose.yaml中的hostname,否则会以容器id,后续展示到grafana中。
访问 http://<yourIpAddress>:9100/metrics

1.2.4 搭建hero04-grafana-influxDB-Prometheus

课程中是需要grafana和promethues面板查看程序的状态信息,另外influxDB时序数据库记录结果。
so,这个部分就是搭建这个。
首先需要安装Docker环境,参照1.2.1.1的内容

1.2.4.1 安装influxDB

创建influxDB目录,在influxDB目录下,创建data目录。
data目录路径为:/root/influxDB/data。
在influx目录下创建docker-compose.yaml文件,内容如下所示:

version: '3.1'

services:
  influxdb:
    image: influxdb:1.8
    restart: always
    volumes:
      - /root/influxDB/data:/var/lib/influxdb
    environment:
      INFLUXDB_DB: jmeter  # 预先创建名为jmeter的数据库
    ports:
      - "8086:8086"
      - "8083:8083"

然后执行 docker compose up -d命令。
image.png
然后登录进去看看jmeter数据库是否有了,通过docker ps命令,可以看见启动的容器名为influxdb-influxdb-1。

docker exec -it influxdb-influxdb-1 influx

然后输入show databases;看见jmeter即算成功。
image.png
然后设置安全组,开放8086和8083两个端口。

InfluxDB 是一个开源时间序列数据库,它使用不同的端口来提供不同的功能:

  • 8086 是默认的HTTP API端口,用于客户端与 InfluxDB 服务器的交云通讯。这包括查询、写入时间序列数据,以及管理数据库的请求。自 InfluxDB 1.0 版本开始,8086 端口也支持 InfluxDB 的 HTTP服务。
  • 8083 曾经是 InfluxDB 的管理界面端口,用来访问 InfluxDB 提供的 Web UI(用户界面),可以在浏览器中对数据库进行操作。然而,从 InfluxDB 1.3 版本开始,这个 UI 和对应的端口8083已经被移除,所有的管理操作推荐通过 CLI(命令行界面)或者通过 InfluxDB 的 HTTP API 端口8086来完成。

对于现代的 InfluxDB 2.x 版本,它使用单一的端口(默认是8086)来处理所有的客户端交云通讯和用户界面访问。如果使用的是 InfluxDB 2.x,通常只需要关心8086端口。目前其实也是关心8086。

image.png
image.png

1.2.4.2 安装promethues

新建promethues目录,然后进入promthues目录新建data目录,data目录路径为:/root/promthues/data

然后在/root/promthues目录下新建prometheus.yml文件,内容如下所示:


global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'hero-Linux'
    static_configs:
      - targets: ['172.17.121.201:9100','172.17.121.202:9100','172.17.121.203:9100']

注意一下,这里我配置了heror-linux的一个抓取任务job,配置的targets就是,之前前面几个实例,三台机器机器IP地址配置的node exporter的端口。地址是对应的实例机器的内网地址。

然后在promethues目录下,新建 docker-compose.yaml文件,内容如下所示:

version: '3.1'
services:
  prometheus:
    image: prom/prometheus:v2.15.1
    container_name: prometheus
    user: root
    ports:
      - "9090:9090"
    volumes:
      - /root/promthues/prometheus.yml:/etc/prometheus/prometheus.yml
      - /root/promthues/data:/prometheus
    restart: always

接下来执行 docker compose up -d 命令即可
image.png
image.png
然后设置开放9090安全组:
image.png
接下来就是通过机器的IP地址访问:

http://<ip>:9090

image.png
image.png

1.2.4.3 安装grafana

接下来是重头戏,安装可视化工具,grafana。这样就能把promethues的node_exporter还有influxDB中的数据读取出来。
首先在root目录下,创建 grafana文件夹,然后进入grafana文件夹下创建data目录,data目录路径为:/root/grafana/data。
然后grafana文件夹下,创建docker-compose.yaml文件,内容如下所示:

version: '3.1'

services:
  grafana:
    image: grafana/grafana:latest
    user: root
    ports:
      - '3000:3000'
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_SECURITY_ADMIN_USER=admin
    volumes:
      - /root/grafana/data:/var/lib/grafana
    restart: always

接下来执行 docker compose up -d 命令即可
image.png
image.png
然后设置开放端口3000安全组:
image.png
接下来就是通过机器的IP地址访问:

http://<ip>:3000

image.png
输入docker-compose配置的用户名和密码,登录进去后配置promethues数据源。
image.png
然后这个地方输入promethues的内网地址即可。
image.png

image.png

然后导入grafana的一些公共模板:
导入Linux系统dashboard

  • Node Exporter for Prometheus Dashboard EN 20201010
    • dashboard-ID: 11074
  • Node Exporter Dashboard
    • dashboard-ID: 16098

image.png
image.png
image.png
image.png
另一个面板也如此配置。
image.png

到现在为止,通过grafana和promethues的联合监控已经完毕。

1.2.4.4 设置jmeter的influxDB监控

这里首先,我们需要执行jmeter,在influxDB中加入数据。
我修改了测试计划,在前面加上了用户定义变量,因为阿里云主机,不绑定弹性公网的情况下,主机的公网ip地址是会被随机分配的。
image.png

image.png
接下来加压大概是这样的。
image.png
点击执行运行,压测结束后,需要看看influxdb是否有数据
image.png
搭建grafana的influxDB的数据源。
image.png
image.png
image.png

因为安装的时候特意选的是1.8版本,所以不用选择用户名和密码。
image.png
image.png
在Grafana的官网找到我们需要的展示模板

  • Apache JMeter Dashboard
    • dashboad-ID:5496
  • JMeter Dashboard(3.2 and up)
    • dashboad-ID:3351

image.png
image.png

到此已经做好了grafana+influxdb+jmeter的搭建。

1.3 结语

后续如果有时间,会考虑更新一下搭建多集群机器进行分布式压测的笔记,我还需要整理一下。

主要是需要一台window server主机和3-4台的jmeter小型压力机。

这样可以做梯度压测,由Windows汇总,也不需要我在mac电脑上压测,可以采用windows server,然后避免ip地址因为云主机启动而不得不变更ip的问题。

本次的搭建过程,其实适用于绝大多数的spring boot项目,主要是环境搭建和监控平台的构建。希望对大家有帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1384792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布形态的度量_峰度系数的探讨

集中趋势和离散程度是数据分布的两个重要特征,但要全面了解数据分布的特点&#xff0c;还应掌握数据分布的形态。 描述数据分布形态的度量有偏度系数和峰度系数, 其中偏度系数描述数据的对称性,峰度系数描述与正态分布的偏离程度。 峰度系数反映分布峰的尖峭程度的重要指标. 当…

2024--Django平台开发-Redis集群(十一)

内容回顾 主从复制。 哨兵&#xff1a;实例启动了&#xff0c;哨兵节点没启动&#xff0c;Python通过redis-py连接报错。一定要确保实例节点和哨兵节点都启动了。 搭建集群用的是虚拟机的多台centos服务器&#xff0c;你在跟着学习的时候&#xff0c;一定要全部都是虚拟机&am…

Mysql-redoLog

Redo Log redo log进行刷盘的效率要远高于数据页刷盘,具体表现如下 redo log体积小,只记录了哪一页修改的内容,因此体积小,刷盘快 redo log是一直往末尾进行追加,属于顺序IO。效率显然比随机IO来的快Redo log 格式 在MySQL的InnoDB存储引擎中,redo log(重做日志)被用…

【UEFI基础】EDK网络框架(VLAN)

VLAN VLAN代码综述 在MNP中有很多的VLAN介绍&#xff0c;MNP存在的一个重要原因也是为了处理VLAN&#xff0c;而本文介绍的NetworkPkg\VlanConfigDxe\VlanConfigDxe.inf其实只是一个帮助模块&#xff0c;真正的VLAN配置还是在MNP中。 VLAN同样是一个UEFI Driver Model&#…

pytorch一致数据增强—异用增强

前作 [1] 介绍了一种用 pytorch 模仿 MONAI 实现多幅图&#xff08;如&#xff1a;image 与 label&#xff09;同用 random seed 保证一致变换的写法&#xff0c;核心是 MultiCompose 类和 to_multi 包装函数。不过 [1] 没考虑不同图用不同 augmentation 的情况&#xff0c;如&…

adb 常用命令汇总

目录 adb 常用命令 1、显示已连接的设备列表 2、进入设备 3、安装 APK 文件到设备 4、卸载指定包名的应用 5、从设备中复制文件到本地 6、将本地文件复制到设备 7、查看设备日志信息 8、重启设备 9、截取设备屏幕截图 10、屏幕分辨率 11、屏幕密度 12、显示设备的…

Linux 压缩与解压缩

参考资料 linux 压缩和解压缩命令gz、tar、zip、bz2tar命令 – 压缩和解压缩文件 目录 一. gzip命令1.1 压缩1.1.1 -k 压缩后保留源文件1.1.2 -l 查看压缩文件中的文件信息1.1.3 -r 递归压缩文件夹中的所有文件 1.2 解压缩 二. zip命令2.1 zip 压缩2.1.1 -r 压缩文件夹2.1.2 压…

Android中的anr定位指导与建议

1.背景 8月份安卓出现了一次直播间卡死(ANR)问题&#xff0c;且由于排查难度较大&#xff0c;持续了较长时间。本文针对如何快速定位安卓端出现ANR问题进行总结和探讨. 这里大致补充一下当时的情况,当时看到情景的是从某一个特定的场景下进入直播间后整个直播间界面立刻就卡住…

css3 2D与3D转换

css3 2D与3D转换 前言2D变形旋转变形 rotate()transform-origin属性 缩放变形 scale()斜切变形 skew()位移变形 translate() 3D变形3D旋转 rotateX() | rotateY()perspective属性 空间移动 制作一个正方体结语 前言 网页设计不再局限于平面&#xff0c;而是充满了立体感和动态…

【ESP32接入语言大模型之智谱清言】

1. 智谱清言 讲解视频&#xff1a; 随着人工智能技术的不断发展&#xff0c;自然语言处理领域也得到了广泛的关注和应用。智谱清言作为千亿参数对话模型 基于ChatGLM2模型开发&#xff0c;支持多轮对话&#xff0c;具备内容创作、信息归纳总结等能力。可以快速注册体验中国版…

Linux系统使用超详细(十)~vi/vim命令①

vi/vim命令有很多&#xff0c;其实只有少数的用法对于我们日常工作中起到了很大帮助&#xff0c;但是既然我选择梳理Linux的学习笔记&#xff0c;那么一定全力把自己的理解和学习笔记的内容认真整理汇总&#xff0c;内容或许有错误&#xff0c;还请发现的C友们发现了及时指出。…

小程序基础学习(发送请求)

原理 通过js发起wx.request的方法发送请求并接受相应数据 实例&#xff08;一&#xff09; 参数&#xff1a; url:请求网址地址&#xff0c; success:请求成功执行的函数&#xff0c; fail:请求失败执行的函数 请求返回的数据 实例&#xff08;二&#xff09; 参数&#xff1…

如何用LLM和自有知识库搭建智能agent?

用LangChain建立知识库&#xff0c;文末中也推荐其他方案。 项目源码&#xff1a;ChatPDF实现 LangChain Indexes使用 对加载的内容进行索引&#xff0c;在indexes中提供了一些功能&#xff1a; Document Loaders&#xff0c;加载文档Text Splitters&#xff0c;文档切分V…

Codeforces Round 768 (Div. 1) D. Flipping Range(思维题 等价类性质 dp)

题目 思路来源 官方题解 洛谷题解 题解 可操作的最短区间长度肯定是gcd&#xff0c;记为g&#xff0c;然后考虑如何dp 考虑g个等价类&#xff0c;每个等价类i,ig,i2*g,... 每次翻转长度为g的区间&#xff0c;会同时影响到g个等价类总的翻转的奇偶性&#xff0c; 性质一&…

Puppeteer让你网页操作更简单(2)抓取数据

Puppeteer让你网页操作更简单(1)屏幕截图】 示例2 —— 让我们抓取一些数据 现在您已经了解了Headless Chrome和Puppeteer的工作原理基础知识,让我们看一个更复杂的示例,其中我们实际上可以抓取一些数据。 首先,请查看此处的Puppeteer API文档。如您所见,有大量不同的方法我…

Python教程39:使用turtle画今天日期

---------------turtle源码集合--------------- Python教程36&#xff1a;海龟画图turtle写春联 Python源码35&#xff1a;海龟画图turtle画中国结 Python源码31&#xff1a;海龟画图turtle画七道彩虹 Python源码30&#xff1a;海龟画图turtle画紫色的小熊 Python源码29&a…

10.9.2 std::function 非OO的多态实现 Page185~187

源代码&#xff1a; #include <iostream> #include <functional> #include <list>using namespace std;//使用function模板类定义一个类型&#xff0c; //该类型要求作为T的 //函数类型是参数是string,返回值是void typedef std::function <void (std::s…

MySQL-多表联合查询

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…

【算法实验】实验1

实验1-1 斐波那契数 【问题描述】斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。 定义&#xff1a;F(0) 0, F(1) 1, F(n) F(n-1) F(n-2) 其中n>1 要求计…

1、计算机的硬件组成、校验码

计算机的硬件组成 CPU的组成与功能 CPU的组成 CPU主要是由运算器、控制器、寄存器组和内部总线等部件组成 CPU的功能 1、程序控制通过执行指令来控制程序的执行顺序2、操作功能一条指令的实现需要若干操作信号配合&#xff0c;控制相应的部件完成相对应的操作3、时间控制对…