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

《每天5分钟玩转kubernetes》读书笔记

笔记

概念

Pod是脆弱的,但应用是健壮的。

kubelet运行在Cluster所有节点上,负责启动Pod和容器。kubeadm用于初始化Cluster。kubectl是k8s命令行工具。通过kubectl可以部署和管理应用,查看各种资源,创建、删除和更新各种组件。

Pending、ContainerCreating、ImagePullBackOff都表明Pod没有就绪,Running才是就绪状态。

k8s的系统组件都被放到kube-system namespace中。

kubelet是唯一没有以容器形式运行的k8s组件,它在Ubuntu中通过Systemd服务运行。

出于安全考虑,默认配置下k8s不会将Pod调度到Master节点。如果希望将k8s-master也当作Node使用,可执行如下命令:
kubectl taint node <k8s-node> node-role.kubernetes.io/master-
如果要恢复Master Only状态,执行如下命令:
kubectl taint node <k8s-node> node-role.kubernetes.io/master="":NoSchedule

默认配置下,Scheduler会将Pod调度到所有可用的Node。不过有些情况希望将Pod部署到指定的Node,如将有大量磁盘I/O的Pod部署到配置SSD的Node;或Pod需要GPU,需要运行在配置GPU的节点上。k8s是通过label来实现这个功能的。

设置label:
kubectl label node <k8s-node> disktype=ssd
查看节点的label:
kubectl get node --show-labels
然后可以编辑 yml 文件设置nodeSelector:disktype:ssd
删除label,-即删除的意思:
kubectl label node <k8s-node> disktype-
删除label后,除非在yml中删除nodeSelector设置,并执行kubectl apply命令重新部署,否则删除label不会生效。

Service

Service从逻辑上代表一组Pod,具体是哪些Pod则是由label来挑选的。Service有自己的不变的IP,客户端只需要访问Service的IP,k8s则负责建立和维护Service与Pod的映射关系。无论后端Pod如何变化,对客户端没有任何影响,因为Service没有变。

Cluster IP是一个虚拟IP,是由k8s节点上的iptables规则管理的。可以通过iptables-save命令打印出当前节点的iptables规则。Cluster的每一个节点都配置了相同的iptables规则,这样就确保了整个Cluster都能够通过Service的Cluster IP访问Service。

除可以通过Cluster IP访问Service,k8s还提供更为方便的DNS访问。k8s部署时会默认安装kube-dns组件,每当有新的Service被创建,kube-dns会添加该Service的DNS记录。Cluster中的Pod可以通过<SERVICE_NAME>.<NAMESPACE_NAME>访问Service。如果在同一个namespace,则可以省略.<NAMESPACE_NAME>

DNS服务器是kube-dns.kube-system.svc.cluster.local,这实际上就是kube-dns组件,它本身是部署在kube-system namespace中的一个Service。

用nslookup查看httpd-svc的DNS信息。

除了Cluster内部可以访问Service,很多情况下也希望应用的Service能够暴露给Cluster外部。k8s提供多种类型的Service,默认是ClusterIP:

  • ClusterIP:Service通过Cluster内部的IP对外提供服务,只有Cluster内的节点和Pod可访问,这是默认的Service类型
  • NodePort:Service通过Cluster节点的静态端口对外提供服务。Cluster外部可以通过<NodeIP>:<NodePort>访问Service
  • LoadBalancer:Service利用cloud provider特有的load balancer对外提供服务,cloud provider负责将load balancer的流量导向Service。目前支持的cloud provider有GCP、AWS、Azure等。

DaemonSet

典型应用场景:

  1. 在集群的每个节点上运行存储Daemon,如glusterd或ceph
  2. 在每个节点上运行日志收集Daemon,如flunentd或logstash
  3. 在每个节点上运行监控Daemon,如Prometheus Node Exporter或collectd

Job Pod执行完容器已经退出,需要用--show-all才能查看Completed状态的Pod。

同时运行多个Pod,提高Job的执行效率。这个可以通过parallelism设置。
completions设置Job成功完成Pod的总数。

spec:completions: 6parallelism: 2

配置解读:每次运行两个Pod,直到总共有6个Pod成功完成。
如果不指定completions和parallelism,默认值均为1。

k8s默认没有enable CronJob功能,需要在kube-apiserver中加入这个功能,修改kube-apiserver的配置文件/etc/kubernetes/manifests/kubeapiserver.yaml,在启动参数中加上--runtime-config=batch/v2alpha1=true,然后重启kubelet服务即可:systemctl restart kubelet.service
验证,输入命令kubectl api-versions,或者执行更精确的命令:kubectl api-versions | grep batch/v2alpha1

健康检查

即Health Check。
k8s默认的健康检查机制:每个容器启动时都会执行一个进程,此进程由Dockerfile的CMD或ENTRYPOINT指定。如果进程退出时返回码非零,则认为容器发生故障,k8s就会根据restartPolicy重启容器。

Liveness探测指定k8s什么时候通过重启容器实现自愈;
Readiness探测指定k8s什么时候可以将容器加入到Service负载均衡池中,对外提供服务。

区别:

  1. Liveness探测和Readiness探测是两种Health Check机制,如果不特意配置,k8s将对两种探测采取相同的默认行为,即通过判断容器启动进程的返回值是否为零来判断探测是否成功
  2. 两种探测的配置方法完全一样,支持的配置参数也一样。不同之处在于探测失败后的行为:Liveness探测是重启容器;Readiness探测则是将容器设置为不可用,不接收Service转发的请求
  3. Liveness探测和Readiness探测是独立执行的,二者之间没有依赖,可单独使用,也可以同时使用。用Liveness探测判断容器是否需要重启以实现自愈;用Readiness探测判断容器是否已经准备好对外提供服务。

健康检查的应用场景:

  1. Scale Up
  2. Rolling Update

滚动更新通过参数maxSurge和maxUnavailable来控制副本替换的数量:

  1. maxSurge:控制滚动更新过程中副本总数超过DESIRED的上限。可以是具体的整数,也可以是百分百,向上取整。maxSurge默认值为25%
  2. maxUnavailable:控制滚动更新过程中,不可用的副本相占DESIRED的最大比例。可以是具体的整数,也可以是百分百,向下取整。maxUnavailable默认值为25%

maxSurge值越大,初始创建的新副本数量就越多;maxUnavailable值越大,初始销毁的旧副本数量就越多。

滚动更新失败,可以通过kubectl rollout undo回滚到上一个版本

回滚

kubectl apply每次更新应用时,k8s都会记录下当前的配置,保存为一个revision,这样就可以回滚到某个特定revision。默认配置下,k8s只会保留最近的几个revision,可在Deployment配置文件中通过revisionHistoryLimit属性配置revision数量。

数据管理

容器和Pod是短暂的。其含义是它们的生命周期可能很短,会被频繁地销毁和创建。容器销毁时,保存在容器内部文件系统中的数据都会被清除。为了持久化保存容器的数据,可以使用k8s Volume。Volume的生命周期独立于容器,Pod中的容器可能被销毁和重建,但Volume会被保留。

本质上,k8s Volume是一个目录,这一点与Docker Volume类似。k8s Volume也支持多种backend类型,包括emptyDir、hostPath、GCE Persistent Disk、AWS Elastic Block Store、NFS、Ceph等。

emptyDir Volume对于容器来说是持久的,对于Pod则不是。当Pod从节点删除时,Volume的内容也会被删除。但如果只是容器被销毁而Pod还在,则Volume不受影响。

emptyDir Volume的生命周期与Pod一致。Pod中的所有容器都可以共享Volume,它们可以指定各自的mount路径。

PVC

Pod通常是由应用的开发人员维护,Volume则通常是由存储系统的管理员维护。开发人员要获得上面的信息,要么询问管理员,要么自己就是管理员。这样就带来一个管理上的问题:应用开发人员和系统管理员的职责耦合在一起了。

解决方案:PVC
PV:PersistentVolume,是外部存储系统中的一块存储空间,由管理员创建和维护。与Volume一样,PV具有持久性,生命周期独立于Pod。

PVC:PersistentVolumeClaim ,是对PV的申请(Claim)。PVC通常由普通用户创建和维护。需要为Pod分配存储资源时,用户可以创建一个PVC,指明存储资源的容量大小和访问模式(比如只读)等信息,k8s会查找并提供满足条件的PV。

有了PVC,用户只需要告诉k8s需要什么样的存储资源,而不必关心真正的空间从哪里分配、如何访问等底层细节信息。这些Storage Provider的底层信息交给管理员来处理,只有管理员才应该关心创建PersistentVolume的细节信息。

accessModes:支持的访问模式有3种,ReadWriteOnce表示PV能以read-write模式mount到单个节点,ReadOnlyMany表示PV能以read-only模式mount到多个节点,ReadWriteMany表示PV能以read-write模式mount到多个节点。

persistentVolumeReclaimPolicy:指定当PV的回收策略为Recycle,支持的策略有3种,Retain表示需要管理员手工回收;Recycle表示清除PV中的数据,效果相当于执行rm -rf/thevolume/*;Delete表示删除Storage Provider上的对应存储资源,例如AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume等。

回收PV

当不需要使用PV时,可用删除PVC回收PV。当PVC被删除后,k8s启动一个新Pod recycler-for-<pv>,这个Pod的作用就是清除PV的数据。此时mypv1的状态为Released,表示已经解除了与PVC的Bound,正在清除数据,不过此时还不可用。当数据清除完毕,PV的状态重新变为Available,此时可以被新的PVC申请。

PV还支持Delete的回收策略,会删除PV在Storage Provider上对应的存储空间。NFS的PV不支持Delete,支持Delete的Provider有AWS EBS、GCE PD、Azure Disk、OpenStack Cinder Volume。

PV动态供给

Static Provision:静态供给,提前创建PV,通过PVC申请PV并在Pod中使用。

Dynamical Provision:动态供给,即如果没有满足PVC条件的PV,会动态创建PV。相比静态供给,动态供给有明显的优势:不需要提前创建PV,减少管理员的工作量,效率高。动态供给是通过StorageClass实现的,StorageClass定义如何创建PV。StorageClass支持Delete和Retain两种reclaimPolicy,默认是Delete。

Secret & Configmap

Secret会以密文的方式存储数据,会以Volume的形式被mount到Pod,容器可通过文件的方式使用Secret中的敏感数据;此外,容器也可以环境变量的方式使用这些数据。

创建Secret的四种方法:

  • --from-literal:一个--from-literal对应一个信息条目
  • --from-file:一个文件内容对应一个信息条目
  • --from-env-file:文件中每行Key=Value对应一个信息条目
  • YAML:文件中的敏感数据必须是通过base64编码后数据

查看Secret

kubectl get secret <secret_name>
kubectl describe secret <secret_name>
kubectl edit secret <secret_name> # 查看加密信息

与Secret一样,ConfigMap也支持四种创建方式。

Helm

两个概念:chart和release

  • chart是创建一个应用的信息集合,包括各种k8s对象的配置模板、参数定义、依赖关系、文档说明等。chart是应用部署的自包含逻辑单元。可以将chart想象成apt、yum中的软件安装包
  • release是chart的运行实例,代表一个正在运行的应用。当chart被安装到k8s集群,就生成一个release。chart能够多次安装到同一个集群,每次安装都是一个release。

Helm是包管理工具,包就是指chart。Helm能够:

  • 从零创建新chart
  • 与存储chart的仓库交互,拉取、保存和更新chart
  • 在k8s集群中安装和卸载release
  • 更新、回滚和测试release

Helm包含两个组件:Helm客户端和Tiller服务器。

Helm客户端是终端用户使用的命令行工具,用户可以:

  • 在本地开发chart
  • 管理chart仓库
  • 与Tiller服务器交互
  • 在远程k8s集群上安装chart
  • 查看release信息
  • 升级或卸载已有的release

Tiller服务器运行在k8s集群中,它会处理Helm客户端的请求,与k8s API Server交互。Tiller服务器负责:

  • 监听来自Helm客户端的请求
  • 通过chart构建release
  • 在k8s中安装chart,并跟踪release的状态
  • 通过API Server升级或卸载已有的release

总结:Helm客户端负责管理chart,Tiller服务器负责管理release。

chart

Helm的应用打包格式,由一系列文件组成,这些文件描述k8s部署应用时所需要的资源。chart将这些文件放置在预定义的目录结构中,通常整个chart被打成tar包,标注上版本信息,便于Helm部署。

Helm采用Go语言的模板来编写chart。Go模板非常强大,支持变量、对象、函数、流控制等功能。

如果存在一些信息多个模板都会用到,则可在templates/_helpers.tpl中将其定义为子模板,然后通过templates函数引用。

randAlphaNumb64encquote都是Go模板语言支持的函数,函数之间可以通过管道|连接。

Helm有两种方式传递配置参数。

常用命令:

helm create mychart # 创建chart
helm lint mychart # 检测chart的语法,报告错误以及给出建议
helm install --dry-run mychart --debug  # 模拟安装chart,并输出每个模板生成的YAML内容
helm search mychart
helm repo add myrepo http://
helm install myrepo/mychart
helm repo update

任何HTTP Server都可以用作chart仓库。

Helm支持四种安装方法:

  1. 安装仓库中的chart,如helm install stable/nginx
  2. 通过tar包安装,如helm install./nginx-1.2.3.tgz
  3. 通过chart本地目录安装,如helm install./nginx
  4. 通过URL安装,如helm install https://example.com/charts/nginx-1.2.3.tgz

网络

基于扁平地址空间的网络模型,集群中的每个Pod都有自己的IP地址,Pod之间不需要配置NAT就能直接通信。另外,同一个Pod中的容器共享Pod的IP,能够通过localhost通信。

CNI,Container Networking Interface规范。CNI是由CoreOS提出的容器网络规范,使用插件(Plugin)模型创建容器的网络栈。

目前已有多种k8s网络方案,如Flannel、Calico、Canal、Weave Net等。因为它们都实现CNI规范,用户无论选择哪种方案,得到的网络模型都一样,即每个Pod都有独立的IP,可以直接通信。区别在于不同方案的底层实现不同,有的采用基于VxLAN的Overlay实现,有的则是Underlay,性能上有区别。再有就是是否支持Network Policy。

Network Policy

k8s的一种资源,Network Policy通过Label选择Pod,并指定其他Pod或外界如何与这些Pod通信。

默认情况下,所有Pod是非隔离的,即任何来源的网络流量都能够访问Pod,没有任何限制。当为Pod定义Network Policy时,只有Policy允许的流量才能访问Pod。不是所有的k8s网络方案都支持Network Policy。比如Flannel就不支持,Calico是支持的。
Canal用Flannel实现k8s集群网络,同时用Calico实现Network Policy。

Dashboard

k8s默认没有部署Dashboard,安装命令:
kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/charts/kubernetes-dashboard.yaml

Dashboard会在kube-system namespace中创建自己的Deployment和Service,

Service是ClusterIP类型,为方便使用,可通过kubectl --namespace=kube-system edit service kubernetes-dashboard修改成NodePort类型。

Dashboard支持Kubeconfig和Token两种认证方式。可以通过配置文件dashboard-admin.yaml为Dashboard默认用户赋予admin权限。

kubectl apply -f dashboard-admin.yaml命令使文件修改生效。

集群监控

Weave Scope

安装:``

Scope会自动构建应用和集群的逻辑拓扑,单击顶部PODS,会显示所有Pod以及Pod之间的依赖关系。

Scope支持关键字搜索和定位资源,还可以进行条件搜索,比如查找和定位MEMORY大于100MB的Pod。

Heapster

Heapster是k8s原生的集群监控方案。Heapster以Pod的形式运行,它会自动发现集群节点,从节点上的Kubelet获取监控数据。Kubelet则是从节点上的cAdvisor收集数据。Heapster将数据按照Pod进行分组,将它们存储到预先配置的backend并进行可视化展示。Heapster当前支持的backend有InfluxDB(通过Grafana展示)、Google Cloud Monitoring等。

整体架构
在这里插入图片描述

Prometheus Operator

Prometheus Operator基于基于Prometheus,可以监控k8s的API Server、Scheduler、Controller Manager等管理组件是否正常工作以及负荷是否过大。

Prometheus Operator的目标是尽可能简化在k8s中部署和维护Prometheus的工作。为方便管理,创建一个单独的Namespace monitoring,Prometheus Operator相关的组件都会部署到这个Namespace。

架构
在这里插入图片描述
组件

  • Prometheus Operator:在k8s中以Deployment运行。其职责是部署和管理Prometheus Server,根据ServiceMonitor动态更新Prometheus Server的监控对象。
  • Prometheus Server会作为k8s应用部署到集群中。为了更好地在k8s中管理Prometheus,CoreOS的开发人员专门定义了一个命名为Prometheus类型的k8s定制化资源。我们可以把Prometheus看作一种特殊的Deployment,它的用途就是专门部署Prometheus Server
  • Service就是Cluster中的Service资源,也是Prometheus要监控的对象,在Prometheus中叫作Target。每个监控对象都有一个对应的Service。比如要监控k8s Scheduler,就得有一个与Scheduler对应的Service。当然,k8s集群默认是没有这个Service的,Prometheus Operator会负责创建。
  • Operator能够动态更新Prometheus的Target列表,ServiceMonitor就是Target的抽象。比如想监控k8s Scheduler,用户可以创建一个与Scheduler Service相映射的ServiceMonitor对象。Operator则会发现这个新的ServiceMonitor,并将Scheduler的Target添加到Prometheus的监控列表中。ServiceMonitor也是Prometheus Operator专门开发的一种k8s定制化资源类型。
  • 除了Prometheus和ServiceMonitor,Alertmanager是Operator开发的第三种k8s定制化资源。我们可以把Alertmanager看作一种特殊的Deployment,它的用途就是专门部署Alertmanager组件。

集群日志管理

相关文章:

《每天5分钟玩转kubernetes》读书笔记

笔记 概念 Pod是脆弱的&#xff0c;但应用是健壮的。 kubelet运行在Cluster所有节点上&#xff0c;负责启动Pod和容器。kubeadm用于初始化Cluster。kubectl是k8s命令行工具。通过kubectl可以部署和管理应用&#xff0c;查看各种资源&#xff0c;创建、删除和更新各种组件。 …...

【RabbitMQ】golang客户端教程4——路由(使用direct交换器)

路由 在上一教程中&#xff0c;我们构建了一个简单的日志记录系统。我们能够向许多接收者广播日志消息。 在本教程中&#xff0c;我们将向它添加一个特性-我们将使它能够只订阅消息的一个子集。例如&#xff0c;我们将只能将关键错误消息定向到日志文件&#xff08;以节省磁盘…...

Shell脚本学习-for循环结构2

案例&#xff1a;通过脚本实现仅sshd、rsyslog、crond、network、sysstat服务在开机时自启动。 Linux系统在开机的服务通常工作在文本模式3级别&#xff0c;因此只需要查找3级别以上的开启的服务即可。查看命令&#xff1a; chkconfig --list |grep 3:on [rootvm1 ~]# chkco…...

vue 老项目 npm install 报错Python,c++等相关错误

​​​ 老项目npm install 下载依赖包报错 解决方法&#xff1a; //下载python 1、 npm install --global --production windows-build-tools//配置环境 &#xff1a; 也可暂时不用配置,能用就不用配置&#xff08;npm config set python "D:\Python27\python.exe&q…...

【c语言初级】c++基础

文章目录 1. C关键字2. 命名空间2.1 命名空间定义2.2 命名空间使用 3. C输入&输出4. 缺省参数4.1 缺省参数概念4.2 缺省参数分类 5. 函数重载5.2 C函数重载的原理--名字修饰采用C语言编译器编译后结果 1. C关键字 C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想…...

idea打开传统eclipse项目

打开传统web项目 1.打开后选择项目文件 2.选择项目结构 3.设置jdk版本 4.导入当前项目模块 5.选择eclipse 6. 设置保存目录 7.右键模块&#xff0c;添加spring和web文件 8. 设置web目录之类的&#xff0c;并且创建打包工具 9.如果有本地lib&#xff0c;添加为库 最后点击应用&…...

全国各城市-财政收入-一般预算收入-各项税收-个人所得税(1999-2020年)

个人所得税是一项反映国家财政状况和个人经济水平的重要数据。通过对全国各城市个人所得税数据的研究&#xff0c;可以提供研究者参考的有益信息。首先&#xff0c;个人所得税数据反映了不同城市居民的收入水平。通过对不同城市的个人所得税数据进行比较&#xff0c;可以了解不…...

【动态网页抓取】 :用Python抓取所有内容的指南

一、说明 您在抓取动态网页内容时是否得到了糟糕的结果&#xff1f;不仅仅是你。对于标准抓取工具来说&#xff0c;爬网动态数据是一项具有挑战性的任务&#xff08;至少可以说&#xff09;。这是因为当发出HTTP请求时&#xff0c;响应程序的某些部分JavaScript在后台运行&…...

Spring Boot数据访问基础知识与JDBC简单实现

目录 Spring Boot数据访问基础知识 Spring Data ORM JDBC JPA JDBC简单实现 步骤1&#xff1a;新建Maven项目&#xff0c;添加依赖 步骤2&#xff1a;配置数据源—让程序可以访问到 步骤3&#xff1a;配置数据源—让IDEA可以访问到 步骤4&#xff1a;添加数据库和表 …...

ubuntu添加万能头文件

ubuntu的C头文件目录为/usr/include 在/usr/include下新建文件夹 bits sudo mkdir bits进入bits&#xff0c;新建stdc.h&#xff0c;并修改权限为744/777 cd bits;sudo touch stdc.h;sudo chmod 777 stdc.h将以下内容粘贴到stdc.h&#xff0c;保存退出 // C includes used …...

聊一聊关于前端语法 ?? 的那些事

当我们在编写前端代码时&#xff0c;语法是非常重要的。正确的语法可以确保我们的代码能够正常运行&#xff0c;并且易于维护和理解。在本文中&#xff0c;我们将探讨一些前端语法的问题&#xff0c;例如空值合并运算符&#xff08;??&#xff09;。 空值合并运算符是ES2020…...

宝塔Linux面板升级“获取更新包失败”怎么解决?

宝塔Linux面板执行升级命令后失败&#xff0c;提示“获取更新包失败&#xff0c;请稍后更新或联系宝塔运维”如何解决&#xff1f;新手站长分享宝塔面板升级失败的解决方法&#xff1a; 宝塔面板升级失败解决方法 1、使用root账户登录到你的云服务器上&#xff0c;宝塔Linux面…...

训练强化学习的经验回放策略:experience replay

经验回放&#xff1a;Experience Replay&#xff08;训练DQN的一种策略&#xff09; 优点&#xff1a;可以重复利用离线经验数据&#xff1b;连续的经验具有相关性&#xff0c;经验回放可以在离线经验BUFFER随机抽样&#xff0c;减少相关性&#xff1b; 超参数&#xff1a;Rep…...

uniapp学习

1 简单的表单校验 <!--uniapp:参考模板和字段生成页面 字段stuNumber 输入框 学号stuName 输入框 学生姓名teacher 输入框 辅导员submitDate 日期选择 填报日期morningTemperature 输入框&#xff08;数字校验一位小数&#xff09; 早上体温noonTemperature 输入框&…...

机器学习深度学习——数值稳定性和模型化参数(详细数学推导)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——Dropout &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们有所帮助 这一部…...

layui 整合UEditor 百度编辑器

layui 整合UEditor 百度编辑器 第一步&#xff1a;下载百度编辑器并配置好路径 百度编辑器下载地址&#xff1a;http://fex.baidu.com/ueditor/ 第二步&#xff1a;引入百度编辑器 代码如下&#xff1a; <div class"layui-form-item layui-form-text"><…...

1、sparkStreaming概述

1、sparkStreaming概述 1.1 SparkStreaming是什么 它是一个可扩展&#xff0c;高吞吐具有容错性的流式计算框架 吞吐量&#xff1a;单位时间内成功传输数据的数量 之前我们接触的spark-core和spark-sql都是处理属于离线批处理任务&#xff0c;数据一般都是在固定位置上&…...

【Spring Boot】Spring Boot 集成 RocketMQ 实现简单的消息发送和消费

文章目录 前言基本概念消息和主题相关发送普通消息 发送顺序消息RocketMQTemplate的API介绍参考资料&#xff1a; 前言 本文主要有以下内容&#xff1a; 简单消息的发送顺序消息的发送RocketMQTemplate的API介绍 环境搭建&#xff1a; RocketMQ的安装教程&#xff1a;在官网…...

uniapp:图片验证码检验问题处理

图形验证码功能实现 uniapp&#xff1a;解决图形验证码问题及利用arraybuffer二进制转base64格式图片&#xff08;后端传的图片数据形式&#xff1a;x00\x10JFIF\x00\x01\x02\x00…&#xff09;_❆VE❆的博客-CSDN博客 UI稿&#xff1a; 需求&#xff1a;向后端请求验证码图片&…...

将Visio和Excel导出成没有白边的PDF文件

1、VISIO如何无白边导出pdf格式 在使用Latex时&#xff0c;要导入矢量图eps格式。但是VISIO无法输出eps格式&#xff0c;这就需要将其导出为pdf。但是导出pdf时&#xff0c;往往会有大量的白边。VISIO无白边导出pdf格式的方法如下&#xff1a; 1.文件——开发工具——显示sha…...

String类及其工具类

一、String类 1.字符串对象 String str new String("hello");String对象是final修饰的&#xff0c;不可修改的&#xff0c;修改后的字符串对象是另外一个对象&#xff0c;只是修改了引用地址。每次创建都会创建一个新的对象。 2. 字面量 String s "hello&…...

踩坑(5)整合kafka 报错 java.net.UnknownHostException: 不知道这样的主机

java.net.UnknownHostException: 不知道这样的主机。 (5c0c3c629db9)at java.base/java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method) ~[na:na]at java.base/java.net.InetAddress$PlatformNameService.lookupAllHostAddr(InetAddress.java:933) ~[na:na]at java.ba…...

rust持续学习 get_or_insert_with

通常使用一个值 if(xnull)xsome_valid_value 忽然今天看见一段代码 pub fn get_id() -> u64 { let mut res struct.data.borrow_mut(); *res.get_or_insert_with(||{let mut xx ...... some logiclet id xx.id; id}); }感觉这个名字蛮奇怪的 insert 然后翻了一下代码&a…...

卡尔曼滤波 | Matlab实现无迹kalman滤波仿真

文章目录 效果一览文章概述研究内容程序设计参考资料效果一览 文章概述 卡尔曼滤波 | Matlab实现无迹kalman滤波仿真 研究内容 无迹kalman滤波(UKF)不是采用的将非线性函数线性化的做法。无迹kalman仍然采用的是线性kalman滤波的架构,对于一步预测方程,使用无迹变换(UT)来…...

C++---list常用接口和模拟实现

list---模拟实现 list的简介list函数的使用构造函数迭代器的使用list的capacitylist element accesslist modifiers list的模拟实现构造函数&#xff0c;拷贝构造函数和迭代器begin和endinsert和eraseclear和析构函数 源码 list的简介 list是用双向带头联表实现的一个容器&…...

[openCV]基于赛道追踪的智能车巡线方案V1

import cv2 as cv import os import numpy as npimport time# 遍历文件夹函数 def getFileList(dir, Filelist, extNone):"""获取文件夹及其子文件夹中文件列表输入 dir&#xff1a;文件夹根目录输入 ext: 扩展名返回&#xff1a; 文件路径列表""&quo…...

SpringIoc-个人学习笔记

Spring的Ioc、DI、AOP思想 Ioc Ioc思想&#xff1a;Inversion of Control&#xff0c;控制反转&#xff0c;在创建Bean的权利反转给第三方 DI DI思想&#xff1a;Dependency Injection&#xff0c;依赖注入&#xff0c;强调Bean之间的关系&#xff0c;这种关系由第三方负责去设…...

【一文搞懂泛型】

3.3泛型 3.3.1泛型出现的背景 泛型出现的背景有两点&#xff1a; 第一点是在集合容器中&#xff0c;如果没有指定对应类型的话&#xff0c;那么底层的元素就是object&#xff0c;要对容器中的元素进行存取的时候&#xff0c;取出来的同时需要进行类型转换&#xff0c;如果有…...

概念解析 | 利用MIMO雷达技术实现高性能目标检测的关键技术解析

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:MIMO雷达目标检测技术 参考资料:何子述, 程子扬, 李军, 等. 集中式 MIMO 雷达研究综述[J]. 雷达学报, 2022, 11(5): 805-829. 利用MIMO雷达技术实现高性能目标检测的关键技术解…...

Grafana制作图表-自定义Flink监控图表

简要 有时候我们在官网的Grafana下载的图表是这样的&#xff0c;如下图 #算子的处理时间&#xff0c;就是处理数据的延迟数据抓取&#xff0c;这个的说明看下下面的文章 metrics.latency.interval: 60 metrics.reporter.promgateway.class: org.apache.flink.metrics.prometh…...