【记一次vsan数据救援的经历】转

发布时间 2023-09-27 18:09:11作者: 时光2020

版权声明:本文为CSDN博主「挪威卒」的原创文章。
原文链接:https://blog.csdn.net/egman/article/details/132803491

 

一个无心的进入运维模式,使30TB数据变成不可访问!记一次vsan数据救援的经历

    1. 背景
    2. 事情起因:
                以下是他自述详细操作步骤:
    事前盘点:
    救援前分析与安排
    第一阶段工作:
    第二阶段工作:
    针对不可访问对象分的救援阶段
                阶段一 :学习vsan 知识,并检查当前情况
                阶段二: 联系vmware售后支持
                阶段三: 在技术论坛上寻找高人指高阶段
                阶段四: 自己尝试修复阶段
                后记

1. 背景

数据中心拓补图

 
业主有三台相同型配置的服务器,组合成了一个最小节点数(>=3)要求的vsan集群.
vcenter 安装在1号机的本地硬盘上。2、3号主机上也复制了一份备用(旧数据)
整个vmware产品是7.0.3. vcetner 是vcsa安装方式。

数据中心原规划是做为研发实验环境的目标建立的,为缓解客户一次性投入费用过大,计划第三期才提交数据备份方案,系统已试用了一年,还在建设中, 当时正在进行第二期的建设,给业主内网建设internal各项子系统, AD、DNS系统建立起来后,计划将各个已建设的子系统加入它们;
业主已经迁移了几个重要的业务系统进来,但备份系统还没有实施(这是个大问题);
我们团队第一次使用vsan产品,团队vsan的知识经验少,运行一年中又没有进入vsan运维。
2. 事情起因:

周六,同事原计划想将vcenter 由初始安装时使用https://ip方式,更改为https://dnsname 方式。
改了名字后,发现vcenter等服务无法启动,只有https://ip:5480方式还能用。
努力做了多次,无果,想改回来,但无法改(事后证明可以改回来,但服务仍无法启动)
他没多想,直接又在1号机上布署了新的vcenter,想将3台主机重新加入该新的vcenter,而重新将主机加入vcenter,
需要使主机进入维护模式。
而本来在正常vcenter里,操作使主机正常的维护模式,vsan默认的选项时”确保数据迁移安全“,但偏偏他是通过登录1号主机后,操作主机进入维护模式,而该操作时,vsan默认的选项是”不迁移数据“。
另外HA也没有关闭。
以下是他自述详细操作步骤:

    上周四下午3点15分:
    1、在vCenter管理界面修改vCenter主机名、DNS,配置后出现网络更新失败
    2、配置后管理界面与vCenter Web client也无法启动
    3、重启vCenter虚拟机,还是无法进入vCenter管理与vCenter Web client,进入vCenter虚拟机,发现vsphere服务没有启动,重置证书与还原主机名与DNS,vCenter管理界面可以登录,vCenter Web client还是无法进入
    4、计划周六重新部署vCenter,并将vSAN迁移至新vCenter中

    周六下午1点:
    1、配置vsan3号主机进入维护模式“无数据迁移”
    2、发现2号机有虚拟机在启动,把2号机启动的虚拟机关机,配置vsan2号主机进入维护模式“无数据迁移”
    3、vsan集群有虚拟机自动启动,vsan1号主机无法配置维护模式,把vsan 2号主机恢复正常模式,把3号主机恢复正常模式
    4、把1号机启动的虚拟机关机,再把3号主机配置维护模式;把2号主机配置维护模式;配置1号主机配置维护模式
    5、发现vsan集群中虚拟机异常,把所有主机恢复正常模式
    6、打电话给xx,等待xx到达,了解具体情况尝试配置故障vCenter

    周六晚上:
    1、与xx进行vCenter修复,到周日下午3点,vCenter无法恢复

    周日下午3点:
    1、启动备用vCenter,重连vsan主机
    2、等待vCenter同步还原工作
    3、手动点击vsan对象立即还原,等待还原
    4、欲清除不可用对象,无法清除,遂保持原样,等待还原工作

 

    损失情况
    业主几乎所有重要的业务系统均不可访问,损失惨重。

事前盘点:

这件事就是典型的缺乏安全生产而产生一连串低级错误、失误造成的人祸:
事前对vcenter、vsan等知识不主动学习
公司在项目还没采购备份系统前,对项目实施过程安全教育不够,检查力度不足。
项目部在实施过程中,未因地制宜,利用现有条件进行数据备份和快照操作。
具体员工安全素质不足,在操作前未进行充分论证方案可行性
。。。
但问题已发生,所以各事情其实并行在处理, 但此文重点讲解后来数据是如何被恢复的(顺带讲一下vcenter的问题)。
救援前分析与安排

考虑到周一前业主的所有业务要运转正常,所以处理内容按时间点分两阶段,前面是尝试将vcenter恢复启来,后面才是不得已下,一边给业主重新搭建新的业务系统,人肉从外部找回数据并放入新的业务系统中。一边想办法恢复不可访问的数据。
第一阶段工作:

 
容量情况
恢复vcenter服务,待续
简要结论:
a) 想vcenter 通过把主机名从localhost改名为xx.yy后,再重新更新证书的方案是不能成功的 (vcsa服务启动不了);
b) 再改回来,也无法再让vcsa服务启动;
c) 必须重新安装一个新的vcenter,再安装时设置新配置信息
由于在2,3号机中均有旧的克隆备份,所以最终启用了2号机的vcenter备份vm机

 

第二阶段工作:
核心目标与工作: 将26个不可访问对象中的vmdk数据恢复出来

 26个不可访问的对象
同步显示有约5.8G数据需要同步,但一直没有任何进展(忘计截图了)
其中两个vm 虚机: SVN与 Edisk 关键业务系统均在不可访问对象中,所以明确了最小目标,将这两个数据恢复回来。
针对不可访问对象分的救援阶段

阶段一 :学习vsan 知识,并检查当前情况
在vmware官网知识库上相同情况的文章:
vSAN—维护—主机同时重启/集群完全关闭—数据不可用风险(60424) https://kb.vmware.com/s/article/60424?lang=zh_cn

看完这篇文章内容提到,有个事前预防的办法(下面的文章),事后解决方案,只给的提示是联系vmware工程师解决 ?
使用内置工具同时重启vSAN集群中的所有主机(70650)   https://kb.vmware.com/s/article/70650
按这个文章操作,到第14步,重启主机,提示执行操时
经过快速学习后知道,vsphere6.7之后,要在vcenter中选中vsan集群后,右键选择 ”关闭vsan集群“ 的命令才是正确的进入维护模式  

https://docs.vmware.com/cn/VMware-vSphere/8.0/vsan-monitoring-troubleshooting/GUID-0D24C5BA-0248-4E3A-ADA3-33FF551C78F5.html

使用 vsan 的 rvc命令, 可以查询到:

/172.31.24.24/xx数据中心/computers/VSAN集群> vsan.disks_stats ~/computers/VSAN集群
+----------------------+-------------+----------+------+------------+---------+----------+----------+----------+----------+----------+---------+----------+----------+
|                      |             |          | Num  | Capacity   |         |          | Physical | Physical | Physical | Logical  | Logical | Logical  | Status   |
| DisplayName          | Host        | DiskTier | Comp | Total      | Used    | Reserved | Capacity | Used     | Reserved | Capacity | Used    | Reserved | Health   |
+----------------------+-------------+----------+------+------------+---------+----------+----------+----------+----------+----------+---------+----------+----------+
| naa.50015ebe0260021f | 172.31.1.11 | Cache    | 0    | 447.13 GB  | 0.00 %  | 0.00 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b43f63 | 172.31.1.11 | Capacity | 36   | 5589.02 GB | 32.37 % | 0.20 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b43f2b | 172.31.1.11 | Capacity | 43   | 5589.02 GB | 27.66 % | 0.27 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b44767 | 172.31.1.11 | Capacity | 31   | 5589.02 GB | 45.35 % | 0.13 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
+----------------------+-------------+----------+------+------------+---------+----------+----------+----------+----------+----------+---------+----------+----------+
| naa.50015ebe0260021e | 172.31.1.11 | Cache    | 0    | 447.13 GB  | 0.00 %  | 0.00 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b44957 | 172.31.1.11 | Capacity | 35   | 5589.02 GB | 30.02 % | 0.13 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b447cb | 172.31.1.11 | Capacity | 32   | 5589.02 GB | 38.30 % | 0.13 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b446cb | 172.31.1.11 | Capacity | 44   | 5589.02 GB | 31.08 % | 0.13 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
+----------------------+-------------+----------+------+------------+---------+----------+----------+----------+----------+----------+---------+----------+----------+
| naa.50015ebe02600e1e | 172.31.1.21 | Cache    | 0    | 447.13 GB  | 0.00 %  | 0.00 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b43fb3 | 172.31.1.21 | Capacity | 46   | 5589.02 GB | 26.20 % | 0.20 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b442d3 | 172.31.1.21 | Capacity | 46   | 5589.02 GB | 27.95 % | 0.13 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b43f6f | 172.31.1.21 | Capacity | 46   | 5589.02 GB | 22.14 % | 0.20 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
+----------------------+-------------+----------+------+------------+---------+----------+----------+----------+----------+----------+---------+----------+----------+
| naa.50015ebe02600e1f | 172.31.1.21 | Cache    | 0    | 447.13 GB  | 0.00 %  | 0.00 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b44047 | 172.31.1.21 | Capacity | 46   | 5589.02 GB | 45.95 % | 0.13 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b4470b | 172.31.1.21 | Capacity | 50   | 5589.02 GB | 25.03 % | 0.13 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b44387 | 172.31.1.21 | Capacity | 46   | 5589.02 GB | 30.78 % | 0.13 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
+----------------------+-------------+----------+------+------------+---------+----------+----------+----------+----------+----------+---------+----------+----------+
| naa.50015ebe0771d21e | 172.31.1.31 | Cache    | 0    | 447.13 GB  | 0.00 %  | 0.00 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b44c3b | 172.31.1.31 | Capacity | 45   | 5589.02 GB | 32.23 % | 0.13 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b43fbf | 172.31.1.31 | Capacity | 44   | 5589.02 GB | 26.99 % | 0.20 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b4499f | 172.31.1.31 | Capacity | 46   | 5589.02 GB | 27.60 % | 0.13 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
+----------------------+-------------+----------+------+------------+---------+----------+----------+----------+----------+----------+---------+----------+----------+
| naa.50015ebe0771d21f | 172.31.1.31 | Cache    | 0    | 447.13 GB  | 0.00 %  | 0.00 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b43f87 | 172.31.1.31 | Capacity | 45   | 5589.02 GB | 28.13 % | 0.20 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b44bf3 | 172.31.1.31 | Capacity | 46   | 5589.02 GB | 27.62 % | 0.20 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
| naa.5000c500e1b44257 | 172.31.1.31 | Capacity | 46   | 5589.02 GB | 25.41 % | 0.27 %   | N/A      | N/A      | N/A      | N/A      | N/A     | N/A      | OK (v15) |
+----------------------+-------------+----------+------+------------+---------+----------+----------+----------+----------+----------+---------+----------+----------+

 

/172.31.24.24/xx数据中心/computers/VSAN集群> vsan.check_state ~/computers/VSAN集群
2023-08-27 13:45:04 +0000: Step 1: Check for inaccessible vSAN objects
Detected 26 objects to be inaccessible
Detected d2928164-b62c-650b-0cbc-5853c0642b44 on 172.31.1.31 to be inaccessible
Detected 6fe89f63-967b-470c-1f4a-5853c06429fc on 172.31.1.31 to be inaccessible
Detected 95f19f63-0a88-5810-43f1-5853c0642b44 on 172.31.1.31 to be inaccessible
Detected d27fa264-ac74-5910-14a4-5853c06429fc on 172.31.1.31 to be inaccessible
Detected ac06db63-4e6d-e030-a369-5853c0642c12 on 172.31.1.31 to be inaccessible
Detected d07aa264-8a53-e15e-a1bb-5853c0642b44 on 172.31.1.31 to be inaccessible
Detected 4465c364-72f2-8e6f-5c5d-5853c0642b44 on 172.31.1.31 to be inaccessible
Detected 624cb563-085f-dd74-a36f-5853c0642b44 on 172.31.1.31 to be inaccessible
Detected d07aa264-3c14-8f77-7b9c-5853c0642b44 on 172.31.1.31 to be inaccessible
Detected 4c48ae64-28bf-dd89-54f6-5853c0642c12 on 172.31.1.31 to be inaccessible
Detected 2680dd64-52c4-668f-c251-5853c06429fc on 172.31.1.31 to be inaccessible
Detected 28a48164-b886-1d90-8d13-5853c0642c12 on 172.31.1.31 to be inaccessible
Detected e967db63-1c72-6493-cc6a-5853c0642b44 on 172.31.1.31 to be inaccessible
Detected 7b239064-925c-6c93-7e3d-5853c0642b44 on 172.31.1.31 to be inaccessible
Detected 0dd5b363-82e7-4da4-e157-5853c0642b44 on 172.31.1.31 to be inaccessible
Detected 8ccd8264-c652-4fa9-142b-5853c06429fc on 172.31.1.31 to be inaccessible
Detected 4c27a063-c01c-45ac-960a-5853c0642c12 on 172.31.1.31 to be inaccessible
Detected be53ae64-c0d5-c5b0-a9b7-5853c06429fc on 172.31.1.31 to be inaccessible
Detected 2648ae64-a81e-72b6-b910-5853c0642c12 on 172.31.1.31 to be inaccessible
Detected abb75d64-82d8-adb9-daa3-5853c06429fc on 172.31.1.31 to be inaccessible
Detected 62249763-b83f-efb9-95d7-5853c06429fc on 172.31.1.31 to be inaccessible
Detected 39fab463-5e2e-a0c2-2278-5853c0642c12 on 172.31.1.31 to be inaccessible
Detected 29a48164-5461-c8d1-a7ce-5853c0642c12 on 172.31.1.31 to be inaccessible
Detected 29a48164-0c43-6dd7-43b8-5853c0642c12 on 172.31.1.31 to be inaccessible
Detected 4bf4b564-1063-09e6-bb85-5853c0642b44 on 172.31.1.31 to be inaccessible
Detected d27fa264-6ac8-03f9-27f1-5853c06429fc on 172.31.1.31 to be inaccessible

2023-08-27 13:45:04 +0000: Step 2: Check for invalid/inaccessible VMs
Detected VM 'Windows10_x64_test' as being 'inaccessible'
Detected VM 'CentOS7_x64_test' as being 'inaccessible'
Detected VM 'Windows_2019_NET_OnlineServer' as being 'inaccessible'
Detected VM 'Windows_2019_x64_SVN' as being 'inaccessible'
Detected VM 'W2022_X64_Core_Partner_XY_ADTRee' as being 'orphaned'
Detected VM 'W2022_X64_Template3' as being 'inaccessible'
Detected VM 'W2022_X64_XY_DHCP' as being 'inaccessible'
Detected VM 'CentOS7_x64_EDisk' as being 'inaccessible'
Detected VM 'W2022_X64_Core_DC_XY_ADTRee' as being 'inaccessible'
Detected VM 'W2022_X64_Core_OA_XY_ADTRee' as being 'inaccessible'
Detected VM 'W2022_X64_ADS2022_DB' as being 'inaccessible'
Detected VM 'CentoS7 X64 For_VPN' as being 'inaccessible'
Detected VM 'CentOS7_X86_For_Freeradius' as being 'inaccessible'
Detected VM 'CentOS7_x64_EDisk (1)' as being 'inaccessible'

 重点是这个:

vsan.object_info   ~/computers/VSAN集群 d2928164-b62c-650b-0cbc-5853c0642b44
DOM Object: d2928164-b62c-650b-0cbc-5853c0642b44 (v15, owner: 172.31.1.31, proxy owner: None, policy: stripeWidth = 1, cacheReservation = 0, proportionalCapacity = 0, hostFailuresToTolerate = 1, forceProvisioning = 0, spbmProfileId = aa6d5a82-1c88-45da-85d3-3d74b91a5bad, spbmProfileGenerationNumber = 0, CSN = 898, SCSN = 897, spbmProfileName = vSAN Default Storage Policy)
  RAID_1
    RAID_D
      Component: d2928164-fc88-710c-24ad-5853c0642b44 (state: ABSENT (6), csn: STALE (888!=898), host: 172.31.1.11, capacity: naa.5000c500e1b43f2b, cache: naa.50015ebe0260021f,
                                                       dataToSync: 0.02 GB, votes: 1, usage: 15.3 GB, proxy component: false)
      Component: c08de964-1213-e344-e681-5853c0642b44 (state: ACTIVE (5), host: 172.31.1.21, capacity: naa.5000c500e1b442d3, cache: naa.50015ebe02600e1e,
                                                       votes: 1, usage: 0.0 GB, proxy component: false)
    Component: d2928164-12f7-740c-312b-5853c0642b44 (state: ABSENT (6), csn: STALE (891!=898), host: 172.31.1.31, capacity: naa.5000c500e1b43fbf, cache: naa.50015ebe0771d21e,
                                                     dataToSync: 100.00 GB, votes: 1, usage: 15.3 GB, proxy component: false)
  Witness: d2928164-2272-770c-15af-5853c0642b44 (state: ACTIVE (5), host: 172.31.1.21, capacity: naa.5000c500e1b44387, cache: naa.50015ebe02600e1f,
                                                 votes: 1, usage: 0.0 GB, proxy component: false)
  Extended attributes:
    Address space: 107374182400B (100.00 GB)
    Object class: vdisk
    Object path: /vmfs/volumes/vsan:528f620b6bdf15ac-0175538fa91d16fe/d1928164-a4da-3dbe-47c7-5853c0642b44/W2022_X64_DC_XY_DNS1.vmdk
    Object capabilities: NONE

 从数据报告上可以看出来, 这个vsan不可访问对象类似一个磁盘阵列,且阵列为镜像(raid1)磁盘+见证元数据构成,只是三个对象的CSN(版本顺序标识)都不同,且数据盘是”缺失“状态,所以应该是这个问题,即没有按操作规范操作,使得 磁盘组态进入了脑裂状态,所以vsan系统无法自动解决这个冲突,即卡住了。
我猜想,数据并没有丢失,只需要使用某个”高级指令“,指定见证与某个数据镜像强制组合,即可恢复它。但找遍网上,和rvc手册, esxi的命令手册,未发现相关处理的案例,自己第一次接触(就只有两天的知识)不敢冒然处理。
阶段二: 联系vmware售后支持

因为vsphere的仍在售后服务期中,周二通过 联想vmware售后,并顺利升级到vmware三线级别的服务。本想着顺利得到解决,但花费了两天,我凭直觉,感受到工程师更多的只是在调取系统的各种日志和操作回传回去,我一再多次的提出我的诉求是,是否能帮我从”被锁定“的对象修复或直接提取出我需要的vmdk数据,但对方表示,他们也没有特殊内部命令,一直反复再跟我对当时操作的细节后,于周四下午,给我发来邮件,告诉我处理结果是:

 我马上给发去邮件,将我心中的疑问提出来,希望他们给予回答。

很遗憾,之后再也没有收到回复邮件

阶段三: 在技术论坛上寻找高人指高阶段

无可奈何下,只得在多个技术论坛上重复发贴,悬赏寻求帮助,幸运的是,晚上有个网友答应帮我看一下。
在简单询问了事情经过后,给其远程ssh的方式,使用了以下指令:
先在vcenter 172.31.24.24 主机上执行rvc命令 vsan.check_state -r 1 取得不可访问对象所在的主机
然后在指示的主机下,执行以下命令
在vsish -e set /vmkModule/vsan/dom/ownerAbdicate uuid(不可访问对象)后,很快出现了同步的现象。
原先26个不可访问对象,变为12个,又继续检查和研究对象的情况, 再次尝试,又变成了还有8个不可访问对象,如此边研究边处理,最终变成了只有1个不可访问对象,即Edisk虚机所在的对象。

Edisk由业主员工所建,划了有足足30T,分了两个vmdk磁盘,系统一个500GB,数据盘30T.
但一直反复尝试,直到凌晨4点,仍始终不见其同步, 分析是否涉及的内部组件过大了(330个组件),最终放弃,让我再找办法再试。
再次电话联系 vmware工程师,告知我所做的努力,并再提出我的诉求,竟然得到的回答是,让我再写一份报告给他们,无奈,只能再写邮件。

 写完后已是周五,联想工程师说,vmware工程师周末是不工作的,让我等到周一上班时再回复我。
到了周六一早,我继续在网上发布悬赏, 另一个网友也答应帮我看一下,他的思路是 ,让我把HA,vCenter,所有vm机关闭情况下,重新再让每台主机依次进入维护模式(vsan模式选择 确保数据安全),再退出维护模式。
我按其提示,做了第一次,没有反应, 再重做了一次,仍然没反应,并结合第一位网友给的方案,也没有任何效果。
阶段四: 自己尝试修复阶段

时间到了周六中午时分,根据这些天得到的信息,突然冒出一个想法:
是否可以案件重演,根据 vsan.check_state -r 1 显示当前不可访问对象所在的主机情况,按顺序 模拟”正确“的进入维护模式,再回到正常模式。
所以根据每次操作显示的顺序,分别让3,1,2主机进入维护模式,再退出正常模式后,突然发现 数据同步出现了很多数据对象,觉得有戏。
约半小时后,所有不可访问对象均消失。
至此,经事后再次确认,所有数据均已恢复。

 后记

周一上班后,联想售后工程师来电,再次又问了一些问题,我提出,目前所有数据已恢复,但没有他们的努力,我想知道为什么。 他反复暗示我,网友提供的”土办法“是有高度风险的,甚至会使用非法泄露的内部命令。
我不解的请他给我指出,我们上述的操作,哪一些是非法的指令,他答复,没有,都是公开的指令,所以我再次问他,为什么我能直觉判断他们没有努力,是因为,他们根本就没有任何尝试去修复(给了他们远程访问),且知识库60424文章给出的解决方案就是找他们,最后,他再次跟我说,那这样,你再写一份事情的经过发送于他们的邮箱做报告吧,我只能无奈的拒绝。
至今,vmware在给出我不可修复的邮件后,对我二次(三次)的询问和报告,均未给我做出任何书面回复(只有上面提到的电话单向沟通)。

————————————————
版权声明:本文为CSDN博主「挪威卒」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/egman/article/details/132803491