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

Kubernetes金丝雀发布

华子目录

  • Canary金丝雀发布
  • 什么是金丝雀发布
  • Canary发布方式
    • 基于header(http包头)灰度发布
    • 基于权重的金丝雀发布

Canary金丝雀发布

在这里插入图片描述

什么是金丝雀发布

  • 金丝雀发布也称为灰度发布,是一种软件发布策略
  • 主要目的是在将新版本软件全面推广到生产环境之前,先在一小部分用户服务器上进行测试验证,以降低新版本引入重大问题而对整个系统造成的影响
  • 是一种Pod发布方式金丝雀发布采取先添加再删除的方式,保证Pod总量不低于期望值。并且在更新部分Pod后,暂停更新,当确认新Pod版本运行正常后再进行其他版本Pod的更新

Canary发布方式

三种发布方式

  • 优先级:head大于cookie大于weight
  • 其中headerweight用的最多

基于header(http包头)灰度发布

在这里插入图片描述
我们可以看到如果包头中有stage=gray键值对,就访问新版本包头中没有那个键值对,就访问旧版本

  • 通过Annotaion扩展
  • 创建灰度ingress,配置灰度头部key以及value
  • 灰度流量验证完毕后,切换正式ingress新版本
  • 之前我们在做升级时可以通过控制器滚动更新,默认25%利用header可以使升级更为平滑,通过keyvalue 测试新的业务体系是否有问题

创建2deployment控制器

#发现没有运行的pod
[root@k8s-master service]# kubectl get pods
No resources found in default namespace.#创建一个deployment控制器,控制器中运行一个pod
[root@k8s-master service]# kubectl create deployment deployment --image myapp:v1 --dry-run=client -o yaml > deployment-v1.yml[root@k8s-master service]# vim deployment-v1.yml
[root@k8s-master service]# cat deployment-v1.yml
apiVersion: apps/v1
kind: Deployment   #指明这是一个deployment控制器
metadata:   #控制器的元数据labels:    #控制器的标签app: deployment1   #控制器的标签name: deployment1   #控制器的名字
spec:  控制器的规格replicas: 1  #pod数量selector:  #pod选择器matchLabels:   #声明的要管理的podapp: myappv1  #标签为app=myappv1的pod会被管理template:    #pod的模板metadata:    #pod的元数据labels:     #pod的标签app: myappv1spec:     #pod的规格containers:- image: myapp:v1name: myappv1#在克隆一份
[root@k8s-master service]# cp deployment-v1.yml deployment-v2.yml
[root@k8s-master service]# vim deployment-v2.yml
[root@k8s-master services]# cat deployment-v2.yml
apiVersion: apps/v1
kind: Deployment  #指明这个一个deployment控制器
metadata:     #控制器的元数据labels:     app: deployment2   #控制器的标签name: deployment2   #控制器的名字
spec:    #控制器的规格replicas: 1    #pod数量selector:     #pod选择器matchLabels:    app: myappv2   #声明需要管理的标签template:    #pod的模板metadata:    #pod的元数据labels:   app: myappv2  #pod的标签spec:   #pod的规格containers:- image: myapp:v2name: myappv2 
[root@k8s-master service]# kubectl apply -f deployment-v1.yml
deployment.apps/deployment1 created
[root@k8s-master service]# kubectl apply -f deployment-v2.yml
deployment.apps/deployment2 created[root@k8s-master service]# kubectl get pods -o wide --show-labels
NAME                           READY   STATUS    RESTARTS   AGE     IP            NODE            NOMINATED NODE   READINESS GATES   LABELS
deployment1-5c47495d84-ds4cl   1/1     Running   0          3m20s   10.244.2.15   k8s-node2.org   <none>           <none>            app=myappv1,pod-template-hash=5c47495d84
deployment2-67cc8c4845-bfnvx   1/1     Running   0          6m49s   10.244.2.14   k8s-node2.org   <none>           <none>            app=myappv2,pod-template-hash=67cc8c4845

创建2service微服务

[root@k8s-master service]# kubectl expose deployment deployment1 --port 8080 --target-port 80 --dry-run=client -o yaml >> deployment-v1.yml[root@k8s-master service]# kubectl expose deployment deployment2 --port 8080 --target-port 80 --dry-run=client -o yaml >> deployment-v2.yml
[root@k8s-master service]# vim deployment-v1.yml
[root@k8s-master service]# cat deployment-v1.yml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: deployment1name: deployment1
spec:replicas: 1selector:matchLabels:app: myappv1template:metadata:labels:app: myappv1spec:containers:- image: myapp:v1name: myappv1---
apiVersion: v1
kind: Service   #指明这是一个service微服务
metadata:   #微服务元数据labels:  app: deployment1  #微服务标签 name: deployment1   #微服务的名字
spec:    #微服务的规格ports:   #是一个端口列表,用于描述service应该监听的端口以及如何将流量转发给pod- port: 8080   #service微服务监听的端口号protocol: TCP   #使用的协议,这里是TCPtargetPort: 80   #pod上应用程序监听的端口selector:    #标签选择器,用于确定哪些pods应该被这个service管理app: myappv1  #pod标签为app=myappv1的被该service管理
[root@k8s-master service]# vim deployment-v2.yml
[root@k8s-master service]# cat deployment-v2.yml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: deployment2name: deployment2
spec:replicas: 1selector:matchLabels:app: myappv2template:metadata:labels:app: myappv2spec:containers:- image: myapp:v2name: myappv2---
apiVersion: v1
kind: Service
metadata:labels:app: deployment2name: deployment2
spec:ports:- port: 8080protocol: TCPtargetPort: 80selector:app: myappv2
[root@k8s-master service]# kubectl apply -f deployment-v1.yml
deployment.apps/deployment1 unchanged
service/deployment1 created
[root@k8s-master service]# kubectl apply -f deployment-v2.yml
deployment.apps/deployment2 unchanged
service/deployment2 created
[root@k8s-master service]# kubectl get pods -o wide --show-labels
NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE            NOMINATED NODE   READINESS GATES   LABELS
deployment1-5c47495d84-ds4cl   1/1     Running   0          15m   10.244.2.15   k8s-node2.org   <none>           <none>            app=myappv1,pod-template-hash=5c47495d84
deployment2-67cc8c4845-bfnvx   1/1     Running   0          18m   10.244.2.14   k8s-node2.org   <none>           <none>            app=myappv2,pod-template-hash=67cc8c4845[root@k8s-master service]# kubectl get svc -o wide
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE    SELECTOR
deployment1   ClusterIP   10.108.37.167   <none>        8080/TCP   3m8s   app=myappv1
deployment2   ClusterIP   10.96.202.197   <none>        8080/TCP   3m2s   app=myappv2
kubernetes    ClusterIP   10.96.0.1       <none>        443/TCP    27d    <none>[root@k8s-master service]# kubectl describe svc deployment1
Name:              deployment1
Namespace:         default
Labels:            app=deployment1
Annotations:       <none>
Selector:          app=myappv1
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.108.37.167
IPs:               10.108.37.167
Port:              <unset>  8080/TCP
TargetPort:        80/TCP
Endpoints:         10.244.2.15:80
Session Affinity:  None
Events:            <none>[root@k8s-master service]# kubectl describe svc deployment2
Name:              deployment2
Namespace:         default
Labels:            app=deployment2
Annotations:       <none>
Selector:          app=myappv2
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.96.202.197
IPs:               10.96.202.197
Port:              <unset>  8080/TCP
TargetPort:        80/TCP
Endpoints:         10.244.2.14:80
Session Affinity:  None
Events:            <none>
  • 创建ingress1.yml
[root@k8s-master service]# kubectl create ingress ingress1 --class nginx --rule='/=deployment1:8080' --dry-run=client -o yaml > ingress1.yml[root@k8s-master service]# vim ingress1.yml
[root@k8s-master service]# cat ingress1.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress1
spec:ingressClassName: nginxrules:- http:paths:- backend:service:name: deployment1port:number: 8080path: /pathType: Prefix
  • 创建ingress2.yml
[root@k8s-master service]# kubectl create ingress ingress2 --class nginx --rule='/=deployment2:8080' --dry-run=client -o yaml > ingress2.yml[root@k8s-master service]# vim ingress2.yml
[root@k8s-master service]# cat ingress2.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/canary: "true"nginx.ingress.kubernetes.io/canary-by-header: "name"   #键nginx.ingress.kubernetes.io/canary-by-header-value: "huazi"  #值name: ingress2
spec:ingressClassName: nginxrules:- http:paths:- backend:service:name: deployment2port:number: 8080path: /pathType: Prefix
[root@k8s-master service]# kubectl apply -f ingress1.yml
ingress.networking.k8s.io/ingress1 created
[root@k8s-master service]# kubectl apply -f ingress2.yml
ingress.networking.k8s.io/ingress2 created
[root@k8s-master service]# kubectl describe ingress ingress1
Name:             ingress1
Labels:           <none>
Namespace:        default
Address:          172.25.254.10
Ingress Class:    nginx
Default backend:  <default>
Rules:Host        Path  Backends----        ----  --------*/   deployment1:8080 (10.244.2.15:80)
Annotations:  <none>
Events:Type    Reason  Age                From                      Message----    ------  ----               ----                      -------Normal  Sync    12m (x2 over 13m)  nginx-ingress-controller  Scheduled for sync[root@k8s-master service]# kubectl describe ingress ingress2
Name:             ingress2
Labels:           <none>
Namespace:        default
Address:          172.25.254.10
Ingress Class:    nginx
Default backend:  <default>
Rules:Host        Path  Backends----        ----  --------*/   deployment2:8080 (10.244.2.14:80)
Annotations:  nginx.ingress.kubernetes.io/canary: truenginx.ingress.kubernetes.io/canary-by-header: namenginx.ingress.kubernetes.io/canary-by-header-value: huazi
Events:Type    Reason  Age                   From                      Message----    ------  ----                  ----                      -------Normal  Sync    2m21s (x2 over 3m3s)  nginx-ingress-controller  Scheduled for sync

在这里插入图片描述

基于权重的金丝雀发布

在这里插入图片描述

  • 通过Annotaion拓展
  • 创建灰度ingress,配置灰度权重以及总权重
  • 灰度流量验证完毕后,切换正式ingress新版本
#删掉基于header的ingress
[root@k8s-master service]# kubectl delete -f ingress2.yml
ingress.networking.k8s.io "ingress2" deleted
[root@k8s-master service]# vim ingress2.yml
[root@k8s-master service]# cat ingress2.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/canary: "true"nginx.ingress.kubernetes.io/canary-weight: "10"    #10/100=10%,将有10%的流量打到新版本上nginx.ingress.kubernetes.io/canary-weight-total: "100"name: ingress2
spec:ingressClassName: nginxrules:- http:paths:- backend:service:name: deployment2port:number: 8080path: /pathType: Prefix
[root@k8s-master service]# kubectl apply -f ingress2.yml
ingress.networking.k8s.io/ingress2 created
[root@k8s-master service]# kubectl describe ingress ingress1
Name:             ingress1
Labels:           <none>
Namespace:        default
Address:          172.25.254.10
Ingress Class:    nginx
Default backend:  <default>
Rules:Host        Path  Backends----        ----  --------*/   deployment1:8080 (10.244.2.15:80)
Annotations:  <none>
Events:Type    Reason  Age                From                      Message----    ------  ----               ----                      -------Normal  Sync    27m (x2 over 27m)  nginx-ingress-controller  Scheduled for sync[root@k8s-master service]# kubectl describe ingress ingress2
Name:             ingress2
Labels:           <none>
Namespace:        default
Address:          172.25.254.10
Ingress Class:    nginx
Default backend:  <default>
Rules:Host        Path  Backends----        ----  --------*/   deployment2:8080 (10.244.2.14:80)
Annotations:  nginx.ingress.kubernetes.io/canary: truenginx.ingress.kubernetes.io/canary-weight: 10nginx.ingress.kubernetes.io/canary-weight-total: 100
Events:Type    Reason  Age                From                      Message----    ------  ----               ----                      -------Normal  Sync    34s (x2 over 44s)  nginx-ingress-controller  Scheduled for sync
  • 写检测脚本
[root@harbor ~]# vim check.sh
#!/bin/bash
v1=0
v2=0
for ((i=0;i<100;i++))
doresponse=`curl -s 172.25.254.50 | grep -c v1`v1=`expr $v1 + $response`v2=`expr $v2 + 1 - $response`
done
echo "v1:$v1  v2:$v2"
[root@harbor ~]# bash check.sh
v1:89  v2:11
[root@harbor ~]# bash check.sh
v1:87  v2:13
#我们发现比例接近于9:1

当我们增加权重

[root@k8s-master service]# vim ingress2.yml
[root@k8s-master service]# cat ingress2.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/canary: "true"nginx.ingress.kubernetes.io/canary-weight: "20"nginx.ingress.kubernetes.io/canary-weight-total: "100"name: ingress2
spec:ingressClassName: nginxrules:- http:paths:- backend:service:name: deployment2port:number: 8080path: /pathType: Prefix
[root@k8s-master service]# kubectl apply -f ingress2.yml
ingress.networking.k8s.io/ingress2 configured
[root@harbor ~]# bash check.sh
v1:76  v2:24
[root@harbor ~]# bash check.sh
v1:79  v2:21
#我们发现比例进阶于8:2

相关文章:

Kubernetes金丝雀发布

华子目录 Canary金丝雀发布什么是金丝雀发布Canary发布方式基于header&#xff08;http包头&#xff09;灰度发布基于权重的金丝雀发布 Canary金丝雀发布 什么是金丝雀发布 金丝雀发布也称为灰度发布&#xff0c;是一种软件发布策略主要目的是在将新版本的软件全面推广到生产环…...

树形DP讲解

文章目录 树形DP讲解一、引言二、树形DP基础1、树的定义2、树形DP的基本思想3、代码示例&#xff1a;子树大小 三、经典例题解析1、树的平衡点1.1、代码示例 2、没有上司的舞会&#xff08;树的最大独立集&#xff09;2.1、代码示例 四、总结 树形DP讲解 一、引言 树形动态规…...

容器:如何调试容器

调试容器&#xff0c;主要是指的调试Dockerfile&#xff0c;调试Dockerfile中的各个命令的执行&#xff0c;大小等 1、docker history查看构建过程和所有的中间层 2、docker run rm -it -u root XXX sh&#xff0c;通过临时容器的方式启动&#xff0c;可以调试中间层文件 3、do…...

用图说明 CPU、MCU、MPU、SoC 的区别

CPU CPU 负责执行构成计算机程序的指令&#xff0c;执行这些指令所指定的算术、逻辑、控制和输入/输出&#xff08;I/O&#xff09;操作。 MCU (microcontroller unit) 不同的 MCU 架构如下&#xff0c;注意这里的 MPU 表示 memory protection unit MPU (microprocessor un…...

牛客周赛 Round 65

文章目录 超市思路&#xff1a;Solved&#xff1a; 雨幕思路&#xff1a;Solved&#xff1a; 闺蜜思路&#xff1a;Solved&#xff1a; 医生思路&#xff1a;Solved&#xff1a; 降温&#xff08;easy&#xff09;思路&#xff1a;Solved&#xff1a; F-降温&#xff08;hard&a…...

超级经典的79个软件测试面试题(内含答案)

1、软件的生命周期(prdctrm) 计划阶段(planning)-〉需求分析(requirement)-〉设计阶段(design)-〉编码(coding)->测试(testing)->运行与维护(running maintrnacne) 测试用例 用例编号 测试项目 测试标题 重要级别 预置条件 输入数据 执行步骤 预期结果 2、问&#xf…...

【Mac】安装 F5-TTS

1、下载项目 项目地址&#xff1a;【GitHub】 SWivid F5-TTS 2、创建并激活 Python 虚拟环境 # 创建 Python 虚拟环境 userMac F5-TTS-main % python3 -m venv f5-tts# 激活进入 Python 虚拟环境 userMac F5-TTS-main % source f5-tts/bin/activate (f5-tts) userrMac F5-TT…...

Leaflet查询矢量瓦片偏移的问题

1、问题现象 使用Leaflet绘制工具查询出来的结果有偏移 2、问题排查 1&#xff09;Leaflet中latLngToContainerPoint和latLngToLayerPoint的区别 2&#xff09;使用Leaflet查询需要使用像素坐标 3&#xff09;经排查发现&#xff0c;container获取的坐标是地图容器坐标&…...

存储引擎技术进化

B-tree 目前支撑着数据库产业的半壁江山。 50 年来不变而且人们还没有改变它的意向 鉴定一个算法的优劣&#xff0c;有一个学派叫 IO复杂度分析 &#xff0c;简单推演真假便知。 下面就用此法分析下 B-tree(traditional b-tree) 的 IO 复杂度&#xff0c;对读、写 IO 一目了…...

CentOS 9 Stream 上安装 Maven

CentOS 9 Stream 上安装 Maven 在 CentOS 9 Stream 上安装 Maven&#xff0c;可以按照以下步骤进行&#xff1a; 更新系统软件包&#xff1a; sudo dnf update安装 Maven&#xff1a; CentOS 9 Stream 默认的包管理器中已经包含 Maven&#xff0c;你可以直接安装&#xff1a; s…...

强势改进!TCN-Transformer时间序列预测

强势改进&#xff01;TCN-Transformer时间序列预测 目录 强势改进&#xff01;TCN-Transformer时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现TCN-Transformer时间序列预测&#xff1b; 2.运行环境为Matlab2023b&#xff1b; 3.单个变量时间序…...

MyBatis的不同参数传递封装

MyBatis参数传递 传参方式 1. 使用 #{} 占位符 这是 MyBatis 中最常用的参数传递方式。它将参数直接替换到 SQL 语句中的占位符位置。 单个参数&#xff1a; <select id"selectUserById" resultType"User">SELECT * FROM users WHERE id #{id}…...

kotlin 协程方法总结

Kotlin 协程是一套强大的异步编程工具&#xff0c;以下是对 Kotlin 协程常用方法的总结&#xff1a; 1. 协程构建器 launch: 启动一个新的协程&#xff0c;不阻塞当前线程&#xff0c;返回一个 Job 对象。 GlobalScope.launch {// 协程体}async: 启动一个新的协程并返回一个…...

脉冲当量计算方法

脉冲的概念&#xff1a; 脉冲当量是指控制器输出一个定位控制脉冲时&#xff0c;所产生的定位控制移动的位移。在直线运动中&#xff0c;它表示移动的距离&#xff1b;在圆周运动中&#xff0c;它表示转动的角度。简而言之&#xff0c;脉冲当量就是电机接收一个脉冲信号后能够移…...

TongWeb7.0.E.6_P11嵌入式版本使用指引(by lqw)

文章目录 声明相关概念手册的使用示范工程安装工程介质 安装前准备示范工程参考&#xff08;spring-boot-helloWorld-2.x&#xff09;示范参考 声明 1.本文参考001_TongWeb_V7.0嵌入式版_JavaEE标准容器用户指南_70E6_P11A01.pdf&#xff0c;实际以最新更新的手册为准。 2.本文…...

Node.js:Express 服务 路由

Node.js&#xff1a;Express 服务 & 路由 创建服务处理请求req对象 静态资源托管托管多个资源挂载路径前缀 路由模块化 Express是Node.js上的一个第三方框架&#xff0c;可以快速开发一个web框架。本质是一个包&#xff0c;可以通过npm直接下载。 创建服务 Express创建一…...

C++之多态(上)

C之多态 多态的概念 多态(polymorphism)的概念&#xff1a;通俗来说&#xff0c;就是多种形态。多态分为编译时多态(静态多态)和运⾏时多 态(动态多态)&#xff0c;这⾥我们重点讲运⾏时多态&#xff0c;编译时多态(静态多态)和运⾏时多态(动态多态)。编译时 多态(静态多态)主…...

PySpark单机模式安装教程

目录 1. 环境准备 1.1 安装要求 1.2 检查Python和Java环境 2. 下载并解压Spark 2.1 下载Spark 2.2 解压安装包 3. 配置环境变量 4. 配置Spark 5. 启动Spark Shell 6. 运行测试 7. 关闭Spark Shell 8. 常见问题 8.1 兼容性问题 8.2 环境变量配置 总结 1. 环境准备…...

DEVOPS: 认证与调度

概述 不知道大家有没有意识到一个现实&#xff0c;就是大部分时候&#xff0c;我们已经不像以前一样通过命令行&#xff0c;或者可视窗口来使用一个系统了现在我们上微博、或者网购&#xff0c;操作的其实不是眼前这台设备&#xff0c;而是一个又一个集群 通常&#xff0c;这样…...

ICPC区域赛成都站【赛后回顾+总结】

传送门 前言赛后总结赛后回顾赛后感悟 前言 首先&#xff0c;这是本人本赛季第一场XCPC区域赛&#xff0c;也是本人算竞生涯中第一场XCPC区域赛&#xff08;之前只打过邀请赛和省赛&#xff09;。 赛后总结 然后赛后总结一下&#xff1a;我队天崩开局&#xff0c;我队出师不利…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

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

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

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板&#xff08;STM32F103RBT6&#xff09;通过I2C驱动ICM20948九轴传感器&#xff0c;实现姿态解算&#xff0c;并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化&#xff0c;适合嵌入式及物联网开发者。在基础驱动上新增…...