JoyLau's Blog

JoyLau 的技术学习与思考

说明

@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”) : 后端 =>前端的转换
@DateTimeFormat(pattern = “yyyy-MM-dd’T’HH:mm:ss”) : 前端 => 后端的转换
@JsonDeserialize(using = LocalDateTimeDeserializer.class) : jackson 反序列化
@JsonSerialize(using = LocalDateTimeSerializer.class): jackson 序列化

注意:

  1. 当 @JsonFormat 和 @JsonDeserialize 或者 @JsonSerialize 同时存在时, @JsonFormat 优先级更高

  2. @JsonFormat不仅可以完成后台到前台参数传递的类型转换,还可以实现前台到后台类型转换。

当content-type为application/json时,优先使用@JsonFormat的pattern进行类型转换。而不会使用@DateTimeFormat进行类型转换。

步骤

设置环境变量:

1
2
3
4
5
  env:
- name: GF_SERVER_ROOT_URL
value: "%(protocol)s://%(domain)s:%(http_port)s/grafana"
- name: GF_SERVER_SERVE_FROM_SUB_PATH
value: "true"

此时 NGINX 进行反向代理的配置:

1
2
3
4
5
6
location /grafana/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://10.55.3.160:31120/;
}

步骤

  1. 下载 minio/mc 项目
  2. 分别添加源服务器和目标服务器: ./mc.exe config host add local http://10.55.3.131:9000 "AKIAIOSFODNN7EXAMPLE" " wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
  3. 按桶进行迁移: ./mc.exe mirror local/blacklist new/blacklist

说明

Open VPN 的客户端不做特殊配置无法同时连接多个服务器,会出现异常。提示设备已在使用

解决

进入 openVPN 的安装目录,以管理员的身份执行 addtap.bat 文件即可, 可在网络适配器里看到多出一块虚拟网卡

第一步: 磁盘分区

  1. 使用 fdisk -l 查看本机磁盘分区情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[root@localhost core]# fdisk -l

磁盘 /dev/vda:85.9 GB, 85899345920 字节,167772160 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x000b2efb

设备 Boot Start End Blocks Id System
/dev/vda1 * 2048 2099199 1048576 83 Linux
/dev/vda2 2099200 167772159 82836480 8e Linux LVM

磁盘 /dev/vdb:1610.6 GB, 1610612736000 字节,3145728000 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节


磁盘 /dev/mapper/centos-root:51.3 GB, 51308920832 字节,100212736 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节


磁盘 /dev/mapper/centos-swap:8455 MB, 8455716864 字节,16515072 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节


磁盘 /dev/mapper/centos-home:25.1 GB, 25052577792 字节,48930816 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节

CentOS 默认挂载盘无法超过 2T, 需要挂载超过 2T 的磁盘,需要先对磁盘的分区方式进行转换成 GPT

转换方式:

1
2
3
4
5
6
parted /dev/vdb

mklabel
gtp
quit

可以看到一个 /dev/vdb 的设备没有使用

  1. 执行分区:
  • fdisk /dev/vdb
  • m 显示命令列表
  • n 新增分区
  • p 主分区
  • 1
  • enter
  • enter
  • w 写入并退出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@localhost core]# fdisk /dev/vdb
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。

Device does not contain a recognized partition table
使用磁盘标识符 0xc83c3572 创建新的 DOS 磁盘标签。

命令(输入 m 获取帮助):n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p
分区号 (1-4,默认 1):
起始 扇区 (2048-3145727999,默认为 2048):
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-3145727999,默认为 3145727999):
将使用默认值 3145727999
分区 1 已设置为 Linux 类型,大小设为 1.5 TiB

命令(输入 m 获取帮助):w
The partition table has been altered!

Calling ioctl() to re-read partition table.
正在同步磁盘。

第二步: 格式化磁盘

通知内核重新读取分区信息 partprobe /dev/vdb

先执行 blkid 查看磁盘的格式

如果是 xfs 格式,执行下面的命令

mkfs -t xfs /dev/vdb1

如果是 ext4 的话

mkfs -t ext4 /dev/vdb1

1
2
3
4
5
6
7
8
9
10
[root@localhost core]# mkfs -t xfs /dev/vdb1
meta-data=/dev/vdb1 isize=512 agcount=4, agsize=98303936 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0, sparse=0
data = bsize=4096 blocks=393215744, imaxpct=5
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
log =internal log bsize=4096 blocks=191999, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0

第四步: 创建目录并挂载

1
2
[root@localhost core]# mkdir /data
[root@localhost core]# mount /dev/vdb1 /data

第五步: 永久挂载

vim /etc/fstab

在最后添加如下一行:

1
/dev/vdb1               /data                   xfs     defaults        0 0

保存生效: mount -a

最后: 查看磁盘挂载情况

lsblk -f

1
2
3
4
5
6
7
8
9
10
11
[root@localhost core]# lsblk -f
NAME FSTYPE LABEL UUID MOUNTPOINT
sr0
vda
├─vda1 xfs cf67c6bc-85c1-4859-a9a2-a3af7641605f /boot
└─vda2 LVM2_member b1HmqI-N1Hq-7cyC-kHUK-iz2K-fzCx-f8Rq2T
├─centos-root xfs cf439706-cf84-4396-a2af-df169a13bdc0 /
├─centos-swap swap 700878b0-cf1b-406d-bb8f-db6af815f83a [SWAP]
└─centos-home xfs 8c6b2b1b-48c4-4860-bc96-a5a0101b1c91 /home
vdb
└─vdb1 xfs 654bab72-7006-4341-a0f6-889130cb15e9 /data

扩展现有磁盘 (LVM 格式)

比如在虚拟机情况下,原来给虚拟机分配的磁盘大小是 100G,后来发现不够用了,在虚拟机操作界面将 100G 扩容到了 200G,然后多出来的 100G, 扩容到现有系统的 /home 目录下

按以下操作即可实现

扩展分区

fdisk -l

1
2
3
4
5
6
7
8
9
10
fdisk /dev/sda
n
p
3
回车
回车
t
L
8e
w

加载分区表

partprobe

创建物理卷

pvcreate /dev/sda3

使用 pvdisplay 可查看当前物理卷的相关信息

将物理卷扩容到现有的卷组

vgextend centos /dev/sda3

使用 vgdisplay 可查看卷组的信息

将卷组中空闲空间扩容到 home 分区

lvextend /dev/mapper/centos-home /dev/sda3

使用 lvdisplay 可查看逻辑卷的信息

刷新 home 分区,在线扩容

xfs_growfs /dev/mapper/centos-home

使用 df -khlsblk 查看磁盘挂载情况

扩展现有磁盘 (非 LVM 格式)

在现有的环境中 /data 目录下挂载一块 1T 的存储盘, 非 LVM 格式,现在,新加了一块 2T 的硬盘,想要扩展到 /data 目录下,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@server-62 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 1024M 0 rom
vda 252:0 0 50G 0 disk
├─vda1 252:1 0 1G 0 part /boot
└─vda2 252:2 0 49G 0 part
├─centos-root 253:0 0 45.1G 0 lvm /
└─centos-swap 253:1 0 3.9G 0 lvm [SWAP]
vdb 252:16 0 64M 0 disk
└─vdb1 252:17 0 63M 0 part
vdc 252:32 0 1000G 0 disk
└─vdc1 252:33 0 1000G 0 part /data
vdd 252:48 0 2T 0 disk

简单说下处理方式,还是转为 LVM 格式,将 2 块硬盘都加入逻辑卷,然后将原来数据花园

备份现有 /data 目录的数据,注意原先目录的权限, 比如
cp -a /data/ /home/backup/

卸载原先磁盘,并删除分区

1
2
3
4
umout /dev/vdc1
fdisk /dev/vdc
d
w

编辑 /etc/fstab 注释掉目录挂载

创建物理卷

1
2
pvcreate /dev/vdd
pvcreate /dev/vdc

创建卷组, 并命名为 vg_data

1
vgcreate vg_data /dev/vdd

将物理卷 /dev/vdc 加入卷组

1
vgextend vg_data /dev/vdc

查看信息

1
2
3
pvdisplay
vgdisplay
vgs

创建逻辑卷, 并命名为 lv_data, 100% 使用

1
lvcreate -l 100%VG -n lv_data vg_data

查看信息

1
lvdisplay

格式化

1
mkfs -t xfs /dev/vg_data/lv_data

最后,创建目录挂载

1
2
3
4
5
vim /etc/fstab
/dev/mapper/vg_data-lv_data /data xfs defaults 0 0

mount -a
lsblk

如果 mount -a 发现挂载不上, 可执行 systemctl daemon-reload 或重启解决

扩展逻辑卷

参考文档

扩容分区和文件系统

参考文档

转换MBR分区为GPT分区

参考文档

背景

使用 docker run -p 或者 docker compose 启动暴露的端口的容器, 会直接穿透防火墙, 不受系统防火墙的 firewalld 的管控

原因

docker 容器会在启动的时候向 iptables 添加转发的规则
而 firewalld 也是通过操作 iptables 来实现的防火墙的功能

1
2
3
4
5
6
7
[root@centOS7 es-test]# iptables -L DOCKER
Chain DOCKER (3 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.18.0.2 tcp dpt:xic
ACCEPT tcp -- anywhere 172.20.0.2 tcp dpt:vrace
ACCEPT tcp -- anywhere 172.20.0.2 tcp dpt:wap-wsp

可以看到是 anywhere

解决方式

第一种 禁用 docker 操作 iptables

在 /etc/docker/daemon.json 配置禁用 iptables:

1
2
{"iptables": false}

之后重启 docker 服务, 可以看到 docker 不会自动往 iptables 里添加规则了

这种方式有个弊端: 就是容器之间无法互相访问, 而且容器里的程序也无法访问外部网络

解决方式:
在防火墙里开始 net 转发:

配置 /etc/firewalld/zones/public.xml

1
2
3
4
5
6
7
<zone>
<short>Public</short>
<description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
<service name="ssh"/>
<service name="dhcpv6-client"/>
<masquerade/>
</zone>

或者使用下面的方式添加 iptables 规则

1
firewall-cmd --zone=public --add-masquerade

之后使用 firewall-cmd –restart 或者 systemctl restart firewalld 使配置生效即可

但是这样做还有个问题, 就是所有访问容器的程序对于容器来说 IP 的变成的网关的 IP
这样的问题对于一些需要特定限制一些 IP 地址来源的应用和使用 IP 地址来作区分的应用来说就有很大问题, 比如注册中心
目前没有找到什么方式解决这个问题

第二种 容器直接指定主机网络

docker run 的时候不显式暴露端口 -p 什么的, 使用 –net host 的形式直接将容器的端口绑定到宿主机上

docker compose 运行的时候使用:

1
2
3
4
version:  '3.2'
services:
abc:
network_mode: "host"

Maven 私服 Nexus3 因磁盘爆满而导致的无法启动的问题

背景

同事在 Nexus3 私服的宿主机上部署了一个服务, 结果因为网络问题导致服务打印大量的日志信息, 将宿主机的磁盘撑爆了,经过一系列排除, 删除了大日志文件
重启 Nexus3 容器,发现无法启动了, 报错如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
com.orientechnologies.orient.core.exception.OStorageException: Cannot open local storage '/nexus-data/db/config' with mode=rw
DB name="config"
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.open(OAbstractPaginatedStorage.java:323)
at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.open(ODatabaseDocumentTx.java:259)
at org.sonatype.nexus.orient.DatabaseManagerSupport.connect(DatabaseManagerSupport.java:178)
at org.sonatype.nexus.orient.DatabaseManagerSupport.createInstance(DatabaseManagerSupport.java:312)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
at org.sonatype.nexus.orient.DatabaseManagerSupport.instance(DatabaseManagerSupport.java:289)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:290)
at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175)
Caused by: java.lang.NullPointerException: null
at com.orientechnologies.orient.core.storage.impl.local.paginated.wal.ODiskWriteAheadLog.cutTill(ODiskWriteAheadLog.java:919)
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.makeFullCheckpoint(OAbstractPaginatedStorage.java:3706)
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.recoverIfNeeded(OAbstractPaginatedStorage.java:3937)
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.open(OAbstractPaginatedStorage.java:288)
... 14 common frames omitted

解决

  1. 进入宿主机存放 Nexus3 数据目录下

先对该目录分配用户和用户组:

1
chown -R 200 /home/transport/maven-repos-data

分别删除 db/config 目录下和 db/component 目录下的所有的 .wal 文件

1
2
3
4
5
6
7
cd /home/transport/maven-repos-data/db/config

rm -rf *.wal

cd /home/transport/maven-repos-data/db/component

rm -rf *.wal
  1. 找到容器中的 nexus-orient-console.jar jar 包
1
find / -name nexus-orient-console.jar

进入上述目录, 我这里是: /var/lib/docker/overlay2/3b9c8d7685a03dcbb9ee69c33cd8fd9b487d980731596da27e7639854c0bb6e1/diff/opt/sonatype/nexus/lib/support

执行 java -jar nexus-orient-console.jar , 来连接数据库

1
connect plocal:/home/transport/maven-repos-data/db/component admin admin

执行下列命令进行修复, 修复完成并退出:

1
2
3
4
5
6
7
rebuild index *

repair database --fix-links

disconnect

exit
  1. 数据目录重新授权
1
chmod 777 -R /home/transport/maven-repos-data/db
  1. 重启容器

Maven 私服 Nexus3 忘记 admin 用户密码的解决

如上述步骤描述的, 运行 nexus-orient-console.jar

进入 security 数据库:

1
connect plocal:/home/transport/maven-repos-data/db/security admin admin

将 admin 用户密码重置为 admin123

1
update user SET password="$shiro1$SHA-512$1024$NE+wqQq/TmjZMvfI7ENh/g==$V4yPw8T64UQ6GfJfxYq2hLsVrBY8D1v+bktfOxGdt4b/9BthpWPNUy/CBk6V9iA0nHpzYzJFWO8v/tZFtES8CA==" UPSERT WHERE id="admin"

数据目录重新授权

1
chmod 777 -R /home/transport/maven-repos-data/db
0%