【Kubernetes】第十七篇 - ECS 服务停机和环境修复
一,前言
上一篇,介绍了 Secret 镜像的使用;
三台服务每天大概 15 块钱的支出,用一个月也是不少钱;
闲时可以停掉,这样每天只有 4 块钱支出,剩下一大笔;
ECS 服务停机后公网 IP 会变化,所以使用到公网 IP 的地方都需要重新配置,恢复环境;
本篇,介绍 ECS 停机后重启的环境修复;
备注:只涉及到目前未知的配置,后续章节可能会新增其他配置项,全部完成之后再补充一篇熊进行说明;
二,ci-service 服务器重启问题
ci-service 服务器停机后重启:
1,导致公网 IP 变化:39.105.212.14 -> 47.94.92.122;
2,服务器重启后:docker 镜像仓库无法访问;
三,环境修复
1,启动 docker 私有镜像仓库
[root@iZ2ze7rkgit9zoa18pxu73Z ~]# cd /usr/local/nexus-3.29.0-02/bin/
[root@iZ2ze7rkgit9zoa18pxu73Z bin]# ./nexus start
WARNING: ************************************************************
WARNING: Detected execution as "root" user. This is NOT recommended!
WARNING: ************************************************************
Starting nexus
http://47.94.92.122:8081/ 可以正常访问私有镜像仓库,登录后查看镜像正常
2,更新公网 ip
ci-service 服务器公网 IP 变化:39.105.212.14 -> 47.94.92.122;
需要更新所有使用私有库镜像的 yaml 配置文件:
1,ci-service 的 jenkins 构建脚本更新,推送镜像到私有仓库部分
修改前脚本
// 更新前
#!/bin/sh -l
npm install --registry=https://registry.npm.taobao.org
npm run build
time=$(date "+%Y%m%d%H%M%s")
docker build -t 39.105.212.14:8082/vue-project:$time .
docker login -u $DOCKER_LOGIN_USERNAME -p $DOCKER_LOGIN_PASSWORD 39.105.212.14:8082
docker push 39.105.212.14:8082/vue-project:$time
修改前,构建失败

修改后脚本
// 更新后
#!/bin/sh -l
npm install --registry=https://registry.npm.taobao.org
npm run build
time=$(date "+%Y%m%d%H%M%s")
docker build -t 47.94.92.122:8082/vue-project:$time .
docker login -u $DOCKER_LOGIN_USERNAME -p $DOCKER_LOGIN_PASSWORD 47.94.92.122:8082
docker push 47.94.92.122:8082/vue-project:$time
修改后,构建成功,配置修改为正确


2,docker 配置更新,更新私有库注册列表
// 解决 http 问题
[root@iZ2ze7rkgit9zoa18pxu73Z ~]# vi /etc/docker/daemon.json // 添加不安全的仓库地址:insecure-registries
{"insecure-registries":["47.94.92.122:8082"],"registry-mirrors": ["https://fwvjnv59.mirror.aliyuncs.com"]
}// 重启 docker
[root@iZ2ze7rkgit9zoa18pxu73Z bin]# systemctl restart docker
后面的贴过来,不测试了:
// 测试镜像推送
[root@iZ2ze7rkgit9zoa18pxu73Z ~]# docker push 39.105.212.14:8082/vue-project:2021123011191640834385
The push refers to repository [39.105.212.14:8082/vue-project]
530879695cfc: Preparing
b0a31e56a1ef: Preparing
332fa54c5886: Preparing
6ba094226eea: Preparing
6270adb5794c: Preparing
unauthorized: access to the requested resource is not authorized// 解决授权问题:登录
[root@iZ2ze7rkgit9zoa18pxu73Z ~]# docker login 39.105.212.14:8082
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-storeLogin Succeeded// 再次推送镜像,成功
[root@iZ2ze7rkgit9zoa18pxu73Z ~]# docker push 39.105.212.14:8082/vue-project:2021123011191640834385
The push refers to repository [39.105.212.14:8082/vue-project]
530879695cfc: Pushed
b0a31e56a1ef: Pushed
332fa54c5886: Pushed
6ba094226eea: Pushing 15.42MB/54.05MB
6270adb5794c: Pushing 14.13MB/55.28MB
3,更新已生成的 Sercet 中的 docker-server
涉及“私有镜像库认证”使用的 Sercet :
- 命令行创建的 Sercet : registry-auth
- 通过文件创建的 Sercet : registry-auth-file.yaml
1)命令行创建的Sercet : registry-auth
// 原始 Sercet 的创建命令
[root@k8s-master deployment]# kubectl create secret docker-registry registry-auth \--docker-username=admin \--docker-password=****** \--docker-email=admin@example.org \--docker-server=39.105.212.14:8082
secret/registry-auth created// 查询、删除、重新创建
[root@k8s-master ~]# kubectl get secret
NAME TYPE DATA AGE
default-token-q4qxd kubernetes.io/service-account-token 3 12d
registry-auth kubernetes.io/dockerconfigjson 1 4d8h
registry-auth-file kubernetes.io/dockerconfigjson 1 4d8h
secret-opaque Opaque 2 4d8h
secret-opaque-flie Opaque 2 4d8h// 删除
[root@k8s-master ~]# kubectl delete secret registry-auth
secret "registry-auth" deleted]// 重新创建
[root@k8s-master ~]# kubectl create secret docker-registry registry-auth \--docker-username=admin \--docker-password=****** \--docker-email=admin@example.org \--docker-server=47.94.92.122:8082
secret/registry-auth created
2)registry-auth-file.yaml
// 原始 Sercet 的创建
vi registry-auth-file.yamlapiVersion: v1
kind: Secret
metadata:name: registry-auth-file
data:.dockerconfigjson: eyJhdXRocyI6eyIzOS4xMDUuMjEyLjE0OjgwODIiOnsidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoiV3pAMTk4ODA4MTgiLCJlbWFpbCI6ImFkbWluQGV4YW1wbGUub3JnIiwiYXV0aCI6IllXUnRhVzQ2VjNwQU1UazRPREE0TVRnPSJ9fX0=
type: kubernetes.io/dockerconfigjson
查看 registry-auth,使用 .dockerconfigjson 更新:
// 读取
[root@k8s-master deployment]# kubectl get secret registry-auth -o yaml
apiVersion: v1
data:.dockerconfigjson: eyJhdXRocyI6eyI0Ny45NC45Mi4xMjI6ODA4MiI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJXekAxOTg4MDgxOCIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5vcmciLCJhdXRoIjoiWVdSdGFXNDZWM3BBTVRrNE9EQTRNVGc9In19fQ==
kind: Secret
metadata:creationTimestamp: "2022-01-03T14:33:48Z"managedFields:- apiVersion: v1fieldsType: FieldsV1fieldsV1:f:data:.: {}f:.dockerconfigjson: {}f:type: {}manager: kubectl-createoperation: Updatetime: "2022-01-03T14:33:48Z"name: registry-authnamespace: defaultresourceVersion: "1594980"uid: 06e43c6e-7e40-4d42-ad5a-427fd0698747
type: kubernetes.io/dockerconfigjson// 解码验证
[root@k8s-master deployment]# echo eyJhdXRocyI6eyI0Ny45NC45Mi4xMjI6ODA4MiI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJXekAxOTg4MDgxOCIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5vcmciLCJhdXRoIjoiWVdSdGFXNDZWM3BBTVRrNE9EQTRNVGc9In19fQ== | base64 -d
{"auths":{"47.94.92.122:8082":{"username":"admin","password":"******","email":"admin@example.org","auth":"YWRtaW46V3pAMTk4ODA4MTg="}}}// 修改
[root@k8s-master deployment]# vi registry-auth-file.yaml
apiVersion: v1
kind: Secret
metadata:name: registry-auth-file
data:.dockerconfigjson: eyJhdXRocyI6eyI0Ny45NC45Mi4xMjI6ODA4MiI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJXekAxOTg4MDgxOCIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5vcmciLCJhdXRoIjoiWVdSdGFXNDZWM3BBTVRrNE9EQTRNVGc9In19fQ==
type: kubernetes.io/dockerconfigjson// 生效
[root@k8s-master deployment]# kubectl apply -f registry-auth-file.yaml
secret/registry-auth-file configured// 读取
[root@k8s-master deployment]# kubectl get secret registry-auth-file -o yaml
apiVersion: v1
data:.dockerconfigjson: eyJhdXRocyI6eyI0Ny45NC45Mi4xMjI6ODA4MiI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJXekAxOTg4MDgxOCIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5vcmciLCJhdXRoIjoiWVdSdGFXNDZWM3BBTVRrNE9EQTRNVGc9In19fQ==
kind: Secret
metadata:annotations:kubectl.kubernetes.io/last-applied-configuration: |{"apiVersion":"v1","data":{".dockerconfigjson":"eyJhdXRocyI6eyI0Ny45NC45Mi4xMjI6ODA4MiI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJXekAxOTg4MDgxOCIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5vcmciLCJhdXRoIjoiWVdSdGFXNDZWM3BBTVRrNE9EQTRNVGc9In19fQ=="},"kind":"Secret","metadata":{"annotations":{},"name":"registry-auth-file","namespace":"default"},"type":"kubernetes.io/dockerconfigjson"}creationTimestamp: "2021-12-30T05:58:33Z"managedFields:- apiVersion: v1fieldsType: FieldsV1fieldsV1:f:data:.: {}f:.dockerconfigjson: {}f:metadata:f:annotations:.: {}f:kubectl.kubernetes.io/last-applied-configuration: {}f:type: {}manager: kubectl-client-side-applyoperation: Updatetime: "2021-12-30T05:58:33Z"name: registry-auth-filenamespace: defaultresourceVersion: "1595453"uid: c865aeac-daa1-425a-90d3-cfd70446ccb9
type: kubernetes.io/dockerconfigjson// 验证
[root@k8s-master deployment]# echo eyJhdXRocyI6eyI0Ny45NC45Mi4xMjI6ODA4MiI6eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJXekAxOTg4MDgxOCIsImVtYWlsIjoiYWRtaW5AZXhhbXBsZS5vcmciLCJhdXRoIjoiWVdSdGFXNDZWM3BBTVRrNE9EQTRNVGc9In19fQ== | base64 -d
{"auths":{"47.94.92.122:8082":{"username":"admin","password":"******","email":"admin@example.org","auth":"YWRtaW46V3pAMTk4ODA4MTg="}}}
修改后,重新生效配置,并查看 Sercet 内容完成验证;
4,更新 deployment-v4.yaml 的镜像地址
[root@k8s-master deployment]# vi deployment-v4.yamlapiVersion: apps/v1
kind: Deployment
metadata:name: v4 #修改
spec:selector:matchLabels:app: v4 #修改replicas: 1template:metadata:labels:app: v4 #修改spec: containers:- name: vue-projectimage: 47.94.92.122:8082/vue-project:2021123011191640834385 #修改ports:- containerPort: 80[root@k8s-master deployment]# kubectl apply -f deployment-v4.yaml
deployment.apps/v4 configured[root@k8s-master deployment]# kubectl get pods
NAME READY STATUS RESTARTS AGE
user-v1-84bdcc465b-vxvl2 1/1 Running 0 4d7h
v4-57b4cf7fd9-zcl45 0/1 ImagePullBackOff 0 4d7h
v4-fb4cd75f5-bf2pf 0/1 ErrImagePull 0 33s[root@k8s-master deployment]# kubectl describe pod v4-fb4cd75f5-bf2pf
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Scheduled 67s default-scheduler Successfully assigned default/v4-fb4cd75f5-bf2pf to k8s-nodeNormal Pulling 28s (x3 over 66s) kubelet Pulling image "47.94.92.122:8082/vue-project:2021123011191640834385"Warning Failed 16s (x3 over 66s) kubelet Failed to pull image "47.94.92.122:8082/vue-project:2021123011191640834385": rpc error: code = Unknown desc = Error response from daemon: Get "https://47.94.92.122:8082/v2/": http: server gave HTTP response to HTTPS clientWarning Failed 16s (x3 over 66s) kubelet Error: ErrImagePullNormal BackOff 4s (x3 over 66s) kubelet Back-off pulling image "47.94.92.122:8082/vue-project:2021123011191640834385"Warning Failed 4s (x3 over 66s) kubelet Error: ImagePullBackOff
生效配置,进入pod验证拉取镜像时,实际访问的镜像地址:47.94.92.122 修改生效
5,本地镜像仓库列表
删除无效的老地址镜像
[root@iZ2ze7rkgit9zoa18pxu73Z bin]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
39.105.212.14:8082/vue-project 2021123011191640834385 cf09bb54e87e 4 days ago 110MB
39.105.212.14:8082/vue-project 2021123011461640835990 cf09bb54e87e 4 days ago 110MB
39.105.212.14:8082/vue-project 2022010316221641198128 cf09bb54e87e 4 days ago 110MB
47.94.92.122:8082/vue-project 2022010316241641198261 cf09bb54e87e 4 days ago 110MB
cicdproject latest 2e9269d7c724 2 weeks ago 110MB
node latest 058747996654 4 weeks ago 992MB
nginx 1.15 53f3fd8007f7 2 years ago 109MB
四,结尾
本篇,介绍了 ci-server 服务器重启后的环境修复;
下一篇,介绍 k8s 的服务间调用,k8s 服务发现;
相关文章:
【Kubernetes】第十七篇 - ECS 服务停机和环境修复
一,前言 上一篇,介绍了 Secret 镜像的使用; 三台服务每天大概 15 块钱的支出,用一个月也是不少钱; 闲时可以停掉,这样每天只有 4 块钱支出,剩下一大笔; ECS 服务停机后公网 IP 会…...
Vue2的生命周期(详解)
Vue的生命周期一、生命周期的概念二、钩子函数三、Vue2的生命周期3.1 初始化阶段3.2 挂载阶段3.3 更新阶段3.4 销毁阶段一、生命周期的概念 Vue实例的生命周期: 从创建到销毁的整个过程 二、钩子函数 Vue框架内置函数,随着组件的生命周期阶段,自动执行 作用:特定的时间点,执行特…...
Potions (Hard Version) and (Easy Version)(背包DP + 反悔贪心)
[TOC](Potions (Hard Version) and (Easy Version)) 一、Potions(Easy Version) 1、问题 2、分析(背包DP 贪心) 简而言之就是我们需要从左到右开始选数字,选的过程中我们需要保证我们选的数字的和始终是大于等于0的,在满足这个…...
剑指 Offer II 017. 含有所有字符的最短字符串
题目链接 剑指 Offer II 017. 含有所有字符的最短字符串 hard 题目描述 给定两个字符串 s和 t。返回 s中包含 t的所有字符的最短子字符串。如果 s中不存在符合条件的子字符串,则返回空字符串 ""。 如果 s中存在多个符合条件的子字符串,返回任…...
Modbus协议初探(C#实现)
由于作者水平有限,如有写得不对得地方请指正 趁着今天休息,就折腾一下Modbus协议,之前零零散散的看过几篇博客,听说搞上位机开发的要会这个协议,虽然我不是搞上位机开发的,但个人对这个比较感兴趣。按照我个…...
【华为OD机试2023】静态扫描 C++ Java Python
【华为OD机试2023】静态扫描 C++ Java Python 前言 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即非性能最优),不能保证通过率。 Tips1:机试为ACM 模式 你的代码需要处理输入输出,input/cin接收输入、…...
函数栈帧的创建和销毁(详解)
函数栈帧的创建和销毁🦖函数栈帧是什么?🦖函数栈帧的创建和销毁解析🐋栈是什么?🐋认识相关寄存器和汇编指令🐋解析函数栈帧的创建和销毁🐳预备知识🐳函数的调用堆栈&…...
【100个 Unity实用技能】 | 脚本无需挂载到游戏对象上也可执行的方法
Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。Unity 平台提供一整套完善的软件解决方案ÿ…...
条件期望5
条件期望例题 随机图 从节点1开始, N为一个随机变量, 表示整个过程第一次出现"贪吃蛇"情形时, 所进行的步数.即Nk⇒Xk(1)∈{1,X(1),X2(1),...Xk−1(1)}其中1,X(1),X2(1),...Xk−1(1)各不相同N k \Rightarrow X^k(1) \in \{1,X(1), X^2(1),...X^{k-1}(1)\} \\ 其中1…...
RecyclerView ViewType二级
实现效果描述: 1、点击recyclerview中item,列表下方出现其他样式的item,作为子item,如下所示 所需要的java文件和xml文件有: 1、创建FoldAdapteradapter, 在FoldAdapter中,定义两种不同的类型ÿ…...
将对象或数组存在 dom元素的属性上,最后取不到完整数据,只取到 [{
目录 一、问题 二、问题及解决方法 三、总结 一、问题 1.我需要在dom元素里面添加了一个属性test存一个对象数组temp,以便我下一次找到这个dom元素时可以直接拿到属性里面的数据来渲染页面。 2.dom 属性上存 对象和数组,必须先JSON.stringify(arr),转…...
Flask源码篇:Flask路由规则与请求匹配过程(超详细,易懂)
目录1 启动时路由相关操作(1)分析app.route()(2)分析add_url_rule()(3)分析Rule类(4)分析Map类(5)分析MapAdapter类(6)分析 url_rule_…...
Jmeter接口测试教程之【参数化技巧总结】,总有一个是你不知道的
目录:导读 一、随机值 二、随机字符串 三、时间戳 四、唯一字符串UUID 说起接口测试,相信大家在工作中用的最多的还是Jmeter。 大家看这个目录就知道jmeter的应用有多广泛了:https://www.bilibili.com/video/BV1e44y1X78S/? JMeter是一个…...
缓存与数据库的双写一致性
背景 在高并发的业务场景下,系统的性能瓶颈往往是出现在数据库上,用户并发访问过大,压力都打到数据库上。所以一般都会用redis做缓存层,起到一个缓冲作用,让请求先访问到缓存层,而不是直接去访问数据库&am…...
力扣-213打家劫舍II(dp)
力扣-213打家劫舍II 1、题目 213. 打家劫舍 II 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通…...
关于【网格结构】岛屿类问题的通用解法DFS(深度遍历)遍历框架+回溯+剪枝总结
最近在刷力扣时遇见的问题,自己总结加上看了力扣大佬的知识总结写下本篇文章,我们所熟悉的 DFS(深度优先搜索)问题通常是在树或者图结构上进行的。而我们今天要讨论的 DFS 问题,是在一种「网格」结构中进行的。岛屿问题…...
【LeetCode】982. 按位与为零的三元组
982. 按位与为零的三元组 题目描述 给你一个整数数组 nums ,返回其中 按位与三元组 的数目。 按位与三元组 是由下标 (i, j, k) 组成的三元组,并满足下述全部条件: 0 < i < nums.length0 < j < nums.length0 < k < num…...
Linux内核源码进程原理分析
Linux内核源码进程原理分析一、Linux 内核架构图二、进程基础知识三、Linux 进程四要素四、task_struct 数据结构主要成员五、创建新进程分析六、剖析进程状态迁移七、写时复制技术一、Linux 内核架构图 二、进程基础知识 Linux 内核把进程称为任务(task),进程的虚…...
电子技术——CMOS反相器
电子技术——CMOS反相器 在本节,我们深入学习CMOS反相器。 电路原理 下图是我们要研究的CMOS反相器的原理图: 下图展示了当输入 vIVDDv_I V_{DD}vIVDD 时的 iD−vDSi_D-v_{DS}iD−vDS 曲线: 我们把 QNQ_NQN 当做是驱动源&#x…...
gazebo仿真轨迹规划+跟踪(不在move_base框架下)
以Tianbot为例子,开源代码如下: https://github.com/tianbot/tianbot_mini GitHub - tianbot/abc_swarm: Ant Bee Cooperative Swarm, indicating air-ground cooperation. This repository is for Tianbot Mini and RoboMaster TT swarm kit. 1.在…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...
