当前位置: 首页 > news >正文

local-path-provisioner的使用(hostPath、local、local-path-provisioner三者对比)

前言

环境:k8s 1.22.17 、centos7.9
有时候,为了使用本地服务器上的磁盘存储资源,我们会使用hostPath这种方式来为k8s提供本地存储,本篇就来对比一下hostPath、local这两种使用本地服务器储存的方案,从而引出第三种local-path本地储存。

hostPath卷

hostPath 卷能将主机节点文件系统上的文件或目录挂载到你的 Pod 中,但是我们知道,pod重启后会随机调度,所以就需要为pod固定主机节点。下面仅演示hostPath的使用方法,挂载一个宿主机上的目录到pod中:

#hostPath示例一
#pod中直接使用hostPath卷
[root@matser data]# vim  nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-179namespace: default
spec:replicas: 1selector:matchLabels:app: nginx-179template:metadata:labels:app: nginx-179spec:nodeName: master					#固定pod能调度的节点,确保pod重启后仍能访问之前的数据containers:- image: nginx:1.7.9imagePullPolicy: IfNotPresentname: nginx-containerports:- containerPort: 80name: httpprotocol: TCPvolumeMounts:- mountPath: /var/log/nginx		#持久化日志name: hostpath-volumerestartPolicy: Alwaysvolumes:- name: hostpath-volumehostPath:						#hostPath卷path: /data/nginx				#使用宿主机上的/data/nginx目录type: DirectoryOrCreatekubectl  apply -f nginx.yaml
kubectl  delete  -f nginx.yaml
#hostPath示例二
#pod中使用pvc,pvc与pv关联,pv中定义hostPath,pod固定调度节点
[root@matser data]# cat hostPath.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:name: hostpath-pvlabels:type: local
spec:storageClassName: ""capacity:storage: 10GiaccessModes:- ReadWriteManyhostPath:path: "/data/nginx"type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: hostpath-pvc
spec:accessModes:- ReadWriteManyresources:requests:storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-179namespace: default
spec:replicas: 1selector:matchLabels:app: nginx-179template:metadata:labels:app: nginx-179spec:nodeName: master					#固定pod能调度的节点,确保pod重启后仍能访问之前的数据containers:- image: nginx:1.7.9imagePullPolicy: IfNotPresentname: nginx-containerports:- containerPort: 80name: httpprotocol: TCPvolumeMounts:- mountPath: /var/log/nginxname: hostpath-volumerestartPolicy: Alwaysvolumes:- name: hostpath-volumepersistentVolumeClaim:		#使用pvcclaimName: hostpath-pvc
[root@matser data]# 
#创建完成pv和pvc,当pvc与pv绑定之后发现并没有创建hostPath目录,只有当pod调度到节点上时才会真正创建hostPath目录。
#当pod重启之后,如果pod没有指定调度的节点,则仍然会在其他节点创建hostPath目录,所以为了使pod能访问之前的数据,都要把pod固定调度到指定节点。
#hostPath示例三
#pod中使用pvc,pvc与pv关联,pv中定义hostPath且定义节点亲和性#为节点打标签,只打了一个节点,如果是多个节点,那么pod会随机调度到这些节点数据就没有唯一性而言。
[root@matser data]# kubectl  label  nodes node2 storage=true
[root@matser data]# cat hostPath.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:name: hostpath-pvlabels:type: local
spec:storageClassName: ""capacity:storage: 10GiaccessModes:- ReadWriteManyhostPath:path: "/data/nginx"type: DirectoryOrCreatenodeAffinity:							#定义了节点亲和性required:nodeSelectorTerms:- matchExpressions:				- key: storageoperator: Invalues:- "true"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: hostpath-pvc
spec:accessModes:- ReadWriteManyresources:requests:storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-179namespace: default
spec:replicas: 1selector:matchLabels:app: nginx-179template:metadata:labels:app: nginx-179spec:					#pod中不在指定调度节点而是有pv中定义了节点亲和性,k8s会根据pv的节点亲和性来判断pod要调度到哪些节点containers:- image: nginx:1.7.9imagePullPolicy: IfNotPresentname: nginx-containerports:- containerPort: 80name: httpprotocol: TCPvolumeMounts:- mountPath: /var/log/nginxname: hostpath-volumerestartPolicy: Alwaysvolumes:- name: hostpath-volumepersistentVolumeClaim:claimName: hostpath-pvc
[root@matser data]# 

hostPath卷总结:我们发现,无论是pod中直接使用hostPath,还是pod调用pvc,pvc调用pv,pv中使用hostPath,两者本质上没啥区别,示例1和实例2中都在pod中固定了调度节点,而实例3是在pv中定义了节点亲和性。

local卷

local 卷所代表的是某个被挂载的本地存储设备,例如磁盘、分区或者目录。
local 卷只能用作静态创建的持久卷。不支持动态配置。

与 hostPath 卷相比,local 卷能够以持久和可移植的方式使用,而无需手动将 Pod 调度到节点。系统通过查看 PersistentVolume 的节点亲和性配置,就能了解卷的节点约束。然而,local 卷仍然取决于底层节点的可用性,并不适合所有应用程序。 如果节点变得不健康,那么 local 卷也将变得不可被 Pod 访问。使用它的 Pod 将不能运行。 使用 local 卷的应用程序必须能够容忍这种可用性的降低,以及因底层磁盘的耐用性特征而带来的潜在的数据丢失风险。

下面是一个使用 local 卷和 nodeAffinity 的持久卷示例:

#local的使用和上面示例三hostPath卷的使用没多大区别,如下
[root@matser data]# cat local.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:name: local-pv
spec:capacity:storage: 10GivolumeMode: FilesystemaccessModes:- ReadWriteManypersistentVolumeReclaimPolicy: Retainlocal:								#这里定义的是local卷,path字段定义的是目录,这个目录必须先创建path: /data/nginxnodeAffinity:							#节点亲和性required:nodeSelectorTerms:- matchExpressions:- key: storageoperator: Invalues:- "true"          
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: local-pvc
spec:accessModes:- ReadWriteManyresources:requests:storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-179namespace: default
spec:replicas: 1selector:matchLabels:app: nginx-179template:metadata:labels:app: nginx-179spec:containers:					#没有定义节点选择器,k8s会根据pv定义的节点亲和性来调度pod- image: nginx:1.7.9imagePullPolicy: IfNotPresentname: nginx-containerports:- containerPort: 80name: httpprotocol: TCPvolumeMounts:- mountPath: /var/log/nginxname: local-volumerestartPolicy: Alwaysvolumes:- name: local-volumepersistentVolumeClaim:claimName: local-pvc
[root@matser data]# 
使用 local 卷时,你需要设置 PersistentVolume 对象的 nodeAffinity 字段。 Kubernetes 调度器使用 PersistentVolume 的 nodeAffinity 信息来将使用 local 卷的 Pod 调度到正确的节点。
PersistentVolume 对象的 volumeMode 字段可被设置为 "Block" (而不是默认值 "Filesystem"),以将 local 卷作为原始块设备暴露出来。
使用 local 卷时,建议创建一个 StorageClass 并将其 volumeBindingMode 设置为 WaitForFirstConsumer。要了解更多详细信息,请参考 local StorageClass 示例。 延迟卷绑定的操作可以确保 Kubernetes 在为 PersistentVolumeClaim 作出绑定决策时,会评估 Pod 可能具有的其他节点约束,例如:如节点资源需求、节点选择器、Pod 亲和性和 Pod 反亲和性。

总结:local卷和hostPath没啥区别,都可以通过在pv中定义节点亲和性,这样使用该pv的pod就会被k8s调度到指定的节点。唯一区别的是,local可以使用裸设备磁盘、分区、目录,而hostPath只能是文件或目录。

local-path-provisioner动态供给localPath或local卷

无论是hostPath卷还是local 卷,他们都不支持动态扩容,而local-path-provisioner很好的弥补了这一缺陷。

kubernetes-sigs版:https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner
注意kubernetes-sigs版不支持动态扩容/动态供给dynamically provisioning,所以建议使用rancher版。这里介绍的都是rancher版。
rancher版:https://github.com/rancher/local-path-provisioner

下载local-path-provisioner yml文件

# 进入https://github.com/rancher/local-path-provisioner,里面有很详细的安装教程
#安装local-path-provisioner
wget https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.24/deploy/local-path-storage.yaml

查看官方configmap解析

#local-path-storage.yaml中定义了一个configmap,我们先来看下官方样例中对这个cm的介绍.
provisioner的配置存储在一个configmap中,configmap包含1个json文件配置即config.json、1个Pod模板即helperPod.yaml、两个bash脚本即setup和teardown,如下所示:kind: ConfigMap
apiVersion: v1
metadata:name: local-path-confignamespace: local-path-storage
data:config.json: |-{"nodePathMap":[{"node":"DEFAULT_PATH_FOR_NON_LISTED_NODES","paths":["/opt/local-path-provisioner"]},{"node":"yasker-lp-dev1","paths":["/opt/local-path-provisioner", "/data1"]},{"node":"yasker-lp-dev3","paths":[]}]}setup: |-#!/bin/shset -eumkdir -m 0777 -p "$VOL_DIR"teardown: |-#!/bin/shset -eurm -rf "$VOL_DIR"helperPod.yaml: |-apiVersion: v1kind: Podmetadata:name: helper-podspec:containers:- name: helper-podimage: busyboxnodePathMap字段是一个数组,用于自定义在每个节点上存储数据的位置。
如果一个节点没有在nodePathMap上列出,而Kubernetes想要在它上面创建卷,那么default_path_for_non_listd_nodes中指定的路径将被用于分配。
如果nodePathMap上列出了一个节点,则将使用paths中指定的路径进行发放。
如果仅列出了节点,但路径设置为[],则提供程序将拒绝在该节点上提供服务。
如果节点上指定了多个路径,则在provision供给时将随机选择路径。
规则:路径必须是绝对路径,路径不能是根/,一个节点可以有多个不同的路径,不能重复列出节点,一个节点不能列出相同的路径。sharedFileSystemPath允许提供者使用同时挂载在所有节点上的文件系统。在这种情况下,支持所有访问模式:ReadWriteOnce, ReadOnlyMany和ReadWriteMany存储声明。
另外,volumeBindingMode: Immediate可以在StorageClass定义中使用。
请注意nodePathMap和sharedFileSystemPath是互斥的。如果使用sharedFileSystemPath,则nodePathMap必须设置为[]。setup脚本:在创建卷之前运行setup脚本来在节点上准备卷目录。
teardown脚本:删除卷后运行teardown脚本,清理节点上的卷目录。
helperPod.yaml模板:用于创建一个helper pod,用这个helper pod来执行setup和teardown脚本。provisioner支持自动热重载,即可以在线修改local-path-config配置,provisioner会自动生效配置,从local-path-provisioner pod中可以查看日志,如果provisioner生效失败,则provisioner仍然会保持上一个有效的local-path-config配置。
#指定local-path-provisioner创建的卷类型,可以通过以下2种方式指定local-path-provisioner要给你创建什么类型的卷
当你手动创建PVC时,在pvc的中添加以下注解:
annotations:volumeType: <local or hostPath>亦可以在存储类的定义中添加以下注解:
StorageClass:
annotations:defaultVolumeType: <local or hostPath>需要注意的是:StorageClass的注释将应用于使用它的所有卷,如果PVC提供了注释,则覆盖SC上的注释。如果这两个注解都没有提供,那么默认使用hostPath。

开始安装local-path-provisioner

#查看修改local-path-storage.yaml内容
[root@matser data]# cat local-path-storage.yaml 
apiVersion: v1
kind: Namespace
metadata:name: local-path-storage
---
apiVersion: v1
kind: ServiceAccount
metadata:name: local-path-provisioner-service-accountnamespace: local-path-storage
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: local-path-provisioner-role
rules:- apiGroups: [ "" ]resources: [ "nodes", "persistentvolumeclaims", "configmaps" ]verbs: [ "get", "list", "watch" ]- apiGroups: [ "" ]resources: [ "endpoints", "persistentvolumes", "pods" ]verbs: [ "*" ]- apiGroups: [ "" ]resources: [ "events" ]verbs: [ "create", "patch" ]- apiGroups: [ "storage.k8s.io" ]resources: [ "storageclasses" ]verbs: [ "get", "list", "watch" ]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: local-path-provisioner-bind
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: local-path-provisioner-role
subjects:- kind: ServiceAccountname: local-path-provisioner-service-accountnamespace: local-path-storage
---
apiVersion: apps/v1
kind: Deployment
metadata:name: local-path-provisionernamespace: local-path-storage
spec:replicas: 1selector:matchLabels:app: local-path-provisionertemplate:metadata:labels:app: local-path-provisionerspec:serviceAccountName: local-path-provisioner-service-accountcontainers:- name: local-path-provisionerimage: rancher/local-path-provisioner:v0.0.24imagePullPolicy: IfNotPresentcommand:- local-path-provisioner- --debug- start- --config- /etc/config/config.jsonvolumeMounts:- name: config-volumemountPath: /etc/config/env:- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespacevolumes:- name: config-volumeconfigMap:name: local-path-config
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: local-pathannotations:					#添加了注释,表示StorageClass提供哪些卷类型,可以是hostPath和local,默认值为hostPathvolumeType: hostPath
provisioner: rancher.io/local-path
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Retain			#修改为Retain,原来默认是Delete
allowVolumeExpansion: true		#允许扩容
---
kind: ConfigMap
apiVersion: v1
metadata:name: local-path-confignamespace: local-path-storage
data:config.json: |-{"nodePathMap":[{"node":"DEFAULT_PATH_FOR_NON_LISTED_NODES",	#指定其它节点使用/data/local-path-provisioner目录作为存储"paths":["/data/local-path-provisioner"]	#存储目录,会自动创建},{"node":"master",			#指定使用master节点的/opt/local-path-provisioner目录作为存储"paths":["/opt/local-path-provisioner"]		#存储目录,会自动创建}	#如果不想让指定节点作为存储节点,则需显示的列出来,并且将该节点的path设置[]]}setup: |-#!/bin/shset -eumkdir -m 0777 -p "$VOL_DIR"teardown: |-#!/bin/shset -eurm -rf "$VOL_DIR"helperPod.yaml: |-apiVersion: v1kind: Podmetadata:name: helper-podspec:containers:- name: helper-podimage: busyboximagePullPolicy: IfNotPresent
[root@matser data]# kubectl apply -f  local-path-storage.yaml

创建pod、pvc进行验证

[root@matser data]# cat local-path.yaml 
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: local-path-pvc
spec:storageClassName: local-pathaccessModes:- ReadWriteOnceresources:requests:storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-179namespace: default
spec:replicas: 1selector:matchLabels:app: nginx-179template:metadata:labels:app: nginx-179spec:containers:- image: nginx:1.7.9imagePullPolicy: IfNotPresentname: nginx-containerports:- containerPort: 80name: httpprotocol: TCPvolumeMounts:- mountPath: /usr/share/nginx/htmlname: local-path-volumerestartPolicy: Alwaysvolumes:- name: local-path-volumepersistentVolumeClaim:claimName: local-path-pvc
[root@matser data]# kubectl apply -f  local-path.yaml#验证发现,pod随机调度到node2节点,并且已经自动创建了/data/local-path-provisioner/目录,并且存在权限是777的pvc-e04ceb06-1a30-4b83-8215-7786850f3d93_default_local-path-pvc目录,所有动态分配pv验证成功了。
#验证过程中发现,pv其实还是具有节点亲和性的,这说明,当节点挂掉的时候,pod无法重新调度到其他节点,因为pod使用的pv定义节点亲和性,
#这也难怪,provisioner创建的卷类型本身就是hostPath或local卷。
[root@matser data]# kubectl  get pv pvc-0926a91c-854a-400f-be54-ad3fdd5e0051  -oyaml
apiVersion: v1
kind: PersistentVolume
metadata:........hostPath:				#其实卷的类型仍是hostPathpath: /opt/local-path-provisioner/pvc-0926a91c-854a-400f-be54-ad3fdd5e0051_default_local-path-pvctype: DirectoryOrCreatenodeAffinity:			#具有节点亲和性required:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- master
........

存在的问题

#发现如果在pod中定义nodeName想让pod调度到某台节点,pod会无法调度,pod的events报错如下:
[root@matser data]# kubectl  describe  pod nginx-1791-5d444554cb-b2mvq 
Events:Type     Reason       Age   From     Message----     ------       ----  ----     -------Warning  FailedMount  6s    kubelet  Unable to attach or mount volumes: unmounted volumes=[local-path-volume], unattached volumes=[local-path-volume kube-api-access-c7h9m]: error processing PVC default/local-path-pvc1: PVC is not bound
查看pvc的报错如下:
[root@matser data]# kubectl  describe  pvc local-path-pvc1
Events:Type    Reason                Age               From                         Message----    ------                ----              ----                         -------Normal  WaitForFirstConsumer  5s (x2 over 15s)  persistentvolume-controller  waiting for first consumer to be created before binding这是怎么回事呢?pod显示pvc没有绑定,pvc又在等待pod来消费,这不是死循环吗。如果pod中不指定nodeName,让pod随机调度,是能正常创建的,但是一旦定义了nodeName就不能正常了,这是什么回事呢?

local-path-provisioner仅支持ReadWriteOnce访问模式

在写pvc的时候,如果将accessModes写成 ReadWriteMany,则pvc将一直处于penging状态,查看local-path-provisioner pod的日志或kubectl describe pvc local-path-pvc 发现了以下报错:

 Type     Reason                Age                  From                                                                                                Message----     ------                ----                 ----                                                                                                -------Normal   WaitForFirstConsumer  11m                  persistentvolume-controller                                                                         waiting for first consumer to be created before bindingNormal   ExternalProvisioning  102s (x42 over 11m)  persistentvolume-controller                                                                         waiting for a volume to be created, either by external provisioner "rancher.io/local-path" or manually created by system administratorNormal   Provisioning          52s (x7 over 11m)    rancher.io/local-path_local-path-provisioner-6464fcbd8b-bhmqs_d68778ed-2a18-4f48-9788-1b2dc0f2b88f  External provisioner is provisioning volume for claim "default/local-path-pvc"Warning  ProvisioningFailed    52s (x7 over 11m)    rancher.io/local-path_local-path-provisioner-6464fcbd8b-bhmqs_d68778ed-2a18-4f48-9788-1b2dc0f2b88f  failed to provision volume with StorageClass "local-path": Only support ReadWriteOnce access mode
[root@matser data]# kubectl  describe  pvc local-path-pvc 
#怎么local-path-provisioner创建的pv仅支持ReadWriteOnce访问模式而已的呢?

卸载local-path-provisioner

#1、手动删除pv,确保已经没有pv是使用local-path 这个存储类的
#2、kubectl delete  -f local-path-storage.yaml
#3、手动删除节点上的目录

总结

1、pod中直接使用hostPath来挂载宿主机的指定目录,但是为了防止pod重启后没有调度到上一次调度的宿主机节点,所以pod中需要定义nodeName指定调度主机。
2、可以在pv中使用hostPath,然后创建pvc与pv进行绑定,然后pod中使用pvc即可,pod中仍需要定义nodeName指定调度主机。
3、可以在pv中使用hostPath并且pv中定义节点亲和性,然后创建pvc与pv进行绑定,然后pod中使用pvc即可,此时pod中不需要定义nodeName指定调度主机,k8s会根据pv中定义的节点亲和性来选择调度pod,这样其实也是间接的指定了pod要调度的主机。
4、local的使用和上面第3点相同,都是在pv中定义节点亲和性,local与hostPath的区别在于,local可以使用裸设备、目录、分区,而hostPath只能是目录或文件。
5、local和hostPath都没有动态供给,都是手动的。
6、引入local-path-provisioner只是为了实现local或hostPath的动态供给。
7、创建一个local-path-provisioner 的pod、存储类、cm、服务账号等资源对象来实现动态供给。
8、本质上local-path-provisioner提供的卷仍是hostPath或local,所以local-path-provisioner提供的pv仍是具有节点亲和性的,这就说明当宿主机挂机了的时候,由于pod绑定的pv具有节点亲和性,所以pod无法在其他节点重新调度,pod就会存在故障。这其实就是hostPath、local卷的劣势。
9、使用local-path-provisioner动态供给pv,发现pod无法使用nodeName节点选择器,这一点有待研究。
10、使用local-path-provisioner动态供给pv,pvc只能是ReadWriteOnce,因为local-path-provisioner pod显示StorageClass "local-path": Only support ReadWriteOnce access mode

相关文章:

local-path-provisioner的使用(hostPath、local、local-path-provisioner三者对比)

前言 环境&#xff1a;k8s 1.22.17 、centos7.9 有时候&#xff0c;为了使用本地服务器上的磁盘存储资源&#xff0c;我们会使用hostPath这种方式来为k8s提供本地存储&#xff0c;本篇就来对比一下hostPath、local这两种使用本地服务器储存的方案&#xff0c;从而引出第三种lo…...

命令行快捷键Mac Iterm2

原文:Jump forwards, backwards and delete a word in iTerm2 on Mac OS iTerm2并不允许你使用 ⌥← 或 ⌥→ 来跳过单词。 你也不能使用 ⌥backspace 来删除整个单词。 下面是在Mac OS上如何配置iTerm2以便能做到这一点的方法。 退格键 首先&#xff0c;你需要将你的左侧 ⌥…...

无涯教程-Lua - Modules(模块)

模块就像可以使用 require 加载的库&#xff0c;并且具有包含Table的单个全局名称&#xff0c;该模块可以包含许多函数和变量。 Lua 模块 其中一些模块示例如下。 -- Assuming we have a module printFormatter -- Also printFormatter has a funtion simpleFormat(arg) -- …...

url重定向

不安全的url跳转 不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。 如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话 就可能发生"跳错对象"的问题。 url跳转比较直接的危害是…...

Linux 查看IP地址、子网掩码和网关的配置信息

使用以下命令来查看IP地址、子网掩码和网关的配置信息&#xff1a; 1&#xff0c;使用ifconfig命令&#xff1a; ifconfig 在输出中&#xff0c;找到你正在使用的网络接口的配置信息。你将看到类似以下的内容&#xff1a; eth0: flags4163<UP,BROADCAST,RUNNING,MULTICA…...

token

token验证流程&#xff1a; ①客户端使用用户名和密码请求登录。 ②服务端收到请求&#xff0c;验证用户名和密码。 ③验证成功后&#xff0c;服务端会生成一个token&#xff0c;然后把这个token发送给客户端。 ④客户端收到token后把它存储起来&#xff0c;可以放在cookie…...

利用awk筛选给定时间范围内的日志

文章目录 筛选给定时间范围内的日志时间时间戳什么是时间戳&#xff1f; 系统时间 筛选日志时间示例简单示例mktime()函数是什么 进阶示例 筛选给定时间范围内的日志 时间 时间的表示方法&#xff1a; 时间戳系统时间&#xff08;年月日时间&#xff09; 时间戳 什么是时间…...

ORACLE字符集概念学习

1、字符集的一些基本知识 字符集有很多种&#xff0c;最初的字符集是ASCII&#xff0c;由于ASCII支持的字符很有限&#xff0c;因此随后又出现了很多的编码方案&#xff0c;这些编码方案大部分都是包括了ASCII 的。EBCDIC编码是另一个比较基本的编码&#xff0c;它的部分字符采…...

时间复杂度、空间复杂度实践练习(力扣OJ)

目录 文章目录 前言 题目一&#xff1a;轮转数组 思路一&#xff1a; 思路二&#xff1a; 思路三&#xff1a; 题目二&#xff1a;消失的数字 思路一&#xff1a; 思路二&#xff1a; 思路三&#xff1a; 题目三&#xff1a;移除元素 思路&#xff1a; 总结 前言 想要编写高效的…...

JMeter(二十四)、使用吞吐量控制器实现不同的用户操纵不同的业务

一、需求 需求&#xff1a;博客系统&#xff0c;模拟用户真实行为&#xff0c;80%的用户阅读文章&#xff0c;20%的用户创建文章&#xff0c;创建文章的用户随机的删除或者修改文章。 二、脚本实现 80%的用户查看文章 20%用户创建文章 根据post_id是否能整除2&#xff0c;决…...

8.1Jmeter5.1:Jmeter SSL

Jmeter配置证书请求双向认证SSL的web接口 需求:需要通过Jmeter配置证书请求双向认证SSL的web接口 提供的证书:P12格式 备注:Jmeter需要导入的证书是keystore证书 那么要先把P12转成keystore文件 1、使用p12生成keystore文件 keytool介绍 这里需要提到提到jdk自带的key…...

7-7 找最小的字符串 (15 分)

7-7 找最小的字符串 &#xff08;15 分) 本题要求编写程序&#xff0c;针对输入的N个字符串&#xff0c;输出其中最小的字符串。 输入格式&#xff1a; 输入第一行给出正整数N&#xff1b;随后N行&#xff0c;每行给出一个长度小于80的非空字符串&#xff0c;其中不会出现换行…...

Red Hat 安装MySQL 8.0与 Navicat

目录 Red Hat 安装 MySQL 8.0 1、更新软件包列表 2、安装MySQL服务器和客户端 3、启动MySQL服务 4、确保MySQL服务器正在运行 5、root 用户的密码 6、登录MySQL&#xff0c;输入mysql密码 7、MySQL默认位置 Red Hat 安装 Navicat 1、下载 Navicat 2、执行命令 Red H…...

17游刃有余:动手实现自己的RPC框架(三)

这篇文章我们来实现跨语言的网络通信。 跨语言RPC框架的必要性主要体现在以下几个方面: 解决不同语言之间的互操作性。不同语言使用的数据类型和序列化方式可能不同,跨语言 RPC 框架可以提供通用的编解码库和语言适配器,以便将不同语言的数据转换为通用的格式进行通信。实现…...

c语言——求n之内的素数和

//求n之内的素数和 //列如&#xff1a;2、3、5等 #include<stdio.h> #include<math.h> int main() {int i,j,k,n0;scanf("%d",&n);for(i2;i<n;i){k(int)sqrt(i);for(j2;j<k;j)if(i%j0)break;if(j>k){printf("%d,",i);n;if(n%50)p…...

【M波段2D双树(希尔伯特)小波多分量图像去噪】基于定向M波段双树(希尔伯特)小波对多分量/彩色图像进行降噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

unity TextMeshPro 富文本

<b>粗体标签</b> <i>斜体标签</i> <u>下划线标签</u> <s>删除线标签</s> <sup>上标标签</sup>前面后边上标签 5<sup>。</sup>C <sub>下标标签&#xff0c;如&#xff1a;</sub>H<sub&…...

【PyTorch】PyTorch、Cuda 的安装和使用

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、Anaconda 中安装 PyTorch 和 CUDA二、检查PyTorch和CUDA版本三、PyTorch的基本使用四、PyTorch调用cuda五、Matplotlib绘制Pytorch损…...

1.初识typescript

在很多地方的示例代码中使用的都是ts而不是js&#xff0c;为了使用那些示例&#xff0c;学习ts还是有必要的 JS有的TS都有&#xff0c;JS与TS的关系很像css与less ts在运行前需要先编译为js&#xff0c;浏览器不能直接运行ts 目录 1 编译TS的工具包 1.1 安装 1.2 基本…...

iPhone 6透明屏是什么?原理、特点、优势

iPhone 6透明屏是一种特殊的屏幕技术&#xff0c;它能够使手机屏幕变得透明&#xff0c;让用户能够透过屏幕看到手机背后的物体。 这种技术在科幻电影中经常出现&#xff0c;给人一种未来科技的感觉。下面将介绍iPhone 6透明屏的原理、特点以及可能的应用。 iPhone 6透明屏的原…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能&#xff1a;服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...