【GitOps系列】从零上手GitOps

文章目录

      • GitOps 介绍
      • 如何将业务代码构建为容器镜像?
      • 如何将容器镜像部署到K8s?
      • K8s如何实现自动扩容和自愈?
        • 1.传统的扩容和自愈
        • 2.k8s自愈机制
        • 3.k8s弹性扩容
      • 如何借助GitOps实现应用秒级自动发布和回滚?
        • 1.传统 K8s 应用发布流程
        • 2.从零搭建 GitOps 发布工作流
            • 1.安装fluxcd
            • 2.本地创建fluxcd目录并创建deploy
            • 3.为 FluxCD 创建仓库连接信息
            • 4.检查 GitRepository 对象
            • 5.为 FluxCD 创建部署策略
            • 6.体验gitops自动发布
            • 7.体验gitops自动回滚

GitOps 介绍

传送门: https://blog.csdn.net/zfw_666666/article/details/126158696

如何将业务代码构建为容器镜像?

前提:需要对Docker容器技术有一定的了解。

#业务代码示例:
root@node1:~# cat app.py 
from flask import Flask
import os
app = Flask(__name__)
app.run(debug=True)@app.route('/')
def hello_world():return 'Hello, my v1 version docker images!! ' + os.getenv("HOSTNAME") + ''
一、编写dockerfile
root@node1:~# cat Dockerfile 
# syntax=docker/dockerfile:1FROM python:3.8-slim-busterRUN apt-get update && apt-get install -y procps vim apache2-utils && rm -rf /var/lib/apt/lists/*WORKDIR /appRUN pip3 install Flask==2.3.0 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.comCOPY app.py .ENV FLASK_ENV=developmentCMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"]二、构建
$ docker build -t hello-world-flask .三、验证
$ docker run -d -p 8000:5000 hello-world-flask:latest四、推送至个人仓库
docker image tag ...
docker push ...
docker pull ccr.ccs.tencentyun.com/app-public/hello-world-flask-amd:latest

如何将容器镜像部署到K8s?

前提:需要本地有k8s集群环境及对k8s资源对象有一定的了解。

1.编写Manifest
root@node1:~# cat flask-dp.yaml 
apiVersion: v1
kind: Service
metadata:labels:app: hello-world-flaskname: hello-world-flask
spec:ports:- port: 5000protocol: TCPtargetPort: 5000selector:app: hello-world-flask---
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: hello-world-flaskname: hello-world-flask
spec:replicas: 2selector:matchLabels:app: hello-world-flasktemplate:metadata:labels:app: hello-world-flaskspec:containers:- image: ccr.ccs.tencentyun.com/app-public/hello-world-flask-amd:latestimagePullPolicy: IfNotPresentname: hello-world-flaskresources:limits:cpu: 100mrequests:cpu: 100m2.查看和访问 Pod
root@node1:~# kubectl get pods,svc |grep flask
pod/hello-world-flask-9d8967487-68kzq              1/1     Running     1 (2d2h ago)   2d3h
pod/hello-world-flask-9d8967487-mbwn9              1/1     Running     1 (2d2h ago)   2d3h
service/hello-world-flask    ClusterIP   10.233.47.55    <none>        5000/TCP            2d6hroot@node1:~# curl http://10.233.47.55:5000
Hello, my v1 version docker images!! hello-world-flask-9d8967487-68kzq

K8s如何实现自动扩容和自愈?

1.传统的扩容和自愈

在 VM 时代,我们的业务以进程的方式运行在虚拟机上,并由虚拟机对外提供服务。随着业务规模的扩大,我们需要支撑更多的访问流量,这时业务扩容就成了首先要考虑的问题。
在公有云环境下,VM 架构最典型的一种扩容方式是 弹性伸缩组。 意思是通过对虚拟机内存、CPU 等监控指标配置伸缩阈值,实现动态地自动伸缩。此外,我们一般还会结合虚拟机镜像、负载均衡器等云产品一并使用,如下图所示。
在这里插入图片描述
在这个架构中,负载均衡器是集群的唯一入口,它在接受访问流量后,一般会将流量通过加权轮训的方式转发到后端集群。负载均衡器一般是直接使用云厂商的产品,有一些团队也会自建高可用的 Nginx 作为集群入口。为了保证伸缩组节点的业务一致性,弹性伸缩组的所有 VM 都使用同一个虚拟机镜像。
其次,要在 VM 粒度实现业务自愈,常见的方案是使用 Crontab 定时检查业务进程或者通过守护进程的方式来运行,例如 Node PM2。
但是,这种架构有一些显而易见的缺陷。最大的问题有两个:(1)扩容慢;(2)负载均衡无法感知业务健康情况。

2.k8s自愈机制

你希望自愈解决什么问题?
我想,你可能最希望自愈能够帮我们解决服务自动重启的问题。也就是说,当业务进程意外中断,或者节点产生故障时,系统可以快速识别,自动重启并恢复服务。其次,你可能还会希望自愈能够自动转移故障,也就是让业务不健康的节点不接收流量,保证用户体验。
听起来是不是很棒,而 K8s 的自动自愈功能都可以帮你解决上面的这些问题,运维童鞋终于能摆脱 7*24 小时 Oncall 了。

【自愈演示】

现阶段,只需要知道三件事:
1. Pod 会被 Deployment 控制器管理起来,例如创建和销毁等;
2. Service 相当于弹性伸缩组的负载均衡器,它能以加权轮训的方式将流量转发到多个 Pod 副本上;
3. Ingress 相当于集群的外网访问入口。此处博主使用的是Traefik ingressroute用svc去不断请求
root@node1:~# while true; do sleep 2; curl http://10.233.47.55:5000; echo -e '\n'$(date);done
Hello, my v1 version docker images!! hello-world-flask-9d8967487-mbwn9
Thu Jul 13 17:06:26 CST 2023
Hello, my v1 version docker images!! hello-world-flask-9d8967487-68kzq
Thu Jul 13 17:06:28 CST 2023
Hello, my v1 version docker images!! hello-world-flask-9d8967487-mbwn9
Thu Jul 13 17:06:30 CST 2023
Hello, my v1 version docker images!! hello-world-flask-9d8967487-68kzq
Thu Jul 13 17:06:32 CST 2023root@node1:~# kubectl exec -it hello-world-flask-9d8967487-mbwn9 -- bash -c "killall python3"
模拟其中的一个 Pod 宕机,观察返回内容。会发现所有的请求流量都被转发到了没有故障的 Pod, 也就是说,故障成功地被转移了!等待几秒钟后pod重启恢复后,重新加入到了负载均衡接收外部流量。

梳理一下全过程。首先, K8s 感知到了业务 Pod 故障,立刻进行了故障转移并隔离了有故障的 Pod,并将请求转发到了其他健康的 Pod 中。随后重启了有故障的 Pod,最后将重启后的 Pod 加入到了负载均衡并开始接收外部请求。这些过程都是自动化完成的。

3.k8s弹性扩容

前提:自动扩容依赖于 K8s Metric Server 提供的监控指标,首先确保本地k8s环境中已经安装了。

一、通过 kubectl autoscale 命令来为 Deployment 创建自动扩容策略
root@node1:~# cat flask-hpa.yaml 
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:name: hello-world-flask
spec:maxReplicas: 10minReplicas: 2scaleTargetRef:apiVersion: apps/v1kind: Deploymentname: hello-world-flasktargetCPUUtilizationPercentage: 10   #CPU 使用率阈值注:
要使自动扩容生效,还需要为刚才部署的 hello-world-flask Deployment 设置资源配额,可以通过patch或者yaml中配置
root@node1:~# kubectl patch deployment hello-world-flask --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/resources", "value": {"requests": {"memory": "100Mi", "cpu": "100m"}}}]'二、模拟业务高峰期场景,使用 ab 命令来创建并发请求
root@node1:~# ab -c 10 -n 5000 http://10.233.47.55:5000/root@node1:~# kubectl get pods |grep flask
hello-world-flask-9d8967487-68kzq              1/1     Running       1 (2d2h ago)   2d4h
hello-world-flask-9d8967487-9mkg8              1/1     Terminating   0              36s
hello-world-flask-9d8967487-dsk7m              1/1     Terminating   0              21s
hello-world-flask-9d8967487-jcnwz              1/1     Terminating   0              36s
hello-world-flask-9d8967487-mbwn9              1/1     Running       1 (2d2h ago)   2d4h
hello-world-flask-9d8967487-rj2wp              0/1     Terminating   0              6s
hello-world-flask-9d8967487-srrk6              0/1     Terminating   0              6s
hello-world-flask-9d8967487-zjrtw              1/1     Terminating   0              21s可以通过参数 --watch 表示持续监听 Pod 状态变化。在 ab 压力测试的过程中,会不断创建新的 Pod 副本, 这说明 K8s 已经感知到了 Pod 的业务压力,并且正在自动进行横向扩容。

如何借助GitOps实现应用秒级自动发布和回滚?

1.传统 K8s 应用发布流程

  • 使用 kubectl set image 命令;
  • 修改本地的 Manifest,kubectl apply -f xx.yaml
  • 修改集群内 Manifest kubectl edit deploy xxx -n xx

2.从零搭建 GitOps 发布工作流

通俗来说,GitOps 就是以 Git 版本控制为理念的 DevOps 实践。
我们会将 Manifest 存储在 Git 仓库中作为期望状态,一旦修改并提交了 Manifest ,那么 GitOps 工作流就会 自动比对 Git 仓库和集群内工作负载的实际差异,并进行部署。

官网:https://fluxcd.io/flux/get-started/

要实现 GitOps 工作流,首先我们需要一个能够帮助我们监听 Git 仓库变化,自动部署的工具。此处以 FluxCD 为例一步步构建出一个 GitOps 工作流。

1.安装fluxcd
root@node1:~# kubectl apply -f https://ghproxy.com/https://raw.githubusercontent.com/lyzhang1999/resource/main/fluxcd/fluxcd.yamlroot@node1:~# kubectl get all -n flux-system
NAME                                               READY   STATUS    RESTARTS       AGE
pod/helm-controller-65d97f86f-hct7z                1/1     Running   4 (2d4h ago)   2d7h
pod/image-automation-controller-75cc9d6964-v9vpk   1/1     Running   3 (2d4h ago)   2d7h
pod/image-reflector-controller-6c99d4c47b-m8blb    1/1     Running   1 (2d4h ago)   2d7h
pod/kustomize-controller-6595b7976c-zqgrz          1/1     Running   1 (2d4h ago)   2d7h
pod/notification-controller-56f8f7f86b-cc786       1/1     Running   5 (2d4h ago)   2d7h
pod/source-controller-846457b955-7hzfc             1/1     Running   1 (2d4h ago)   2d7hNAME                              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/notification-controller   ClusterIP   10.233.11.156   <none>        80/TCP    2d7h
service/source-controller         ClusterIP   10.233.4.62     <none>        80/TCP    2d7h
service/webhook-receiver          ClusterIP   10.233.47.213   <none>        80/TCP    2d7hNAME                                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/helm-controller               1/1     1            1           2d7h
deployment.apps/image-automation-controller   1/1     1            1           2d7h
deployment.apps/image-reflector-controller    1/1     1            1           2d7h
deployment.apps/kustomize-controller          1/1     1            1           2d7h
deployment.apps/notification-controller       1/1     1            1           2d7h
deployment.apps/source-controller             1/1     1            1           2d7hNAME                                                     DESIRED   CURRENT   READY   AGE
replicaset.apps/helm-controller-65d97f86f                1         1         1       2d7h
replicaset.apps/image-automation-controller-75cc9d6964   1         1         1       2d7h
replicaset.apps/image-reflector-controller-6c99d4c47b    1         1         1       2d7h
replicaset.apps/kustomize-controller-6595b7976c          1         1         1       2d7h
replicaset.apps/notification-controller-56f8f7f86b       1         1         1       2d7h
replicaset.apps/source-controller-846457b955             1         1         1       2d7h
2.本地创建fluxcd目录并创建deploy
$ mkdir fluxcd-demo && cd fluxcd-demo
➜ fluxcd-demo (main) ✔ cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: hello-world-flaskname: hello-world-flask
spec:replicas: 2selector:matchLabels:app: hello-world-flasktemplate:metadata:labels:app: hello-world-flaskspec:containers:- image: ccr.ccs.tencentyun.com/app-public/hello-world-flask-amd:v1.0name: hello-world-flaskimagePullPolicy: IfNotPresentresources:limits:cpu: 100mrequests:cpu: 100m最后,在 Github 或 Gitlab 中创建 fluxcd-demo 仓库。为了方便测试,需要将仓库设置为公开权限,主分支为 Main,并将我们创建的 Manifest 推送至远端仓库:
https://github.com/Hugh-yw/fluxcd-demo
3.为 FluxCD 创建仓库连接信息
root@node1:~# cat fluxcd-repo.yaml 
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:name: hello-world-flask
spec:interval: 5sref:branch: mainurl: https://github.com/Hugh-yw/fluxcd-demo:
要将 URL 字段修改为你实际仓库的地址并使用 HTTPS 协议,branch 字段设置 main 分支。这里的 interval 代表每 5 秒钟主动拉取一次仓库并把它作为制品存储。
4.检查 GitRepository 对象
root@node1:~# kubectl get gitrepository
NAME                URL                                      AGE    READY   STATUS
hello-world-flask   https://github.com/Hugh-yw/fluxcd-demo   2d7h   True    stored artifact for revision 'main/2c93e18e9700373a4fd29eb533ecf447b4765b57'
5.为 FluxCD 创建部署策略
root@node1:~# cat fluxcd-kustomize.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:name: hello-world-flask
spec:interval: 5spath: ./prune: truesourceRef:kind: GitRepositoryname: hello-world-flasktargetNamespace: default注:
interval 参数表示 FluxCD 会每 5 秒钟运行一次工作负载差异对比;
path 参数表示 deployment.yaml 位于仓库的根目录中。
FluxCD在对比期望状态和集群实际状态的时候,如果发现差异就会触发重新部署。资源检查:
root@node1:~# kubectl get kustomization
NAME                AGE    READY   STATUS
hello-world-flask   2d7h   True    Applied revision: main/2c93e18e9700373a4fd29eb533ecf447b4765b57
6.体验gitops自动发布
1.代码提交
$ git add -A && git commit -m "Update image tag to v1"
$ git push origin mainroot@node1:~# kubectl get pods --show-labels|grep flask
hello-world-flask-7d78848d75-ht6fk                     1/1     Running       0              36s     app=hello-world-flask,pod-template-hash=7d78848d75
hello-world-flask-7d78848d75-mqgl9                     1/1     Running       0              31s     app=hello-world-flask,pod-template-hash=7d78848d75
hello-world-flask-9d8967487-68kzq                      1/1     Terminating   1 (2d4h ago)   2d6h    app=hello-world-flask,pod-template-hash=9d8967487
hello-world-flask-9d8967487-mbwn9                      1/1     Terminating   1 (2d4h ago)   2d6h    app=hello-world-flask,pod-template-hash=9d89674872.查看触发重新部署的事件
root@node1:~# kubectl describe kustomization hello-world-flask
Name:         hello-world-flask
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  kustomize.toolkit.fluxcd.io/v1beta2
Kind:         Kustomization
Metadata:Creation Timestamp:  2023-07-11T04:07:02ZFinalizers:finalizers.fluxcd.ioGeneration:  1Managed Fields:API Version:  kustomize.toolkit.fluxcd.io/v1beta2Fields Type:  FieldsV1fieldsV1:f:metadata:f:finalizers:.:v:"finalizers.fluxcd.io":Manager:      gotk-kustomize-controllerOperation:    UpdateTime:         2023-07-11T04:07:02ZAPI Version:  kustomize.toolkit.fluxcd.io/v1beta2Fields Type:  FieldsV1fieldsV1:f:status:f:conditions:f:inventory:.:f:entries:f:lastAppliedRevision:f:lastAttemptedRevision:f:observedGeneration:Manager:      gotk-kustomize-controllerOperation:    UpdateSubresource:  statusTime:         2023-07-11T04:07:02ZAPI Version:  kustomize.toolkit.fluxcd.io/v1beta2Fields Type:  FieldsV1fieldsV1:f:spec:.:f:force:f:interval:f:path:f:prune:f:sourceRef:.:f:kind:f:name:f:targetNamespace:Manager:         kubectl-createOperation:       UpdateTime:            2023-07-11T04:07:02ZResource Version:  40288002UID:               d4c061f3-fd9a-4c2f-8791-1b71e739bc51
Spec:Force:     falseInterval:  5sPath:      ./Prune:     trueSource Ref:Kind:            GitRepositoryName:            hello-world-flaskTarget Namespace:  default
Status:Conditions:Last Transition Time:  2023-07-13T11:34:17ZMessage:               Applied revision: main/2f35a6700aa47aa6872b595dc75acc9dea4a6f04Reason:                ReconciliationSucceededStatus:                TrueType:                  ReadyInventory:Entries:Id:                   default_hello-world-flask_apps_DeploymentV:                    v1Last Applied Revision:    main/2f35a6700aa47aa6872b595dc75acc9dea4a6f04   #最新commitidLast Attempted Revision:  main/2f35a6700aa47aa6872b595dc75acc9dea4a6f04Observed Generation:      1
Events:Type    Reason                   Age                     From                  Message----    ------                   ----                    ----                  -------Normal  ReconciliationSucceeded  45s (x37589 over 2d4h)  kustomize-controller  (combined from similar events): Reconciliation finished in 53.523094ms, next run in 5s3.验证是否已更新
root@node1:~# curl http://10.233.47.55:5000
Hello, my first docker images! hello-world-flask-7d78848d75-mqgl9

通过上面的配置,我们让 FluxCD 自动完成了监听修改、比较和重新部署三个过程。

7.体验gitops自动回滚
要回滚 fluxcd-demo 仓库,首先需要找到上一次的提交记录。我们可以使用 git log 来查看它:
commit 2f35a6700aa47aa6872b595dc75acc9dea4a6f04 (HEAD -> main, origin/main)
Author: ywcheng 
Date:   Thu Jul 13 19:33:56 2023 +0800Update image tag to latestcommit 2c93e18e9700373a4fd29eb533ecf447b4765b57
Author: ywcheng 
Date:   Tue Jul 11 12:54:31 2023 +0800Update image tag to v1.0
--------------------------------------------------------------------
➜ fluxcd-demo (main) ✔ git reset --hard 2c93e18e9700373a4fd29eb533ecf447b4765b57
HEAD is now at 2c93e18 Update image tag to v1.0
➜ fluxcd-demo (main) ✔ git push origin main -f
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:Hugh-yw/fluxcd-demo.git+ 2f35a67...2c93e18 main -> main (forced update)再次查看触发器的events:
root@node1:~# kubectl describe kustomization hello-world-flask
......Inventory:Entries:Id:                   default_hello-world-flask_apps_DeploymentV:                    v1Last Applied Revision:    main/2c93e18e9700373a4fd29eb533ecf447b4765b57Last Attempted Revision:  main/2c93e18e9700373a4fd29eb533ecf447b4765b57Observed Generation:      1
Events:Type    Reason                   Age                       From                  Message----    ------                   ----                      ----                  -------Normal  ReconciliationSucceeded  3m43s (x37649 over 2d4h)  kustomize-controller  (combined from similar events): Reconciliation finished in 40.521018ms, next run in 5sroot@node1:~# curl http://10.233.47.55:5000
Hello, my v1 version docker images!! hello-world-flask-9d8967487-7j5n8

到这里,我们就成功体验了GitOps 工作流基础环节的发布和回滚实现(小部分)。

参考资料:https://time.geekbang.org/column/intro/100312001?tab=catalog

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/159.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Arduino小车实践】陀螺仪的使用

一、MPU6050简介 MPU6050是一款陀螺仪模块&#xff0c;可以测量X、Y、Z三轴的角速度和加速度&#xff0c;还带有温度传感器和数字运动处理器(DMP)。 二、学习步骤 1. I2C协议 MPU6050是通过I2C协议进行驱动的&#xff0c;配置寄存器和获取数据都需要通过I2C协议去实现开发板与…

CentOS环境下的Nginx安装

Nginx 安装 下载 nginx 下载地址&#xff1a;http://nginx.org/en/download.html 将下载好的压缩包拷贝到根目录下 通过xshell如果出现 bash: rz: 未找到命令 &#xff0c;需要先运行下面的命令 yum -y install lrzsz安装 解压到当前目录 tar -zxvf nginx-1.22.1.tar.gz安…

Hive SQL 迁移 Flink SQL 在快手的实践

摘要&#xff1a;本文整理自快手数据架构工程师张芒&#xff0c;阿里云工程师刘大龙&#xff0c;在 Flink Forward Asia 2022 生产实践专场的分享。本篇内容主要分为四个部分&#xff1a; Flink 流批一体引擎 Flink Batch 生产实践 核心优化解读 未来规划 点击查看原文视频…

走进人工智能| Computer Vision 数字化时代的视觉启示录

前言&#xff1a; 计算机视觉是通过模仿人类视觉系统的工作原理&#xff0c;使计算机能够感知、理解和解释图像和视频的能力。 文章目录 序言背景适用领域技术支持应用领域程序员如何学总结 序言 计算机视觉是人工智能领域的一个重要分支&#xff0c;它涉及使计算机能够“看”…

靶场的安装

sqli-lab 1.将安装包解压放到WWW目录下 2.修改 db-creds.inc文件里面的数据库的用户名密码为自己的用户名密码 路径&#xff1a;D:\phpStudy_64\phpstudy_pro\WWW\sqli-labs-master\sql-connections\db-creds.inc 3. 更改php版本位5.9版本&#xff0c;不然会报错 4.安装数…

MFC学习之2048小游戏程序源码

2048游戏的开发原理相对简单&#xff0c;它基于一个4x4的方格&#xff0c;通过控制数字方块的移动来合成相同的数字方块&#xff0c;并生成新的数字方块。 具体实现过程如下&#xff1a; 确定需求&#xff1a;首先需要明确游戏的功能需求&#xff0c;如产生随机数字方块、控制…

MYSQL执行一条SELECT语句的具体流程

昨天CSDN突然抽风 我一个ctrlz把整篇文章给撤掉了还不能复原 直接心态崩了不想写了 不过这部分果然还是很重要,还是写出来吧 流程图 这里面总共有两层结构Server层 储存引擎 Server 层负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在这实现&#xff0c;主要包…

WebSocket理解

WebSocket理解 WebSocket定义与HTTP关系相同点:不同点&#xff1a;联系总体过程 HTTP问题长轮询Ajax轮询 WebSocket特点 WebSocket 定义 本质上是TCP的协议 持久化的协议 实现了浏览器和服务器的全双工通信&#xff0c;能更好的节省服务器资源和带宽 与HTTP关系 相同点: 基于…

接口测试 react+unittest+flask 接口自动化测试平台

目录 1 前言 2 框架 2-1 框架简介 2-2 框架介绍 2-3 框架结构 3 平台 3-1 平台组件图 1 新建用例 2 生成测试任务 3 执行并查看测试报告 3-2 用例管理 3-2-1 用例设计 3-3 任务管理 3-3-1 创建任务 3-3-2 执行任务 3-3-3 测试报告 3-3-4 邮件通知 1 前言 构建…

【力扣算法12】之 11. 盛最多水的容器 python

文章目录 问题描述示例1示例2提示 思路分析代码分析完整代码详细分析运行效果截图调用示例运行结果完结 问题描述 给定一个长度为 n 的整数数组 height 。有n条垂线&#xff0c;第i条线的两个端点是(i, 0)和(i, height[i])。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构…

解决IDEA项目external libraries依赖包消失的问题

有时候电脑重启后&#xff0c;再打开IDEA上的项目时会出现external libraries目录下的依赖包都消失了的情况&#xff0c;只剩下了一个JDK的包 网上说可以通过刷新IDEA的缓存解决&#xff0c;但我试了没有效果&#xff0c;最后使用如下办法解决&#xff1a; 1.删除项目目录下的…

图论算法笔记

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 第12章 最短路径算法12-1 有权图的最短路径问题最短路径问题-路径规划单源最短路径带权图的最短路径和无权图的最短路径带权图的最短路径算法-Dijkstra算法 12-2 Di…

搭载率突破40%!智能数字座舱比拼,车企还有降本空间吗?

进入2023年&#xff0c;汽车行业的「降本」风潮&#xff0c;驱动产业链上下游开始思考智能化、电动化的投入产出。除了显性的硬件成本&#xff08;继续堆料&#xff0c;强调性价比&#xff0c;还是减配&#xff09;&#xff0c;软件及背后的开发成本&#xff0c;对于车企来说&a…

GitLab 入选 Forrester Wave™️ 集成软件交付平台,并获评唯一「领导者」!

越来越多企业意识到多工具链集成带来的低效和高成本问题&#xff0c;同时承受着可见性低、反馈不畅通、网络风险大等痛点&#xff0c;应用平台方法来交付软件的呼声越来越大。 极狐(GitLab) 很早就意识到了平台方法的价值&#xff0c;也坚信极狐GitLab 这种单一应用程序的 DevS…

学习vue2笔记

学习vue2笔记 文章目录 学习vue2笔记脚手架文件结构关于不同版本的Vuevue.config.js配置文件ref属性props配置项mixin(混入)插件scoped样式总结TodoList案例webStorage组件的自定义事件全局事件总线&#xff08;GlobalEventBus&#xff09;消息订阅与发布&#xff08;pubsub&am…

el-date-picker 日期时间进行限制,精确到时分秒

需求&#xff1a;用户只能选择当时时间或当前时间之前的时间&#xff0c;且精确到时分秒 实现效果&#xff1a;用户只能选择当前时间的时间&#xff0c;如果选择是当天之前的时间&#xff0c;时分秒不做限制&#xff0c;如果选择的是当天时间&#xff0c;就要判断时分秒&#…

【数据挖掘】时间序列教程【十】

5.4 通用卡尔曼滤波 上一节中描述的状态空间模型作为观测方程的更一般的公式 和状态方程 这里是一个p1 向量是一个k1 向量, 是一个pk 矩阵, 是kk 矩阵。我们可以想到的和 给定初始状态 和 &#xff0c;预测方程为&#xff08;类似于上面&#xff09; 并且更新方程是&#x…

华为Harmony应用开发初探

HarmonyOS是一款面向万物互联时代的、全新的分布式操作系统。在传统的单设备系统能力基础上,HarmonyOS提出了基于同一套系统能力、适配多种终端形态的分布式理念,能够支持手机、平板、智能穿戴、智慧屏、车机等多种终端设备,提供全场景(移动办公、运动健康、社交通信、媒体…

外包干了2个月,技术退步明显...

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

Linux进程(二)---进程的优先级和环境变量

我想在这先完成上一章的一个未说完的话题.最后一个我们讲到了僵尸进程&#xff0c;是指子进程已经结束&#xff0c;但是父进程还在运行没有来得及回收.此时这个子进程便是僵尸进程. 但是如果父进程运行完了&#xff0c;也没有回收就直接结束了&#xff0c;那这个子进程改由谁维…