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

kubernetes|云原生| 如何优雅的重启和更新pod---pod生命周期管理实务

前言:

kubernetes的管理维护的复杂性体现在了方方面面,例如,pod的管理,服务的管理,用户的管理(RBAC),网络的管理等等,因此,kubernetes安装部署完毕仅仅是万里长征的第一步,后面的运营和维护工作才是更为关键的东西。

那么,pod的生命周期是什么概念呢?这些和重启与更新这样的操作有着怎样的联系呢?进一步的说,什么是优雅,优雅的重启和更新有什么好处?如何做到优雅的重启和更新?

以上问题是本文想要搞清楚的,也应该搞清楚的问题,下面就以上问题做一个尽量详细的解答,如有不对的地方,还请各位轻喷(水或者火)

一,

pod的生命周期

Pod 是 Kubernetes 中最基本的工作单元,代表了一个可执行的应用程序实例。Pod 的生命周期由一系列状态组成,如下所示:

  1. Pending:表示 Pod 已经被创建,但尚未调度到任何节点上。
  2. Running:表示 Pod 已经被成功调度并正在运行。
  3. Succeeded:表示 Pod 所包含的所有容器都已经成功终止,且不会被重启。
  4. Failed:表示 Pod 所包含的至少有一个容器未能成功终止,或者 Pod 本身出现了故障。
  5. Unknown:表示无法确定 Pod 的状态,通常是由于 API 服务器无法与 Pod 进行通信。
  6. terrimer 挂起状态,表示此pod不可用,一般是删除期间的旧pod的状态

当然了,pod的状态还有十来种,例如,outofcpu 等等这样的,但主要的常用的状态就是上面的这些。

Pod创建:
      1. API Server 在接收到创建pod的请求之后,会根据用户提交的参数值来创建一个运行时的pod对象。
      2. 根据 API Server 请求的上下文的元数据来验证两者的 namespace 是否匹配,如果不匹配则创建失败。
      3. Namespace 匹配成功之后,会向 pod 对象注入一些系统数据,如果 pod 未提供 pod 的名字,则 API Server 会将 pod 的 uid 作为 pod 的名字。
      4. API Server 接下来会检查 pod 对象的必需字段是否为空,如果为空,创建失败。
      5. 上述准备工作完成之后会将在 etcd 中持久化这个对象,将异步调用返回结果封装成 restful.response,完成结果反馈。
      6. API Server 创建过程完成,剩下的由 scheduler 和 kubelet 来完成,此时 pod 处于 pending 状态。
      7. Scheduler选择出最优节点。
      8. Kubelet启动该Pod。
   Pod删除:
      1. 用户发出删除 pod 命令
      2. 将 pod 标记为“Terminating”状态
         监控到 pod 对象为“Terminating”状态的同时启动 pod 关闭过程
         endpoints 控制器监控到 pod 对象关闭,将pod与service匹配的 endpoints 列表中删除
         Pod执行PreStop定义的内容
      3. 宽限期(默认30秒)结束之后,若存在任何一个运行的进程,pod 会收到 SIGKILL 信号
      4. Kubelet 请求 API Server 将此 Pod 资源宽限期设置为0从而完成删除操作

那么,pod的生命周期运行机制是比较复杂的,上面只是粗略的说了一下,底层的东西并无必要在本文详细讲解,而一个pod从创建到彻底的删除或回收我们就可以简单的认为这是一个生命周期,而在此期间pod可能会经历种种状态,并不是简单的说一个pod创建完了就等待删除,这些想法是不正确的。

二,

pod生命周期的管理

由于kubernetes是一个自动化的容器管理平台,因此,我们总是希望pod被部署好后,是处于一个稳定的状态,也就是说除了running状态,其它的状态基本是不可接受的,除了部分的job类型或者init类型的pod,那么,现在的目标就很简单了,如何保持pod的状态总是running

下面以一个实际的例子来说明问题:

kubernetes的版本

[root@node1 ~]# kubectl get no -owide
NAME    STATUS   ROLES                  AGE    VERSION    INTERNAL-IP      EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION           CONTAINER-RUNTIME
node1   Ready    control-plane,master   117d   v1.23.16   192.168.123.11   <none>        CentOS Linux 7 (Core)   3.10.0-1062.el7.x86_64   docker://20.10.8
node2   Ready    control-plane,master   117d   v1.23.16   192.168.123.12   <none>        CentOS Linux 7 (Core)   3.10.0-1062.el7.x86_64   docker://20.10.8
node3   Ready    control-plane,master   117d   v1.23.16   192.168.123.13   <none>        CentOS Linux 7 (Core)   3.10.0-1062.el7.x86_64   docker://20.10.8
node4   Ready    worker                 117d   v1.23.16   192.168.123.14   <none>        CentOS Linux 7 (Core)   3.10.0-1062.el7.x86_64   docker://20.10.8

  创建了一个名为nginx的deployment,然后将它修改为两个副本,随后又修改为三个副本

kubectl create deployment nginx --image=nginx:1.18
kubectl scale deployment nginx  --replicas=2
kubectl scale deployment nginx  --replicas=3

创建一个nodeport类型的service将该后端服务发布出去,经查询,可以看到端口30353是对外端口:

kubectl expose deployment nginx --type=NodePort --port=80 --target-port=80
[root@node1 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP        117d
nginx        NodePort    10.96.24.248   <none>        80:30353/TCP   36s

此时,可以利用watch命令监听此服务:

watch curl -I http://192.168.123.11:30353/




OK,现在一切都还是正常的,那么,现在我们更新此deployment的镜像为1.20.1,这个时候会出现什么情况呢?

通过kubelet get events命令,可以发现,kubectl set 命令更改镜像不会对服务造成任何的影响,服务没有任何中断:

<invalid>   Normal    SuccessfulCreate         replicaset/nginx-648458674d   Created pod: nginx-648458674d-gldmc
<invalid>   Normal    Scheduled                pod/nginx-648458674d-gldmc    Successfully assigned default/nginx-648458674d-gldmc to node4
<invalid>   Normal    Pulling                  pod/nginx-648458674d-gldmc    Pulling image "nginx:1.20.1"
<invalid>   Normal    Starting                 node/node4                    Starting kubelet.
<invalid>   Normal    Pulled                   pod/nginx-648458674d-gldmc    Successfully pulled image "nginx:1.20.1" in 55.174012251s (55.174015279s including waiting)
<invalid>   Normal    Created                  pod/nginx-648458674d-gldmc    Created container nginx
<invalid>   Normal    Started                  pod/nginx-648458674d-gldmc    Started container nginx
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              Scaled down replica set nginx-6888c79454 to 2
<invalid>   Normal    SuccessfulDelete         replicaset/nginx-6888c79454   Deleted pod: nginx-6888c79454-g24tx
<invalid>   Normal    Killing                  pod/nginx-6888c79454-g24tx    Stopping container nginx
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              (combined from similar events): Scaled up replica set nginx-648458674d to 2
<invalid>   Normal    SuccessfulCreate         replicaset/nginx-648458674d   Created pod: nginx-648458674d-kfgb4
<invalid>   Normal    Scheduled                pod/nginx-648458674d-kfgb4    Successfully assigned default/nginx-648458674d-kfgb4 to node4
<invalid>   Normal    Pulled                   pod/nginx-648458674d-kfgb4    Container image "nginx:1.20.1" already present on machine
<invalid>   Normal    Created                  pod/nginx-648458674d-kfgb4    Created container nginx
<invalid>   Normal    Started                  pod/nginx-648458674d-kfgb4    Started container nginx
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              (combined from similar events): Scaled down replica set nginx-6888c79454 to 1
<invalid>   Normal    SuccessfulDelete         replicaset/nginx-6888c79454   Deleted pod: nginx-6888c79454-dhhts
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              (combined from similar events): Scaled up replica set nginx-648458674d to 3
<invalid>   Normal    Killing                  pod/nginx-6888c79454-dhhts    Stopping container nginx
<invalid>   Normal    SuccessfulCreate         replicaset/nginx-648458674d   Created pod: nginx-648458674d-v4lwp
<invalid>   Normal    Scheduled                pod/nginx-648458674d-v4lwp    Successfully assigned default/nginx-648458674d-v4lwp to node4
<invalid>   Normal    Pulled                   pod/nginx-648458674d-v4lwp    Container image "nginx:1.20.1" already present on machine
<invalid>   Normal    Created                  pod/nginx-648458674d-v4lwp    Created container nginx
<invalid>   Normal    Started                  pod/nginx-648458674d-v4lwp    Started container nginx
<invalid>   Normal    Killing                  pod/nginx-6888c79454-dhhts    Stopping container nginx
<invalid>   Warning   FailedKillPod            pod/nginx-6888c79454-dhhts    error killing pod: failed to "KillContainer" for "nginx" with KillContainerError: "rpc error: code = Unknown desc = Error response from daemon: No such container: 0c27aa115f96cbc5d713a2d508310d20035021046b59878ffc50bb2bd6ee9271"
<invalid>   Normal    SuccessfulDelete         replicaset/nginx-6888c79454   Deleted pod: nginx-6888c79454-gcw24
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              (combined from similar events): Scaled down replica set nginx-6888c79454 to 0
<invalid>   Normal    Killing                  pod/nginx-6888c79454-gcw24    Stopping container nginx
<invalid>   Normal    Starting                 node/node4                    Starting kubelet.
<invalid>   Normal    Scheduled                pod/nginx-6888c79454-tlczp    Successfully assigned default/nginx-6888c79454-tlczp to node4
<invalid>   Normal    SuccessfulCreate         replicaset/nginx-6888c79454   Created pod: nginx-6888c79454-tlczp
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              Scaled up replica set nginx-6888c79454 to 2
<invalid>   Normal    Starting                 node/node4                    Starting kubelet.
<invalid>   Normal    Starting                 node/node4                    Starting kubelet.
<invalid>   Normal    Starting                 node/node4                    Starting kubelet.
<invalid>   Normal    Pulled                   pod/nginx-6888c79454-tlczp    Container image "nginx:1.18" already present on machine
<invalid>   Normal    Created                  pod/nginx-6888c79454-tlczp    Created container nginx
<invalid>   Normal    Started                  pod/nginx-6888c79454-tlczp    Started container nginx
<invalid>   Normal    Starting                 node/node4                    Starting kubelet.
<invalid>   Normal    Starting                 node/node4                    Starting kubelet.
<invalid>   Normal    Starting                 node/node4                    Starting kubelet.
<invalid>   Normal    Starting                 node/node4                    Starting kubelet.
<invalid>   Normal    Scheduled                pod/nginx-6888c79454-6tfk2    Successfully assigned default/nginx-6888c79454-6tfk2 to node4
<invalid>   Normal    SuccessfulCreate         replicaset/nginx-6888c79454   Created pod: nginx-6888c79454-6tfk2
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              Scaled up replica set nginx-6888c79454 to 3
<invalid>   Normal    Starting                 node/node4                    Starting kubelet.
<invalid>   Normal    Pulled                   pod/nginx-6888c79454-6tfk2    Container image "nginx:1.18" already present on machine
<invalid>   Normal    Created                  pod/nginx-6888c79454-6tfk2    Created container nginx
<invalid>   Normal    Started                  pod/nginx-6888c79454-6tfk2    Started container nginx
<invalid>   Normal    Starting                 node/node4                    Starting kubelet.

说明:以上是kubernetes的调度过程,关键的地方如下,表示scale逐步扩张新镜像的pod,缩减旧镜像的pod:

(combined from similar events): Scaled up replica set nginx-648458674d to 2(combined from similar events): Scaled down replica set nginx-6888c79454 to 1
(combined from similar events): Scaled up replica set nginx-648458674d to 3
(combined from similar events): Scaled down replica set nginx-6888c79454 to 0

pod的最终状态如下:

[root@node1 ~]# kubectl get po -owide
NAME                     READY   STATUS    RESTARTS   AGE         IP             NODE    NOMINATED NODE   READINESS GATES
nginx-648458674d-gldmc   1/1     Running   0          <invalid>   10.244.41.18   node4   <none>           <none>
nginx-648458674d-kfgb4   1/1     Running   0          <invalid>   10.244.41.19   node4   <none>           <none>
nginx-648458674d-v4lwp   1/1     Running   0          <invalid>   10.244.41.20   node4   <none>           <none>

OK,这样的更新我们可以认为是一个平滑的,优雅的更新,而如果是通过部署清单yaml文件先删除deploment,在修改文件后重新创建deployment,这样的方式无疑是简单的,粗暴的,会导致服务中断的,此时我们认为这个更新不是平滑的,粗暴的一种更新方式。

那么,重启的话,只是省略掉修改部署清单yaml 文件这一步,同样的是粗暴的一种方式。

具体的操作也不就演示了,大体上就是kubectl delete -f 文件  然后kubelet apply -f文件  这种形式。

三,

更为精细的pod版本控制 kubectl rollout

以上介绍的两种pod管理方式,可以看出,并不是特别的精准,因为都是命令行的形式,所有更改并没有具体的体现,因此,平常的工作中,还是需要使用部署清单yaml文件的。

那么,kubectl rollout 命令是可以满足优雅重启和更新的,下面接上面的例子说明:

[root@node1 ~]# kubectl get po
NAME                     READY   STATUS    RESTARTS   AGE
nginx-648458674d-gldmc   1/1     Running   0          <invalid>
nginx-648458674d-kfgb4   1/1     Running   0          <invalid>
nginx-648458674d-v4lwp   1/1     Running   0          <invalid>

直接重启deployment控制器:

[root@node1 ~]# kubectl rollout restart deployment nginx
deployment.apps/nginx restarted

 

查看events:

命令:

kubectl get events -w

部分输出: 

<invalid>   Normal    ScalingReplicaSet        deployment/nginx              (combined from similar events): Scaled up replica set nginx-5fc8f974d9 to 1
<invalid>   Normal    SuccessfulCreate         replicaset/nginx-5fc8f974d9   Created pod: nginx-5fc8f974d9-9gn8z
<invalid>   Normal    Scheduled                pod/nginx-5fc8f974d9-9gn8z    Successfully assigned default/nginx-5fc8f974d9-9gn8z to node4
<invalid>   Normal    Pulled                   pod/nginx-5fc8f974d9-9gn8z    Container image "nginx:1.18" already present on machine
<invalid>   Normal    Created                  pod/nginx-5fc8f974d9-9gn8z    Created container nginx
<invalid>   Normal    Started                  pod/nginx-5fc8f974d9-9gn8z    Started container nginx
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              (combined from similar events): Scaled down replica set nginx-bf95bf86b to 2
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              (combined from similar events): Scaled up replica set nginx-5fc8f974d9 to 2
<invalid>   Normal    SuccessfulDelete         replicaset/nginx-bf95bf86b    Deleted pod: nginx-bf95bf86b-jsssl
<invalid>   Normal    Killing                  pod/nginx-bf95bf86b-jsssl     Stopping container nginx
<invalid>   Normal    SuccessfulCreate         replicaset/nginx-5fc8f974d9   Created pod: nginx-5fc8f974d9-nkcbd
<invalid>   Normal    Scheduled                pod/nginx-5fc8f974d9-nkcbd    Successfully assigned default/nginx-5fc8f974d9-nkcbd to node4
<invalid>   Normal    Pulled                   pod/nginx-5fc8f974d9-nkcbd    Container image "nginx:1.18" already present on machine
<invalid>   Normal    Created                  pod/nginx-5fc8f974d9-nkcbd    Created container nginx
<invalid>   Normal    Started                  pod/nginx-5fc8f974d9-nkcbd    Started container nginx
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              (combined from similar events): Scaled down replica set nginx-bf95bf86b to 1
<invalid>   Normal    SuccessfulDelete         replicaset/nginx-bf95bf86b    Deleted pod: nginx-bf95bf86b-98lpj
<invalid>   Normal    Killing                  pod/nginx-bf95bf86b-98lpj     Stopping container nginx
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              (combined from similar events): Scaled up replica set nginx-5fc8f974d9 to 3
<invalid>   Normal    SuccessfulCreate         replicaset/nginx-5fc8f974d9   Created pod: nginx-5fc8f974d9-xw64m
<invalid>   Normal    Scheduled                pod/nginx-5fc8f974d9-xw64m    Successfully assigned default/nginx-5fc8f974d9-xw64m to node4
<invalid>   Normal    Pulled                   pod/nginx-5fc8f974d9-xw64m    Container image "nginx:1.18" already present on machine
<invalid>   Normal    Created                  pod/nginx-5fc8f974d9-xw64m    Created container nginx
<invalid>   Normal    Started                  pod/nginx-5fc8f974d9-xw64m    Started container nginx
<invalid>   Normal    ScalingReplicaSet        deployment/nginx              (combined from similar events): Scaled down replica set nginx-bf95bf86b to 0
<invalid>   Normal    SuccessfulDelete         replicaset/nginx-bf95bf86b    Deleted pod: nginx-bf95bf86b-nfh5r

更新完毕后,pod的状态:

[root@node1 ~]# kubectl get po
NAME                    READY   STATUS    RESTARTS   AGE
nginx-bf95bf86b-98lpj   1/1     Running   0          <invalid>
nginx-bf95bf86b-jsssl   1/1     Running   0          <invalid>
nginx-bf95bf86b-nfh5r   1/1     Running   0          <invalid>[root@node1 ~]# kubectl get replicasets.apps 
NAME               DESIRED   CURRENT   READY   AGE
nginx-5fc8f974d9   3         3         3       <invalid>
nginx-648458674d   0         0         0       <invalid>
nginx-6888c79454   0         0         0       <invalid>
nginx-bf95bf86b    0         0         0       <invalid>

此时看rollout的历史,应该是4个,输出可以看到和上面的rc是一一对应的关系:

[root@node1 ~]# kubectl rollout history deployment 
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>
4         <none>

查看deployment的历史详情:

kubectl rollout history deployment nginx --revision=1
deployment.apps/nginx with revision #1
Pod Template:Labels:	app=nginxpod-template-hash=6888c79454Containers:nginx:Image:	nginx:1.18Port:	<none>Host Port:	<none>Environment:	<none>Mounts:	<none>Volumes:	<none>[root@node1 ~]# kubectl rollout history deployment nginx --revision=2
deployment.apps/nginx with revision #2
Pod Template:Labels:	app=nginxpod-template-hash=6888c79454Containers:nginx:Image:	nginx:1.18Port:	<none>Host Port:	<none>Environment:	<none>Mounts:	<none>Volumes:	<none>root@node1 ~]# kubectl rollout history deployment nginx --revision=3
deployment.apps/nginx with revision #3
Pod Template:Labels:	app=nginxpod-template-hash=bf95bf86bAnnotations:	kubectl.kubernetes.io/restartedAt: 2023-11-18T17:06:24+08:00Containers:nginx:Image:	nginx:1.18Port:	<none>Host Port:	<none>Environment:	<none>Mounts:	<none>Volumes:	<none>[root@node1 ~]# kubectl rollout history deployment nginx --revision=4
deployment.apps/nginx with revision #4
Pod Template:Labels:	app=nginxpod-template-hash=5fc8f974d9Annotations:	kubectl.kubernetes.io/restartedAt: 2023-11-18T17:10:02+08:00Containers:nginx:Image:	nginx:1.18Port:	<none>Host Port:	<none>Environment:	<none>Mounts:	<none>Volumes:	<none>

升级镜像到1.20.1 ,生成新历史版本5:

[root@node1 ~]# kubectl apply -f nginx.yaml 
deployment.apps/nginx configured
[root@node1 ~]# kubectl rollout history deployment nginx --revision=5
deployment.apps/nginx with revision #5
Pod Template:Labels:	app=nginxpod-template-hash=6469d4d479Annotations:	kubectl.kubernetes.io/restartedAt: 2023-11-18T17:10:02+08:00Containers:nginx:Image:	nginx:1.20.1Port:	<none>Host Port:	<none>Environment:	<none>Mounts:	<none>Volumes:	<none>

回滚版本到2:

先查询历史版本

[root@node1 ~]# kubectl get rs -o wide
NAME               DESIRED   CURRENT   READY   AGE         CONTAINERS   IMAGES         SELECTOR
nginx-5fc8f974d9   0         0         0       <invalid>   nginx        nginx:1.18     app=nginx,pod-template-hash=5fc8f974d9
nginx-6469d4d479   3         3         3       <invalid>   nginx        nginx:1.20.1   app=nginx,pod-template-hash=6469d4d479
nginx-648458674d   0         0         0       <invalid>   nginx        nginx:1.20.1   app=nginx,pod-template-hash=648458674d
nginx-6888c79454   0         0         0       <invalid>   nginx        nginx:1.18     app=nginx,pod-template-hash=6888c79454
nginx-bf95bf86b    0         0         0       <invalid>   nginx        nginx:1.18     app=nginx,pod-template-hash=bf95bf86b
[root@node1 ~]# kubectl rollout history deployment nginx 
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>
4         <none>
5         <none>[root@node1 ~]# kubectl rollout history deployment nginx --revision=2
deployment.apps/nginx with revision #2
Pod Template:Labels:	app=nginxpod-template-hash=6888c79454Containers:nginx:Image:	nginx:1.18Port:	<none>Host Port:	<none>Environment:	<none>Mounts:	<none>Volumes:	<none>

回滚:

[root@node1 ~]# kubectl rollout undo deployment nginx --to-revision=2
deployment.apps/nginx rolled back

查看是否正确回滚:

[root@node1 ~]# kubectl get deployments.apps -owide
NAME    READY   UP-TO-DATE   AVAILABLE   AGE    CONTAINERS   IMAGES       SELECTOR
nginx   3/3     3            3           177m   nginx        nginx:1.18   app=nginx

那么,重启pod一般常见的就是删除pod后在重新创建,但,对于多副本的pod来说,会有服务中断的风险,更新一般也是暴力方式删除pod后,修改后在重新启动了,或者副本数先设置为0后,在恢复到原先的设置。

而如果想要服务不中断的,优雅的更新或者重启,首选还得是kubectl rollout 命令啦。

相关文章:

kubernetes|云原生| 如何优雅的重启和更新pod---pod生命周期管理实务

前言&#xff1a; kubernetes的管理维护的复杂性体现在了方方面面&#xff0c;例如&#xff0c;&#xff50;&#xff4f;&#xff44;的管理&#xff0c;服务的管理&#xff0c;用户的管理&#xff08;&#xff32;&#xff22;&#xff21;&#xff23;&#xff09;&#xf…...

【总结】坐标变换和过渡矩阵(易忘记)

xCy&#xff0c;此为x到y的坐标变换。 [β1,β2,…,βn] [α1,α2,…αn]C&#xff0c;此为基α到基β的过渡矩阵。 这个概念经常忘记。。。alpha到beta看来就是alpha后面加一个过渡矩阵了&#xff0c;很直观。坐标变换就是根据过渡矩阵和基本形式推一推得到吧&#xff0c;记…...

第十一周任务总结

本周任务总结 本周物联网方面主要继续进行网关的二次开发与规则引擎实现设备联动的实现 非物联网方面主要复习了docker的使用与算法的学习 1.网关的二次开发&#xff0c;本周将实现debug调试输出的文件下载到了网关&#xff0c;但网关出了问题无法连接&#xff0c;最终跟客服…...

Java Web——JavaScript基础

1. 引入方式 JavaScript程序不能独立运行&#xff0c;它需要被嵌入HTML中&#xff0c;然后浏览器才能执行 JavaScript 代码。 通过 script 标签将 JavaScript 代码引入到 HTML 中&#xff0c;有3种方式&#xff1a; 1.1. 内嵌式(嵌入式) 直接写在html文件里&#xff0c;用s…...

Vue3 toRaw 和 markRaw

一、toRaw 我们可以使用ref 和 reactive 将普通对象类型的数据变为响应式的数据。 我们可以使用toRaw 将reactive 对象的数据变为一般对象类型的数据。 使用toRaw 需要先进行引入&#xff1a; import { toRaw } from vue; 语法格式&#xff1a; const xxx toRaw(数据) set…...

麒麟信安助力长沙市就业与社保数据服务中心政务系统向自主创新演进

应用场景 长沙市就业与社保数据服务中心依托长沙市“政务云”的公共基础资源和相应的支撑能力&#xff0c;围绕社保、就业、人事人才、劳动关系等人社全量业务服务&#xff0c;力求建立以“智慧服务、智慧监管、智慧决策”为核心的“智慧人社”综合服务平台&#xff0c;实现人…...

【LeetCode刷题-双指针】--16.最接近的三数之和

16.最接近的三数之和 方法&#xff1a;排序双指针 class Solution {public int threeSumClosest(int[] nums, int target) {Arrays.sort(nums);int ans nums[0] nums[1] nums[2];for(int i 0;i<nums.length;i){int start i1,end nums.length - 1;while(start < en…...

Mac 安装 protobuf 和Android Studio 使用

1. 安装,执行命令 brew install protoc 2. Mac 错误提示&#xff1a;zsh: command not found: brew解决方法 解决方法&#xff1a;mac 安装homebrew&#xff0c; 用以下命令安装&#xff0c;序列号选择中科大&#xff08;1&#xff09;或 阿里云 /bin/zsh -c "$(curl…...

MongoDB入门级别教程全(Windows版,保姆级教程)

下载mongodb 进入官网&#xff1a; Download MongoDB Community Server | MongoDB 选择msi&#xff0c;Windows版本 下载完后直接双击&#xff1a; 选择complete 这里建议改地方&#xff1a; 我这里直接改成d盘&#xff1a;work目录下面&#xff1a; 点击next&#xff1a; 因…...

基于机器学习的居民消费影响因子分析预测

项目视频讲解: 基于机器学习的居民消费影响因子分析预测_哔哩哔哩_bilibili 主要工作内容: 完整代码: import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import missingno as msno import warnings warnings.filterwarnin…...

Qt HTTP 摘要认证(海康球机摄像机ISAPI开发)

接到一个需求是开发下海康的球机,控制云台,给到我的是一个开发手册,当然了是海康的私有协议 ISAPI开发手册https://download.csdn.net/download/qq_37059136/88547425关于开发这块读文档就可以理解了,海康使用的是摘要认证,当然了海康已经给出使用范例 通过libcurl就可以直接连…...

srs webrtc推拉流环境搭建(公网)

本地环境搭建 官方代码https://github.com/ossrs/srs 拉取代码&#xff1a; git clone https://github.com/ossrs/srs.gitcd ./configure make ./objs/srs -c conf/https.rtc.confsrs在公网上&#xff0c;由于srs是lite-ice端&#xff0c;导致他不会主动到srs获取自己的公网i…...

【Flutter】设计原则(2)深入解析 SOLID 原则的应用

【Flutter】设计原则(2)深入解析 SOLID 原则的应用 文章目录 一、前言二、SOLID原则三、在 Flutter 中应用单一职责原则1. 专注单一功能的 Widget2. 提高代码可维护性四、在 Flutter 中应用开闭原则1. 利用多态和基类实现可扩展的 Widget2. 增强应用的可扩展性和灵活性五、在…...

python爬虫概述及简单实践:获取豆瓣电影排行榜

目录 前言 Python爬虫概述 简单实践 - 获取豆瓣电影排行榜 1. 分析目标网页 2. 获取页面内容 3. 解析页面 4. 数据存储 5. 使用代理IP 总结 前言 Python爬虫是指通过程序自动化地对互联网上的信息进行抓取和分析的一种技术。Python作为一门易于学习且强大的编程语言&…...

ts视频文件转为mp4(FFmpeg)

有些视频资源下载下来之后发现是.ts的文件&#xff0c;除了用下载它时用的工具或是浏览器才能看&#xff0c;那有没有将ts文件转换成更加通用视频格式的方法。 几乎万能的音视频工具--ffmpeg登场 安装和环境配置可看这篇博客&#xff1a;FFmpeg指令行打开usb摄像头&#xff0…...

2023年咸阳市《网络建设与运维》赛题解析------四、安全配置

安全配置 说明:IP地址按照题目给定的顺序用“ip/mask”表示,IPv4 any地址用0.0.0.0/0,IPv6 any地址用::/0,禁止用地址条目,否则按零分处理。 1.FW1配置IPv4 nat,实现集团产品1段IPv4访问Internet IPv4,转换ip/mask为200.200.200.16/28,保证每一个源IP产生的所有会话将…...

什么是java枚举?为什么要用java枚举?

什么是java枚举&#xff1f; 原始的接口定义常量 public interface IConstants {String MON "Mon";String TUE "Tue";String WED "Wed";String THU "Thu";String FRI "Fri";String SAT "Sat";String SUN …...

USB复合设备构建CDC+HID鼠标键盘套装

最近需要做一个小工具&#xff0c;要用到USB CDCHID设备。又重新研究了一下USB协议和STM32的USB驱动库&#xff0c;也踩了不少坑&#xff0c;因此把代码修改过程记录一下。 开发环境&#xff1a; ST-LINK v2 STM32H743开发板 PC windows 11 cubeMX v6.9.2 cubeIDE v1.13.2 cub…...

准备篇(四)HTTP 基本原理

URI 和 URLURIURLURI vs URLHTTP 和 HTTPS超文本HTTPHTTP 请求与响应HTTPS你是否想过,在浏览器中敲入 URL 到 获取网页内容 之间发生了什么? 了解这些,有助于进一步了解爬虫的基本原理。 URI 和 URL URI(Uniform Resource Identifier),即统一资源标识符;URL(Universa…...

模板初阶笔记分享

有道云笔记...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...