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

实践005-Gitlab CICD全项目整合

文章目录

    • 环境准备
      • 环境准备
      • 集成Kubernetes
    • Gitlab CICD项目整合
      • 项目整合
        • 整合设计
      • 后端Java项目部署
        • 后端Java项目静态检查
        • 后端Java项目镜像构建
        • 创建Java项目部署文件
        • 创建完整流水线
      • 前端webui项目部署
        • 前端webui项目镜像构建
        • 创建webui项目部署文件
        • 创建完整流水线
      • 构建父子类型流水线
      • 查看流水线
      • 确认验证
        • 部署情况确认
        • 验证后端应用
        • 验证前端应用
      • Ddevops梳理

环境准备

环境准备

单独测试前后端项目的时候已成功部署相关应用,为便于后续整合,将已部署的应用进行清理。

root@master01:~# kubectl -n gitlabci delete deployments.apps deploy-apiserver-ci deploy-webui-ci
root@master01:~# kubectl -n gitlabci delete service service-apiserver-ci service-webui-ci
root@master01:~# kubectl delete ns gitlabciroot@master01:~# kubectl get ns

整个环境需要发布镜像至阿里云,需要将应用部署到 Kubernetes 。
因此提前在 gitlab 中创建 ALIYUN_USER 和 ALIYUN_PASSWORD 、KUBE_CONFIG 变量,配置阿里云镜像推送的账号和密码。

集成Kubernetes

当前 Gitlab 的 runner 是基于 helm 部署 gitla 的同时配套部署的,即 runner 是运行在 Kubernetes 中的一个 Pod,runner 类型是 Kubernetes ,如下所示:

root@master01:~# kubectl -n gitlab exec -ti mygitlab-gitlab-runner-798986f578-h2thf -- bash
camygitlab-gitlab-runner-798986f578-h2thf:/$ cat /home/gitlab-runner/.gitlab-runner/config.toml
#……
[[runners]]
#……executor = "kubernetes"

因此该 runner 后续需要直接在 Kubernetes 中部署业务,需要安装 kubectl 命令,以及配置 kubeconfig 上下文。

从而需要提前将 kubeconfig 内容以变量形式引入到 runner Pod 中。

root@master01:~# echo $(cat ~/.kube/config | base64) | tr -d " "
YXBpVmVyc2lvbjogdjEKY2x1c3RlcnM6Ci0gY2x1c3RlcjoKICA……

添加变量 KUBE_CONFIG 。
227

提示:由于后续流水线中作业有 main 和 tag 两种触发方式,因此建议将变量取消受保护。
同时对于 Kubernetes 的部署可参考: 附042.Kubernetes_v1.33.0生成环境高可用部署方案

Gitlab CICD项目整合

项目整合

整合设计

当前后端 java 和前端 web 的构建、测试、编译基于学习目的,都由独立项目通过 gitlab 验证,基于生产环境需要,现需要整合至一个项目中,从而将多个子项目放在一个项目代码仓中。

gitlab 创建总项目: mycicd 。
由于整合后的新项目为 mycicd ,因此原有部分文件的内容涉及路径部分均需要稍作调整,sonarqube代码检查对接的gitlab项目也需要重新调整。
213

[root@gitclient ~]# git clone git@gitlab.linuxsb.com:mygroup/mycicd.git
[root@gitclient ~]# cd mycicd/

复制前后端项目至该目录。

[root@gitclient mycicd]# cp -rp ../apiserver .
[root@gitclient mycicd]# cp -rp ../webui .
[root@gitclient mycicd]# tree -L 2 .
.
├── apiserver
│   ├── deployjavaci.yaml
│   ├── deployjavaprod.yaml
│   ├── deployjavatest.yaml
│   ├── Dockerfile
│   ├── HELP.md
│   ├── mvnw
│   ├── mvnw.cmd
│   ├── pom.xml
│   ├── README.md
│   └── src
├── README.md
└── webui├── babel.config.js├── deploywebuici.yaml├── deploywebuiprod.yaml├── deploywebuitest.yaml├── Dockerfile├── jsconfig.json├── node_modules├── package.json├── package-lock.json├── public├── README.md├── src└── vue.config.js

后端Java项目部署

后端Java项目静态检查

参考实践002-Gitlab CICD静态代码检查 ,重新配置 sonarqube 对 gitlab 新建的 mycicd 项目的检查。

214

后端Java项目镜像构建

目录有所调整。

[root@gitclient mycicd]# vim apiserver/Dockerfile
FROM uhub.service.ucloud.cn/imxhy/maven:3.8.5-openjdk-17MAINTAINER xhy@itzgr.cnRUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezoneEXPOSE 8080WORKDIR /opt/apiserviceCOPY target/apiservice-0.0.1-SNAPSHOT.jar ./ENTRYPOINT ["java","-jar","/opt/apiservice/apiservice-0.0.1-SNAPSHOT.jar"]
创建Java项目部署文件

调整如下 ci 、 test 、 prod 部署文件。

  • ci 部署文件
[root@gitclient mycicd]# vim apiserver/deployjavaci.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabci---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-apiserver-cinamespace: gitlabci
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: apiserver-cistrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: apiserver-cispec:containers:- name: apiserver-cienv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-apiserver-cinamespace: gitlabci
spec:ports:- nodePort: 32101port: 8080protocol: TCPtargetPort: 8080selector:app: apiserver-cisessionAffinity: ClientIPtype: NodePort
  • test 部署文件
[root@gitclient mycicd]# vim apiserver/deployjavatest.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabtest---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-apiserver-testnamespace: gitlabtest
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: apiserver-teststrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: apiserver-testspec:containers:- name: apiserver-testenv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-apiserver-testnamespace: gitlabtest
spec:ports:- nodePort: 32102port: 8080protocol: TCPtargetPort: 8080selector:app: apiserver-testsessionAffinity: ClientIPtype: NodePort
  • prod 部署文件
[root@gitclient mycicd]# vim apiserver/deployjavaprod.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabprod---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-apiserver-prodnamespace: gitlabprod
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: apiserver-prodstrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: apiserver-prodspec:containers:- name: apiserver-prodenv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /demo/helloport: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-apiserver-prodnamespace: gitlabprod
spec:ports:- nodePort: 32103port: 8080protocol: TCPtargetPort: 8080selector:app: apiserver-prodsessionAffinity: ClientIPtype: NodePort
创建完整流水线

创建如下流水线,并且将后端 Java 项目的编译构建阶段全部整合到一起。并且最后直接使用 git clone 使用 autotest 项目进行最后的测试。

即对于后端 Java 项目,整合 UnitTest+compile+sonarqube-check ----> build ----> deploy_java_ci/deploy_java_test ----> check_java_ci_pod/check_java_test_pod ----> test 全链路流程。

[root@gitclient mycicd]# vim apiserver/.gitlab-ci.yml
stages:- compile- build- deploy- check- testvariables:KUBECONFIG: "/.kube/config"PROJECT_DIR: "${CI_PROJECT_DIR}/apiserver"GITLAB_HOST: gitlab.linuxsb.comGITLAB_PORT: "32222"REPO_URL: git@${GITLAB_HOST}:mygroup/autotest.gitunittest_java:stage: compileimage: maven:3.8.5-openjdk-17script:- cd ${PROJECT_DIR}- mvn verify -Dmaven.test.failure.ignore=true- ls target/surefire-reports/*.xmlrules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGartifacts:when: alwaysreports:junit:- apiserver/target/surefire-reports/TEST-*.xml- apiserver/target/failsafe-reports/TEST-*.xmltags:- study-runnercompile_java:stage: compileimage: uhub.service.ucloud.cn/imxhy/maven:3.8.5-openjdk-17artifacts:paths:- apiserver/target/apiservice-0.0.1-SNAPSHOT.jarscript:- pwd- cd ${PROJECT_DIR}- mvn clean- mvn compile- mvn package -Dmaven.test.skip=true- ls targetrules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGtags:- study-runnersonarqube_check_java:stage: compileimage: maven:3.8.5-openjdk-17variables:SONAR_USER_HOME: "${CI_PROJECT_DIR}/apiserver/.sonar"GIT_DEPTH: "0"cache:key: "${CI_JOB_NAME}"paths:- .sonar/cachescript:- cd ${PROJECT_DIR}- mvn verify sonar:sonar -Dsonar.projectKey=mygroup_mycicd_AZaRvvQBjzPXArMYpIcZallow_failure: truerules:- if: $CI_COMMIT_BRANCH == "main"tags:- study-runnerbuild_java:stage: buildimage: uhub.service.ucloud.cn/imxhy/executor:v1.9.0-debugneeds:- unittest_java- compile_javascript:- cd ${PROJECT_DIR}- ls target- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- echo ${IMAGE_TAG_TO_INSTALL}- mkdir -p /kaniko/.docker- echo "{\"auths\":{\"registry.cn-hangzhou.aliyuncs.com\":{\"username\":\"${ALIYUN_USER}\",\"password\":\"${ALIYUN_PASSWORD}\"}}}" > /kaniko/.docker/config.json- cat /kaniko/.docker/config.json- echo ${PROJECT_DIR}- echo {\"username\":\"${ALIYUN_USER}\",\"password\":\"${ALIYUN_PASSWORD}\"}- ls ${PROJECT_DIR}/Dockerfile- >/kaniko/executor--context "${PROJECT_DIR}"--dockerfile "${PROJECT_DIR}/Dockerfile"--destination "registry.cn-hangzhou.aliyuncs.com/xhyimages/apiservice:${IMAGE_TAG_TO_INSTALL}"--registry-mirror "https://dbzucv6w.mirror.aliyuncs.com"rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGtags:- study-runnerdeploy_java_ci:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- echo $IMAGE_TAG_TO_INSTAL- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/apiservice:${IMAGE_TAG_TO_INSTALL}#g" apiserver/deployjavaci.yaml- kubectl apply -f apiserver/deployjavaci.yaml || exit 1rules:- if: $CI_COMMIT_BRANCH == "main"tags:- study-runnerdeploy_java_test:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0when: manualscript:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- echo $IMAGE_TAG_TO_INSTAL- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/apiservice:${IMAGE_TAG_TO_INSTALL}#g" apiserver/deployjavatest.yaml- kubectl apply -f apiserver/deployjavatest.yaml || exit 1rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGtags:- study-runnerdeploy_java_prod:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0when: manualscript:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- echo $IMAGE_TAG_TO_INSTAL- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/apiservice:${IMAGE_TAG_TO_INSTALL}#g" apiserver/deployjavaprod.yaml- kubectl apply -f apiserver/deployjavaprod.yaml || exit 1rules:- if: $CI_COMMIT_TAGtags:- study-runnercheck_java_ci_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabci -l app=apiserver-ci --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_BRANCH == "main"needs:- deploy_java_citags:- study-runnercheck_java_test_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabtest -l app=apiserver-test --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGneeds:- deploy_java_testtags:- study-runnercheck_java_prod_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabprod -l app=apiserver-prod --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_TAGneeds:- deploy_java_prodtags:- study-runnertest:stage: testimage: python:3.13.3before_script:- mkdir -p ~/.ssh- chmod 700 ~/.ssh- echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa- chmod 600 ~/.ssh/id_rsa- echo "Host ${GITLAB_HOST}" >> ~/.ssh/config- echo "    Port ${GITLAB_PORT}" >> ~/.ssh/config- echo "    User git" >> ~/.ssh/config- echo "    IdentityFile ~/.ssh/id_rsa" >> ~/.ssh/config- echo "    StrictHostKeyChecking no" >> ~/.ssh/config- ssh-keyscan -p ${GITLAB_PORT} ${GITLAB_HOST} >> ~/.ssh/known_hostsscript:- git clone -b main ${REPO_URL}- cd autotest- python -m pip install --no-cache-dir -r requirements.txt- mkdir -p tests/reports- cd tests && pytest -s --junitxml=reports/report.xml || echo "Pytest exited with $?"- pwd- ls -l .- ls -l reportsartifacts:reports:junit: autotest/tests/reports/report.xmlrules:- if: $CI_COMMIT_BRANCH == "main"tags:- study-runner

前端webui项目部署

前端webui项目镜像构建

目录有所调整。

[root@gitclient mycicd]# vim webui/Dockerfile
FROM uhub.service.ucloud.cn/imxhy/node:23.11.0MAINTAINER xhy@itzgr.comRUN npm install -g @vue/cliWORKDIR /opt/webui/COPY . ./RUN npm installENTRYPOINT ["npm","run","serve"]
创建webui项目部署文件

调整如下 ci 、 test 、 prod 部署文件。

  • ci 部署文件
[root@gitclient mycicd]# vim webui/deploywebuici.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabci---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-webui-cinamespace: gitlabci
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: webui-cistrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: webui-cispec:containers:- name: webui-cienv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-webui-cinamespace: gitlabci
spec:ports:- nodePort: 32111port: 8080protocol: TCPtargetPort: 8080selector:app: webui-cisessionAffinity: ClientIPtype: NodePort
  • test 部署文件
[root@gitclient mycicd]# vim webui/deploywebuitest.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabtest---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-webui-testnamespace: gitlabtest
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: webui-teststrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: webui-testspec:containers:- name: webui-testenv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-webui-testnamespace: gitlabtest
spec:ports:- nodePort: 32112port: 8080protocol: TCPtargetPort: 8080selector:app: webui-testsessionAffinity: ClientIPtype: NodePort
  • prod 部署文件
[root@gitclient mycicd]# vim webui/deploywebuiprod.yaml
---
apiVersion: v1
kind: Namespace
metadata:name: gitlabprod---
apiVersion: apps/v1
kind: Deployment
metadata:name: deploy-webui-prodnamespace: gitlabprod
spec:replicas: 2revisionHistoryLimit: 5selector:matchLabels:app: webui-prodstrategy:type: RollingUpdaterollingUpdate:maxUnavailable: 25%maxSurge: 25%template:metadata:labels:app: webui-prodspec:containers:- name: webui-prodenv:- name: TZvalue: Asia/Shanghaiimage: __POD_CONTAINERS_IMAGE__imagePullPolicy: IfNotPresentports:- containerPort: 8080protocol: TCPreadinessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10livenessProbe:httpGet:path: /port: 8080scheme: HTTPinitialDelaySeconds: 30periodSeconds: 10---
apiVersion: v1
kind: Service
metadata:name: service-webui-prodnamespace: gitlabprod
spec:ports:- nodePort: 32113port: 8080protocol: TCPtargetPort: 8080selector:app: webui-prodsessionAffinity: ClientIPtype: NodePort
创建完整流水线

创建如下流水线,并且将前端 webui 项目的构建阶段全部整合到一起。
即对于前端 webui 项目,整合 build ----> deploy_webui_ci/deploy_webui_test ----> check_webui_ci_pod/check_webui_test_pod 全链路流程。

[root@gitclient mycicd]# vim webui/.gitlab-ci.yml
stages:- build- deploy- checkvariables:KUBECONFIG: "/.kube/config"PROJECT_DIR: "${CI_PROJECT_DIR}/webui"build_webui:stage: buildimage: uhub.service.ucloud.cn/imxhy/executor:v1.9.0-debugscript:- cd ${PROJECT_DIR}- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- echo $IMAGE_TAG_TO_INSTALL- mkdir -p /kaniko/.docker- echo "{\"auths\":{\"registry.cn-hangzhou.aliyuncs.com\":{\"username\":\"${ALIYUN_USER}\",\"password\":\"${ALIYUN_PASSWORD}\"}}}" > /kaniko/.docker/config.json- cat /kaniko/.docker/config.json- echo ${PROJECT_DIR}- echo {\"username\":\"${ALIYUN_USER}\",\"password\":\"${ALIYUN_PASSWORD}\"}- ls ${PROJECT_DIR}/Dockerfile- >/kaniko/executor--context "${PROJECT_DIR}"--dockerfile "${PROJECT_DIR}/Dockerfile"--destination "registry.cn-hangzhou.aliyuncs.com/xhyimages/webui:${IMAGE_TAG_TO_INSTALL}"--registry-mirror "https://dbzucv6w.mirror.aliyuncs.com"rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGtags:- study-runnerdeploy_webui_ci:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/webui:${IMAGE_TAG_TO_INSTALL}#g" webui/deploywebuici.yaml- kubectl apply -f webui/deploywebuici.yaml || exit 1rules:- if: $CI_COMMIT_BRANCH == "main"tags:- study-runnerdeploy_webui_test:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0when: manualscript:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/webui:${IMAGE_TAG_TO_INSTALL}#g" webui/deploywebuitest.yaml- kubectl apply -f webui/deploywebuitest.yaml || exit 1rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGtags:- study-runnerdeploy_webui_prod:stage: deployimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0when: manualscript:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- kubectl version- IMAGE_TAG=$(echo "${CI_COMMIT_TIMESTAMP}" | sed 's/T/_/g; s/-//g; s/://g' | cut -c1-15)- IMAGE_TAG_TO_INSTALL=${CI_COMMIT_TAG:-$IMAGE_TAG}- sed -i "s#__POD_CONTAINERS_IMAGE__#registry.cn-hangzhou.aliyuncs.com/xhyimages/webui:${IMAGE_TAG_TO_INSTALL}#g" webui/deploywebuiprod.yaml- kubectl apply -f webui/deploywebuiprod.yaml || exit 1rules:- if: $CI_COMMIT_TAGtags:- study-runnercheck_webui_ci_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabci -l app=webui-ci --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_BRANCH == "main"needs:- deploy_webui_citags:- study-runnercheck_webui_test_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabtest -l app=webui-test --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_TAGneeds:- deploy_webui_testtags:- study-runnercheck_webui_prod_pod:stage: checkimage: uhub.service.ucloud.cn/imxhy/kubectl:1.33.0script:- mkdir -p /.kube- echo $KUBE_CONFIG | base64 -d > $KUBECONFIG- timeout 120 bash -c "until kubectl get pods -n gitlabprod -l app=webui-prod --field-selector=status.phase=Running --no-headers | grep '1/1'; do sleep 3; done"rules:- if: $CI_COMMIT_TAGneeds:- deploy_webui_prodtags:- study-runner

构建父子类型流水线

父子类型流水线适用于将多个子项目放在一个项目代码仓中的场景。
该场景中,流水线中存在后端 Java 、前端 webui 两个项目的编译、构建、发布以及集成在一起的测试和部署等。
因此可以使用父子类型的流水线,且配置是如果只修改了Java子项目,则只执行和Java子项目相关的流水线任务即可。

前端子项目的目录为 webui,后端子项目的目录为apiserver,组建父子类型的流水线,就是在项目的根目录创建流水线发布文件.gitlab-ci.yml作为父流水线的配置,各子项目分别创建一个.gitlab-ci.yml作为子流水线的位置。

如上所致 java 后端和 webui 前端流水线均创建完成。

  • 父流水线
    子流水线不会自动触发,需要项目根目录下的.gitlab-ci.yml文件进行触发。
    在父流水线中调用子流水线需要使用关键字 trigger 和 include 。
[root@gitclient mycicd]# vim .gitlab-ci.yml
stages:- triggers- pre-checkverify_files:stage: pre-checkscript:- ls -l apiserver/.gitlab-ci.yml- ls -l webui/.gitlab-ci.ymltrigger_apiserver:stage: triggerstrigger:include: apiserver/.gitlab-ci.ymlforward:pipeline_variables: truevariables:PARENT_TAG: $CI_COMMIT_TAGrules:- if: $CI_COMMIT_BRANCH == "main"changes:- apiserver/*- if: $CI_COMMIT_TAGchanges: []trigger_webui:stage: triggerstrigger:include: webui/.gitlab-ci.ymlforward:pipeline_variables: truevariables:PARENT_TAG: $CI_COMMIT_TAGrules:- if: $CI_COMMIT_BRANCH == "main"changes:- webui/*- if: $CI_COMMIT_TAGchanges: []

如上定义了一个节点, trigger ,然后 trigger 里定义了两个任务,通过 include 关键字将子目录下的 .gitlab-ci.yml 引用。
rules 和 changes 关键字是用来控制 job 触发执行的,指定具体的目录。
如上 trigger_back 的 job 指定了检测目录为 apiserver,即只有当 apiserver 目录中的文件或代码发生了变化,apiserver 目录中的子流水线才会执行。

  • 提交流水线
    首次提交后,由于前后端都是第一次生成,因此会自动执行完所有任务。
[root@gitclient mycicd]# git add .
[root@gitclient mycicd]# git status [root@gitclient mycicd]# git commit -m "Deploy apiserver and webui cicd"
[root@gitclient mycicd]# git push origin main

查看流水线

查看提交流水线后的作业情况。

215

216
217

确认验证

部署情况确认

查看部署在 Kubernetes 后的应用,

root@master01:~# kubectl -n gitlabci get pods -o wide
NAME                                   READY   STATUS    RESTARTS   AGE    IP             NODE       NOMINATED NODE   READINESS GATES
deploy-apiserver-ci-68655894c8-qzcwr   1/1     Running   0          117m   10.10.19.82    worker03   <none>           <none>
deploy-apiserver-ci-68655894c8-vrdwd   1/1     Running   0          117m   10.10.5.47     worker01   <none>           <none>
deploy-webui-ci-5cfb75dfcf-7zm8w       1/1     Running   0          111m   10.10.19.115   worker03   <none>           <none>
deploy-webui-ci-5cfb75dfcf-zncr9       1/1     Running   0          111m   10.10.5.35     worker01   <none>           <none>
root@master01:~# kubectl -n gitlabci get svc -o wide
NAME                   TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE    SELECTOR
service-apiserver-ci   NodePort   10.20.29.161   <none>        8080:32101/TCP   117m   app=apiserver-ci
service-webui-ci       NodePort   10.20.10.106   <none>        8080:32111/TCP   112m   app=webui-ci
root@master01:~# kubectl -n gitlabci get deployments.apps
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
deploy-apiserver-ci   2/2     2            2           117m
deploy-webui-ci       2/2     2            2           112m
验证后端应用

浏览器直接访问: http://172.24.8.180:32101/demo/hello 。

218

验证前端应用

浏览器直接访问: http://172.24.8.180:32111
219

Ddevops梳理

如上所示为一个包含前后端的完整流水线,其主要包括过程总结如下:

  1. 当后端研发人员提交代码后,流水线会自动触发。首先执行compile阶段,主要包括unittest_java、compile_java和静态代码检查sonarqube_check_java,这三个认为是并行执行的。而且只要compile阶段执行完成,不论单元测试和静态代码检查是否执行完成,都会执行第二个build镜像构建阶段。当build镜像构建阶段完成后,自动部署到CI环境,CI环境部署完成后,开始检查CI环境中的Pod状态是否正常。检查完成后,开始自动执行自动化测试。当自动化测试执行完成后,根据测试结果及其他需求,计划是否要部署到测试环境,测试环境的部署由手动执行。

  2. 部署到测试环境后,流水线执行如下,然后测试团队可以对测试环境进行测试:

221

  1. 当测试团队测试完成,并对测试结果进行bug修复完成后,可以通过tags部署线上生产环境。

222

  1. 打完tag后同样会触发新的流水线,通过打tag触发的流水线有两个选择,即部署测试环境或部署生产环境,同时保留手动执行,即在通过CI环境同时修复bug后打tag,然后人为审核是否发版,然后手动执行。
    223

  2. 手动部署 test 环境,然后可以通知测试人员对test环境进行测试。
    224

  3. 测试团队确认后,可以手动开始部署 prod 生产环境。
    225

226

相关文章:

实践005-Gitlab CICD全项目整合

文章目录 环境准备环境准备集成Kubernetes Gitlab CICD项目整合项目整合整合设计 后端Java项目部署后端Java项目静态检查后端Java项目镜像构建创建Java项目部署文件创建完整流水线 前端webui项目部署前端webui项目镜像构建创建webui项目部署文件创建完整流水线 构建父子类型流水…...

为了摸鱼和吃瓜,我开发了一个网站

平时上班真的比较累&#xff0c;摸鱼和吃瓜还要跳转多个平台的话&#xff0c;就累上加累了。 所以做了一个聚合了全网主流平台热搜的网站。 目前市面上确实有很多这种网站了&#xff0c;所以目前最主要有两点和他们不同&#xff1a; 给热搜列表增加了配图&#xff0c;刷的时候…...

React -> AI组件 -> 调用Ollama模型, qwen3:1.7B非常聪明

使用 React 搭建一个现代化的聊天界面&#xff0c;支持与 Ollama 本地部署的大语言模型进行多轮对话。界面清爽、功能完整&#xff0c;支持 Markdown 渲染、代码高亮、<think> 隐藏思考标签、流式渐进反馈、暗黑模式适配等特性。 &#x1f9e9; 核心功能亮点 ✅ 模型选择…...

算法中的数学:约数

1.求一个整数的所有约数 对于一个整数x&#xff0c;他的其中一个约数若为i&#xff0c;那么x/i也是x的一个约数。而其中一个约数的大小一定小于等于根号x&#xff08;完全平方数则两个约数都为根号x&#xff09;&#xff0c;所以我们只需要遍历到根号x&#xff0c;然后计算出另…...

性能远超SAM系模型,苏黎世大学等开发通用3D血管分割基础模型

如果把人的身体比作一座庞大的城市&#xff0c;那么血管无疑就是这座城市的「道路」&#xff0c;动脉、静脉以及毛细血管对应着高速公路、城市道路以及乡间小道&#xff0c;它们相互协作&#xff0c;通过血液将营养物质、氧气等输送到身体各处&#xff0c;从而维持着这座「城市…...

对 Kotlin 中的 data 关键字的理解,相比于普通类有哪些特点?

Kotlin 中的 data 关键字用于声明数据类&#xff08;Data Class&#xff09;&#xff0c;它专门为简化数据模型的实现而设计的。 1 主构造函数必须至少有一个参数&#xff0c;且参数标记为 val 或 var 数据类的主构造函数必须至少有一个参数&#xff0c;并且这些参数必须使用…...

电厂参与全球能源效率排名的方法

在全球积极推动可持续能源发展的大背景下&#xff0c;电厂参与全球能源效率排名&#xff0c;对提升自身竞争力、推动行业进步意义重大。这不仅有助于电厂明确自身在全球能源领域的地位&#xff0c;还能促进其通过能效对标&#xff0c;学习先进经验&#xff0c;实现节能减排与高…...

〖 Linux 〗解决 VS Code 远程连接服务器的常见问题

文章目录 解决 VS Code 远程连接服务器的断开问题VS Code Remote-SSH一直弹出输入密码的问题VsCode C 语法检测失效不标红色波浪线 解决办法卸载扩展方式&#xff1a; 解决vscode C智能提示缓慢 解决 VS Code 远程连接服务器的断开问题 解决 vscode 卡顿&#xff0c;卡死&…...

谷歌 Gemma 大模型安装步骤

1.下载OllamaSetup安装包 下载地址&#xff1a;https://ollama.com/download 这里已Windows系统为例&#xff1a; 2.安装OllamaSetup客户端 3.部署大模型 在系统搜索栏里面&#xff0c;搜索cmd并打开 根据电脑实际配置情况选择对应的模型进行安装 【1】. 普通7B版 安装指…...

【Linux修炼手册】Linux开发工具的使用(一):yum与vim

文章目录 一、Linux 软件包管理器——yum安装与卸载的使用方法查看软件包 二、Linux编辑器——vimvim命名模式常用指令底行模式常用指令 一、Linux 软件包管理器——yum Linux安装软件的方式有3种&#xff1a; 源代码安装——成本极高rmp安装——具有安装依赖、安装源、安装版…...

JAVA房屋租售管理系统房屋出租出售平台房屋销售房屋租赁房屋交易信息管理源码

一、源码描述 这是一套房屋租售管理源码&#xff0c;基于SpringBootVue框架&#xff0c;后端采用JAVA开发&#xff0c;源码功能完善&#xff0c;涵盖了房屋租赁、房屋销售、房屋交易等业务。 二、源码截图...

XL32F001国产低成本单片机,24MHz主频,24KB Flash,3KB SRAM

XL32F001 是一颗基于ARM Cortex-M0内核的32 位微控制器&#xff0c;专为低成本、低功耗、小型化嵌入式系统设计&#xff0c;适合对资源需求中等但强调性价比和能效的场景。主频可达24M&#xff0c;内存方面有24KB Flash和3KB SRAM&#xff0c;适用于资源需求不大的应用场景。1.…...

k8s术语之job

Job类型 Kubernetes支持以下几种Job: 非并行Job&#xff1a;通常创建一个Pod直至其成功结束 固定结束次数的Job:设置.spec.completions&#xff0c;创建多个 Pod&#xff0c;直到 .spec.completions 个 Pod 成功结束 带有工作队列的并行Job&#xff1a;设置.spec.Parallelism 但…...

单片机-STM32部分:8、外部中断

飞书文档https://x509p6c8to.feishu.cn/wiki/ENFswNTSGiblehkIMtfc9dYinqh 创建工程 按工程创建章节步骤&#xff0c;把工程创建好&#xff0c;并配置外部时钟源&#xff0c;SWD调试模式&#xff0c;时钟72MHz。 设置引脚模式 找到需要配置的按键&#xff0c;例如PC2&#…...

电子电器架构 --- 电气/电子架构如何发展以满足其处理和传感器融合需求

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…...

WordPress插件:WPJAM Basic优化设置

WPJAM Basic 插件的「优化设置」是我爱水煮鱼博客多年使用 WordPress 的经验而整理的各类优化设置。 一、功能屏蔽 功能屏蔽就是屏蔽一些WordPress中用不上、难用的功能&#xff0c;目前的支持屏蔽以下功能&#xff1a; &#xff08;1&#xff09;屏蔽文章修订功能 文章修…...

数字电子技术基础(五十六)——JK触发器

目录 1 JK触发器 2 使用Digital软件来绘制JK触发器 1 JK触发器 对于D触发器来说&#xff0c;其功能是过于简单了&#xff0c;D触发器只有置0和置1的操作&#xff0c;而JK触发器相对于D触发器处理原来的保持、置位和复位的操作&#xff0c;还增加了翻转操作。JK触发器通过优化…...

python小说网站管理系统-小说阅读系统

目录 技术栈介绍具体实现截图![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/97a315fa68d742a68f8393ddc0be8190.png)![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/38eb9e68a134491d900ded262720e203.png)系统设计研究方法&#xff1a;设计步骤设计流程核…...

Python程序,输入IP,扫描该IP哪些端口对外是开放的,输出端口列表

#!/usr/bin/env python # -*- coding: utf-8 -*-""" IP端口扫描程序 输入IP地址&#xff0c;扫描该IP哪些端口对外是开放的&#xff0c;输出端口列表 """import socket import sys import concurrent.futures import ipaddress from tabulate im…...

极狐GitLab 容器镜像仓库功能介绍

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 极狐GitLab 容器镜像库 (BASIC ALL) 您可以使用集成的容器镜像库&#xff0c;来存储每个极狐GitLab 项目的容器镜像。 要为您…...

【嵌入式开发-IIC】

嵌入式开发-IIC ■ IIC简介■ IIC ■ IIC简介 ■ IIC...

能见度测量仪:能适应各种恶劣天气状况

云境天合TH-BN10能见度测量仪是一种用于测量大气能见度的专业仪器&#xff0c;在气象观测、交通运输、航空航海等领域发挥着关键作用。 能见度即目标物的能见距离&#xff0c;指观测目标物时&#xff0c;能从背景上分辨出目标物轮廓的最大距离&#xff0c;是重要的气象观测要素…...

运维打铁:服务器分类及PHP入门

文章目录 C/S架构和B/S架构C/S架构B/S架构 服务器分类服务器类型服务器软件 使用 WampServer 搭建 HTTP服务集成环境的分类WampServer 的安装测试访问配置网站根目录 静态网站和动态网站PHP的常见语法第一段 php 代码注释变量数据类型运算符函数的定义类和对象内容输出循环语句…...

SpringBoot应急知识学习系统开发实现

概述 一个基于SpringBoot开发的应急知识学习系统&#xff0c;该系统提供了完整的用户注册、登录、知识学习与测评功能。对于开发者而言&#xff0c;这是一个值得参考的免费Java源码项目&#xff0c;可以帮助您快速构建类似的教育平台。 主要内容 5.2 注册模块的实现 系统采…...

系统思考助力富维东阳

刚刚完成了长春一家汽车零配件公司关于系统思考的项目&#xff01; 在开班仪式上&#xff0c;公司总经理深刻阐述了项目的背后意义&#xff0c;强调了系统思考与公司战略的紧密联系。这不仅是一次培训&#xff0c;更是一次关于“如何全方位看待问题”的深度对话。 在这个过程中…...

《供应链网络攻击的风险与防范》

中国古语有云&#xff1a;“千里之堤&#xff0c;溃于蚁穴。”供应链攻击正是利用这种系统性弱点发起攻势。近年来&#xff0c;随着国内数字化转型加速&#xff0c;供应链安全问题频发。从某盟删库事件到某头部物流企业数据泄露&#xff0c;从某国产工业软件遭恶意代码植入到某…...

【MySQL】进阶知识详解

目录 引言一、约束:数据完整性的守护者1.1 约束的作用与分类1.2 约束的语法详解非空约束唯一约束主键约束外键约束1.3 约束实战案例二、数据库设计:表关系的艺术2.1 三种核心表关系一对多(部门-员工)多对多(学生-课程)一对一(用户-详情)三、多表查询:数据关联的桥梁3.…...

SpringBoot中使用MCP和通义千问来处理和分析数据-连接本地数据库并生成实体类

文章目录 前言一、正文1.1 项目结构1.2 项目环境1.3 完整代码1.3.1 spring-mcp-demo的pom文件1.3.2 generate-code-server的pom文件1.3.3 ChatClientConfig1.3.4 FileTemplateConfig1.3.5 ServiceProviderConfig1.3.6 GenerateCodeController1.3.7 Columns1.3.8 Tables1.3.9 Fi…...

算法每日一题 | 入门-分支结构-Apples Prologue/苹果和虫子

Apples Prologue/苹果和虫子 题目描述 小 B 喜欢吃苹果。她现在有 m m m&#xff08;1 ≤ m ≤100&#xff09;个苹果&#xff0c;吃完一个苹果需要花费 t t t&#xff08;0 ≤ t≤ 100&#xff09;分钟&#xff0c;吃完一个后立刻开始吃下一个。 现在时间过去了 s s s&a…...

浙大与哈佛联合开源图像编辑模型IC-Edit,实现高效、精准、快速的指令编辑~

项目背景 研究动机与目标 ICEdit&#xff08;In-Context Edit&#xff09;由浙江大学团队开发&#xff0c;旨在通过自然语言指令实现高效、精准的图像编辑&#xff0c;降低对大规模训练数据和计算资源的需求。传统图像编辑方法&#xff08;如基于微调的扩散模型或无训练技术&…...

查看jdk是否安装并且配置成功?(Android studio安装前的准备)

WinR输入cmd打开命令提示窗口 输入命令 java -version 回车显示如下&#xff1a;...

Off-Policy策略演员评论家算法SAC详解:python从零实现

引言 软演员评论家&#xff08;SAC&#xff09;是一种最先进的Off-Policy策略演员评论家算法&#xff0c;专为连续动作空间设计。它在 DDPG、TD3 的基础上进行了显著改进&#xff0c;并引入了最大熵强化学习的原则。其目标是学习一种策略&#xff0c;不仅最大化预期累积奖励&a…...

基于大模型的计划性剖宫产全流程预测与方案优化研究报告

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 二、大模型在计划性剖宫产中的应用原理 2.1 大模型介绍 2.2 数据收集与处理 2.3 模型训练与优化 三、术前预测与准备 3.1 风险因素评估 3.2 大模型术前预测 3.3 术前准备方案 四、术中预测与应对 4.1 术中…...

在Lua中使用轻量级userdata在C/C++之间传递数据和调用函数

在Lua中使用轻量级userdata在C/C之间传递数据和调用函数 轻量级userdata是Lua中一种高效的数据传递机制&#xff0c;它允许你在C/C和Lua之间传递指针而不创建完整的userdata对象。下面是如何使用轻量级userdata的详细说明&#xff1a; 基本概念 轻量级userdata&#xff1a;只…...

总线通信篇:I2C、SPI、CAN 的底层结构与多机通信设计

本文为嵌入式通信协议系列第三章,深入剖析 MCU 世界中的三大总线协议 —— I2C、SPI 和 CAN。 这些总线协议广泛应用于传感器数据采集、Flash 存储、外设扩展、汽车电子、工业设备控制等领域,是嵌入式开发不可或缺的通信骨架。 📜 一、总线通信的基本概念 1.1 什么是总线?…...

心跳策略(Heartbeat) 和 Ping/Echo 策略

一、心跳策略&#xff08;Heartbeat&#xff09; 原理&#xff1a;客户端定期向服务端发送心跳包&#xff0c;服务端监控客户端存活状态&#xff0c;超时未收到心跳则判定客户端离线 服务端代码 using System; using System.Net; using System.Net.Sockets; using System.Coll…...

探索网络设备安全:Shodan 的原理与合法应用

在数字化时代&#xff0c;网络摄像头因其便捷性和高效性被广泛应用于家庭、商业和工业领域。然而&#xff0c;这些设备的安全性问题也日益受到关注。Shodan&#xff0c;这个被称为“设备搜索引擎”的工具&#xff0c;能够帮助我们发现和分析网络摄像头的分布和安全性。本文将深…...

Java JWT 配置类 (JwtProperties) 学习笔记

1. 核心作用&#xff1a; 此类 (JwtProperties) 作为一个集中的“配置信息持有者”&#xff0c;专门用来存储项目中与 JWT&#xff08;JSON Web Token&#xff0c;一种用于身份验证的令牌&#xff09;相关的配置参数。 2. 关键注解说明&#xff1a; Component: 含义&#xff…...

沃伦森电容器支路阻抗特性监控系统 电容器组智能健康管理专家

行业现状与挑战 在现代电力系统中&#xff0c;电容器组作为无功补偿的核心设备&#xff0c;对保障电网稳定运行和提升电能质量至关重要。然而&#xff0c;长期运行中面临的谐波干扰、过电压/过电流冲击等问题&#xff0c;极易导致电容值衰减、介质老化甚至爆炸等严重故障&#…...

macOS Arduino IDE离线安装ESP8266支持包

其实吧&#xff0c;本来用platformio也是可以的&#xff0c;不过有时候用Arduino IDE可能更快一些&#xff0c;因为以前一直是Arduino.app和Arduino IDE.app共存了一段时间&#xff0c;后来下决心删掉Arduino.app并升级到最新的Arduino IDE.app。删除了旧的支持板级支持包之后就…...

在Fiddler中添加自定义HTTP方法列并高亮显示

在Fiddler中添加自定义HTTP方法列并高亮显示 Fiddler 是一款强大的 Web 调试代理工具&#xff0c;允许开发者检查和操作 HTTP 流量。一个常见需求是自定义 Web Sessions 列表&#xff0c;添加显示 HTTP 方法&#xff08;GET、POST 等&#xff09;的列&#xff0c;并通过颜色区…...

HTTP学习

HTTP知识 01. 经典五层模型 应用层 为应用软件提供了很多服务&#xff0c;构建于协议之上。 传输层 数据的传输都是在这层定义的&#xff0c;数据过大分包&#xff0c;分片。 网络层 为数据在节点之间传输创建逻辑链路 数据链路层 通讯实体间建立数据链路连接 物理层 主要作用…...

正态分布和幂律分布

1. 背景与引入 正态分布 历史来源&#xff1a;18世纪由高斯&#xff08;Gauss&#xff09;在研究测量误差时提出&#xff0c;后被广泛应用于自然现象和社会科学的数据建模。重要性&#xff1a;被称为“钟形曲线”&#xff0c;是统计学中最核心的分布之一&#xff0c;支撑中心极…...

网络安全赛题解析

扫描之后发现目标靶机 上开启了 ftp ssh http mysql等服务 第一题 第一题需要获取文件 首先尝试 ftp 匿名用户 从这里可以发现 hint.txt 文件的大小为 127b 或 127bytes 提交127b 第二题 通过hint.txt 文件可以发现目标主机 上有用户 Jay 密码为五位字符串 其中三位不知道 利…...

Android单例模式知识总结

六种核心实现方式对比 1. 饿汉式单例&#xff08;Eager Initialization&#xff09; 原理&#xff1a;利用类加载时静态变量初始化的特性&#xff0c;天然线程安全。 代码&#xff1a; public class EagerSingleton {private static final EagerSingleton INSTANCE new Eag…...

何不乘东风?利用mcp实现小红书自动发布

1.准备环境 conda create -n mcpo python3.11 conda activate mcpo pip install mcpo pip install uvnpx puppeteer/browsers install chromedriver134.0.6998.166pip install xhs-mcp-server 2.进行登陆 env phoneYOUR_PHONE_NUMBER json_pathPATH_TO_STORE_YOUR_COOKIES u…...

DeepSeek多尺度数据:无监督与原则性诊断方案全解析

DeepSeek 多尺度数据诊断方案的重要性 在当今的 IT 领域,数据如同石油,是驱动各类智能应用发展的核心资源。随着技术的飞速发展,数据的规模和复杂性呈爆炸式增长,多尺度数据处理成为了众多领域面临的关键挑战。以计算机视觉为例,在目标检测任务中,小目标可能只有几个像素…...

【开源】Python打造高效剪贴板历史管理器:实现跨平台生产力工具

&#x1f4cb;【开源】Python打造高效剪贴板历史管理器&#xff1a;实现跨平台生产力工具 &#x1f308; 个人主页&#xff1a;创客白泽 - CSDN博客 &#x1f525; 系列专栏&#xff1a;&#x1f40d;《Python开源项目实战》 &#x1f4a1; 热爱不止于代码&#xff0c;热情源自…...

Day 14 训练

Day 14 训练 SHAP&#xff08;SHapley Additive exPlanations&#xff09;1.创建解释器2.将特征贡献可视化第一部分&#xff1a;绘制SHAP特征重要性条形图第二部分&#xff1a;绘制SHAP特征重要性蜂巢图 SHAP&#xff08;SHapley Additive exPlanations&#xff09; 旨在解释复…...

V型球阀材质性能深度解析:专攻颗粒、料浆与高腐蚀介质的工业利器-耀圣

V型球阀材质性能深度解析&#xff1a;专攻颗粒、料浆与高腐蚀介质的工业利器 在工业流体控制领域&#xff0c;V型球阀凭借其独特的V型切口设计与多元化材质适配能力&#xff0c;成为含颗粒、纤维、料浆及强腐蚀性介质的“终极克星”。本文从材质性能与驱动适配性两大维度切入&…...