0. 前言

从今天起,我们来共同学习讨论一下 ”COSBench“ 这个东西。

本系列一共分为下面几大部分:

  1. COSBench 知道、运用、成果剖析
  2. COSBench 开发环境装备
  3. COSBench 源码剖析(主要是cosbench-s3)
  4. COSBench 开发一个适配器

现在我们开端榜首部分。

1. 介绍

随着云年代的到来,公有云、私有云、混合云等快速进入到我们的视界,随着数据量指数级增加,数据存储成了重中之重。目标存储结合了块存储的速度和文件存储的容量,应对海量数据,它更加游刃有余。现在各厂的存储产品除了自研,其他根本都是根据Ceph或Minio等开源方案进行开发。当我们开发出了一款存储产品,很大一块的宣传便是它的功能怎么怎么,那么我们怎么来衡量呢?那么COSBench则是衡量目标存储功能的其中一款测验东西。

COSBench 是 Intel团队根据 Java言语开发,衡量云目标存储服务功能基准测验东西,全称是Cloud Object Storage Bench。同所有的功能测验东西一样,COSBench 也分控制台和主张恳求的driver,且driver能够散布式布置。能够支撑swift、s3、Openstack等接口,SineIO团队根据cosbench-openio版别做了新的开发,自界说了根据S3协议的新适配器(sio、gdas),更加贴合自研目标存储产品。这两个新适配器新增了功能与优化(比方分段上传、列出目标逻辑优化、SDK版别升级等等),我们能够经过地址进行下载和试用(github.com/sine-io/cos…

COSBench 支撑自界说适配器,这一点给了它非常优异的扩展性和适配性,为它成为目标存储协议通用功能基准测验东西打好了坚实的基础。

2. 架构

下图很好的诠释了CosBench架构:

【COSBench系列】1. COSBench认识、使用、结果分析
CosBench 经过controller 加载自界说的压力模型装备文件(xxx.xml),并分发压力到各个driver上,由driver对底层存储服务施加压力,到达功能压测的目的。

drivers 采用散布式布置,多个 driver 在压力服务器上为多个Java进程,每个driver会多线程并发恳求(在CosBench中为workers数)。

说几点我的经历,供我们参阅:

  • a. controller发动一个即可,这个是共识,就不说了
  • b. drivers散布于各个压力节点上,每个节点我会发动多个drivers(我一般发动2个,最多的时分发动到4个)
  • c. 压测装备文件中,每个driver 我一般会分配50个workers
  • d. 压测机的CPU(比方:48核心)/内存(比方:64GB)最好大一些,OS盘最好是SSD
  • e. 压测之前,要测验压力机与存储服务器间的网络是否有瓶颈(我一般用iperf3,记住双向都打一下)
  • f. 压测之前,主张用fio这类的压测东西打一下盘,看一下raid卡等硬件有没有瓶颈(直接压多个硬盘就行)
  • g. 最后一点是底层存储的功能预算,我一般用的预算公式是:单个存储服务器的硬盘个数*单个硬盘的带宽 * 0.7

举例:底层存储为3节点,每个节点的数据池含HDD 36块,假设每块HDD的写速度为150MB/s,那写入的带宽预算公式为:36*150*0.7=3780MB/s

当然,这仅仅理论预算,一般底层存储无法悉数运用硬件的功能。像HDD,一般读写均匀带宽在80MB/s就不错了(个人见解),所以我们要根据实际状况去印证自己的预算,逐步纠偏。

3. 布置

了解了东西是什么,干什么用的,那接下来看看它到底怎么用。

3.0 压力机规划

节点称号 发动服务 人物
压力机1 controller * 1drivers *2 或 4 主控机压力机
压力机2 drivers *2 或 4 压力机
压力机3 drivers *2 或 4 压力机

3.1 布置 — 非容器化办法

# CentOS 7.7 or 7.9 操作系统

# 封闭防火墙或许防火墙翻开19088 19089 18088 18089端口,我这儿直接封闭防火墙
systemctl stop firewalld

# 装置依靠包
yum install telnet nmap-ncat curl wget vim -y

# 装置openjdk或许自己装置java环境,我这儿直接装置openjdk
yum install java-1.8.0-openjdk -y
# 这儿说明一下,主张用1.8及以上的java,由于之前的版别会存在bug,可能会导致测验不精确或许程序异常等问题。

# 铲除环境变量
unset http_proxy
# 下载布置包后解压进行布置(三个压力节点均下载和履行)
wget https://github.com/sine-io/cosbench-sineio/releases/download/0.4.7.9/cosbench-0.4.7.9-sineio.tar.gz
tar -xf cosbench-0.4.7.9-sineio.tar.gz
cd cosbench-0.4.7.9-sineio

# 在压力机1、2、3上均发动2个driver
sh start-driver.sh 2

# 在压力机1上发动controller
vim conf/controller.conf

注意:

  1. drivers的数量要与下面提供的driver数量保持一致
  2. 各个driver的姓名不能重复
[controller]
drivers = 6
log_level = INFO
log_file = log/system.log
archive_dir = archive
[driver1]
name = driver1
url = http://压力机1IP:18088/driver
[driver2]
name = driver2
url = http://压力机1IP:18188/driver
[driver3]
name = driver3
url = http://压力机2IP:18288/driver
[driver4]
name = driver4
url = http://压力机2IP:18088/driver
[driver5]
name = driver5
url = http://压力机3IP:18188/driver
[driver6]
name = driver6
url = http://压力机3IP:18288/driver
# 保存退出

# 发动controller
sh start-controller.sh

# 浏览器翻开CosBench网站即可运用
http://压力机1IP:19088/controller/index.html

3.2 布置 — docker-compose办法

我们参照cosbench-openio(在此对openio的开发人员表示感谢)编写并制作了cosbench-sineio的docker镜像(分别根据Ubuntu、CentOS和Alpine),我们能够运用docker发动COSBench。

后续还会添加docker swarm、K8S的办法,敬请期待。

前提:三台压力机上均布置好docker、docker-compose环境

# docker-compose办法
# 参阅GitHub地址:https://github.com/sine-io/cosbench-sineio.git项目下的docker目录

# 压力机2和3上 发动driver
cd /opt/
mkdir cosbench-sineio && cd cosbench-sineio

# 编辑docker-compose文件,也能够直接下载后进行编辑
vim drivers.yml

注:能够自行更换为alpine版别

version: '3.9'
services:
  driver1:
    image: "sineio/cosbench-sineio:0.4.7.9-ubuntu"
    environment:
      CONTROLLER: false
      DRIVER: true
      DRIVER_PORT: 18088
      COSBENCH_PLUGINS: "SIO,S3"
    volumes:
      - /data/cosbench/driver1-log/:/cosbench/log
      - /etc/resolv.conf:/etc/resolv.conf:ro
      - /etc/hosts:/etc/hosts:ro
      - /etc/localtime:/etc/localtime:ro
    healthcheck:
      test: ["CMD", "curl", "-f", "http://127.0.0.1:18088/driver"]
      interval: 30s
      timeout: 20s
      retries: 3
    restart: unless-stopped
    tty: true
    stdin_open: true
    network_mode: "host"
  driver2:
    image: "sineio/cosbench-sineio:0.4.7.9-ubuntu"
    environment:
      CONTROLLER: false
      DRIVER: true
      DRIVER_PORT: 18188
      COSBENCH_PLUGINS: "SIO,S3"
    volumes:
      - /data/cosbench/driver2-log/:/cosbench/log
      - /etc/resolv.conf:/etc/resolv.conf:ro
      - /etc/hosts:/etc/hosts:ro
      - /etc/localtime:/etc/localtime:ro
    healthcheck:
      test: ["CMD", "curl", "-f", "http://127.0.0.1:18188/driver"]
      interval: 30s
      timeout: 20s
      retries: 3
    restart: unless-stopped
    tty: true
    stdin_open: true
    network_mode: "host"
# 保存退出,发动drivers(请保证端口18088、18188、18089、18189未被占用)
docker-compose -f drivers.yml up -d
# 在 压力机1 上发动2个drivers 和 1个controller
cd /opt/
mkdir cosbench-sineio && cd cosbench-sineio
vim all.yml
version: '3.9'
services:
  driver1:
    image: "sineio/cosbench-sineio:0.4.7.9-ubuntu"
    environment:
      CONTROLLER: false
      DRIVER: true
      DRIVER_PORT: 18088
      COSBENCH_PLUGINS: "SIO,S3"
    volumes:
      - /data/cosbench/driver1-log/:/cosbench/log
      - /etc/resolv.conf:/etc/resolv.conf:ro
      - /etc/hosts:/etc/hosts:ro
      - /etc/localtime:/etc/localtime:ro
    healthcheck:
      test: ["CMD", "curl", "-f", "http://127.0.0.1:18088/driver"]
      interval: 30s
      timeout: 20s
      retries: 3
    restart: unless-stopped
    tty: true
    stdin_open: true
    network_mode: "host"
  driver2:
    image: "sineio/cosbench-sineio:0.4.7.9-ubuntu"
    environment:
      CONTROLLER: false
      DRIVER: true
      DRIVER_PORT: 18188
      COSBENCH_PLUGINS: "SIO,S3"
    volumes:
      - /data/cosbench/driver2-log/:/cosbench/log
      - /etc/resolv.conf:/etc/resolv.conf:ro
      - /etc/hosts:/etc/hosts:ro
      - /etc/localtime:/etc/localtime:ro
    healthcheck:
      test: ["CMD", "curl", "-f", "http://127.0.0.1:18188/driver"]
      interval: 30s
      timeout: 20s
      retries: 3
    restart: unless-stopped
    tty: true
    stdin_open: true
    network_mode: "host"
  controller:
    image: "sineio/cosbench-sineio:0.4.7.9-ubuntu"
    environment:
      CONTROLLER: true
      DRIVER: false
      DRIVERS: "http://压力机1IP:18088/driver,http://压力机1IP:18188/driver,http://压力机2IP:18088/driver,http://压力机2IP:18188/driver,http://压力机3IP:18088/driver,http://压力机3IP:18188/driver,"
    depends_on:
      driver1:
        condition: service_healthy
      driver2:
        condition: service_healthy
    volumes:
      - /data/cosbench/archive/:/cosbench/archive
      - /data/cosbench/controller-log/:/cosbench/log
      - /etc/resolv.conf:/etc/resolv.conf
      - /etc/hosts:/etc/hosts
      - /etc/localtime:/etc/localtime:ro
    healthcheck:
      test: ["CMD", "curl", "-f", "http://127.0.0.1:19088/controller/index.html"]
      interval: 60s
      timeout: 20s
      retries: 3
    restart: unless-stopped
    tty: true
    stdin_open: true
    network_mode: "host"

注:如有问题,欢迎提PR和issue至github上:

github.com/sine-io/cos…

4. 运用

到这儿,软件已经布置好了,那么接下来,我们来看一下怎么用。

注:压缩包解压完毕后,在解压目录的conf文件夹下有示例,供我们参阅。

示例1:sio-config-sample.xml

示例1参阅地址:github.com/sine-io/cos…

示例2:gdas-config-sample.xml

示例2参阅地址:github.com/sine-io/cos…

4.1 装备文件解说

下面以sio-config-sample.xml解说一下:

<?xml version="1.0" encoding="UTF-8" ?>
<!-- workload处于最外层,包裹了整个功能测验过程 -->
<workload name="xml-sample" description="sample benchmark for ehualu s3">
  <!-- workflow 界说了整个功能作业流,它含有1个或多个workstage -->
  <workflow>
    <!-- New feature to sio and siov2 -->
	<!-- mprepare, multipart upload object -->
    <!-- workstage界说了一个测验阶段,比方此阶段我们只做写入(经过type来修正)的功能测验-->
	<workstage name="mprepare example">
      <!-- storage界说了存储类型,包含许多类型,假如是S3协议存储,能够sio或s3等等,经过type进行指定即可 -->
      <!-- config里面装备了连接此存储的AK/SK,endpoint等信息,不同存储的可装备参数不同,sio的可参阅下面装备 -->
	  <storage type="sio" config="accesskey=<accesskey>;secretkey=<scretkey>;proxyhost=<proxyhost>;proxyport=<proxyport>;endpoint=<endpoint>;path_style_access=true" />
      <!-- work界说了负载,其中type界说了负载类型,是写入/读取等等,workers界说了并发数,config界说了负载的一些参数,下面来一一说明 -->
      <!-- cprefix为存储桶的前缀,containers是紧跟前缀的字符,假如我创立一个存储桶姓名为test1,那么cprefix为test,containers为r(1,1) -->
      <!-- 其中r(1,1)中的r是挑选器,cosbench包括多种挑选器,不同的workstage可是运用的挑选器也不同,我们能够参阅COSBenchUserGuide.pdf -->
      <!-- objects界说了目标姓名从1到10,假如不加oprefix的话,那前缀为默认值,oprefix主张添加 -->
      <!-- sizes界说了文件粒度,能够是单个粒度,也能够是不同粒度配比 -->
      <work type="mprepare" workers="1" config="cprefix=s3testqwer;containers=r(1,2);objects=r(1,10);sizes=c(64)KB" />
    </workstage>
	<!-- end -->
	<!-- mwrite, multipart upload object -->
    <workstage name="mwrite example">
      <work name="mwrite test" workers="8" runtime="30">
	    <!-- part_size: default is 5MiB, must be set >= 5MiB -->
	    <storage type="sio" config="accesskey=<accesskey>;secretkey=<scretkey>;proxyhost=<proxyhost>;proxyport=<proxyport>;endpoint=<endpoint>;path_style_access=true;part_size=5242880" />
        <operation type="mwrite" ratio="100" config="cprefix=s3testqwer;containers=u(1,2);objects=u(11,20);sizes=c(64)KB" />
      </work>
    </workstage>
	<!-- end -->
	<!-- restore, restore object -->
	<workstage name="restore object example">
      <work name="restore test" workers="8" runtime="30">
	    <!-- restore_days: default is 1 -->
	    <storage type="sio" config="accesskey=<accesskey>;secretkey=<scretkey>;proxyhost=<proxyhost>;proxyport=<proxyport>;endpoint=<endpoint>;path_style_access=true;restore_days=1" />
        <operation type="restore" ratio="100" config="cprefix=s3testqwer;containers=u(1,2);objects=u(11,20);sizes=c(64)KB" />
      </work>
    </workstage>
	<!-- end -->
	<!-- storage_class, default is STANDARD -->
	<workstage name="set object's storage_class">
      <work name="storage class test" workers="8" runtime="30">
	  <!-- storage_class must exist in your storage -->
	    <storage type="sio" config="accesskey=<accesskey>;secretkey=<scretkey>;proxyhost=<proxyhost>;proxyport=<proxyport>;endpoint=<endpoint>;path_style_access=true;storage_class=GLACIER" />
		<!-- write, mwrite -->
        <operation type="write" ratio="100" config="cprefix=s3testqwer;containers=u(1,2);objects=u(11,20);sizes=c(64)KB" />
      </work>
    </workstage>
	<!-- end -->
	<!-- no_verify_ssl, default is false -->
	<workstage name="disable verify ssl example">
      <work name="https test" workers="8" runtime="30">
	    <storage type="sio" config="accesskey=<accesskey>;secretkey=<scretkey>;proxyhost=<proxyhost>;proxyport=<proxyport>;endpoint=<endpoint>;path_style_access=true;no_verify_ssl=true" />
		<!-- write, read, etc. -->
        <operation type="head" ratio="100" config="cprefix=s3testqwer;containers=u(1,2);objects=u(11,20);sizes=c(64)KB" />
      </work>
    </workstage>
	<!-- end -->
	<!-- GiB, MiB, KiB, etc. 2^n, not 10^n -->
	<workstage name="object size is 1024 based">
      <work name="object size test" workers="8" runtime="30">
	    <storage type="sio" config="accesskey=<accesskey>;secretkey=<scretkey>;proxyhost=<proxyhost>;proxyport=<proxyport>;endpoint=<endpoint>;path_style_access=true;no_verify_ssl=true" />
		<!-- write, mwrite, both ok. -->
        <operation type="write" ratio="100" config="cprefix=s3testqwer;containers=u(1,2);objects=u(11,20);sizes=c(64)KiB" />
      </work>
    </workstage>
	<!-- end -->
	<!-- aws_region: just for siov2 -->
	<workstage name="set aws_region example">
      <work name="https test" workers="8" runtime="30">
	    <!-- aws_region: default is us-east-1. Normally, there is no need to set this parameter. -->
	    <storage type="siov2" config="accesskey=<accesskey>;secretkey=<scretkey>;proxyhost=<proxyhost>;proxyport=<proxyport>;endpoint=<endpoint>;path_style_access=true;aws_region=us-east-1" />
		<!-- write, read, etc. -->
        <operation type="head" ratio="100" config="cprefix=s3testqwer;containers=u(1,2);objects=u(11,20);sizes=c(64)KiB" />
      </work>
    </workstage>
	<!-- end -->
  </workflow>
  <!-- Same to s3, storage type: gdas or sio or s3, both ok. -->
  <!--
  <storage type="s3" config="accesskey=<accesskey>;secretkey=<scretkey>;proxyhost=<proxyhost>;proxyport=<proxyport>;endpoint=<endpoint>;path_style_access=true" />
  <workflow>
    <workstage name="init">
      <work type="init" workers="1" config="cprefix=s3testqwer;containers=r(1,2)" />
    </workstage>
    <workstage name="prepare">
      <work type="prepare" workers="1" config="cprefix=s3testqwer;containers=r(1,2);objects=r(1,10);sizes=c(64)KB" />
    </workstage>
    <workstage name="main">
      <work name="main" workers="8" runtime="30">
        <operation type="read" ratio="80" config="cprefix=s3testqwer;containers=u(1,2);objects=u(1,10)" />
        <operation type="write" ratio="20" config="cprefix=s3testqwer;containers=u(1,2);objects=u(11,20);sizes=c(64)KB" />
      </work>
    </workstage>
    <workstage name="cleanup">
      <work type="cleanup" workers="1" config="cprefix=s3testqwer;containers=r(1,2);objects=r(1,20)" />
    </workstage>
    <workstage name="dispose">
      <work type="dispose" workers="1" config="cprefix=s3testqwer;containers=r(1,2)" />
    </workstage>
  </workflow>
  -->
</workload>

operation的解说:

  1. write:对应上传接口(put-object)
  2. read:对应下载目标接口(get-object)
  3. mwrite:对应分段上传目标接口(create-multipart-upload+upload-part+complete-multipart-upload)
  4. restore:对应取回目标接口(restore-object)
  5. delete:对应删去目标接口(delete-object)
  6. list:对应列出桶内目标接口(list-objects-v2)
  7. head:对应获取目标信息接口(head-object)
  8. filewrite:将本地的目标经过上传接口(put-object)上传到目标存储
  9. mfilewrite:将本地的目标经过分段上传接口(create-multipart-upload+upload-part+complete-multipart-upload)上传到目标存储

注意几个特殊的workstage:

  1. init一般用于创立存储桶
  2. prepare一般用于创立文件,用的put-object接口,供后续的读操作运用
  3. mprepare跟prepare相同的作用,用的分段上传接口
  4. cleanup一般用于后续的整理作业(删目标)
  5. dispose一般用于整理作业(删桶)

我一般不进行cleanup和dispose,由于存储中有一定数据量后,检查功能是否下降也是一个测验方面,我们可自行挑选。

4.2 提交测验

办法一、运用controller web提交,这是我常用的办法,由于便于调查和排错
a. 将编辑好的xml文件保存到电脑的某个目录下
b. 访问 http://你的IP地址:19088/controller/index.html
c. 点击Submit new workloads
d. 在Workload config那里挑选文件后进行submit即可
办法二、运用cli提交使命(我不常用)
cd cosbench-0.4.7.9-sineio
sh cli.sh submit xxx.xml anonymous:cosbench@你的IP:19088
之后我们能够去web页面上检查提交的使命

注意:

  1. 我们能够提交多个使命(即多个xml文件),它会主动加入到使命行列中,我们还能够对使命进行排序。

5. 成果剖析

当我们提交完测验后,能够在index页面的Active Workloads中找到已提交的使命,这儿能够检查正在运转使命的详细信息。我们点击View details后能够进入使命详情页面。

5.1 index页面的解释

【COSBench系列】1. COSBench认识、使用、结果分析

5.2 关于workload的页面

【COSBench系列】1. COSBench认识、使用、结果分析

这儿讲一下General Report这一栏,侧重重视下面几个值:

Avg-ResTime:均匀时延,它为存储服务处理恳求的时刻,包含数据传输时刻,一般小文件(比方KB等级)我们也会重视这个值,此值越低,小文件的IOPS越好

Avg-ProcTime:均匀处理时刻,它为存储服务处理恳求的时刻,不包含数据传输时刻

Throughput:吞吐量,当我们的文件粒度为1M及以下时,侧重重视这个值,描绘了当前文件粒度下的读写等功能(IOPS)

Bandwidth:带宽,当我们的文件粒度为1M以上时,侧重重视这个值,描绘了当前文件粒度下的读写等功能(MB/s等单位)

Succ-Ratio:恳求成功率,这儿一般都要求100%

这儿说一下IOPS这个单位,避免有人误会。IOPS一般用于块存储,在我测验目标存储功能的过程中,给其他搭档描绘的时分,我们普遍接受IOPS这个单位,我跟其他存储厂商搭档交流过,他们也用这个表示过。所以我就直接拿来用于代表小文件的功能,我们一看根本就能明白。假如您不喜欢这么表示,能够运用OP/s

特别提示:
1. 测验过程中要到压力机和存储服务器中看一下资源状况
我会用top检查CPU,内存等资源状况
用iostat检查硬盘状况
用sar检查网络带宽状况
2. 有条件的能够建立一套Prometheus + Grafana + node-exporter 进行资源监控
3. 进行监控的目的有几个,一要确认咱给的压力是不是合适、二要看数据到底有没有落盘、三是监控与web页面的值进行比照

5.3 剖析

当测验履行完毕后,我们要进行成果收集与剖析,下面顺次来讲一下我的做法。

5.3.1 成果收集

我们进行功能测验,不可能运用1个driver,当我们运用多个drivers的时分,在General Report处会有多行值,我会把这个值拷贝到Excel中进行处理。

【COSBench系列】1. COSBench认识、使用、结果分析

  1. 在我们拷贝到Excel中之前,首要我们应该重视Succ-Ratio,全是100%,理论上代表悉数成功了。
  2. 稳妥起见,我们能够到controller节点的cosbench-0.4.7.9-sineio目录下,去检查workload.log中是否有WARN或ERROR关键字 — 一般大文件大并发(512MB及以上)我会做此过程。日志途径为:~/cosbench-0.4.7.9-sineio/archive/w9-write 3050-16K-22320/workload.log

​ w9-write 3050-16K-22320为你运转完毕的这个workload

  1. 以大文件举例:选中Bandwidth这几行(红框),在Excel中进行 数据 —> 分列,然后进行求和即可

当我们得出功能总值之后,要进行剖析,我们在剖析章节分解。

5.3.2 剖析改善

功能测验是一个“长期”的过程,我一般从以下几点来进行成果剖析:

a. 当我们以某种并发测验出一组成果之后,我会首要与网络功能、硬盘预算功能、软件上个版别功能等进行比照

​ a.1 假如测出来的功能值进行比照后,相差过大,我会进行复测(增大/减少并发量,增大数据量等)

​ a.2 假如经过比照后,此组值可用,那么我会成果整理完毕后,与存储搭档进行交流,假如达成一致则此值保存。假如有不同意见,会进行剖析改善后复测。

b. 我有些时分会添加一些并发,检查Avg-ResTime增加和Throughput/Bandwidth增加是不是明显

​ b.1 当Avg-ResTime增加很明显,可是Throughput/Bandwidth增加不明显,那么我会选取Avg-ResTime相比照较好时的功能值。

​ b.2 当Throughput/Bandwidth增加明显(我个人主张:≥5%增加率)的时分,我会持续施加压力

c. 想到其他的,再弥补。

6. 结尾

至此,这一篇文章就完毕了,我们从What,When,Why,How几方面进行了解说。此东西运用起来稍微有点杂乱,尤其是手动界说负载那块(编写xml文件),可是游刃有余,我们多用多看多剖析多总结,也会很快上手。

假如能够,欢迎在GitHub上给我的项目来个Star :star: ,这将给予我极大的动力和精神鼓励。也非常欢迎提交PR和issue,谢谢。

本篇想要共享的就这么多,我们下篇文章再会,谢谢。