网络性能及IO性能测试工具
文章目录
- 简介
- IO性能
- pidstat
- iostat
- fio
- blktrace
- 网络性能
- ipef
- trek
简介
网络性能和IO性能测试工具在现代计算环境中至关重要。无论是评估网络带宽、优化数据传输速度,还是检测磁盘读写性能,选择适合的工具至关重要。本文将介绍各种网络性能和IO性能测试工具,帮助您深入了解其功能、用途和如何选择最佳工具。
IO性能
pidstat
pidstat -d 1 #整体情况
pidstat -dt -p 73739 1 pidstat -d 1 #获取 pid 后可使用下面的命令观测该进程的所有线程的IO占用情况
pidstat -dt -p 73739 1
iostat
1.简介
iostat工具会对系统的磁盘操作活动进行监视,同时也会打印CPU的使用情况。
2.安装
iostat属于sysstat软件包,如果系统没有安装则通过 yum install sysstat/apt-get install sysstat 来安装。
3.主要参数
-c 仅显示CPU使用情况
-d 仅显示设备利用率
-k 显示状态以千字节每秒为单位,而不使用块每秒
-m 显示状态以兆字节每秒为单位
-p 仅显示块设备和所有被使用的其他分区的状态
-t 显示每个报告产生时的时间,并显示终端和CPU的信息
-C 显示CPU使用情况
-N 显示磁盘阵列(LVM) 信息
-n 显示NFS 使用情况
-x 显示详细信息
4.常用命令
iostat -xm 1
5.应用
场景:监控磁盘是否有延时
1. 查看磁盘 qbd30 使用信息。
命令 iostat -xm qbd30 3 12 表示监测磁盘 qbd30 ,打印详细信息并以 MB/s 为单位,每 3s 打印一次,打印 12 次。
开启监控后还需要去使用磁盘,这里可以和fio命令结合使用。
[root@rhel69 ~]# iostat -xm qbd30 3 12
Linux 2.6.32-696.el6.x86_64 (rhel69) 11/17/2022 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.12 0.00 0.30 5.35 0.81 93.42
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
qbd30 0.00 36.75 4.11 13.39 0.25 0.35 70.16 2.70 154.27 400.26 78.71 8.82 15.43
avg-cpu: %user %nice %system %iowait %steal %idle
0.00 0.00 0.00 0.00 2.96 97.04
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
qbd30 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
avg-cpu: %user %nice %system %iowait %steal %idle
0.80 0.00 4.49 3.53 9.46 81.72
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
qbd30 0.00 0.00 0.00 1312.33 0.00 5.13 8.00 15.57 11.66 0.00 11.66 0.20 26.67
...
如果不想关系cpu,仅想关系磁盘可以添加 -b 参数;也可以利用 nohup 把监测放在后台执行,并把输出重定向到文件中,方便统计。
如:
[root@rhel69 yyl]# nohup iostat -xdm qbd30 6 25 > /home/yyl/iostat_qbd30 &
%user : cpu 在用户模式占用时间比
%nice : cpu 在带Nice值(进程优先级)的用户模式占用的时间比
%system : cpu 在系统模式占用的时间比
%iowait : cpu 等待输入输出完成占用的时间比
%idle : cpu空闲时间百分比
rrqm/s: 每秒完成的读请求合并数
wrqm/s: 每秒完成的写请求合并数
r/s: 每秒完成的读请求次数
w/s: 每秒完成的写请求次数
rsec/s: 每秒读扇区数
wsec/s: 每秒写扇区数
rMB/s: 每秒读取的字节数. 单位 MB/s
wMB/s: 每秒写入的字节数. 单位 MB/s
avgrq-sz:平均每次I/O操作的扇区数.
avgqu-sz:平均I/O队列长度.
await: 平均每次I/O操作的等待时间 (毫秒).
r_await:平均每次读I/O操作的等待时间 (毫秒)
w_await:平均每次写I/O操作的等待时间 (毫秒)
svctm: 每次I/O请求,磁盘读或写操作执行的时间 (毫秒). (该值不可靠)
%util: I/O 请求发送到设备期间,占用 CPU 时间的百分比。如果统计间隔1秒,该设备有0.8秒在处理IO,而0.2秒闲置 那么%util=80%。
这里需要监控磁盘是否有延时,则需要关心 await 和 %iowait 这两个值。
fio
1.简介
fio 是用来测试磁盘IO,和对磁盘进行压力测试的工具,也可以一定程度上观测到是磁盘读写是否存在延时。
2.安装
①.下载源码后,解压。执行 ./configure; make; make install
②.yum install fio
3. 常要参数
--name:测试任务名称。
--filename:测试设备的路径
--bs :单次io的块文件大小
--rw :定义测试时的读写策略。 常用的值有:randread(随机读),randwrite(随机写),read(顺序读),write(顺序写),randrw(混合随机读写)
--iodepth :定义测试时的IO队列深度,默认为1
--direct : 是否使用direct IO,值为1表示是
--size :定义测试IO操作的数据量,若未指定runtime这类参数,fio会将指定大小的数据量全部 读/写完成,然后才停止测试
--runtime :定义测试时间。如果未配置,则持续将size指定的文件大小,以每次bs值为分块大小读/ 写完。
--ioengine : 值为libaio表示异步模式,值为sync表示同步模式
4.常用命令
4k随机写 :fio --name=pool/vol_linux_release3-4k-write-16-b --filename=/dev/qbd/pool/vol_linux_release3 --bs=4k --iodepth=64 --rw=randwrite --ioengine=libaio --direct=1 --runtime=2h
4k随机读 :fio --name=pool/vol_linux_release3-4k-write-16-b --filename=/dev/qbd/pool/vol_linux_release3 --bs=4k --iodepth=64 --rw=randread --ioengine=libaio --direct=1 --runtime=2h
5.应用
场景:测试磁盘pool/vol_linux_release3,以异步方式、随机写、采用direct IO、单次块大小为 4K、运行时间为 2h
[root@rhel69 ~]# fio --name=pool/vol_linux_release3-4k-write-16-b --filename=/dev/qbd/pool/vol_linux_release3 --bs=4k --iodepth=64 --rw=randwrite --ioengine=libaio --direct=1 --runtime=2h
pool/vol_linux_release3-4k-write-16-b: (g=0): rw=randwrite, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=64
fio-2.19
Starting 1 process
Jobs: 1 (f=1): [w(1)][100.0%][r=0KiB/s,w=37.5MiB/s][r=0,w=9582 IOPS][eta 00m:00s]
pool/vol_linux_release3-4k-write-16-b: (groupid=0, jobs=1): err= 0: pid=25034: Thu Nov 17 12:40:42 2022
write: IOPS=6697, BW=26.2MiB/s (27.5MB/s)(157GiB/6145178msec)
slat (usec): min=4, max=37766, avg=47.91, stdev=179.91
clat (usec): min=122, max=96761, avg=9501.69, stdev=5645.79
lat (usec): min=640, max=96783, avg=9549.60, stdev=5646.54
clat percentiles (usec):
| 1.00th=[ 2416], 5.00th=[ 3664], 10.00th=[ 4320], 20.00th=[ 5216],
| 30.00th=[ 6048], 40.00th=[ 6880], 50.00th=[ 7904], 60.00th=[ 9152],
| 70.00th=[10688], 80.00th=[12992], 90.00th=[17024], 95.00th=[20608],
| 99.00th=[29312], 99.50th=[33024], 99.90th=[42240], 99.95th=[46336],
| 99.99th=[56064]
lat (usec) : 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.02%
lat (msec) : 2=0.49%, 4=6.86%, 10=58.44%, 20=28.53%, 50=5.64%
lat (msec) : 100=0.03%
cpu : usr=4.06%, sys=14.36%, ctx=49956556, majf=2, minf=27
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
issued rwt: total=0,41156608,0, short=0,0,0, dropped=0,0,0
latency : target=0, window=0, percentile=100.00%, depth=64
Run status group 0 (all jobs):
WRITE: bw=26.2MiB/s (27.5MB/s), 26.2MiB/s-26.2MiB/s (27.5MB/s-27.5MB/s), io=157GiB (169GB), run=6145178-6145178msec
在输出中
IOPS : 每秒 I/O 的次数
BW : 磁盘吞吐量。(总传输量/总耗时) (157GiB/6145178msec)
slat (usec):将I/O 发送到内核的消耗的时间。 (usec)表示单位微秒
clat (usec):I/O提交到Kernel到IO完成返回之间的时间。
lat (usec): avg(slat) + avg(clat) =~ avg(lat)
lat (usec) : 250=0.01%, 500=0.01%, 750=0.01%, 1000=0.02%
表示
0.01%的I/O 请求在 250 微秒内完成,0.01% 的I/O 请求在 250 微秒到 500 微秒之间完成 [250,500),依次类推。
上面的输出中 58.44% 的请求都在 [4,10) 毫秒之间完成的。有0.03%的请求都超过了100ms。
blktrace
1.简介
Blktrace 是针对 Linux 内核中 Block IO 的跟踪工具,它可以监测一个 IO 请求各个阶段的耗时情况。
2.安装
apt-get install blktrace
3.blktrace 记录的一次io请求生命周期
Q------->G------------>P--------->I------>M------>U------------------->D----------------------------->C
Q : IO handled by request queue code; 准备发起IO请求(此时还没有请求)
G : Get request ; 生成IO请求
P : Plug request ;插入请求
I : IO inserted onto request queue ; 将IO请求插入到请求队列
M : IO back merged with request on queue ;合并请求
U : Unplug request ;合并完成后取出请求
D : IO issued to driver ;将IO请求发送给设备
C : IO completion ; 完成请求(设备处理结束)
https://linux.die.net/man/1/blkparse
4.常用命令
1.blktrace 采集磁盘io
blktrace /dev/qbd30 #可同时采集多个 如blktrace /dev/qbd30 /dev/qbd0
2. blkparse 分析已采集的信息,并以文件输出
blkparse -i qbd30 -d qbd30.blktrace.bin
3.btt 协助分析
btt -i qbd30.blktrace.bin
5.应用
场景:监控磁盘qbd30
1. 使用前先要挂载debugfs
mount -t debugfs debugfs /sys/kernel/debug
2. 先采集磁盘使用情况(采集过程中需要使用被采集磁盘)
blktrace /dev/qbd30 #可同时采集多个 如blktrace /dev/qbd30 /dev/qbd0
3.采集结束后会在当前文件下生成多个文件。名为qbd30.blktrace.[cpuid]
[root@rhel69 ~]# ls -l qbd30.*
-rw-r--r--. 1 root root 799968 Nov 18 17:09 qbd30.blktrace.0
-rw-r--r--. 1 root root 151848 Nov 18 17:09 qbd30.blktrace.1
-rw-r--r--. 1 root root 3848 Nov 18 17:09 qbd30.blktrace.2
-rw-r--r--. 1 root root 4510336 Nov 18 17:09 qbd30.blktrace.3
4.生成的文件可以用blkparse查看,但是输出内容太多,不便分析建议生成一个二进制文件再用 btt 分析
[root@rhel69 ~]# blkparse -i qbd30 -d qbd30.blktrace.bin
[root@rhel69 ~]# ls qbd30.blktrace.bin
qbd30.blktrace.bin
5.利用 btt 协助分析
[root@rhel69 ~]# btt -i qbd30.blktrace.bin
==================== All Devices ====================
ALL MIN AVG MAX N
--------------- ------------- ------------- ------------- -----------
Q2Q 0.000659491 0.000990258 0.008431694 15888
Q2G 0.000000590 0.000000970 0.000021513 15889
G2I 0.000000899 0.000001310 0.000031724 15889
I2D 0.000001726 0.000002859 0.000034533 15889
D2C 0.000639059 0.000959647 0.008373098 15888
Q2C 0.000642936 0.000964786 0.008378853 15888
==================== Device Overhead ====================
DEV | Q2G G2I Q2M I2D D2C
---------- | --------- --------- --------- --------- ---------
(250,480) | 0.1006% 0.1358% 0.0000% 0.2963% 99.4673%
---------- | --------- --------- --------- --------- ---------
Overall | 0.1006% 0.1358% 0.0000% 0.2963% 99.4673%
[...]
Q2G:生成IO请求耗费的时间
G2I:IO请求放入到请求队列耗费的时间
I2D:IO请求发送给磁盘设备耗费的时间
D2C:磁盘设备处理IO请求耗费的时间
Q2C:整个IO请求耗费的总时间
通过btt的信息,得知处理IO的时间,99.4673%都花费在D2C的过程。
------------------
#blktrace -d /dev/qbd30 -o - | blkparse -i - 可以在shell实时查看
blkparse 输出信息的解释
250,480 3 2 0.000020396 1486 Q WS 297144200 + 8 [fio]
250,480 3 3 0.000021184 1486 G WS 297144200 + 8 [fio]
250,480 3 4 0.000021945 1486 P N [fio]
250,480 3 5 0.000022339 1486 I WS 297144200 + 8 [fio]
250,480 3 6 0.000024168 1486 U N [fio] 1
250,480 3 7 0.000025124 1486 D WS 297144200 + 8 [fio]
250,480 3 8 0.000921274 27859 C WS 297144200 + 8 [0]
第一列 250,480: 为主设备,次设备号
[root@rhel69 ~]# ls -l /sys/dev/block/ | grep qbd30
lrwxrwxrwx 1 root root 0 Nov 17 20:31 250:480 -> ../../devices/virtual/block/qbd30
第二列 3 :为cpuid
第三列 2 :为序列ID
第四列 0.000020396 :为时间偏移
第五列 0.000020396 :发起本次IO的进程ID
第六列 Q :IO进行到了那一步 (对应上面的生命周期)
第七列 WS :Rwbs输出 ,R 代表 read 、W 表示 write、D 表示 块设备 discard 操作 、B 表示 barrier 操作、S 同步操作。
第八列 297144200 + 8 :Offset + Size
第九列 [fio] :表示发起IO请求进程名称
网络性能
ipef
1.简介
iperf可以测试最大TCP和UDP带宽性能,具有多种参数和UDP特性,可以根据需要调整,可以报告带宽、延迟抖动和数据包丢失.
2.安装
①.官网下载对应的安装包 https://iperf.fr/iperf-download.php 安装
②. yum install iperf / apt-get install iperf
3.主要参数
Server or Client:
-p, --port 设置监听或连接的端口
-f, --format 输出时的单位: K, M, G, T
-i, --interval 输出打印的间隔时间
-F, --file name 指定传输的文件
--logfile f 输出到指定的文件
-B, --bind host 绑定网卡(指定数据包从那张网卡经过)
Server specific:
-s, --server 以server运行
-D, --daemon 作为守护进程
Client specific:
-R, --reverse 以反向模式运行(服务器发送,客户端接收)
-c, --client 以 client 运行,连接到 server
-u, --udp 使用 UDP (默认TCP)
--connect-timeout 连接超时 (ms)
-t, --time 设定传输时间间隔,单位 secs (默认 10 secs)
-4, --version4 only use IPv4
-6, --version6 only use IPv6
4.常用命令
# 服务器端 iperf3 -s
# 客户端 iperf3 -c <server ip>
-------
# 单服务器多网卡指定特定网卡
# 服务器 iperf3 -B <本机网卡的ip地址> -s
# 客户端 iperf3 -B <本机网卡的ip地址> -c <server ip>
5.应用
场景:如想知道终端 A 和终端 B 之间网络带宽或排查物理网络是否有延时。
举例:neonsan06 为终端 A 作为 server 端;rhel69 为终端 B 作为 client 端。
1. server 端开启监听。 -s 表示它是 server 端。
root@neonsan06:~# iperf3 -s -p 13145 -f M
-----------------------------------------------------------
Server listening on 13145
-----------------------------------------------------------
2.client端 去连接 server 端,-c 表示它是 client 端后面接 server 端的 ip 地址。
[root@rhel69 yyl]# /usr/local/bin/iperf3 -c 192.168.112.156 -i 1 -p 13145 -f M
Connecting to host 192.168.112.156, port 13145
[ 5] local 192.168.122.114 port 49310 connected to 192.168.112.156 port 13145
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 258 MBytes 257 MBytes/sec 22 269 KBytes
[ 5] 1.00-2.00 sec 269 MBytes 270 MBytes/sec 0 283 KBytes
[ 5] 2.00-3.00 sec 246 MBytes 246 MBytes/sec 0 294 KBytes
[ 5] 3.00-4.00 sec 276 MBytes 276 MBytes/sec 0 307 KBytes
[ 5] 4.00-5.00 sec 282 MBytes 282 MBytes/sec 0 321 KBytes
[ 5] 5.00-6.00 sec 292 MBytes 292 MBytes/sec 0 337 KBytes
[ 5] 6.00-7.00 sec 267 MBytes 267 MBytes/sec 0 349 KBytes
[ 5] 7.00-8.00 sec 329 MBytes 329 MBytes/sec 0 389 KBytes
[ 5] 8.00-9.00 sec 332 MBytes 332 MBytes/sec 0 457 KBytes
[ 5] 9.00-10.00 sec 332 MBytes 332 MBytes/sec 72 474 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 2.81 GBytes 288 MBytes/sec 94 sender
[ 5] 0.00-10.00 sec 2.81 GBytes 288 MBytes/sec receiver
iperf Done.
--------------------------------------------------
上面输出中:
Interval表示时间间隔。
Transfer表示时间间隔里面转输的数据量。
Bandwidth是时间间隔里的传输速率。
Retr表示需要重新发送的TCP报文数,该值大于0的值表示包丢失
如何判断网络是否存在问题?
测试所得的传输速率(Bitrate)在正常的情况下应该接近于网卡带宽。
如上面测试中neonsan06是万兆网卡(10000Mb/s), 它测试正常值应该接近 10 Gbits/sec 才算正常。
上面输出中距离 10 Gbits/sec 这个相差太大,由此可以判断网络是存在问题的, 此时可以再用 “iperf3 -c 192.168.112.156 -R”测试下行速率。
trek
trex是cisco开源的一款基于dpdk的发包工具,可以模拟各种类型的网络流量进行测试。
https://trex-tgn.cisco.com/trex/doc/trex_manual.html
1.安装
按手册内容来,需要注意的是,mellanox网卡必须用centos 7.9, 并且需要安装ofed
# OFED 安装
# Modify the variable to desired Mellanox OFED version
MOFED_VERSION=5.2-2.2.0.0
# Modify the variable to desired OS
#MOFED_OS=ubuntu20.04
MOFED_OS=rhel7.9
curl -fSsL https://www.mellanox.com/downloads/ofed/MLNX_OFED-${MOFED_VERSION}/MLNX_OFED_LINUX-${MOFED_VERSION}-${MOFED_OS}-x86_64.tgz | tar -zxpf -
cd MLNX_OFED_LINUX-*
./mlnxofedinstall
# 这里会提示很多依赖没安装,按要求都装上,然后重装几次就可以完成
trex 解压了就行,无需安装。
2.配置说明
- trex 设计初是2个端口互相收发,所以要求有偶数个端口才可以启动。可以增加个’dummy‘端口来解决这个问题。
- threads 是收发线程可以使用的cpu核,要跟master/latency线程分开
- 目标报文mac都是default_gw的mac,所以目标ip跟default_gw要相同
cat /etc/trex_cfg.yaml
- port_limit : 2
version : 2
#List of interfaces. Change to suit your setup. Use ./dpdk_setup_ports.py -s to see available options
interfaces : ["00:09.0", 'dummy']
port_info : # Port IPs. Change to suit your needs. In case of loopback, you can leave as is.
- ip : 192.168.0.2
default_gw : 192.168.0.3
- ip : 192.168.0.3
default_gw : 192.168.0.3
platform :
master_thread_id : 0
latency_thread_id : 1
dual_if :
- socket : 0
threads : [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
3.编辑测试脚本
trex自带了很多例子,基于stl/udp_for_benchmarks.py改一下,就是发包压测脚本。
# cat stl/udp_for_benchmarks.py
from trex_stl_lib.api import *
import argparse
# Tunable example
#
#trex>profile -f stl/udp_for_benchmarks.py
#
#Profile Information:
#
#
#General Information:
#Filename: stl/udp_for_benchmarks.py
#Stream count: 1
#
#Specific Information:
#Type: Python Module
#Tunables: ['stream_count = 1', 'direction = 0', 'packet_len = 64']
#
#trex>start -f stl/udp_for_benchmarks.py -t packet_len=128 --port 0
#
class STLS1(object):
'''
Generalization of udp_1pkt_simple, can specify number of streams and packet length
'''
def create_stream (self, packet_len, stream_count):
packets = []
for i in range(stream_count):
sport=1025 + i
base_pkt = Ether()/IP(src="192.168.0.2",dst="192.168.0.3")/UDP(dport=12,sport=sport)
base_pkt_len = len(base_pkt)
base_pkt /= 'x' * max(0, packet_len - base_pkt_len)
packets.append(STLStream(
packet = STLPktBuilder(pkt = base_pkt),
mode = STLTXCont(pps = 1200000)
))
return packets
def get_streams (self, tunables, **kwargs):
parser = argparse.ArgumentParser(description='Argparser for {}'.format(os.path.basename(__file__)),
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--packet_len',
type=int,
default=64,
help="The packets length in the stream")
parser.add_argument('--stream_count',
type=int,
default=12,
help="The number of streams")
args = parser.parse_args(tunables)
# create 1 stream
return self.create_stream(args.packet_len - 4, args.stream_count)
# dynamic load - used for trex console or simulator
def register():
return STLS1()
4.启动测试
需要两个ssh终端
- 启动服务, 其中 -c 10 表示用10个核,./t-rex-64 -c 10 -f /etc/trex_cfg.yaml -i.
- 在另一个终端使用console启动测试
[root@i-bse38fxo v2.88]# ./trex-console
Using 'python3' as Python interpeter
Connecting to RPC server on localhost:4501 [SUCCESS]
Connecting to publisher server on localhost:4500 [SUCCESS]
Acquiring ports [0]: [SUCCESS]
Server Info:
Server version: v2.88 @ STL
Server mode: Stateless
Server CPU: 1 x QEMU Virtual CPU
Ports count: 1 x 25Gbps @ MT27800 Family [ConnectX-5 Virtual Function]
-=TRex Console v3.0=-
Type 'help' or '?' for supported actions
trex>start -f stl/udp_for_benchmarks.py
4.这时可以在服务终端看到统计信息。这个测试是在pekt3的vm里面运行的,由于hyper是10G网卡,此时已经达到线速。
-Global stats enabled
Cpu Utilization : 7.3 % 20.1 Gb/core
Platform_factor : 1.0
Total-Tx : 7.37 Gbps
Total-Rx : 38.24 bps
Total-PPS : 14.39 Mpps
Total-CPS : 0.00 cps
Expected-PPS : 0.00 pps
Expected-CPS : 0.00 cps
Expected-BPS : 0.00 bps
Active-flows : 0 Clients : 0 Socket-util : 0.0000 %
Open-flows : 0 Servers : 0 Socket : 0 Socket/Clients : -nan
Total_queue_full : 1522870939
drop-rate : 7.37 Gbps
current time : 518.1 sec
test duration : 0.0 sec
5.停止测试: 在console里面输入stop
参考文档
https://netdevconf.info/0x14/session.html?talk-test-your-limits-with-trex-traffic-generator
https://mp.weixin.qq.com/s/qg6S6ONkl46CmxLbjzx-WA