Linux服务器基准性能测试常用工具

对Linux服务器做基准测试可以帮助确定服务器在特定任务或负载下的性能。这不仅有助于我们了解服务器的处理能力、响应时间、吞吐量等关键性能指标,也有助于我们进行服务器容量规划,确保服务器在未来的工作负载下仍能保持良好的性能。

本文总结Linux下常用的基准测试工具的使用场景和方法,按硬件组成分为CPU、内存、磁盘和网络四个部分。其中有些工具不是Linux自带的,此时需要先安装工具。以fio为例,在Ubuntu里使用sudo apt-get install fio,在CentOS里则使用sudo yum install fio即可完成安装。

一、CPU基准测试

lscpu - 查看CPU硬件信息

命令lscpu是显示关于 CPU 体系结构信息的一个工具,它从/proc/cpuinfo和其他系统文件中收集数据,汇总并以易于阅读的格式显示,不需要root权限。我们通常用它了解CPU的架构、核数和主频等基本信息:

> lscpu
Architecture:                    aarch64   <-- CPU架构,这里是ARM架构的
CPU op-mode(s):                  64-bit
Byte Order:                      Little Endian
CPU(s):                          128   <-- CPU核心数量128个
On-line CPU(s) list:             0-127
Thread(s) per core:              1  <-- 每核心线程数
Core(s) per socket:              64
Socket(s):                       2  <-- 两个物理CPU插槽
NUMA node(s):                    4  <-- NUMA节点数
Vendor ID:                       0x48
Model:                           0
Stepping:                        0x1
CPU max MHz:                     2600.0000   <-- CPU最大频率
CPU min MHz:                     200.0000
BogoMIPS:                        200.00
L1d cache:                       8 MiB
L1i cache:                       8 MiB
L2 cache:                        64 MiB
L3 cache:                        128 MiB     <-- 三级缓存大小,此缓存是多核共享的
NUMA node0 CPU(s):               0-31
NUMA node1 CPU(s):               32-63
NUMA node2 CPU(s):               64-95
NUMA node3 CPU(s):               96-127
...

其中Core、Socket和NUMA node的概念可以参考下图(来源):

file

sysbench cpu - 测试CPU性能

使用sysbench工具可以测试CPU的实际性能,它内部是通过反复查找指定范围(默认10000)内所有素数实现的,每完整查找完成一次即为一个事件(event),默认10秒后输出平均每秒完成的事件次数(eps, events per second)作为衡量CPU性能的指标。

若测试时在命令行里添加--threads参数指定了多线程,则eps指标也会相应上升,简单公平起见我们都用默认单线程测试即可。

> sysbench cpu run
Prime numbers limit: 10000
Initializing worker threads...
Threads started!

CPU speed:
    events per second:  3329.35   <-- 主要关注这个eps指标

General statistics:
    total time:                          10.0002s
    total number of events:              33299

Latency (ms):
         min:                                    0.30
         avg:                                    0.30
         max:                                    0.62
         95th percentile:                        0.31
         sum:                                 9994.03

Threads fairness:
    events (avg/stddev):           33299.0000/0.00
    execution time (avg/stddev):   9.9940/0.00

二、内存基准测试

dmidecode - 查看内存条硬件信息

命令dmidecode从系统的 DMI(Desktop Management Interface)表中读取数据,提供关于系统硬件组件的详细信息,如 主板、BIOS、处理器、内存、缓存、芯片组和其他系统硬件的信息。我们通常用它查看主板上各个内存条的型号、容量、频率等硬件信息。

查看已安装的物理内存条数及容量:

> sudo dmidecode -t memory | grep 'GB'
Size: 32 GB  <-- 单条内存容量32GB
Size: 32 GB
Size: 32 GB
Size: 32 GB

查看已安装的物理内存频率:

> sudo dmidecode -t memory | grep 'MT/s'
Speed: 3200 MT/s                    <-- 物理内存支持的最大频率
Configured Memory Speed: 2933 MT/s  <-- 实际运行频率, 通常是CPU无法支持到内存最高频率导致的
Speed: 3200 MT/s
Configured Memory Speed: 2933 MT/s
Speed: 3200 MT/s
Configured Memory Speed: 2933 MT/s
Speed: 3200 MT/s
Configured Memory Speed: 2933 MT/s

在测试内存性能时,需要注意缓存的影响,下图(来源)展示了典型的三级缓存架构。测试项目所处理的数据量应该大大超过缓存的大小,否则就变成了测试缓存的性能。

file

sysbench memory - 测试内存性能

sysbench工具可以测试内存的实际性能:

> sysbench memory run
Running memory speed test with the following options:
  block size: 1KiB
  total size: 102400MiB
  operation: write
  scope: global

Initializing worker threads...
Threads started!

Total operations: 38967914 (3896177.52 per second)
38054.60 MiB transferred (3804.86 MiB/sec)

General statistics:
    total time:                          10.0002s
    total number of events:              38967914

Latency (ms):
         min:                                    0.00
         avg:                                    0.00
         max:                                    0.26
         95th percentile:                        0.00
         sum:                                 4468.85

Threads fairness:
    events (avg/stddev):           38967914.0000/0.00
    execution time (avg/stddev):   4.4688/0.00

三、磁盘基准测试

lsblk - 查看磁盘信息

此命令可列出所有块设备及其属性,且不需要root权限。

> lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda      8:0    0 446.6G  0 disk
├─sda1   8:1    0   512M  0 part /boot/efi
└─sda2   8:2    0 446.1G  0 part /

fdisk - 查看磁盘分区信息

命令fdisk是一个磁盘分区工具,也经常被用于显示磁盘信息,需要root权限。它比lsblk给出的信息更加详细一些,例如包含了每个磁盘分区的大小和文件系统信息。

> sudo fdisk -l
Disk /dev/sda: 446.64 GiB, 479559942144 bytes, 936640512 sectors
Disk model: SAS3908
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 262144 bytes / 262144 bytes
Disklabel type: gpt
Disk identifier: 6819FBA6-5719-44F1-A2B6-F444F542E8BC

Device       Start       End   Sectors   Size Type
/dev/sda1     2048   1050623   1048576   512M EFI System
/dev/sda2  1050624 936638463 935587840 446.1G Linux filesystem

fio - 测试磁盘性能

fio是一个专业的磁盘性能测试工具。它可以配置多种测试场景,包括顺序读写和随机读写等,我们主要关注IOPS(每秒操作数)和BW(带宽)指标。

以测试顺序读写性能为例:

> fio --rw=rw  --directory=/tmp --size=256m --direct=1 --name=mytest
mytest: (g=0): rw=rw, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=psync, iodepth=1
fio-3.7
Starting 1 process
Jobs: 1 (f=1): [M(1)][100.0%][r=1749KiB/s,w=1789KiB/s][r=437,w=447 IOPS][eta 00m:00s]
mytest: (groupid=0, jobs=1): err= 0: pid=25055: Sun Jun 30 11:44:53 2024
...
Run status group 0 (all jobs):
   READ: bw=1712KiB/s (1753kB/s), 1712KiB/s-1712KiB/s (1753kB/s-1753kB/s), io=128MiB (134MB), run=76476-76476msec
  WRITE: bw=1716KiB/s (1757kB/s), 1716KiB/s-1716KiB/s (1757kB/s-1757kB/s), io=128MiB (134MB), run=76476-76476msec

命令行参数--direct表示是否使用操作系统级的磁盘缓存,默认值1。取01对结果影响很大(几十倍),0反映磁盘本身的性能,1更接近实际使用场景。

命令行参数--rw是指定要测试的项目,可选项是以下之一:

: read       Sequential read
: write      Sequential write
: trim       Sequential trim
: randread   Random read
: randwrite  Random write
: randtrim   Random trim
: rw         Sequential read and write mix
: readwrite  Sequential read and write mix
: randrw     Random read and write mix
: trimwrite  Trim and write mix, trims preceding writes

dd - 测试磁盘性能(仅顺序读写)

如果在服务器上无法安装fio等专业工具,可以用dd命令粗略测试磁盘的顺序读写性能,绝大部分linux发行版都自带dd命令,它本来的作用是快速复制和转换文件,不需要root权限。

凭空创建一个大小为 1GB 的文件 testfile,以此测量顺序写入的速度:

> dd if=/dev/zero of=/tmp/testfile bs=1G count=1 oflag=direct
1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.834568 s, 1.3 GB/s

从刚才创建的 testfile 中读取数据,以此测量顺序读取的速度:

> dd if=testfile of=/dev/null bs=1G count=1 iflag=direct
1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.665267 s, 1.6 GB/s

四、网络基准测试

lspci - 查看网卡硬件信息

用Linux自带的lspci命令可以查看所有pci设备的基本信息,我们用ethernet过滤一下就可以得到网卡信息,例如网卡型号。此命令不需要root权限。

> lspci | grep -i ethernet
7d:00.0 Ethernet controller: Huawei Technologies Co., Ltd. HNS GE/10GE/25GE RDMA Network Controller (rev 21)
7d:00.1 Ethernet controller: Huawei Technologies Co., Ltd. HNS GE/10GE/25GE Network Controller (rev 21)
7d:00.2 Ethernet controller: Huawei Technologies Co., Ltd. HNS GE/10GE/25GE RDMA Network Controller (rev 21)
7d:00.3 Ethernet controller: Huawei Technologies Co., Ltd. HNS GE/10GE/25GE Network Controller (rev 21)

更详细的信息可以加-v参数获得:

> lspci -v | grep -i ethernet -A 10
7d:00.0 Ethernet controller: Huawei Technologies Co., Ltd. HNS GE/10GE/25GE RDMA Network Controller (rev 21)
        Subsystem: Huawei Technologies Co., Ltd. HNS GE/10GE/25GE RDMA Network Controller
        Flags: bus master, fast devsel, latency 0, NUMA node 0
        Memory at 121000000 (64-bit, prefetchable) [size=64K]
        Memory at 120000000 (64-bit, prefetchable) [size=1M]
        Capabilities: <access denied>    <-- 要显示全部能力需要加sudo
        Kernel driver in use: hns3
        Kernel modules: hclge, hns3, hns_roce_hw_v2
...

不过lspci命令无法看到网卡的MAC地址,为解决这个问题我们可以使用ifconfig命令或ip命令。

ip -查看MAC地址和IP地址

以前我们经常使用ifconfig命令查看mac地址和ip地址,但这个工具已经几乎停止开发,逐渐被新的ip命令取代。因此这里我们仅介绍后者的使用方法。

注:有些Linux发行版已经不再默认提供ifconfig,若一定要使用,请先安装net-tools组件,例如sudo apt-get install net-tools

使用ip addr命令可以查看mac地址和ip地址。在下面的例子里,网卡1是LoopBack接口用于与本机通讯,网卡2~4为没有接入网络的物理网卡(DOWN),网卡5为已接入网络的网卡(UP)

> ip addr
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp125s0f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether c0:4e:f6:5d:24:06 brd ff:ff:ff:ff:ff:ff
3: enp125s0f1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether c0:4e:f6:5d:24:07 brd ff:ff:ff:ff:ff:ff
4: enp125s0f2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether c0:4e:f6:5d:24:08 brd ff:ff:ff:ff:ff:ff
5: enp125s0f3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether c0:4e:f6:5d:24:09 brd ff:ff:ff:ff:ff:ff                  <-- MAC地址
    inet 192.168.1.6/16 brd 192.168.255.255 scope global enp125s0f3     <-- IP地址、广播地址
       valid_lft forever preferred_lft forever
    inet6 fe80::b24f:a6ff:fe5c:1409/64 scope link
       valid_lft forever preferred_lft forever

ip命令还有很多功能,例如ip link set可以修改网卡属性,ip route可以操作静态路由表等,限于篇幅这里不作展开了。

netperf - 测试网络性能

使用 netperf 测试网络性能需要两台服务器,一台以netserver命令启动服务端(默认端口12865):

> sudo netserver -4 -L 0.0.0.0 -p 9292
Starting netserver with host '0.0.0.0' port '9292' and family AF_INET

另一台作为客户端以netperf命令向服务端反复发送数据,下面的例子中-t TCP_CRR表示为每次交易建立一个新的tcp连接(http的场景),-r 4k,1k指定请求和响应内容的大小,-l 30指定测试时长为30秒:

> netperf  -H 127.0.0.1 -P 9292 -l 30 -t TCP_CRR -- -r 4k,1k
MIGRATED TCP Connect/Request/Response TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 127.0.0.1 () port 0 AF_INET : demo
Local /Remote
Socket Size   Request  Resp.   Elapsed  Trans.
Send   Recv   Size     Size    Time     Rate
bytes  Bytes  bytes    bytes   secs.    per sec

16384  131072 4000     1000    30.00    10808.27    <-- 每秒完成10808个请求响应
16384  131072

GlusterFS复制卷迁移至分布式复制卷

GlusterFS是广泛使用的去中心化的分布式文件系统,本文主要介绍GlusterFS里创建不同类型卷的方法,以及如何对已有卷转换类型。

GlusterFS没有提供专门的命令行选项指定卷类型,而是根据根据副本(replica)数量与块(brick)数量关系自动进行判断。

环境信息

CentOS 7.9
GlusterFS 9.4

创建复制卷(Replicate)

GlusterFS的复制卷可以类比于RAID1。当一个volume的replica是brick的整数倍(包含1倍)时创建出来的卷就是复制模式:

> gluster volume create volume1 replica 2 server1:/exp1 server2:/exp2
volume create: volume1: success: please start the volume to access data

> gluster volume start volume1
volume start: volume1: success

> gluster volume info
Volume Name: volume1
Type: Replicate
...

文件在复制卷上的分布,图片来自GlusterFS官方文档:

file

创建分布式复制卷(Distributed-Replicate)

GlusterFS的分布式复制卷可以类比于RAID10当brick数量是replica的整数倍(不含1倍)时,创建出来的卷是分布式复制模式:

> gluster volume create volume1 replica 2 server1:/exp1 server2:/exp2 server3:/exp3 server4:/exp4
volume create: volume1: success: please start the volume to access data

> gluster volume start volume1
volume start: volume1: success

> gluster volume info
Volume Name: volume1
Type: Distributed-Replicate
...

文件在分布式复制卷上的分布,图片来自GlusterFS官方文档:

file

将复制卷转为分布式复制卷

假设现在的复制卷是4节点4副本,要将其转换为4节点2副本。转换方法是先收缩位2节点2副本,再扩展为4节点2副本。

注意:收缩副本后,确保不用的旧目录(前面例子中/exp3和/exp4)一定要手工删除,不要直接使用这些目录进行扩容,否则会出现重复文件问题。

> gluster volume info
Volume Name: volume1
Type: Replicate
Volume ID: 38f39495-6678-40c1-9aa7-36399f6285cc
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 4 = 4
...

# 收缩(对replicate卷需要加force参数)
> gluster volume remove-brick volume1 replica 2 server3:/exp3 server4:/exp4 force

> gluster volume info
Volume Name: volume1
Type: Replicate
Volume ID: 38f39495-6678-40c1-9aa7-36399f6285cc
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 2 = 2
...

# 扩展(对replicate卷需要加force参数)
> gluster volume add-brick volume1 replica 2 server3:/exp3 server4:/exp4 force

> gluster volume info
Volume Name: volume1
Type: Distributed-Replicate
Volume ID: 38f39495-6678-40c1-9aa7-36399f6285cc
Status: Started
Snapshot Count: 0
Number of Bricks: 1 x 2 = 2
...

# 平衡
> gluster volume rebalance volume1 start
volume rebalance: volume1: success: Rebalance on volume1 has been started successfully. Use rebalance status command to check status of the rebalance process.
ID: 58799899-5f18-4cfb-98d9-96ab91ce6739

> gluster volume rebalance volume1 status
Node     ebalanced-files          size       scanned      failures       skipped               status  run time in h:m:s
---------      -----------   -----------   -----------   -----------   -----------         ------------     --------------
server2                2        0Bytes             5             0             0            completed        0:00:00
server3                0        0Bytes             5             0             0            completed        0:00:00
server4                0        0Bytes             5             0             0            completed        0:00:00
localhost              0        0Bytes             5             0             0            completed        0:00:00

当文件数量较多时,平衡所需的时间可能会很长,但这并不影响新文件写入glusterfs。下面是某个生产环境做平衡的过程,大约需要半个月:

         Node Rebalanced-files          size       scanned      failures       skipped               status  run time in h:m:s
    ---------      -----------   -----------   -----------   -----------   -----------         ------------     --------------
 10.102.9.127           496771         7.2TB       3340719             0             0          in progress       68:05:36
 10.102.9.128           403741         1.2TB       3433837             0             0          in progress       68:05:36
 10.102.9.132                1       28Bytes        675030            11         34918          in progress       68:05:31
 10.102.9.133                0        0Bytes        673981             0         12583          in progress       68:05:32
 10.102.9.134               12        93.2MB        681215             0         15036          in progress       68:05:34
    localhost           362702       677.4GB       3143169             0             0          in progress       68:05:36
Estimated time left for rebalance to complete :      322:37:43

遇到的问题

1、ls时发现有部分文件和目录名重复:

> ls -l /my/glusterfs
drwxr-xr-x 188 k2data k2data  4096 1月  22 10:14 ALaS
drwxr-xr-x 517 k2data k2data  4096 1月  24 15:19 AoF
drwxr-xr-x 517 k2data k2data  4096 1月  24 15:19 AoF
drwxr-xr-x 358 k2data k2data  4096 1月  22 09:23 BaiGL
drwxr-xr-x 328 k2data k2data  4096 1月  21 20:40 BaiS
drwxr-xr-x 328 k2data k2data  4096 1月  21 20:40 BaiS
...

此问题是由于有一个节点的brick目录没有清除,之前认为只要重命名即可(保留文件以便万一需要时恢复),但发现glusterfs似乎会识别到重命名后的文件,观察其下面的.glusterfs隐藏目录里的内容,修改时间一直在变。

后用gluster replace-brick命令从glusterfs里剔除此节点替换为另一个新服务器后问题消失。

2、有些目录权限丢失
例如下面的目录,一些目录权限变成了000,并且owner从k2data变成了root,导致相关程序报错Permission denied

> ls -l /my/glusterfs
drwxr-xr-x 273 k2data k2data  4096 1月  21 21:44 DiL
d--------- 315 root   root    4096 1月  21 21:46 FanC
drwxr-xr-x 338 k2data k2data  4096 1月  27 10:15 FengDS
...

出现原因不明,解决方法是手工将这些目录权限改过来(从000改为755):

ls -l | grep d--- | awk '{print $9}' | xargs chown k2data:k2data -R
ls -l | grep d--- | awk '{print $9}' | xargs chmod 755 -R

3、文件信息显示为问号

ls -l /my/glusterfs/data/172.17.23.230/20230629
ls: 无法访问/my/gluster/repo_FengDS_hfqfile/data/172.17.23.230/20230629/_zipped.zip: 没有那个文件或目录
总用量 0
-????????? ? ? ? ?            ? _zipped.zip

经排查是因为这个文件所在的物理目录不正确,例如文件本应在brick1、2、3,但实际被放在了brick4、5、6,如果手工移动到正确位置则问题消失。

产生这个问题的原因是gluster的元信息与文件实际所在物理节点不符,例如gluster认为文件a.txt存放在物理节点1和2上,但由于某种原因a.txt实际存放在节点3和4上。手工将文件移动到正确的位置后问题消失。

4、部分文件脑裂

> gluster volume heal volumn1 info
Brick server1:/my/glusterfs
<gfid:c22fa080-f917-4862-b9d9-a12aff40d392> - Is in split-brain
Status: Connected
Number of entries: 1

Brick server2:/my/glusterfs
<gfid:a60abad3-e42a-49ba-8b8e-463ea656c9cb>
<gfid:12c6e0ae-638c-4d59-96ff-c35a3bda3e07> - Is in split-brain
<gfid:f429f4ad-d935-48a0-bbfa-23407d433e8c> - Is in split-brain
<gfid:6e99bf54-07ab-4c55-92c1-0f5b297079a5> - Is in split-brain
/k2box/apps/com.my.import03/job - Is in split-brain
<gfid:5235e32e-4a7c-457a-ba08-3b7ef61a77e7> - Is in split-brain
<gfid:ba80b4bf-cff3-4dd2-b6a5-cba656431641> - Is in split-brain
/k2box/apps/com.my.import03/job/3471565
<gfid:493df16c-6c91-485a-b6f1-87208395b8f4>
<gfid:afd49274-d9e4-48b2-8814-53fd76fce327> - Is in split-brain
Status: Connected
Number of entries: 10
...

自动修复:

> gluster volume heal volumn1

5、有一个brick的统计信息异常
gluster volume top命令查询当前各brick打开文件数量,有一个brick的数量明显异常(18446744073709534192个):

> gluster volume top volume1 open | grep fds -B 2
Brick: 10.102.9.126:/my/glusterfs
Current open fds: 0, Max open fds: 1767, Max openfd time: 2023-08-16 04:08:46.556300 +0000
--
186883          /k2box/repos/repo_XuTuan_1sec/.repo/meta.settings
Brick: 10.102.9.134:/my/glusterfs
Current open fds: 18446744073709534192, Max open fds: 18446744073709551615, Max openfd time: 2024-02-01 20:44:34.245111 +0000
--
882             /k2box/apps/com.acme.import01/job/3527701/output/log/stats.log
Brick: 10.102.9.133:/my/glusterfs
Current open fds: 0, Max open fds: 400, Max openfd time: 2024-02-01 13:19:06.438338 +0000
--
2124            /k2box/repos/repo_ZhengXBQ_hive/.repo/batch.settings
Brick: 10.102.9.132:/my/glusterfs
Current open fds: 0, Max open fds: 400, Max openfd time: 2024-02-01 13:19:06.439036 +0000
...

重启glusterd服务或重新mount都无效。

参考资料

https://docs.gluster.org/en/latest/Administrator-Guide/Setting-Up-Volumes

NFS挂载意外断开导致java启动docker容器失败

一、环境信息

NFS客户端:
银河麒麟V10,ARM架构
Linux version 4.19.90-24.4.v2101.ky10.aarch64

NFS服务器:
Windows Server 2022 Standard

二、问题现象

通过java api启动docker容器时发现容器没有起来,查询后台日志信息如下:

[2024-01-14 15:10:01.141] [INFO] Starting docker container
[2024-01-14 15:10:02.117] [INFO] Recoverable I/O exception (java.net.SocketException) caught when processing request to {}->http://192.168.101.80:22375
[2024-01-14 15:10:02.152] [INFO] Docker client connected successfully
[2024-01-14 15:10:07.154] [INFO] Recoverable I/O exception (java.net.SocketException) caught when processing request to {}->http://192.168.101.80:22375
[2024-01-14 15:10:07.220] [INFO] Docker client connected successfully
[2024-01-14 15:10:12.221] [INFO] Recoverable I/O exception (java.net.SocketException) caught when processing request to {}->http://192.168.101.80:22375
[2024-01-14 15:10:12.282] [INFO] Docker client connected successfully
[2024-01-14 15:10:17.284] [INFO] Recoverable I/O exception (java.net.SocketException) caught when processing request to {}->http://192.168.101.80:22375
[2024-01-14 15:10:17.354] [INFO] Docker client connected successfully
[2024-01-14 15:10:22.356] [INFO] Recoverable I/O exception (java.net.SocketException) caught when processing request to {}->http://192.168.101.80:22375
[2024-01-14 15:10:22.391] [INFO] Docker client connected successfully

初步怀疑磁盘空间被占满导致,执行df命令时发现没有响应:

[root@192 storage]# df -h
(卡死在这里没有任何输出,只能按ctrl+c退出)

三、问题解决

由于前几天出现过df命令无响应的情况,所以马上意识到可能是远程nfs挂载的远程磁盘有问题,经过询问果然是有人改了远程nfs服务器的ip地址。

让运维恢复了nfs服务器的地址,然后重启一下rpcbind服务:

systemctl restart rpcbind

如果以上命令无效,可以尝试强制卸载nfs路径:

umount -f -l /mnt/hdfs/k2repos/CMSFTPServer

此时df命令恢复正常:

[root@192 storage]# df -h | grep -v docker
Filesystem                    Size  Used Avail Use% Mounted on
devtmpfs                       32G     0   32G   0% /dev
tmpfs                          32G     0   32G   0% /dev/shm
tmpfs                          32G  546M   31G   2% /run
tmpfs                          32G     0   32G   0% /sys/fs/cgroup
/dev/mapper/klas-root         4.0T  207G  3.8T   6% /
tmpfs                          32G     0   32G   0% /tmp
/dev/vda2                    1014M  218M  797M  22% /boot
/dev/vda1                     599M  6.5M  593M   2% /boot/efi
192.168.101.251:/home/data   1022G   15G 1007G   2% /mnt/hdfs/k2repos
10.144.136.169:/CMSFTPServer  7.3T  6.1T  1.3T  83% /mnt/hdfs/k2repos/CMSFTPServer
tmpfs                         6.3G     0  6.3G   0% /run/user/0

日志显示java启动docker容器也恢复正常:

[2024-01-14 16:00:01.149] [INFO] Starting docker container
[2024-01-14 16:00:13.955] [INFO] Container started, status code: 1

四、预防措施

为了预防类似情况发生时严重影响业务,可以考虑以soft模式挂载nfs服务(默认为hard模式),这样当nfs服务不可用时进程不会hang住,而是返回一个错误:

mount -o soft -t nfs 10.144.136.169:/CMSFTPServer /mnt/hdfs/k2repos/CMSFTPServer

实测以soft模式启动后,若nfs服务不可用,docker容器能够正常启动,但此时df命令仍然无响应,此时用df -x nfs4命令可以查看除nfs以外的磁盘。

但soft模式也有代价:

Since nfsv4 performs open/lock operations that have their ordering strictly enforced by the server, the options intr and soft cannot be safely used. hard nfsv4 mounts are strongly recommended.

五、参考链接

时钟导致TDengine偶尔连接失败问题排查和解决

一、环境信息

CentOS 7.9
TDengine 3.1.0.0
OpenJDK 11

二、问题现象

一个数据接入程序,定时将数据从指定文件导入到TDengine,发现每天执行的约1000次导入作业里,有1%~2%是失败的,查询失败作业的日志可以看到抛出如下异常:

[2023-08-07 08:35:00.370] [INFO] [INFO ][2023-08-07 08:33:36] 导入中 2001637/QiJia003/1650038400000/Sec_20220416.csv, 已成功导入 51000 行, 182 MB
[2023-08-07 08:35:06.980] [INFO] [INFO ][2023-08-07 08:33:34] 导入中 2001637/QiJia001/1650038400000/Sec_20220416.csv, 已成功导入 57000 行, 183 MB
[2023-08-07 08:35:00.875] [ERROR] create connection SQLException, url: jdbc:TAOS://:/repo_QiJia_1sec, errorCode -2147483637, state 
java.sql.SQLException: TDengine ERROR (8000000b): Unable to establish connection
    at com.taosdata.jdbc.TSDBError.createSQLException(TSDBError.java:76) ~[k2box-storage-taos3-2.2.5.jar:?]
    at com.taosdata.jdbc.TSDBJNIConnector.executeQuery(TSDBJNIConnector.java:119) ~[k2box-storage-taos3-2.2.5.jar:?]
    at com.taosdata.jdbc.TSDBStatement.executeQuery(TSDBStatement.java:47) ~[k2box-storage-taos3-2.2.5.jar:?]
    at com.alibaba.druid.pool.DruidAbstractDataSource.validateConnection(DruidAbstractDataSource.java:1419) ~[k2box-storage-taos3-2.2.5.jar:?]
    at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1719) ~[k2box-storage-taos3-2.2.5.jar:?]
    at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2813) ~[k2box-storage-taos3-2.2.5.jar:?]
[2023-08-07 08:35:00.883] [ERROR] create connection SQLException, url: jdbc:TAOS://:/repo_QiJia_1sec, errorCode -2147483637, state 
java.sql.SQLException: TDengine ERROR (8000000b): Unable to establish connection
    at com.taosdata.jdbc.TSDBError.createSQLException(TSDBError.java:76) ~[k2box-storage-taos3-2.2.5.jar:?]
    at com.taosdata.jdbc.TSDBJNIConnector.executeQuery(TSDBJNIConnector.java:119) ~[k2box-storage-taos3-2.2.5.jar:?]
    at com.taosdata.jdbc.TSDBStatement.executeQuery(TSDBStatem

三、问题排查

由于此环境的TDengine是不久前从2.6.0升级到3.1.0.0的,升级之前没有这个问题,所以一开始怀疑是TDengine的新版本有问题,或者是新版本的默认参数与旧版本不同导致的。但尝试修改了服务端和客户端(连接池)的各种参数后问题依旧。用ulimit -nlsof -p查询打开的文件数量和文件上限也在正常范围内。

后来考虑是否作业(docker容器)消耗资源有异常,查看资源占用图表时发现折线图有向反方向走的情况(下图红色箭头指向的位置),说明服务器系统时间有倒流的情况。

file

仔细查看前面的失败作业日志,其实也有时间戳倒流的现象,并且连接失败现象与时间戳倒流是同时发生的:

file

因此将问题嫌疑定位到与系统时钟有关。经过进一步排查发现,此服务器使用ntpdate定期从两台ntp服务器分别进行周期性的对时:

1、每5分钟从服务器10.102.9.31同步时间:

[root@taos-1 ~]# crontab -l
*/5 * * * * /usr/sbin/ntpdate 10.102.9.31 >/dev/null 2>&1

2、每64秒从服务器10.102.9.32同步时间:

[root@taos-1 ~]# ntpstat
synchronised to NTP server (10.102.9.32) at stratum 3
   time correct to within 115 ms
   polling server every 64 s
[root@taos-1 ~]#

并且服务器10.102.9.32的时钟比10.102.9.31慢7秒左右,这就造成了这台服务器的时钟周期性的向前和向后跳动。当TDengine服务端的时钟改变时,连接池里原有的连接会失效无法连接。

[root@taos-1 ~]# /usr/sbin/ntpdate 10.102.9.32
 7 Aug 18:51:23 ntpdate[49651]: step time server 10.102.9.32 offset 7.341666 sec

[root@taos-1 ~]# /usr/sbin/ntpdate 10.102.9.31
 7 Aug 18:54:31 ntpdate[1798]: step time server 10.102.9.31 offset -7.200571 sec

四、问题解决

从两台服务器分别对时显然是没有必要的,应该是运维人员不了解情况的情况下操作导致的,去掉其中一个对时的任务后即可。这里我们去掉的是ntpstat里配置的对时服务,我们发现它是用chrony服务实现的,因此执行systemctl stop chronydsystemctl disable chronyd

Linux inode和常用操作

Linux系统里的inode中文名索引文件,用于保存文件的大小、时间、权限等元信息。每个文件都对应一个inode,每个inode也对应一个文件。因为在Linux里目录、设备等也是文件,所以也对应一个inode。

inode与文件块是分开保存的,它们都会占用磁盘空间,通常情况下是后者先占满,但当磁盘上有大量小文件时,可能前者会先达到上限,从而导致磁盘虽然还有空间但无法写入新文件。这种场景应提前考虑增加inode的上限数量,例如将2KB降为1KB。

file
图片来源:Wikipedia

让我们做一些实验来验证一下inode的行为:

查看磁盘已用和可用inode数量

执行df -i可查看分区里inode数量,一个分区下最大inode数量是格式化时确定的,默认最大数量是分区大小除以2KB得到
file

查看文件inode信息

执行ls -i可查看当前目录每个文件的inode值:
file

验证软链接有自己的inode

软链接是一个文件,其inode值与链接目标文件是不相同的。
file

验证硬链接共享同一个inode

硬链接不是一个文件,其inode号与链接目标文件相同。其实很正常,linux内部对文件的管理都是通过inode完成的,文件名只是一个易读的符号。
file

验证.和..是硬链接

分别对应当前目录的inode和上一级目录的inode。
file

验证通过inode号反查文件名

find -inum命令:
file

文件名存储在哪里?

inode里并不保存文件名(否则硬链接无法实现),那么文件名存储在哪里?答案是存储在“目录文件”里,当我们ls时,Linux就查询目录文件(但我们不能直接cat目录),此文件包含此目录下所有文件名到inode的映射关系。
file

注:以上均默认ext2文件系统。

使用Netdata实时监控服务器资源

Netdata是一款轻量的服务器资源监控软件,与Promethues这样的套件相比,其在Linux下的安装部署十分简便,即装即用,本身占用的资源不算高(但默认只能记录1天左右的数据,要记录更长时间数据需要配置数据库)。Netdata还支持监控每个docker容器的资源占用,对使用docker作为底座的系统十分有用,可以更方便的找出有问题的容器。

在CentOS里安装netdata:

yum install netdata

安装后服务即自动启动。需要修改/etc/netdata/netdata.conf里的ip地址(默认值是localhost,阿里云环境需要修改为网卡的内网地址):

bind to xx.xx.xx.xx

重启netdata服务:

service netdata restart

必要时在防火墙上开启19999端口。

通过浏览器访问netdata地址http://xx.xx.xx.xx:19999(阿里云环境使用公网ip访问)

file

阿里云Centos 6.5迁移到7.6记录

主要原因是tensorflow在centos 6.5环境下配置遇到很多问题,主要是gcc和相关环境的版本问题,因此新购一台阿里云ec2使用centos 7.6版本。原服务器上的webapp(v7和wordpress)需要迁移,大量文件(>300w个)需要迁移。

参考之前一篇centos 6.5的服务器配置记录:Amazon EC2配置步骤和一些问题

一、购买ec2并添加数据盘

过程略。

二、阿里云格式化数据盘

https://help.aliyun.com/document_detail/25426.html?spm=a2c4g.11186623.2.27.558a1692XkXC7y#concept-jl1-qzd-wdb

三、安装必要的工具

yum install git
yum install nano
yum install lsof
yum install unzip

四、迁移mysql数据

安装mysql 5.7

https://dev.mysql.com/doc/refman/5.6/en/linux-installation-yum-repo.html

恢复数据库

mysql -uroot mydatabase < myexportedfile.sql

创建用户并授权

grant all privileges ON mydatabase.* TO 'username'@'localhost' identified by 'mypassword' with grant option;
flush privileges;

五、迁移其他服务

安装服务器软件

yum install java-1.8.0-openjdk
yum install httpd
yum install php php-mysql
yum install tomcat

配置jk和ssl

2.4版apache参考这个链接:How do I install mod_jk on Apache 2.4 webserver

修改/etc/crontab定时任务

crontab -e

配置服务自启动

chkconfig mysqld on
chkconfig httpd on
chkconfig tomcat on

六、大量文件迁移

因为原来的数据盘容量100GB,已经转移了50GB到OSS对象存储,因此新购的数据盘容量为60GB。阿里云不支持“数据盘缩容”,且原数据盘由于是包年包月方式无法从原ec2卸载,因此需要先为原数据盘创建一个100GB的镜像,然后购买一个按量付费的数据盘并选择从镜像创建,将这个新数据盘挂在到新ec2下,再用Linux自带的cp命令(加-a参数以便保留文件属性)将大量文件复制到60GB的数据盘。完成后删除按量付费数据盘和100GB镜像。

实测cp命令一开始速度较低(约300KB/s,通过多次执行du命令手工计算),可能是阿里云新购数据盘需要预热过程的原因,1小时后逐渐上升到接近1MB/s,4小时后达到8MB/s。

这次没有来得及尝试lsyncd+rsync的方案,从网上资料看,对处理海量小文件效率比较高。

安装miniconda(根据系统自带python版本选择miniconda2或miniconda3)

yum install bzip2
wget https://repo.anaconda.com/miniconda/Miniconda2-latest-Linux-x86_64.sh
bash Miniconda2-latest-Linux-x86_64.sh
source ~/.bashrc
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/

七、安装tensorflow

conda create --name tensorflow python=3.5.2
source activate tensorflow
pip install tensorflow

从二进制包安装的tensorflow不支持CPU扩展指令集,例如阿里云ec2支持AVX2, FMA,因此如果要用CPU最好编译源代码安装(用GPU的可以忽略),方法见官方安装文档

这里需要注意一下,按官方安装文档安装的bazel是最新版(0.22),可能不支持某些历史版本的tensorflow(1.12),需要下载历史版本bazel)。实际上在安装文档下方有tensorflow和bazel版本对照表,可以查到tensorflow 1.12对应bazel 0.15.9,bazel安装包下载地址在https://github.com/bazelbuild/bazel/releases 。

八、迁移后发现的问题

1、tomcat日志文件catalina.out里没有内容

tomcat6时catalina.out里有webapp用log4j输出的信息,到tomcat7里没有了,catalina.out只有28个字节。原因猜测可能是tomcat6和tomcat7的缺省行为不一样。查看了此webapp下的log4j.properties(在WEB-INF/classes目录下),配置的是只输出到console,在tomcat7的server.xml的context里添加swallowOutput="true"后,localhost_2019-02-20.log里可以看到webapp输出的信息了,但格式不好内容不够紧凑。

但查资料发现swallowOutput这个属性的问题比较多,所以改为在webapp的log4j.properties里指定输出到文件,但文件路径纠结了一会儿:用相对路径发现无法生成日志文件,可能是权限原因(没有深究),所以仿照tomcat7自带的logging.properties文件,使用${catalina.base}/logs前缀:

log4j.rootLogger=INFO, console

log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A1.File=${catalina.base}/logs/v7.log
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}] %m%n

log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.Encoding=GBK
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}] %m%n

2、mysql里部分查询变慢

待解决

IBM x3950 M2服务器安装OpenSuse问题和解决记录

file

服务器配置:Xeon 2.93Ghz x4, 64G, OpenSuse Enterprise 11.0 64bit

1、服务器安装基本过程

开箱,把所有选件(内存、内存、光纤适配器、RAID卡ServeRAID 10k)插进相应的位置,搬上机架并扣好(因为机器很重,该步骤需要至少两个人)。最后把几个硬盘都插进去完事。

2、配置RAID

服务器自带的ServerGuide光盘可以启动系统并配置RAID,但好像只适用于安装windows操作系统。我选择的方式是在服务器开机后,看到<ctrl+h>提示后按Ctrl+H进入RAID卡的BIOS进行配置。配置过程比较简单,选择创建一个Virtual Drive即可,我选择的是把四块硬盘做成RAID5。

3、安装Linux

首先从opensuse网站下载映像,因为内存比较大,所以我选择的是64位企业版,然后刻录成DVD。用这张光盘启动服务器(在服务器启动时按F12可以选择启动顺序,缺省好像也会先以光盘启动),OpenSuse的安装是图形化的很容易,也不需要做太多改动。我只修改了缺省的分区,因为自动生成的分区给/只分配了20G空间,我改为了200G,/home分配了250G左右。修改分区大小时,要先删除一个分区,这个分区原来的空间才能分配给其他分区,这一点稍显麻烦。

安装过程比较长,大约花了40分钟,中途断开了显示器去配置其他服务器,再连回去以后发现机器停在了Suse启动的画面很久。无奈取出光盘强行关机重启,这次顺利进入系统,系统又进行了一些配置工作,安装就算完成了。

再次重启以后发现一个问题,可能是显示器没有被正确识别,桌面的分辨率超出了支持范围,导致无法看到桌面。解决的方法是按Ctrl+Alt+1进入命令行界面,修改/etc/X11/xorg.conf文件里的[Monitor]一节下的PreferredSize值,原来是1280x1024,改为1024x768以后,重启顺利进入gnome桌面。

4、安装所需软件

OpenSuse所带的YAsT能通过网络安装常用软件,不过这台服务器所处环境无法访问外网,所以要使用本地更新。具体方法参考这个链接

IBM x346服务器两个问题和解决

服务器型号IBM x346,使用随机提供的Server安装光盘配置并安装Windows 2003 Server英文标准版。

问题1:安装了5G物理内存,在Win2003 server里只能认出3.36G。

解决方法:在c:\boot.ini里加/PAE参数可以认到4G内存,但Win2003 server standard版最多支持4G内存,要想完全解决需要advanced server。

multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Standard" /fastdetect /NoExecute=OptOut /PAE

问题2:在RAID界面可以看到硬盘为146G,但在Win2003 server里只看到一个48.8G的c盘。

解决方法:在Control Panel->Administrative Tools->Computer Management里选Disk Management,应该可以看到剩余未被划分的空间,创建为新的逻辑分区并格式化即可。

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2006/11/28/575550.html

用Debian遇到的部分问题和解决

1、待机命令

echo mem>/sys/power/state

这之前要确认acpid服务已经启动;

2、打开Firefox的profilemanager

firefox -profilemanager

3、支持speedstep,在/etc/modules里加入speedstep-ich、cpufreq_powersave和cpufreq_userspace这三项,其中第一项是针对PIIIM的笔记本,如果是迅驰用speedstep-centrino;

4、查看pcmcia读卡器的设备名

cat /proc/partions

5、释放空间:

apt-get clean

6、Linux下听ape用SuperMMX的mac-port:http://sourceforge.net/projects/mac-port/

7、从stable转换到testing后,在一个窗口输入过汉字后,alt-tab会失效无法切换到其他窗口,考虑是fcitx的问题,所以决定 换输入法系统。apt-get install scim,scim-tables-zh,scim-gtk2-immodule,然后编辑/etc/X11/Xsession.d/90chinput -start内容如下:

export XMODIFIERS=@im=SCIM
export XIM=xim
export XIM_PROGRAM="scim -d"
export GTK_IM_MODULE=xim
export QT_IM_MODULE=xim
scim -d

scim-tables-zh里并不包括拼音输入法,所以apt-get install scim-pinyin(这个包以前叫scim-chinese),而且我是添加了一个unstable源才找到的。

Update2006-4-21:解决有些程序里不能输入中文的问题,要安装scim-gtk2-immodule这个包,然后把上面的90chinput-start文件改为如下:

export XMODIFIERS="@im=SCIM"
export GTK_IM_MODULE="SCIM"
scim -d

8、手动关闭显示器

xset dpms force off

9、更改gnome的splash:#update-alternatives --config desktop-splash,(来自Debian学习笔记

10、用totem播放其他格式:从这个地址下载win32codecs-essential-20040703.tar.bz2和rp9codecs-20050115.tar.bz2,解开的内容放到/usr/lib/win32(如果不存在建一个)即可。

11、DNS解析很慢可能是ipv6造成的,去掉ipv6的方法:在/etc/modprobe.d/aliases中,把“alias net-pf-10 ipv6”注释掉,然后update-modules,再重启。(这个方法更方便:在firefox地址栏里输入about:config,用 filter找到network.dns.disableIPv6,修改为true。来自Ubuntu快速入门手册

12、如遇到空间不足,可以考虑先清掉apt的cache:apt-get clean;还可以用debfoster工具删除不需要的deb包。

13、文件名转码工具convmv,用于转换windows分区拷文件过来可能出现文件名乱码,例如

convmv -f utf8 -t cp936 --notest *

14、把从cd抓下来的ape文件分为多个:安装cuetools和shntool,然后cuebreakpoints -i cue CDImage.cue|shnsplit -n track CDImage.ape,这样得到的是多个.wav文件,可以给shnsplit加-o ape参数转为ape,但要使用特别的mac版本,在shntool主页有下载。

15、修改grub的背景:修改/boot/grub/menu.lst,加入splashimage (hd0,2)/boot/grub/images/xxx.xpm.gz,图片文件要自己制作或者下载现成的。

16、修改console分辨率,在menu.lst的kernel行最后加入vga=791,表示1024x768的分辨率。好像还可以vga=ask?

17、彩蛋:在gnome里按alt+f2打开运行程序对话框,输入free the fish,会出现一条小鱼(旺达)在屏幕上游动。

18、对时用ntpdate,教育网内时间服务成员列表

19、用wget批量下载,方法1:seq 20 | awk '{print "http://mydomain/file"$1".zip"}' | wget -i -;方法2:for i in seq 1 20;do wget http://domain/$i.txt;done;更简单的:curl http://mydomain/file[1-20].zip -O

20、代理服务器的环境变量:

export http_proxy="myproxy:port"
export ALL_PROXY="myproxy:port"

21、使用usb光驱

mount -t iso9660 -o iocharset=cp936 /dev/scd0 /mnt/usb

22、网卡命名:nameif(链接

23、同步internet时间

ntpdate time.nist.gov

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2005/11/09/272253.html