研发工程师玩转Kubernetes——PVC通过storageClassName进行延迟绑定
不同的PV可以使用相同的StorageClass,它们是一对多的关系。

PV可以设置节点亲和性。比如下图,local-storage-class-waitforfirstconsumer-pv-ubuntuc只能在节点ubuntuc上;local-storage-class-waitforfirstconsumer-pv-ubuntud只能在节点ubuntud上。

如果我们使用《研发工程师玩转Kubernetes——PVC使用storageClassName选择PV》一文中的“立即绑定”型的StorageClass。
# local_storage_class_immediate.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: local-storage-class-immediate
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: Immediate
则在创建PVC时,立即会选择一个PV。这样这个PVC可能绑定到节点ubuntuc对应的PV上,也可能绑定到节点ubuntud对应的PV上。现在我们假定它绑定到ubuntuc对应的PV——local-storage-class-immediate-pv-ubuntuc上。
假如PVC的使用者——Pod在调度时,清单文件要求它只能在ubuntud上使用。而其PVC却在ubuntuc上,则会调度失败。
立即绑定导致Pod调度失败的案例
StorageClass
注意volumeBindingMode是Immediate,即PVC创建时立即绑定PV。
# local_storage_class_immediate.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: local-storage-class-immediate
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: Immediate
PersistentVolume
ubuntuc
# local_storage_class_immediate_pv_ubuntuc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: local-storage-class-immediate-pv-ubuntuc
spec:capacity:storage: 1MivolumeMode: FilesystemaccessModes:- ReadWriteOncepersistentVolumeReclaimPolicy: DeletestorageClassName: local-storage-class-immediatelocal:path: /tmpnodeAffinity:required:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- ubuntuc
ubuntud
# local_storage_class_immediate_pv_ubuntud.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: local-storage-class-immediate-pv-ubuntud
spec:capacity:storage: 1MivolumeMode: FilesystemaccessModes:- ReadWriteOncepersistentVolumeReclaimPolicy: DeletestorageClassName: local-storage-class-immediatelocal:path: /tmpnodeAffinity:required:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- ubuntud
PersistentVolumeClaim
# local_storage_class_immediate_pvc_600k.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: local-storage-class-immediate-pvc-600k
spec:resources:requests:storage: 600KiaccessModes:- ReadWriteOncestorageClassName: local-storage-class-immediate
创建完上述组件,我们查看下PVC的状态。
kubectl describe persistentvolumeclaims local-storage-class-immediate-pvc-600k
Name: local-storage-class-immediate-pvc-600k
Namespace: default
StorageClass: local-storage-class-immediate
Status: Bound
Volume: local-storage-class-immediate-pv-ubuntuc
Labels: <none>
Annotations: pv.kubernetes.io/bind-completed: yespv.kubernetes.io/bound-by-controller: yes
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 1Mi
Access Modes: RWO
VolumeMode: Filesystem
Used By: <none>
Events: <none>
可以看到这个PVC处于绑定状态。
Deployment
# local_deployment_immediate.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: local-pv-app-immediate-deployment
spec:replicas: 1selector:matchLabels:app: local-pv-app-immediatetemplate:metadata:labels:app: local-pv-app-immediatespec:containers:- name: local-pv-app-immediateimage: busyboxcommand: ["/bin/sh", "-c", "if [ -f /tempdir/lockfile ] && ! { set -C; 2>/dev/null >/tempdir/lockfile; }; then tail -f /tempdir/lockfile; else exec 3>/tempdir/lockfile; if [ -n \"$POD_NAME\" ]; then name=$POD_NAME; else name=\"unknown\"; fi; while true; do echo \"this is $name.$name write something to lockfile\"; echo \"$name write something to lockfile\" >&3; sleep 1; done; fi"] volumeMounts:- name: local-pvc-volumemountPath: /tempdirenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.namevolumes:- name: local-pvc-volumepersistentVolumeClaim:claimName: local-storage-class-immediate-pvc-600kaffinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- ubuntud
这个清单要求Pod使用local-storage-class-immediate-pvc-600k这个PVC,但是要求自己只能被部署在节点ubuntud上。
错误表现
kubectl describe pod local-pv-app-immediate-deployment-6dd57d98f5-s5vpz
Name: local-pv-app-immediate-deployment-6dd57d98f5-s5vpz
Namespace: default
Priority: 0
Service Account: default
Node: <none>
Labels: app=local-pv-app-immediatepod-template-hash=6dd57d98f5
Annotations: <none>
Status: Pending
IP:
IPs: <none>
Controlled By: ReplicaSet/local-pv-app-immediate-deployment-6dd57d98f5
Containers:local-pv-app-immediate:Image: busyboxPort: <none>Host Port: <none>Command:/bin/sh-cif [ -f /tempdir/lockfile ] && ! { set -C; 2>/dev/null >/tempdir/lockfile; }; then tail -f /tempdir/lockfile; else exec 3>/tempdir/lockfile; if [ -n "$POD_NAME" ]; then name=$POD_NAME; else name="unknown"; fi; while true; do echo "this is $name.$name write something to lockfile"; echo "$name write something to lockfile" >&3; sleep 1; done; fiEnvironment:POD_NAME: local-pv-app-immediate-deployment-6dd57d98f5-s5vpz (v1:metadata.name)Mounts:/tempdir from local-pvc-volume (rw)/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-r48fn (ro)
Conditions:Type StatusPodScheduled False
Volumes:local-pvc-volume:Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)ClaimName: local-storage-class-immediate-pvc-600kReadOnly: falsekube-api-access-r48fn:Type: Projected (a volume that contains injected data from multiple sources)TokenExpirationSeconds: 3607ConfigMapName: kube-root-ca.crtConfigMapOptional: <nil>DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300snode.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:Type Reason Age From Message---- ------ ---- ---- -------Warning FailedScheduling 8s default-scheduler 0/5 nodes are available: 1 node(s) didn't match Pod's node affinity/selector. preemption: 0/5 nodes are available: 1 Preemption is not helpful for scheduling, 4 No preemption victims found for incoming pod..
可以看到Pod调度失败,处于Pending状态。

延迟绑定导致Pod调度成功的案例
StorageClass
注意volumeBindingMode是WaitForFirstConsumer,即PVC创建时不绑定PV。而在PVC被使用(Pod被调度到)时绑定PV。
# local_storage_class_waitforfirstconsumer.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: local-storage-class-waitforfirstconsumer
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
PersistentVolume
和之前的PV设置相似,核心就是storageClassName不同,使用了延迟绑定的StorageClass。
ubuntuc
# local_storage_class_waitforfirstconsumer_pv_ubuntuc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: local-storage-class-waitforfirstconsumer-pv-ubuntuc
spec:capacity:storage: 1MivolumeMode: FilesystemaccessModes:- ReadWriteOncepersistentVolumeReclaimPolicy: DeletestorageClassName: local-storage-class-waitforfirstconsumerlocal:path: /tmpnodeAffinity:required:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- ubuntuc
ubuntud
# local_storage_class_waitforfirstconsumer_pv_ubuntud.yaml
apiVersion: v1
kind: PersistentVolume
metadata:name: local-storage-class-waitforfirstconsumer-pv-ubuntud
spec:capacity:storage: 1MivolumeMode: FilesystemaccessModes:- ReadWriteOncepersistentVolumeReclaimPolicy: DeletestorageClassName: local-storage-class-waitforfirstconsumerlocal:path: /tmpnodeAffinity:required:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- ubuntud
PersistentVolumeClaim
和之前例子的区别就是storageClassName选择了延迟绑定的local-storage-class-waitforfirstconsumer。
# local_storage_class_waitforfirstconsumer_pvc_600k.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: local-storage-class-waitforfirstconsumer-pvc-600k
spec:resources:requests:storage: 600KiaccessModes:- ReadWriteOncestorageClassName: local-storage-class-waitforfirstconsumer
我们先创建上述组件,然后观察PVC的状态。
kubectl describe persistentvolumeclaims local-storage-class-waitforfirstconsumer-pvc-600k
Name: local-storage-class-waitforfirstconsumer-pvc-600k
Namespace: default
StorageClass: local-storage-class-waitforfirstconsumer
Status: Pending
Volume:
Labels: <none>
Annotations: <none>
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Used By: <none>
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal WaitForFirstConsumer 2s (x2 over 11s) persistentvolume-controller waiting for first consumer to be created before binding
可以看到这次PVC没有立即绑定,而是处于Pending状态,且原因是等待第一个使用者触发绑定。
Deployment
# local_deployment_waitforfirstconsumer.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: local-pv-app-waitforfirstconsumer-deployment
spec:replicas: 1selector:matchLabels:app: local-pv-app-waitforfirstconsumertemplate:metadata:labels:app: local-pv-app-waitforfirstconsumerspec:containers:- name: local-pv-app-waitforfirstconsumerimage: busyboxcommand: ["/bin/sh", "-c", "if [ -f /tempdir/lockfile ] && ! { set -C; 2>/dev/null >/tempdir/lockfile; }; then tail -f /tempdir/lockfile; else exec 3>/tempdir/lockfile; if [ -n \"$POD_NAME\" ]; then name=$POD_NAME; else name=\"unknown\"; fi; while true; do echo \"this is $name.$name write something to lockfile\"; echo \"$name write something to lockfile\" >&3; sleep 1; done; fi"] volumeMounts:- name: local-pvc-volumemountPath: /tempdirenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.namevolumes:- name: local-pvc-volumepersistentVolumeClaim:claimName: local-storage-class-waitforfirstconsumer-pvc-600kaffinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- ubuntud
创建完我们查看Pod的状态。
kubectl describe pod local-pv-app-waitforfirstconsumer-deployment-84449895c4-x7ddx
Name: local-pv-app-waitforfirstconsumer-deployment-84449895c4-x7ddx
Namespace: default
Priority: 0
Service Account: default
Node: ubuntud/172.22.244.197
Start Time: Wed, 09 Aug 2023 17:07:01 +0000
Labels: app=local-pv-app-waitforfirstconsumerpod-template-hash=84449895c4
Annotations: cni.projectcalico.org/containerID: cb10dba20771f872b242bc6284eb9d790565b7f2c1a2fbb096ff1581a73d4de5cni.projectcalico.org/podIP: 10.1.202.206/32cni.projectcalico.org/podIPs: 10.1.202.206/32
Status: Running
IP: 10.1.202.206
IPs:IP: 10.1.202.206
Controlled By: ReplicaSet/local-pv-app-waitforfirstconsumer-deployment-84449895c4
Containers:local-pv-app-waitforfirstconsumer:Container ID: containerd://3fda11a2670236dc37409dd1fd6c5efae36d48bbcf1ce71266f72bd7b0b55b98Image: busyboxImage ID: docker.io/library/busybox@sha256:3fbc632167424a6d997e74f52b878d7cc478225cffac6bc977eedfe51c7f4e79Port: <none>Host Port: <none>Command:/bin/sh-cif [ -f /tempdir/lockfile ] && ! { set -C; 2>/dev/null >/tempdir/lockfile; }; then tail -f /tempdir/lockfile; else exec 3>/tempdir/lockfile; if [ -n "$POD_NAME" ]; then name=$POD_NAME; else name="unknown"; fi; while true; do echo "this is $name.$name write something to lockfile"; echo "$name write something to lockfile" >&3; sleep 1; done; fiState: RunningStarted: Wed, 09 Aug 2023 17:07:04 +0000Ready: TrueRestart Count: 0Environment:POD_NAME: local-pv-app-waitforfirstconsumer-deployment-84449895c4-x7ddx (v1:metadata.name)Mounts:/tempdir from local-pvc-volume (rw)/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-52426 (ro)
Conditions:Type StatusInitialized True Ready True ContainersReady True PodScheduled True
Volumes:local-pvc-volume:Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)ClaimName: local-storage-class-waitforfirstconsumer-pvc-600kReadOnly: falsekube-api-access-52426:Type: Projected (a volume that contains injected data from multiple sources)TokenExpirationSeconds: 3607ConfigMapName: kube-root-ca.crtConfigMapOptional: <nil>DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300snode.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Scheduled 8s default-scheduler Successfully assigned default/local-pv-app-waitforfirstconsumer-deployment-84449895c4-x7ddx to ubuntudNormal Pulling 8s kubelet Pulling image "busybox"Normal Pulled 5s kubelet Successfully pulled image "busybox" in 2.266071612s (2.266078813s including waiting)Normal Created 5s kubelet Created container local-pv-app-waitforfirstconsumerNormal Started 5s kubelet Started container local-pv-app-waitforfirstconsumer
可以看到Pod按清单要求被成功调度到ubuntud上。
kubectl describe persistentvolumeclaims local-storage-class-waitforfirstconsumer-pvc-600k
Name: local-storage-class-waitforfirstconsumer-pvc-600k
Namespace: default
StorageClass: local-storage-class-waitforfirstconsumer
Status: Bound
Volume: local-storage-class-waitforfirstconsumer-pv-ubuntud
Labels: <none>
Annotations: pv.kubernetes.io/bind-completed: yespv.kubernetes.io/bound-by-controller: yes
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 1Mi
Access Modes: RWO
VolumeMode: Filesystem
Used By: local-pv-app-waitforfirstconsumer-deployment-84449895c4-x7ddx
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal WaitForFirstConsumer 2m23s (x16 over 6m2s) persistentvolume-controller waiting for first consumer to be created before binding
这个Pod使用的PVC也被分配到ubuntud上。

参考资料
- https://www.qikqiak.com/k8strain/storage/local/
相关文章:
研发工程师玩转Kubernetes——PVC通过storageClassName进行延迟绑定
不同的PV可以使用相同的StorageClass,它们是一对多的关系。 PV可以设置节点亲和性。比如下图,local-storage-class-waitforfirstconsumer-pv-ubuntuc只能在节点ubuntuc上;local-storage-class-waitforfirstconsumer-pv-ubuntud只能在节点ubu…...
6.利用matlab完成 符号矩阵的秩和 符号方阵的逆矩阵和行列式 (matlab程序)
1.简述 利用M文件建立矩阵 对于比较大且比较复杂的矩阵,可以为它专门建立一个M文件。下面通过一个简单例子来说明如何利用M文件创建矩阵。 例2-2 利用M文件建立MYMAT矩阵。(1) 启动有关编辑程序或MATLAB文本编辑器,并输入待建矩阵:(2) 把…...
python获取类名__qualname__,解决django接口ObjectDoesNotExist异常寻找model的问题
在django项目中,经常使用类似Model.objects.get(id1)的方法取对象,默认抛出的异常是ObjectDoesNotExist类型,通过try catch可以把异常捕获,获取的异常是Model.DoesNotExist类型, 要获知其类名,可以使用__na…...
电流的测量(分流电流表)
在当今的大多数仪器应用中,可以使用两种常见的电流测量方法:分流电流表方法和反馈电流表方法。分流电流表方法通常与通用数字万用表 (DMM)一起使用,用于测量分流电阻器上的电压测量值。该电压测量结果与已知的电阻值相结合,得出电…...
Leetcode每日一题:23. 合并 K 个升序链表(2023.8.12 C++)
目录 23. 合并 K 个升序链表 题目描述: 实现代码与解析: 优先级队列: 原理思路: 23. 合并 K 个升序链表 题目描述: 给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表…...
越南的区块链和NFT市场调研
越南的区块链和NFT市场调研 基本介绍 https://zh.wikipedia.org/wiki/%E8%B6%8A%E5%8D%97 语言文字: 越南语, 文字以国语字(越南罗马字)为主,汉喃文(汉字) 货币:越南盾 人口(2022…...
MySQL常用语句
当涉及到与关系型数据库进行交互时,以下是一些常用的 SQL 语句,可以帮助你进行数据查询、插入、更新和删除等操作: 查询数据: 查询所有数据:SELECT * FROM table_name; 查询特定列数据:SELECT column1, col…...
Mongodb:业务应用(1)
环境搭建参考:mongodb:环境搭建_Success___的博客-CSDN博客 需求: 在文章搜索服务中实现保存搜索记录到mongdb 并在搜索时查询出mongdb保存的数据 1、安装mongodb依赖 <dependency><groupId>org.springframework.data</groupI…...
【vue】vue中按钮权限控制:
文章目录 一、获取权限码二、三种按钮级别的权限控制方式【1】函数方式【2】组件方式【3】指令方式 一、获取权限码 要做权限控制,肯定需要一个code,无论是权限码还是角色码都可以,一般后端会一次性返回,然后全局存储起来就可以了…...
【博客695】k8s subPathExpr作用
k8s subPathExpr作用 场景: 对于一个deployment或者job拉起的服务,所有pod都是一样的配置,如果都挂载了宿主机的同一个目录,那么就会互相干扰,我们希望挂载相同目录,且在这个目录下,每个pod建立…...
微信小程序中键盘弹起输入框自动跳到键盘上方处理
效果展示 键盘未弹起时 键盘弹起后: 实现方式 话就不多说了 我直接贴代码了 原理就是用你点击的输入框的底部 距离顶部的位置 减去屏幕高度除以2,然后设成负值,再将这个值给到最外层相对定位的盒子的top属性,这样就不会出现顶…...
excel将主信息和明细信息整理为多对多(每隔几行空白如何填充)
excel导出的数据是主信息和明细信息形式。 方法如下:1、首先,从第一个单元格开始选中要填充的数据区域。2、按CtrlG或者F5调出定位对话框,点击左下角的【定位条件】。3、在【定位条件】中选择【空值】,然后点击【确定】按钮。4、按照上述操作…...
卷积神经网络实现彩色图像分类 - P2
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍦 参考文章:365天深度学习训练营-第P2周:彩色识别🍖 原作者:K同学啊 | 接辅导、项目定制🚀 文章来源:K同学的学习圈子…...
【博客694】k8s kubelet 状态更新机制
k8s kubelet 状态更新机制 场景: 当 Kubernetes 中 Node 节点出现状态异常的情况下,节点上的 Pod 会被重新调度到其他节点上去,但是有的时候我们会发现节点 Down 掉以后,Pod 并不会立即触发重新调度,这实际上就是和 K…...
【博客692】grafana如何解决step动态变化时可能出现range duration小于step
grafana如何解决step动态变化时可能出现range duration小于step 1、grafana中的step和resolution grafana中的 “step” grafana本身是没有提供step参数的,因为仪表盘根据查询数据区间以及仪表盘线条宽度等,对于不同查询,相同的step并不能…...
eNSP:ibgp的破水平切割练习
实验要求: 拓扑展示: 命令操作: R1: <Huawei>sys [Huawei]sys r1 [r1]int g 0/0/1 [r1-GigabitEthernet0/0/1]ip add 12.1.1.1 24 [r1-GigabitEthernet0/0/1]int lo0 [r1-LoopBack0]ip add 1.1.1.1 24 [r1-LoopBack0]osp…...
maven是什么?安装+配置
目录 1.什么是maven? 1.2.maven的核心功能是什么? 2.Maven安装配置 2.1Maven的安装 2.2Maven环境配置 1.配置 MAVEN_HOME ,变量值就是你的 maven 安装的路径(bin 目录之前一级目录) 2.将MAVEN_HOME 添加到Path系…...
基于长短期神经网络LSTM的多分类代码
目录 背影 摘要 LSTM的基本定义 LSTM实现的步骤 基于长短期神经网络LSTM的股票预测 MATALB编程实现,附有代码:基于长短期神经网络LSTM的多分类代码,基于LSTM的多分类预测-深度学习文档类资源-CSDN文库 https://download.csdn.net/download/abc991835105/88184779 效果图 结果…...
利用爬虫爬取图片并保存
1 问题 在工作中,有时会遇到需要相当多的图片资源,可是如何才能在短时间内获得大量的图片资源呢? 2 方法 我们知道,网页中每一张图片都是一个连接,所以我们提出利用爬虫爬取网页图片并下载保存下来。 首先通过网络搜索…...
设计模式之Bridge模式的C++实现
目录 1、Bridge模式的提出 2、Bridge模式的定义 3、Bridge模式总结 4、需求描述 5、多继承方式实现 6、使用Bridge设计模式实现 1、Bridge模式的提出 在软件功能模块设计中,如果类的实现功能划分不清晰,使得继承得到的子类往往是随着需求的变化&am…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
