当前位置: 首页 > 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透明屏的原…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...