持续集成部署-k8s-配置与存储-存储类:动态创建NFS-PV案例

动态创建NFS-PV案例

  • 1. 前置条件
  • 2. StorageClass 存储类的概念和使用
  • 3. RBAC 配置
  • 4. storageClass 配置
  • 5. 创建应用,测试 PVC 的自动配置
  • 6. 解决 PVC 为 Pending 状态问题
  • 7. 单独测试自动创建 PVC

1. 前置条件

这里使用 NFS 存储的方式,来演示动态创建 PV 的案例。

前置条件是需要在 K8s 集群中安装 NFS 的环境,安装可参考:持续集成部署-k8s-数据持久化-NFS安装与使用

确保 NFS 服务器正常可用之后,接着后续的步骤操作。

验证配置是否生效:

  • 在当前nfs-server 上查看:
[root@docker-54 nfs]# showmount --export
Export list for docker-54:
/home/nfs/ro          192.168.104.0/24
/home/nfs/rw          192.168.104.0/24
[root@docker-54 nfs]#
  • 在 nfs-client 上查看:
[root@docker-55 ~]# showmount -e master
Export list for master:
/home/nfs/ro          192.168.104.0/24
/home/nfs/rw          192.168.104.0/24
[root@docker-55 ~]# [root@docker-56 ~]# showmount -e master
Export list for master:
/home/nfs/ro          192.168.104.0/24
/home/nfs/rw          192.168.104.0/24
[root@docker-56 ~]# 

可以看到,两台 Node 节点上均已显示 NFS Server 的信息了。

在动态创建 PV 之前,我们需要先了解下用到的组件的基础概念。

2. StorageClass 存储类的概念和使用

Kubernetes 中,StorageClass 是用于定义动态存储卷的对象。它允许管理员定义不同类型的存储,并使开发人员能够按需创建 PVC(Persistent Volume Claim 持久卷声明)。

StorageClass 可以看作是一种存储资源的抽象,它定义了存储的类型、属性和参数等信息。Kubernetes 可以根据这些信息动态地创建 PV(Persistent Volume 持久卷),并将其绑定到 PVC 上。
在这里插入图片描述
在数据存储,动态构建 PV 的过程,如上面的流程图所示。

但是在我们创建的过程中,则需要先创建 StorageClass,才能保证在 PVC 使用时,对应上,另外 在 Pod 创建时指定的 PVC 也是需要提前创建才行。

3. RBAC 配置

新建配置文件:nfs-provisioner-rbac.yaml

apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-client-provisionernamespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]resources: ["persistentvolumes"]verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]resources: ["persistentvolumeclaims"]verbs: ["get", "list", "watch", "update"]
- apiGroups: [""]resources: ["endpoints"]verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: ["storage.k8s.io"]resources: ["storageclasses"]verbs: ["get", "list", "watch"]
- apiGroups: [""]resources: ["events"]verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccountname: nfs-client-provisionernamespace: kube-system
roleRef:kind: ClusterRolename: nfs-client-provisioner-runnerapiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: leader-locking-nfs-client-provisioner
rules:
- apiGroups: [""]resources: ["endpoints"]verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:name: leader-locking-nfs-client-provisioner
subjects:
- kind: ServiceAccountname: nfs-client-provisioner# replace with namespace where provisioner is deployednamespace: kube-system
roleRef:kind: Rolename: leader-locking-nfs-client-provisionerapiGroup: rbac.authorization.k8s.io

这个对应了 k8s 中角色权限的部分内容,在 k8s 的服务管理方面,其实就是一套类似 HTTP 的 RESTful 风格的 API,这些 API 默认是具备一个 RBAC 权限的。

上面的配置文件创建了角色、账号,以及如何把角色和账号关联起来。

4. storageClass 配置

新建的配置文件:nfs-storage-class.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: managed-nfs-storage
provisioner: fuseim.pri/ifs
parameters:archiveOnDelete: "false" # 是否存档 false 表示不存档,会删除 oldPath 下的数据,true表示会存档,会重命名路径
reclaimPolicy: Retain # 回收策略, 默认为 Delete  可以配置为 Retain 
volumeBindingMode: Immediate # 默认为 Immediate,表示创建 PVC 立即绑定,只有azuredisk 和 AWSelasticblockstore 支持其他值

新建制备器配置文件:nfs-provisioner-deployment.yaml

apiVersion: v1
kind: ServiceAccount
metadata:name: nfs-client-provisionernamespace: kube-system
---
kind: Deployment
apiVersion: apps/v1
metadata:namespace: kube-systemname: nfs-client-provisionerlabels:app: nfs-client-provisioner
spec:replicas: 1strategy:type: Recreateselector:matchLabels:app: nfs-client-provisionertemplate:metadata:labels:app: nfs-client-provisionerspec:serviceAccount: nfs-client-provisionercontainers:- name: nfs-client-provisioner
#          image: quay.io/external_storage/nfs-client-provisioner:latestimage: registry.cn-beijing.aliyuncs.com/pylixm/nfs-subdir-external-provisioner:v4.0.0volumeMounts:- name: nfs-client-rootmountPath: /persistentvolumesenv:- name: PROVISIONER_NAMEvalue: fuseim.pri/ifs # 对应 sc 里面的provisioner 的名称- name: NFS_SERVERvalue: 192.168.104.54 # nfs 服务的IP 和 路径 都需要关联上才行- name: NFS_PATHvalue: /home/nfs/rwvolumes:- name: nfs-client-rootnfs:server: 192.168.104.54path: /home/nfs/rw

上面这些东西,可能刚开始的时候看有点熟悉,又有点懵,上面的内容,不需要特殊记忆,理解就行,需要改动的地方,也就是最下面 volumes 相关的 server 和 path ,其他内容均为官方配置的内容。基本上也不会有很大的改动。

接着最后是应用的配置文件:nfs-sc-demo-statefulset.yaml

---
apiVersion: v1
kind: Service
metadata:name: nginx-sclabels:app: nginx-sc
spec:type: NodePortports:- name: webport: 80protocol: TCPselector:app: nginx-sc
---
apiVersion: apps/v1
kind: StatefulSet
metadata:name: nginx-sc
spec:replicas: 1serviceName: "nginx-sc" # 对应上面的 Service selector:matchLabels:app: nginx-sc # 匹配到下面的 Pod 的标签配置template:metadata:labels:app: nginx-sc # Pod 模板标签spec:containers:- image: nginxname: nginx-scimagePullPolicy: IfNotPresentvolumeMounts:- mountPath: /usr/share/nginx/html # 挂载到容器的哪个目录name: nginx-sc-test-pvc # 挂载哪个 volumevolumeClaimTemplates:- metadata:name: nginx-sc-test-pvcspec:storageClassName: managed-nfs-storageaccessModes:- ReadWriteManyresources:requests:storage: 1Gi

这里创建了 Service 和 StatefulSet ,来管理 Nginx 的 Pod。

volumeClaimTemplates 的配置为 希望可以帮我自动创建一个 PVC,这个 PVC 声明了使用的存储类 storageClass,配置了 storageClass 的名称storageClassName和访问模式accessModes,这声明为可以多个节点同时读写的一个模式。最后声明,期望所需的资源最小是 1Gi

5. 创建应用,测试 PVC 的自动配置

我们希望的效果是,一旦上面的应用创建起来之后,它自动帮我们把 PVC 创建出来,并且把 PV 也创建出来。

接下来完成上面这些内容的构建,分别把他们构建出来,然后再去把应用跑起来。

先看下当前环境中 pv 和 pvc 的情况:

[root@docker-54 ~]# kubectl get pv | grep nginx
[root@docker-54 ~]# 
[root@docker-54 ~]# kubectl get pvc 
No resources found in default namespace.
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl get storageclass
NAME                    PROVISIONER   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-storage (default)   nfs-client    Delete          Immediate           false                  132d
[root@docker-54 ~]#

可以看到,当前是没有对应的 PV 和 PVC 的。

接着需要先把 RBAC启动起来:

[root@docker-54 ~]# cd /opt/k8s/config/
[root@docker-54 config]# ls
application.yaml   file-test-pod.yaml               nfs-provisioner-rbac.yaml  nginx.conf                   test
env-test-pod.yaml  nfs-provisioner-deployment.yaml  nfs-storage-class.yaml     private-image-pull-pod.yaml
[root@docker-54 config]# 
[root@docker-54 config]# kubectl apply -f nfs-provisioner-rbac.yaml 
serviceaccount/nfs-client-provisioner unchanged
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner configured
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner unchanged
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner unchanged
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner unchanged
[root@docker-54 config]# 

这里由于我之前创建过一些 RBAC 权限,这里有的显示 unchanged,首次执行这个应该是 created或者configured
可以看到,上面RBAC 里面配置了一个 serviceaccount以及它对应的集群角色,然后是角色的绑定。接着是一个普通的角色以及普通角色的绑定。

创建完权限,接着来创建 deployment:

[root@docker-54 config]# kubectl apply -f nfs-provisioner-deployment.yaml 
serviceaccount/nfs-client-provisioner unchanged
deployment.apps/nfs-client-provisioner configured
[root@docker-54 config]# 

接着创建 StorageClass:kubectl apply -f nfs-storage-class.yaml

[root@docker-54 config]# kubectl apply -f nfs-storage-class.yaml
storageclass.storage.k8s.io/managed-nfs-storage created
[root@docker-54 config]#

这里 StorageClass 也创建完成后,可以查看下:

[root@docker-54 config]# kubectl get sc
NAME                    PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
managed-nfs-storage     fuseim.pri/ifs   Retain          Immediate           false                  60s
nfs-storage (default)   nfs-client       Delete          Immediate           false                  132d
[root@docker-54 config]# 

可以看到,这里确实多了一条记录managed-nfs-storage,并且 PROVISIONER 的值,也正是我们配置的 fuseim.pri/ifs,这个是我们后续使用时关联的一个标识。

接着我们来看下上面创建的 Deployment :

[root@docker-54 config]# kubectl get po -n kube-system | grep nfs
nfs-client-provisioner-77bdfd69d9-9hzhx   1/1     Running   0              134m
[root@docker-54 config]# 

可以看到已经是正常运行的状态了。

接下来我们创建statefulsetkubectl apply -f nfs-sc-demo-statefulset.yaml

[root@docker-54 config]# kubectl apply -f nfs-sc-demo-statefulset.yaml 
service/nginx-sc created
statefulset.apps/nginx-sc created
[root@docker-54 config]# 

接着看下应用的状态:

[root@docker-54 config]# kubectl get sts
NAME       READY   AGE
nginx-sc   1/1     54s
[root@docker-54 config]# 
[root@docker-54 config]# kubectl get po | grep nginx
nginx-sc-0                     1/1     Running     0                115s
[root@docker-54 config]#

可以看到正常创建、并启动了。

6. 解决 PVC 为 Pending 状态问题

如果这里 Nginx 的 Pod 为 Pending 状态,则要检查下:kubectl describe po nginx-sc-0

Events:Type     Reason            Age    From               Message----     ------            ----   ----               -------Warning  FailedScheduling  3m20s  default-scheduler  0/3 nodes are available: 3 pod has unbound immediate PersistentVolumeClaims.Normal   Scheduled         3m18s  default-scheduler  Successfully assigned default/nginx-sc-0 to docker-55Normal   Pulled            3m18s  kubelet            Container image "nginx" already present on machineNormal   Created           3m18s  kubelet            Created container nginx-scNormal   Started           3m18s  kubelet            Started container nginx-sc
[root@docker-54 config]# 

如果状态异常,上面命令可以看到具体的原因。这里有个FailedScheduling的警告,提示我们三个节点都是可用的,但是 3 个 pod 还是 unbound ,意思是还未绑定到 PVC。

这时候可以排查下 PVC 的状态及原因:

[root@docker-54 config]# kubectl get pvc
NAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
nginx-sc-test-pvc-nginx-sc-0   Bound    pvc-ba5db961-8b17-4507-a287-ca767d607fa9   1Gi        RWX            managed-nfs-storage   6m18s
[root@docker-54 config]# 

如果这里也为 Pending,状态,此时可能 PV 也是非正常的,可以使用 describe 看下具体原因或者看下 PV 的状态。

[root@docker-54 config]# kubectl get pv | grep nginx
pvc-ba5db961-8b17-4507-a287-ca767d607fa9   1Gi        RWX            Retain           Bound       default/nginx-sc-test-pvc-nginx-sc-0   managed-nfs-storage            8m3s
[root@docker-54 config]#

我这里 PV 是正常的,是因为我修改了,k8s制备器的镜像,k8s 默认是quay.io/external_storage/nfs-client-provisioner:latest 镜像,这个镜像需要用到 K8s 中的 一个 selfLink 的功能,但是从 1.20 版本之后,k8s 把这个功能给关掉了,可能是处于性能以及 API 调用请求的一个方向考虑的,把这个功能给禁用掉了,所以就意味着我们新版本不能再直接使用这个镜像了。

我这里使用的版本是v1.22.6

[root@docker-54 config]#   kubectl version
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.6", GitCommit:"f59f5c2fda36e4036b49ec027e556a15456108f0", GitTreeState:"clean", BuildDate:"2022-01-19T17:33:06Z", GoVersion:"go1.16.12", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.6", GitCommit:"f59f5c2fda36e4036b49ec027e556a15456108f0", GitTreeState:"clean", BuildDate:"2022-01-19T17:26:47Z", GoVersion:"go1.16.12", Compiler:"gc", Platform:"linux/amd64"}
[root@docker-54 config]# 

这里PVC 处于 Pending 状态有两种解决方案:

  • 第一种是配置 SelfLink:修改 apiserver 配置文件
vim /etc/kubernetes/manifests/kube-apiserver.yamlspec:containers:- command:- kube-apiserver- --feature-gates=RemoveSelfLink=false # 新增该行......

修改后重新应用该配置,

kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml

这样可以解决因为版本导致 PVC pending 状态的问题。不过既然官方已经不支持了,我们也没必要强制修改让它支持,看下第二种方案。

  • 第二种是使用不需要 SelfLinkprovisioner:将 provisioner 修改为如下镜像之一即可,下面的为阿里云的镜像,性价比更高。
gcr.io/k8s-staging-sig-storage/nfs-subdir-external-provisioner:v4.0.0registry.cn-beijing.aliyuncs.com/pylixm/nfs-subdir-external-provisioner:v4.0.0

修改完镜像后,然后执行:nfs-provisioner-deployment.yaml 更新deployment

当看到 Pod 的状态正常,PVC 和 PV 的状态正常后,就完事了。

7. 单独测试自动创建 PVC

如果我们想单独测试下这个自动创建 PVC ,那么可以这么操作:

新建配置文件:auto-pv-test-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: auto-pv-test-pvc
spec:accessModes:- ReadWriteOnceresources:requests:storage: 300MistorageClassName: managed-nfs-storage

这里直接创建 PVC,并没有声明关于 PV 的内容,仅仅声明了 PVC 的名称、需要的资源、使用的 storageClassName

[root@docker-54 config]# kubectl apply -f auto-pv-test-pvc.yaml 
persistentvolumeclaim/auto-pv-test-pvc created
[root@docker-54 config]# 
[root@docker-54 config]# kubectl get pvc
NAME                           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
auto-pv-test-pvc               Bound    pvc-1a180c44-a4d3-44e3-83d0-b69bbf73f2df   300Mi      RWO            managed-nfs-storage   26s
nginx-sc-test-pvc-nginx-sc-0   Bound    pvc-ba5db961-8b17-4507-a287-ca767d607fa9   1Gi        RWX            managed-nfs-storage   47m
[root@docker-54 config]# 

可以看到,新建的 PVC auto-pv-test-pvc 已经正常绑定到名为pvc-1a180c44-a4d3-44e3-83d0-b69bbf73f2df的 PV 上了。这样也是可以达到自动创建 PVC 的目的。

在后续的使用中,我们使用自动创建 PVC 就不用关心 PV ,我们只需要写我们的需求就好了,系统可以根据我们的需求自动创建PV 来自动绑定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/174400.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI数字人与虚拟人:区别与应用场景

随着人工智能和虚拟技术的不断发展,AI数字人和虚拟人成为了数字世界中的两个重要概念。本文将介绍AI数字人和虚拟人的区别,并探讨它们在不同领域的应用场景。 一、AI数字人与虚拟人的区别 定义和概念: AI数字人:是利用人工智能技术…

MFC—CTabCtrl 、CListCtrl

为了方便自己查找 1、官方文档 CTabCtrl CListCtrl 2、create(窗口样式) 基本上安流程来都能出出来。看一下视图的窗口样式。主要是report的。 CTabCtrl选项卡控件样式 CListCtrl列表视图窗口样式(这里的名字又变了,List-Vi…

单例模式-支持并发的C语言实现

代码实现&#xff1a; c #include <stdio.h> #include <stdlib.h> #include <pthread.h>// 定义单例对象结构体 typedef struct {// 单例对象的数据成员int value; } Singleton;// 静态变量&#xff0c;用于保存唯一实例的指针 static Singleton* instance …

wireshark 抓包提示

[TCP Previous segment not captured] 在TCP的传输阶段&#xff0c;同一台主机发出的数据段应该是连续的&#xff0c;即后一个包的Seq等于前一个包的SeqLen&#xff08;三次握手和四次挥手是个例外&#xff09;。如果wireshark发现后一个包的Seq号大于前一个包的SeqLen&#xf…

28. Spring源码篇依赖注入之Optional

简介 我们知道&#xff0c;java中的Optional是解决臭名昭著的空指针异常&#xff0c;在spring的依赖注入中&#xff0c;如果没有找到Bean也会抛异常&#xff0c;就算将required写为false&#xff0c;后面也会需要判空 在spring中也支持Optional的依赖注入 创建Optional jav…

【TinyALSA全解析(一)】TinyALSA简介

TinyALSA简介 一、TinyALSA概述1.1 TinyALSA背景和用途1.2 TinyALSA主要内容1.3 TinyALSA与ALSA的关系 二、TinyALSA具体有哪些内容2.1 libtinyalsa.so 库2.2 一组工具 三、tinyalsa完整目录分析四、tinyalsa的编译方法和使用方法4.1 tinyalsa编译方法4.1.1 TinyALSA全编译方法…

【JVM系列】- 穿插·对象的实例化与直接内存

对象的实例化与直接内存 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#xff0c;大家一起学习成长&#xff01; 文章目录…

SpringCloud系列文章目录(总纲篇)

文章目录 前言正文一、原理性文章1.1 OpenFeign篇 二、实战性文章1.1 注册中心、配置中心篇1.2 网关篇1.3 OpenFeign篇 前言 SpringCloud系列文章&#xff0c;有些文章上下文存在联系。 并且&#xff0c;它们数量巨多&#xff0c;有涉及原理的&#xff0c;有涉及实战的。 本文…

域名邮箱与企业邮箱的区别:功能、应用与优势

根据使用者的不同需求&#xff0c;电子邮件分为域名邮箱和企业邮箱两种类型。那么这两种邮箱之间究竟存在哪些区别呢&#xff1f;本文将从定义、优势和劣势三个方面进行详细解析。 什么是域名邮箱&#xff1f; 域名邮箱&#xff0c;顾名思义是以域名作为后缀的电子邮箱。域名邮…

【UGUI】制作用户注册UI界面

这里面主要的操作思想就是 1.打组 同一个事情里面包含两个UI元素都应该打组便于管理和查找 2.设置锚点位置 每次创建一个UI都应该设置他的锚点以便于跟随画布控制自己的&#xff1a;相对位置 3. 设置尺寸&#xff08;像素大小&#xff09; 每一次UI元素哪怕是作为父物体的…

我叫:归并排序【JAVA】

1.认识我一下 1.归并排序(MERGE-SORT)利用归并的思想实现的排序方法,该算法采用经典的分治策略2.分治法将问题分成一些小的问题然后递归求解,而治的阶段则将分的阶段得到的各答案"修补"在一起&#xff0c;即分而治之。 2.分合思想 3 分久必合 /*** 合并** param arr …

tp6框架 万级数据入库

用框架自带的saveall方法 当数据超过一千就会出现遗漏的情况 下面是原生sql方法&#xff1a; function saveCourse($newArr, $count) {$sql "replace into edu_wx_school_self_course (study_hour,code,cn_name,en_name,study_score,school_qy) values";for ($a…

(数据结构)顺序表的定义

#include<stdio.h> //顺序表的实现——静态分配 #define MAX 10 //定义最大长度 typedef struct List {int data[MAX]; //用静态的数组存放数据int lenth; //顺序表现在的长度 }List; //顺序表的初始化 void ChuShiHua(List L) {L.lenth 0; //将顺序表的长度初始化…

Tensorflow检测不到GPU解决办法(针对本人4060有效)

目录 前置条件硬件条件当前日期 检查方法解决方法版本列表tensorflow2.10.0CUDA12.1cudnn8.8 结果 前置条件 硬件条件 R5-5600G RTX4060 当前日期 当前时间是2023年11月27日&#xff0c;请注意本文的时效性&#xff0c;保不齐后续出现某个组件的更新能够直接解决这个问题。…

YOLOv8优化策略:自适应改变核大小卷积AKConv,效果优于标准卷积核和DSConv |2023.11月最新成果

🚀🚀🚀本文改进: AKConv 中,通过新的坐标生成算法定义任意大小的卷积核的初始位置。 为了适应目标的变化,引入了偏移量来调整每个位置的样本形状。 此外,我们通过使用具有相同大小和不同初始采样形状的 AKConv 来探索神经网络的效果。 AKConv 通过不规则卷积运算完成…

STM32项目经验分享:常用软件

文章目录 硬件设计软件软件设计软件英文文档阅读 硬件设计软件 Altium Designer&#xff08;在公司用会被维权&#xff09; 3D模型&#xff08;3D contentcentral&#xff09; 嘉立创 先用立创EDA画原理图然后再用AD画PCB,3D模型可以用3D contentcentral下载 软件设计软件 …

【备忘录】软件记录

Anaconda 虚拟环境 创建Python环境 Spyder Python程序编辑 Jupyter Notebook 交互式开发环境

Spring第二课响应的完全,如何理解前后端互联

目录 一、响应 Control,RestController 1.Controller的源码&#xff0c;代表什么意思 2.返回数据 Responsebody 3.返回HTML片段 4.返回JSON 5.那么假如我们使用集合会怎么样呢 设置状态码&#xff0c;虽然不影响展示&#xff0c;但是确实显示起来也就是401的情况。 2.我…

[设计模式] 常见的设计模式

文章目录 设计模式的 6 大设计原则设计模式的三大分类常见的设计模式有哪几种1. 单例模式&#xff1a;保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。&#xff08;连接池&#xff09;1. 饿汉式2. 懒汉式3. 双重检测 2. 工厂模式3. 观察者模式● 推模型● 拉…

自动化横行时代,手工测试如何突破重围?测试之路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 自动化测试是每个…