【Kubernetes】第十一篇 - 滚动发布的介绍与实现
一,前言
上一篇,介绍了灰度发布和流量切分的集中方式,以及如何实现 k8s 的灰度发布;
本篇,介绍滚动发布的实现;
二,滚动发布简介
滚动发布
- 滚动发布,则是我们一般所说的无宕机发布。其发布方式如同名称一样,一次取出一台/多台服务器(看策略配置)进行新版本更新。当取出的服务器新版确保无问题后,接着采用同等方式更新后面的服务器
- k8s创建副本应用程序的最佳方法就是部署(Deployment),部署自动创建副本集(ReplicaSet),副本集可以精确地控制每次替换的Pod数量,从而可以很好的实现滚动更新
- k8s每次使用一个新的副本控制器(replication controller)来替换已存在的副本控制器,从而始终使用一个新的Pod模板来替换旧的pod模板
- 创建一个新的 replication controller;
- 增加或减少 pod 副本数量,直到满足当前批次期望的数量;
- 删除掉旧的 replication controller;
发布流程和策略
-
优点
- 不需要停机更新,无感知平滑更新;
- 版本更新成本小,不需要新旧版本共存;
-
缺点
- 更新时间长:每次只更新一个/多个镜像,需要频繁连续等待服务启动缓冲
- 旧版本环境无法得到备份:始终只有一个环境存在
- 回滚版本异常:如果滚动发布到一半出了问题,回滚时需要使用同样的滚动策略回滚旧版本
三、环境初始化
由于 k8s-node 资源问题,先清理一下 k8s-node 上的资源占用;
查看资源情况
[root@k8s-master deployment]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 0/3 3 0 2d1h
pay-v1 0/3 3 0 6h52m
user-v1 0/3 3 0 8m11s
user-v2 0/3 3 0 5h11m[root@k8s-master deployment]# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d16h
nginx NodePort 10.107.223.32 <none> 80:32117/TCP 2d1h
service-pay-v1 NodePort 10.106.98.218 <none> 80:30872/TCP 6h32m
service-user-v1 NodePort 10.104.13.40 <none> 80:31071/TCP 28h
service-user-v2 NodePort 10.100.196.142 <none> 80:30289/TCP 5h12m[root@k8s-master deployment]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-g2zst 0/1 CrashLoopBackOff 53 2d
nginx-6799fc88d8-2wvl2 1/1 Running 1 2d1h
nginx-6799fc88d8-lkct4 1/1 Running 1 2d1h
nginx-6799fc88d8-pktqq 1/1 Running 1 2d1h
pay-v1-655587b6f5-lpft2 1/1 Running 1 6h41m
pay-v1-655587b6f5-pcnrp 1/1 Running 2 6h42m
pay-v1-655587b6f5-spj85 1/1 Running 1 6h41m
user-v1-5895c69847-8tkm9 0/1 Pending 0 9m18s
user-v1-5895c69847-swp52 0/1 Pending 0 9m18s
user-v1-5895c69847-xr4r8 0/1 Pending 0 9m18s
user-v2-fc9d84585-2zztd 1/1 Running 2 5h13m
user-v2-fc9d84585-ss2ss 1/1 Running 1 5h13m
user-v2-fc9d84585-xrvnf 1/1 Running 1 5h13m
删除无用 pod
注意:想要删除 pod,需要删除掉 deployment,否则副本依然还在;
以 nginx 为例:目前的有 3 个正在运行的 nginx 副本
[root@k8s-master deployment]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-4nq2q 0/1 Pending 0 4m19s
nginx-6799fc88d8-2wvl2 1/1 Running 1 2d1h
nginx-6799fc88d8-lkct4 1/1 Running 1 2d2h
nginx-6799fc88d8-pktqq 1/1 Running 1 2d1h
pay-v1-655587b6f5-lpft2 1/1 Running 1 6h53m
pay-v1-655587b6f5-pcnrp 1/1 Running 2 6h53m
pay-v1-655587b6f5-spj85 1/1 Running 1 6h53m
user-v1-5895c69847-8tkm9 0/1 Pending 0 20m
user-v1-5895c69847-swp52 0/1 Pending 0 20m
user-v1-5895c69847-xr4r8 0/1 Pending 0 20m
user-v2-fc9d84585-2zztd 1/1 Running 2 5h24m
user-v2-fc9d84585-ss2ss 1/1 Running 1 5h24m
user-v2-fc9d84585-xrvnf 1/1 Running 1 5h24m[root@k8s-master deployment]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 0/3 3 0 2d2h
pay-v1 0/3 3 0 7h8m
user-v1 0/3 3 0 23m
user-v2 0/3 3 0 5h27m
删除 nginx 的 deploy 后,pod 状态变为 Terminating
[root@k8s-master deployment]# kubectl delete deployment nginx
deployment.apps "nginx" deleted[root@k8s-master deployment]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-4nq2q 0/1 Pending 0 9m50s
nginx-6799fc88d8-2wvl2 1/1 Terminating 1 2d1h
nginx-6799fc88d8-lkct4 1/1 Terminating 1 2d2h
nginx-6799fc88d8-pktqq 1/1 Terminating 1 2d1h
pay-v1-655587b6f5-lpft2 1/1 Terminating 1 6h58m
pay-v1-655587b6f5-pcnrp 1/1 Terminating 2 6h59m
pay-v1-655587b6f5-spj85 1/1 Terminating 1 6h58m
user-v1-5895c69847-8tkm9 0/1 Pending 0 26m
user-v1-5895c69847-swp52 0/1 Pending 0 26m
user-v1-5895c69847-xr4r8 0/1 Pending 0 26m
user-v2-fc9d84585-2zztd 1/1 Terminating 2 5h30m
user-v2-fc9d84585-ss2ss 1/1 Terminating 1 5h30m
user-v2-fc9d84585-xrvnf 1/1 Terminating 1 5h30m
继续再删除 pod
[root@k8s-master deployment]# kubectl delete pod nginx-6799fc88d8-2wvl2 --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "nginx-6799fc88d8-2wvl2" force deleted[root@k8s-master deployment]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-4nq2q 0/1 Pending 0 14m
nginx-6799fc88d8-lkct4 1/1 Terminating 1 2d2h
nginx-6799fc88d8-pktqq 1/1 Terminating 1 2d1h
pay-v1-655587b6f5-lpft2 1/1 Terminating 1 7h3m
pay-v1-655587b6f5-pcnrp 1/1 Terminating 2 7h3m
pay-v1-655587b6f5-spj85 1/1 Terminating 1 7h3m
user-v1-5895c69847-8tkm9 0/1 Pending 0 30m
user-v1-5895c69847-swp52 0/1 Pending 0 30m
user-v1-5895c69847-xr4r8 0/1 Pending 0 30m
user-v2-fc9d84585-2zztd 1/1 Terminating 2 5h34m
user-v2-fc9d84585-ss2ss 1/1 Terminating 1 5h34m
user-v2-fc9d84585-xrvnf 1/1 Terminating 1 5h34m
重复操作,删除全部无用 pod
这个 mysql 删除不掉
[root@k8s-master deployment]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
user-v1 0/3 3 0 33m[root@k8s-master deployment]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-xqsgz 0/1 Pending 0 13s
user-v1-5895c69847-8tkm9 0/1 Pending 0 35m
user-v1-5895c69847-swp52 0/1 Pending 0 35m
user-v1-5895c69847-xr4r8 0/1 Pending 0 35m
删除 Service
kubectl delete service service-pay-v1 service-user-v2 nginx[root@k8s-master deployment]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d16h
service-user-v1 NodePort 10.104.13.40 <none> 80:31071/TCP 28h
重启阿里云服务
[root@k8s-master deployment]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready control-plane,master 2d16h v1.20.4
k8s-node Ready <none> 2d16h v1.20.4[root@k8s-master deployment]# kubectl get pods
NAME READY STATUS RESTARTS AGE
user-v1-5895c69847-8zs9n 1/1 Running 0 20m
user-v1-5895c69847-tdkhj 1/1 Running 0 20m
user-v1-5895c69847-xcdwl 1/1 Running 0 20m
测试连接
[root@k8s-master deployment]# curl http://172.17.178.106:31071
user-v1
[root@k8s-master deployment]# curl http://172.17.178.105:31071
user-v1
四,实现滚动更新
重新做一下,用 user-v1 测试滚动更新
目前基于 deployment-user-v1.yaml 创建了 deployment 部署实例;
基于 user-service-v1.yaml 创建了 service,并创建了 3 个 pod 副本
修改 deployment 配置,实现滚动更新
将 v1 升级成 v3,原始 deployment-user-v1.yaml:
[root@k8s-master deployment]# cat deployment-user-v1.yaml apiVersion: apps/v1 #API版本号
kind: Deployment #资源类型部署
metadata:name: user-v1 #资源名称
spec:selector:matchLabels:app: user-v1 #告诉deployment根据规则匹配相应的Pod进行控制和管理,matchLabels字段匹配Pod的label值replicas: 3 #声明Pod副本的数量template:metadata:labels:app: user-v1 #Pod名称spec: #描述Pod内的容器信息containers:- name: nginx #容器的名称image: nginx:user-v1 #镜像ports:- containerPort: 80 #容器内映射的端口
修改 deployment-user-v1.yaml
apiVersion: apps/v1 #API 配置版本
kind: Deployment #资源类型
metadata:name: user-v1 #资源名称
spec:
+ minReadySeconds: 1
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ maxUnavailable: 0
+ selector:
+ matchLabels:
+ app: user-v1 #告诉deployment根据规则匹配相应的Pod进行控制和管理,matchLabels字段匹配Pod的label值replicas: 10 #声明一个 Pod,副本的数量template:metadata:labels:app: user-v1 #Pod的名称spec: #组内创建的 Pod 信息containers:- name: nginx #容器的名称
+ image: nginx:user-v3 #使用哪个镜像ports:- containerPort: 80 #容器内映射的端口
相关参数介绍
| 参数 | 含义 | 备注 |
|---|---|---|
| minReadySeconds | 容器接受流量延缓时间:单位为秒,默认为0。如果没有设置的话,k8s会认为容器启动成功后就可以用了。设置该值可以延缓容器流量切分 | 容器启动好了,并不代表服务启动好了,比如还要去连接数据库,初始化缓存等服务初始化工作 |
| strategy.type = RollingUpdate | ReplicaSet 发布类型,声明为滚动发布,默认也为滚动发布 | |
| strategy.rollingUpdate.maxSurge | 最多Pod数量:为数字类型/百分比。如果 maxSurge 设置为1,replicas 设置为10,则在发布过程中pod数量最多为10 + 1个(多出来的为旧版本pod,平滑期不可用状态)。maxUnavailable 为 0 时,该值也不能设置为0 | |
| strategy.rollingUpdate.maxUnavailable | 升级中最多不可用pod的数量:为数字类型/百分比。当 maxSurge 为 0 时,该值也不能设置为0 |
扩容数量,是不包括激增量的
pod 最大数量 = 容量 + 激增数
应用配置
[root@k8s-master deployment]# kubectl apply -f deployment-user-v1.yaml
deployment.apps/user-v1 configured
分析更新过程
// 更新前
[root@k8s-master deployment]# kubectl get pods
NAME READY STATUS RESTARTS AGE
user-v1-5895c69847-9mdm8 1/1 Running 0 2m49s
user-v1-5895c69847-wjzfh 1/1 Running 0 2m51s
user-v1-5895c69847-x8n7z 1/1 Running 0 2m54s// 开始更新
[root@k8s-master deployment]# kubectl apply -f deployment-user-v1.yaml
deployment.apps/user-v1 configured// 更新中
[root@k8s-master deployment]# kubectl get pods
NAME READY STATUS RESTARTS AGE
user-v1-5895c69847-9mdm8 1/1 Terminating 0 3m27s
user-v1-5895c69847-wjzfh 1/1 Running 0 3m29s
user-v1-5895c69847-x8n7z 1/1 Running 0 3m32s
user-v1-8cc9f4fb5-52hmd 0/1 ContainerCreating 0 0s
user-v1-8cc9f4fb5-zqj2l 1/1 Running 0 3s// 更新完成
[root@k8s-master deployment]# kubectl get pods
NAME READY STATUS RESTARTS AGE
user-v1-8cc9f4fb5-52hmd 1/1 Running 0 48s
user-v1-8cc9f4fb5-6l7mz 1/1 Running 0 46s
user-v1-8cc9f4fb5-zqj2l 1/1 Running 0 51s
验证使用镜像是否变更:
[root@k8s-master deployment]# kubectl describe pod user-v1-8cc9f4fb5-zqj2l
Name: user-v1-8cc9f4fb5-zqj2l
Namespace: default
Priority: 0
Node: k8s-node/172.17.178.106
Start Time: Fri, 24 Dec 2021 18:30:57 +0800
Labels: app=user-v1pod-template-hash=8cc9f4fb5
Annotations: <none>
Status: Running
IP: 10.244.1.67
IPs:IP: 10.244.1.67
Controlled By: ReplicaSet/user-v1-8cc9f4fb5
Containers:nginx:Container ID: docker://436d2058c9a6a85000b2c32a3a87c1b7c892427894db1c7d851adb953ba01e88Image: nginx:user-v3Image ID: nginx@sha256:c3826e7a5cd2abc9f0e92fe02fe4897ab4346539438ce4f6c811371677f7494bPort: 80/TCPHost Port: 0/TCPState: RunningStarted: Fri, 24 Dec 2021 18:30:58 +0800Ready: TrueRestart Count: 0Environment: <none>Mounts:/var/run/secrets/kubernetes.io/serviceaccount from default-token-q4qxd (ro)
Conditions:Type StatusInitialized True Ready True ContainersReady True PodScheduled True
Volumes:default-token-q4qxd:Type: Secret (a volume populated by a Secret)SecretName: default-token-q4qxdOptional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300snode.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Scheduled 7m8s default-scheduler Successfully assigned default/user-v1-8cc9f4fb5-zqj2l to k8s-nodeNormal Pulled 7m8s kubelet Container image "nginx:user-v3" already present on machineNormal Created 7m8s kubelet Created container nginxNormal Started 7m8s kubelet Started container nginx
是 nginx:user-v3,说明应用已更新成功;
访问 service-user-v1
curl http://172.17.178.105:31071
curl http://172.17.178.106:31071[root@k8s-master deployment]# curl http://172.17.178.105:31071
user-v3
[root@k8s-master deployment]# curl http://172.17.178.106:31071
user-v3
五,结尾
下一篇,服务的可用性探针;
相关文章:
【Kubernetes】第十一篇 - 滚动发布的介绍与实现
一,前言 上一篇,介绍了灰度发布和流量切分的集中方式,以及如何实现 k8s 的灰度发布; 本篇,介绍滚动发布的实现; 二,滚动发布简介 滚动发布 滚动发布,则是我们一般所说的无宕机发…...
【尊享版】如何系统构建你的思维认知模型?
超友们,早上好,国庆节快乐~ 今天为你带来的分享是《如何系统构建你的思维认知模型?》,主要分为三个部分: 第一部分:【实现爆发式成长的 10 个思维模型】 第二部分:【6 个不可不知的…...
urho3D编码约定
缩进样式类似于Allman(BSD),即在控制语句的下一行使用大括号,在同一级别缩进。在switch-case语句中,case与switch语句处于相同的缩进级别。 缩进使用4个空格而不是制表符。不应保留空行上的缩进。 类和结构名称以大写…...
Overleaf推广奖励:增加合作者的数量、解锁Dropbox同步和项目修改历史
Overleaf推广奖励 Overleaf是一个LaTeX\LaTeXLATEX在线编译器,它可以让你与合作者共同在线编辑文档。但是默认的免费账号仅能邀请一个合作者。那么如何增加合作者的数量呢? Overleaf推出了一个奖励计划,你邀请其他人注册Overleaf…...
ChatGPT的互补工具Perplexity的详细使用方法(持续更新)
大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,科大讯飞比赛第三名,CCF比赛第四名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…...
【Linux驱动开发100问】如何编译Linux内核?
🥇今日学习目标:如何编译Linux内核? 🤵♂️ 创作者:JamesBin ⏰预计时间:10分钟 🎉个人主页:嵌入式悦翔园个人主页 🍁专栏介绍:Linux驱动开发100问 如何编译…...
15、条件概率、全概率公式、贝叶斯公式、马尔科夫链
条件概率定义:设A、B是两个事件,且,P(A) > 0 则称 为事件A发生的条件下事件B的条件概率对这个式子进行变形,即可得到概率的乘法公式:P(A) > 0 时,则P(B) > 0 时,则乍一看,…...
Eureka服务注册与发现
注册中心是分布式开发的核心组件之一,而Eureka是spring cloud推荐的注册中心实现。简单分析一下Eureka的原理。Eureka基础概念与流程1、服务注册在微服务架构中,一个服务提供者本质上也是一个Eureka客户端。启动时,会调用Eureka所提供的服务注…...
20230226 引用类型和指针类型的区别 - chatGPT
绝了,把chatGPT当百度之后真爽! 引用类型和指针类型都是C语言中的重要概念,它们都提供了访问和操作内存的方法,但它们之间有几个关键的区别。 1. 定义和初始化方式不同 指针类型的变量定义和初始化的方式是通过使用*符号来声明…...
《操作系统》——第二章 进程与线程
目录 2.1.1进程的概念、组成、特征 2.1.2进程的状态与转换、进程的组织 2.1.3进程控制 2.1.4进程通信 2.1.5线程的概念 2.1.6线程的实现方式和多线程模型 2.2.1调度的概念、层次 2.2.2进程调度的时机、切换与过程、方式 2.2.4调度算法的评价指标 2.2.5调度算法(1) 2…...
网络原理之初识
目录 一. 网络互连 1. 局域网 2. 广域网 二. 网络通信基础 1. IP 地址 2. 端口号 3. 网络协议 4. 协议分层 5. TCP/IP 五层网络模型 (简述) 6. 网络数据传输的基本流程 一. 网络互连 随着时代的发展,越来越需要计算机之间互相通信&am…...
CAN总线开发一本全(4) - FlexCAN的驱动程序
CAN总线开发一本全(4) - FlexCAN的驱动程序 苏勇,2023年2月 文章目录CAN总线开发一本全(4) - FlexCAN的驱动程序引言从MindSDK获取FlexCAN驱动程序数据结构配置通信引擎的结构体类型访问MB的结构体类型配置ID过滤器的…...
如何分析linux tcp/ip 丢包问题
引用手把手教你用Dropwatch诊断问题通过dropwatch定位系统内核丢包Finding out if/why a server is dropping packetsgithub source coed: pavel-odintsov/drop_watchHow to drop a packet in Linux in more ways than one试试Linux下的ip命令,ifconfig已经过时了Ho…...
旅游规划(树型dp)
W 市的交通规划出现了重大问题,市政府下定决心在全市各大交通路口安排疏导员来疏导密集的车流。 但由于人员不足,W 市市长决定只在最需要安排人员的路口安排人员。 具体来说,W 市的交通网络十分简单,由 n 个交叉路口和 n−1 条街道…...
【C++】string类的模拟实现
当你将放弃作为一种习惯,你一辈子也不会有出息… 文章目录一、Default member functions1.Constructor2.Copy constructor(代码重构:传统写法和现代写法)3.operator(代码重构:传统写法和现代写法ÿ…...
笔记(一)——STL容器
容器分类:序列式容器:每个元素都有固定位置,取决于插入的时机和地点,和元素无关,如vector、deque、list、stack、queue。关联式容器:元素位置取决于特定的排序准则,和插入顺序无关,如…...
红黑树
红黑树是一个相对的平衡,减少了旋转的消耗 一个节点不是红的就是黑的根节点是黑的一个节点是红的,孩子是黑的(没有连续的红色节点)对于每个节点,从该节点到后代节点的简单路径,都包含相同的黑色࿰…...
RIP路由协议的更新(电子科技大学TCP/IP第二次实验)
一.实验目的 1、掌握 RIP 协议在路由更新时的发送信息和发送方式 2、掌握 RIP 协议的路由更新算法 二.预备知识 1、静态路由选择和动态路由选择 2、内部网关协议和外部网关协议 3、距离向量路由选择 三.实验原理 RIP 协议(…...
基于JWT实现用户身份认证
常见场景 账号/密码登录、手机号验证码登录、微信扫码登录 解决方案 基于Session认证方案 什么是session认证方案 服务端生成httpsession认证(内存-sessionId)sessionId写到浏览器cookie浏览器请求的header中自动带sessionId到服务端服务端校验sessionId是否合法 优点 .…...
SaltStack 远程命令执行漏洞(CVE-2020-16846)
目录 (一)漏洞描述 (二)漏洞复现 1、在vulhub上启动docker 2、访问docker靶机 https /ip:8000...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
ArcPy扩展模块的使用(3)
管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如,可以更新、修复或替换图层数据源,修改图层的符号系统,甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...
