k8s 中的金丝雀发布(灰度发布)

news2024/11/30 12:54:36

目录

1 什么是金丝雀发布

2 Canary 发布方式

3 Canary 两种发布方式实操

3.1 准备工作

3.1.1 将 nginx 命名两个版本 v1 与 v2

3.1.2 暴露端口并指定微服务类型

3.1.3 进入 pod 修改默认发布文件

3.1.4 测试 service 是否正常

 3.2 基于权重的灰度发布

3.2.1 创建 Igress 资源类型文件

3.2.2 解释关于配置文件的意思

3.2.3 声明 Igress 文件

3.2.4 客户端测试

3.3 基于客户端请求的灰度发布

3.3.1 如何实现客户端请求的灰度发布介绍

3.3.2 创建 Igress 资源类型文件

3.3.3 关于配置文件的解释:

3.3.4 声明 Igress 文件

3.3.5 客户端进行测试


1 什么是金丝雀发布

金丝雀发布(Canary Release)也称为灰度发布,是一种软件发布策略。

主要目的是在将新版本的软件全面推广到生产环境之前,先在一小部分用户或服务器上进行测试和验证,以降低因新版本引入重大问题而对整个系统造成的影响。

是一种Pod的发布方式。金丝雀发布采取先添加、再删除的方式,保证Pod的总量不低于期望值。并且在更新部分Pod后,暂停更新,当确认新Pod版本运行正常后再进行其他版本的Pod的更新。

2 Canary 发布方式

其中header和weight中的最多

3 Canary 两种发布方式实操

3.1 准备工作

3.1.1 将 nginx 命名两个版本 v1 与 v2

# 创建版本v1的deployment资源类型的nginx
[root@k8s-master ingress]# kubectl create deployment nginx-v1 \
--image nginx:latest \
--dry-run=client \
--port 80 \
--replicas 1  \
-o yaml > nginx-v1.yml

[root@k8s-master ingress]# cat nginx-v1.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-v1    # 此标签一定要与微服务的标签对得上,不然微服务无法找到deployment
  name: nginx-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-v1
  template:
    metadata:
      labels:
        app: nginx-v1
    spec:
      containers:
      - image: nginx:latest
        name: nginx-v1
        ports:
        - containerPort: 80

# 创建版本 v2 的 deployment 资源类型的 nginx
[root@k8s-master ingress]# kubectl create deployment nginx-v2 \
--image nginx:latest \
--dry-run=client \
--port 80 \
--replicas 1  \
-o yaml > nginx-v2.yml

[root@k8s-master ingress]# cat nginx-v2.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-v2
  name: nginx-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-v2
  template:
    metadata:
      labels:
        app: nginx-v2
    spec:
      containers:
      - image: nginx:latest
        name: nginx-v2
        ports:
        - containerPort: 80


# 声明这两个版本的清单文件
[root@k8s-master ingress]# kubectl apply -f nginx-v1.yml 
deployment.apps/nginx-v1 created

[root@k8s-master ingress]# kubectl apply -f nginx-v2.yml 
deployment.apps/nginx-v2 created

# 查看deployment是否正常运行
[root@k8s-master ingress]# kubectl get deployments.apps 
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
nginx-v1   1/1     1            1           12s
nginx-v2   1/1     1            1           6s

3.1.2 暴露端口并指定微服务类型

创建微服务清单文件并将其加入到deployment的清单文件中

# 创建清单文件追加到deployment清单文件中
[root@k8s-master ingress]# kubectl expose deployment nginx-v1 \
--name=svc-nginx-v1 \
--port 80 --target-port 80 \
--dry-run=client \
--type=ClusterIP -o yaml >> nginx-v1.yml 

[root@k8s-master ingress]# kubectl expose deployment nginx-v2 \
--name=svc-nginx-v2 --port 80 --target-port 80 \
--dry-run=client \
--type=ClusterIP -o yaml >> nginx-v2.yml 

[root@k8s-master ingress]# cat nginx-v1.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-v1
  name: nginx-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-v1
  template:
    metadata:
      labels:
        app: nginx-v1
    spec:
      containers:
      - image: nginx:latest
        name: nginx-v1
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-v1
  name: svc-nginx-v1
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx-v1
  type: ClusterIP



[root@k8s-master ingress]# cat nginx-v2.yml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-v2
  name: nginx-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-v2
  template:
    metadata:
      labels:
        app: nginx-v2
    spec:
      containers:
      - image: nginx:latest
        name: nginx-v2
        ports:
        - containerPort: 80
---        
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-v2
  name: svc-nginx-v2
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx-v2
  type: ClusterIP


# 重新声明更新配置

[root@k8s-master ingress]# kubectl apply -f nginx-v1.yml 

[root@k8s-master ingress]# kubectl apply -f nginx-v2.yml 

# 服务创建成功
[root@k8s-master ingress]# kubectl get service
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP   3d22h
svc-nginx-v1   ClusterIP   10.107.76.175    <none>        80/TCP    15s
svc-nginx-v2   ClusterIP   10.100.188.171   <none>        80/TCP    9s

3.1.3 进入 pod 修改默认发布文件

[root@k8s-master ingress]# kubectl get pods 
NAME                       READY   STATUS    RESTARTS   AGE
nginx-v1-dbd4bc45b-49hhw   1/1     Running   0          5m35s
nginx-v2-bd85b8bc4-nqpv2   1/1     Running   0          5m29s

[root@k8s-master ingress]# kubectl exec -it pods/nginx-v1-dbd4bc45b-49hhw -- bash

root@nginx-v1-dbd4bc45b-49hhw:/# echo this is nginx-v1 `hostname -I` > /usr/share/nginx/html/index.html 

[root@k8s-master ingress]# kubectl exec -it pods/nginx-v2-bd85b8bc4-nqpv2 -- bash

root@nginx-v2-bd85b8bc4-nqpv2:/# echo this is nginx-v2 `hostname -I` > /usr/share/nginx/html/index.html 

3.1.4 测试 service 是否正常

[root@k8s-master ingress]# kubectl get service
NAME           TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP   3d22h
svc-nginx-v1   ClusterIP   10.107.76.175    <none>        80/TCP    15s
svc-nginx-v2   ClusterIP   10.100.188.171   <none>        80/TCP    9s

[root@k8s-master ingress]# curl 10.107.76.175
this is nginx-v1 10.244.2.54

[root@k8s-master ingress]# curl 10.100.188.171
this is nginx-v2 10.244.1.35

 3.2 基于权重的灰度发布

3.2.1 创建 Igress 资源类型文件

[root@k8s-master Cannary]# kubectl create ingress canary --class nginx \
--rule "nginx.shuyan.com/=svc-nginx-v1:80" \
--dry-run=client -o yaml > canary.yml

[root@k8s-master Cannary]# kubectl create ingress canary --class nginx \
--rule "nginx.shuyan.com/=svc-nginx-v2:80" \
--dry-run=client -o yaml >> canary.yml

# 以下是修改过后的资源类型
[root@k8s-master Cannary]# cat canary.yml 
# 第一个Ingress定义,用于常规服务
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-v1  # 定义Ingress的名称
spec:
  ingressClassName: nginx  # 指定使用的Ingress控制器类型
  rules:
  - host: nginx.shuyan.com  # 设置主机名,所有的请求都会被转发到这个域名下的服务
    http:
      paths:
      - backend:
          service:
            name: svc-nginx-v1  # 指定后端服务的名字
            port:
              number: 80  # 指定后端服务监听的端口
        path: /  # 所有访问根路径的请求都会被转发到此服务
        pathType: Prefix  # 路径类型为前缀,表示所有以"/"开头的请求都将被转发到此服务

---

# 第二个Ingress定义,用于灰度发布服务
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:  # 添加注解来控制灰度发布
    nginx.ingress.kubernetes.io/canary: "true"  # 开启灰度发布模式
    nginx.ingress.kubernetes.io/canary-weight: "10"  # 设置灰度发布的权重为10%,即10%的流量会被路由至此服务
    nginx.ingress.kubernetes.io/canary-weight-total: "100"  # 这个注解并不是标准NGINX Ingress Controller支持的,可以忽略
  name: canary-v2  # 定义Ingress的名称
spec:
  ingressClassName: nginx  # 指定使用的Ingress控制器类型
  rules:
  - host: nginx.shuyan.com  # 设置主机名,所有的请求都会被转发到这个域名下的服务
    http:
      paths:
      - backend:
          service:
            name: svc-nginx-v2  # 指定后端服务的名字
            port:
              number: 80  # 指定后端服务监听的端口
        path: /  # 所有访问根路径的请求都会被转发到此服务
        pathType: Prefix  # 路径类型为前缀,表示所有以"/"开头的请求都将被转发到此服务

3.2.2 解释关于配置文件的意思

第一个Ingress (canary-v1):

  • 这个Ingress没有使用任何灰度发布的注解。
  • 它将处理所有发往 nginx.shuyan.com 的请求,并将这些请求路由到名为 svc-nginx-v1 的服务上。

第二个Ingress (canary-v2):

  • 使用了灰度发布的注解 nginx.ingress.kubernetes.io/canary: "true" 和nginx.ingress.kubernetes.io/canary-weight: "10"。
  • 这些注解表明该Ingress将处理一部分流量(本例中为10%),并将这部分流量路由到名为 svc-nginx-v2 的服务上。

3.2.3 声明 Igress 文件

[root@k8s-master Cannary]# kubectl apply -f canary.yml 
ingress.networking.k8s.io/canary-v1 created
ingress.networking.k8s.io/canary-v2 created

3.2.4 客户端测试

# 客户端添加解析
[root@harbor ~]# vim /etc/hosts
192.168.239.241  nginx.shuyan.com

# 测试
[root@harbor ~]# curl nginx.shuyan.com
this is nginx-v2 10.244.1.35
[root@harbor ~]# curl nginx.shuyan.com
this is nginx-v1 10.244.2.54
[root@harbor ~]# curl nginx.shuyan.com
this is nginx-v1 10.244.2.54
[root@harbor ~]# curl nginx.shuyan.com
this is nginx-v1 10.244.2.54
[root@harbor ~]# curl nginx.shuyan.com
this is nginx-v1 10.244.2.54
[root@harbor ~]# curl nginx.shuyan.com
this is nginx-v1 10.244.2.54

# 编写脚本循环测试

[root@harbor ~]# vim canary.sh
#!/bin/bash

# 初始化计数器
v1=0
v2=0

# 循环发送请求并统计结果
for (( i=0; i<100; i++ )); do
    # 发送请求并检查响应中是否包含 "v1"
    response=`curl -s nginx.shuyan.com | grep -c "v1"`

    # 根据响应结果更新计数器
    if [ "$response" -eq 1 ]; then
        ((v1++))
    else
        ((v2++))
    fi
done

# 输出统计结果
echo "v1: $v1, v2: $v2"

# 运行脚本进行测试
[root@harbor ~]# bash canary.sh 
v1: 88, v2: 12
[root@harbor ~]# bash canary.sh 
v1: 88, v2: 12
[root@harbor ~]# bash canary.sh 
v1: 90, v2: 10
[root@harbor ~]# bash canary.sh 
v1: 90, v2: 10
[root@harbor ~]# bash canary.sh 
v1: 87, v2: 13

 

3.3 基于客户端请求的灰度发布

3.3.1 如何实现客户端请求的灰度发布介绍

基于客户端请求的流量切分要求客户端在 HTTP 请求头中包含指定键值对或在 Cookie 中包含指定键值对。当 HTTP 请求头包含“canary=always”时,流量会被路由到新版本(Canary 版本),一旦新版本验证通过,流量就会被逐步切分到新版本。这种策略比较适合将特定的客户端请求路由到新版本,以便进行更具体的测试和验证。

3.3.2 创建 Igress 资源类型文件

# 回收以上实验的资源
[root@k8s-master Cannary]# kubectl delete -f canary.yml 

# 创建 ingress 清单文件

[root@k8s-master Cannary]# kubectl create ingress canary-cookie-old \
--class nginx \
--rule "nginx.shuyan.com/=svc-nginx-v1:80" \
--dry-run=client -o yaml > canary-cookie.yml 

[root@k8s-master Cannary]# kubectl create ingress canary-cookie-new \
--class nginx \
--rule "nginx.shuyan.com/=svc-nginx-v2:80" \
--dry-run=client -o yaml >> canary-cookie.yml 


# 修改部分参数

[root@k8s-master Cannary]# cat canary-cookie.yml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-cookie-old  # 定义第一个Ingress资源的名称
spec:
  ingressClassName: nginx  # 指定使用的Ingress控制器类型
  rules:
  - host: nginx.shuyan.com  # 设置主机名,所有请求都会被转发到这个域名下的服务
    http:
      paths:
      - backend:
          service:
            name: svc-nginx-v1  # 指定后端服务的名字
            port:
              number: 80  # 指定后端服务监听的端口
        path: /  # 所有访问根路径的请求都会被转发到此服务
        pathType: Prefix  # 路径类型为前缀,表示所有以"/"开头的请求都将被转发到此服务

---
# 分割线,表示这是一个新的Ingress资源定义

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary-cookie-new  # 定义第二个Ingress资源的名称
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"  # 开启灰度发布模式
    nginx.ingress.kubernetes.io/canary-by-header: "canary"  # 指定使用HTTP头部来区分流量
    nginx.ingress.kubernetes.io/canary-by-header-value: "new"  # 指定HTTP头部的值为"new"时,请求会被路由到新版本服务
spec:
  ingressClassName: nginx  # 指定使用的Ingress控制器类型
  rules:
  - host: nginx.shuyan.com  # 设置主机名,所有请求都会被转发到这个域名下的服务
    http:
      paths:
      - backend:
          service:
            name: svc-nginx-v2  # 指定后端服务的名字
            port:
              number: 80  # 指定后端服务监听的端口
        path: /  # 所有访问根路径的请求都会被转发到此服务
        pathType: Prefix  # 路径类型为前缀,表示所有以"/"开头的请求都将被转发到此服务

3.3.3 关于配置文件的解释:


第一个Ingress (canary-cookie-old):

  • 这个Ingress没有使用任何灰度发布的注解。
  • 它将处理所有发往 nginx.shuyan.com 的请求,并将这些请求路由到名为 svc-nginx-v1 的服务上。

第二个Ingress (canary-cookie-new):

  • 使用了灰度发布的注解 nginx.ingress.kubernetes.io/canary: "true" 来开启灰度发布模式。
  • 使用 nginx.ingress.kubernetes.io/canary-by-header: "canary" 来指定使用HTTP头部来区分流量。
  • 使用 nginx.ingress.kubernetes.io/canary-by-header-value: "new" 来指定HTTP头部的值为 "new" 时,请求会被路由到新版本服务 svc-nginx-v2。

工作原理:

  • 当客户端请求包含头部 canary: new 时,请求将会被路由到 svc-nginx-v2。
  • 如果客户端请求不包含头部 canary: new,请求将会被路由到 svc-nginx-v1。

3.3.4 声明 Igress 文件

[root@k8s-master Cannary]# kubectl apply -f canary-cookie.yml 
ingress.networking.k8s.io/canary-cookie-old created
ingress.networking.k8s.io/canary-cookie-new created

# 查看是否正常创建
[root@k8s-master Cannary]# kubectl get ingress
NAME                CLASS   HOSTS              ADDRESS           PORTS   AGE
canary-cookie-new   nginx   nginx.shuyan.com   192.168.239.241   80      53s
canary-cookie-old   nginx   nginx.shuyan.com   192.168.239.241   80      53s


[root@k8s-master Cannary]# kubectl describe ingress 
Name:             canary-cookie-new
Labels:           <none>
Namespace:        default
Address:          192.168.239.241
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host              Path  Backends
  ----              ----  --------
  nginx.shuyan.com  
                    /   svc-nginx-v2:80 (10.244.1.35:80)
Annotations:        nginx.ingress.kubernetes.io/canary: true
                    nginx.ingress.kubernetes.io/canary-header: canary
                    nginx.ingress.kubernetes.io/canary-header-value: new
Events:
  Type    Reason  Age                    From                      Message
  ----    ------  ----                   ----                      -------
  Normal  Sync    7m37s (x2 over 8m18s)  nginx-ingress-controller  Scheduled for sync


Name:             canary-cookie-old
Labels:           <none>
Namespace:        default
Address:          192.168.239.241
Ingress Class:    nginx
Default backend:  <default>
Rules:
  Host              Path  Backends
  ----              ----  --------
  nginx.shuyan.com  
                    /   svc-nginx-v1:80 (10.244.2.54:80)
Annotations:        <none>
Events:
  Type    Reason  Age                    From                      Message
  ----    ------  ----                   ----                      -------
  Normal  Sync    7m37s (x2 over 8m19s)  nginx-ingress-controller  Scheduled for sync

3.3.5 客户端进行测试

# 客户端添加解析
[root@harbor ~]# vim /etc/hosts
192.168.239.241  nginx.shuyan.com

# 没带 cookie 值的就会被访问到 v1 去
[root@harbor ~]# curl -s  nginx.shuyan.com
this is nginx-v1 10.244.2.54

# 带 cookie 值的就会访问到 v2 去
[root@harbor ~]# curl -s  -H "canary: new" nginx.shuyan.com
this is nginx-v2 10.244.1.35

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

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

相关文章

Uncaught TypeError: 0 is not a function的解决方法

好久不见&#xff0c;我胡汉三又回来了。 是的&#xff0c;我又发现问题了。 写JS的时候&#xff0c;发现了一堆原则性的问题&#xff0c;但是这些问题又刚好是别人没怎么遇到的。 是的&#xff0c;我用ChatGPT了。 (function frame() {window.requestAnimationFrame(frame)…

NVIDIA网卡系列之ConnectX-3规格信息(10G-PCIe 3.0x4-PF?VF?-2013年发布)

背景 NVIDIA ConnectX-3系列的网卡&#xff0c;早期还在Mellanox未被NVIDIA收购的时候就发布了&#xff0c;支持10G&#xff0c;PCIe3.0&#xff0c;最大x8通道lanes。 是10G级别的一代&#xff08;10G-CX3&#xff0c;50G-CX4&#xff0c;100G-CX5&#xff0c;200G-CX6&#…

Linux线程(七)线程安全详解

当我们编写的程序是一个多线程应用程序时&#xff0c;就不得不考虑到线程安全的问题&#xff0c;确保我们编写的程序是一个线程安全&#xff08;thread-safe&#xff09;的多线程应用程序&#xff0c;什么是线程安全以及如何保证线程安全&#xff1f;带着这些问题&#xff0c;本…

光伏项目管理如何更高效化?

一、项目规划与启动阶段的优化 1、智能规划工具&#xff1a;光伏管理软件通常配备有智能项目规划模块&#xff0c;能够根据地理位置、气候条件、政策补贴等因素&#xff0c;自动计算最佳装机容量、预测发电量及收益&#xff0c;帮助项目团队快速制定合理的项目方案。这大大缩短…

大数据毕业设计选题推荐-NBA球员数据分析系统-Python数据可视化-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、PHP、.NET、Node.js、GO、微信小程序、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇…

知识图谱入门——9: spaCy中命名实体识别(NER)任务中的预定义标签详解及案例(GPE、MONEY、PRODUCT、LAW、FAC、NORP是什么?)

命名实体识别&#xff08;NER, Named Entity Recognition&#xff09;是自然语言处理&#xff08;NLP&#xff09;中的重要任务之一&#xff0c;旨在从文本中识别出特定的实体&#xff0c;如人名、地名、时间等。spaCy 是一个广泛使用的 NLP 库&#xff0c;它提供了预训练的模型…

数据结构之排序(5)

摘要&#xff1a;本文主要讲各种排序算法&#xff0c;注意它们的时间复杂度 概念 将各元素按关键字递增或递减排序顺序重新排列 评价指标 稳定性: 关键字相同的元素经过排序后相对顺序是否会改变 时间复杂度、空间复杂度 分类 内部排序——数据都在内存中 外部排序——…

涂色问题 乘法原理(2024CCPC 山东省赛 C)

//*下午打得脑子连着眼睛一起疼 很多很基础的题目都没有做出来&#xff0c;规律题也找得很慢。比如下面这题&#xff0c;一定要多做&#xff0c;下次看到就直接写。 原题链接&#xff1a;https://codeforces.com/group/w6iGs8kreW/contest/555584/problem/C C. Colorful Segm…

LabVIEW光偏振态检测系统

开发一套LabVIEW的高精度光偏振态检测系统&#xff0c;采用机械转动法结合光电探测器和高性能数据采集硬件&#xff0c;能快速、准确地测量光的偏振状态。该系统广泛应用于物理研究、激光技术和光学工业中。 系统组成 该光偏振态检测系统主要由以下硬件和软件模块构成&#xf…

无人机+无人车+机器狗+无人船:大规模组网系统技术详解

无人机、无人车、机器狗和无人船的大规模组网系统技术&#xff0c;是实现海陆空全空间无人设备协同作业的关键。这种组网系统技术通过集成先进的通信、控制、感知和决策技术&#xff0c;使得不同类型的无人平台能够高效、准确地完成各种复杂任务。以下是对该技术的详细解析&…

SysML案例-呼吸机

DDD领域驱动设计批评文集>> 《软件方法》强化自测题集>> 《软件方法》各章合集>> 图片示例摘自intercax.com&#xff0c;作者是Intercax公司总裁Dirk Zwemer博士。

【项目安全设计】软件系统安全设计规范和标准(doc原件)

1.1安全建设原则 1.2 安全管理体系 1.3 安全管理规范 1.4 数据安全保障措施 1.4.1 数据库安全保障 1.4.2 操作系统安全保障 1.4.3 病毒防治 1.5安全保障措施 1.5.1实名认证保障 1.5.2 接口安全保障 1.5.3 加密传输保障 1.5.4终端安全保障 资料获取&#xff1a;私信或者进主页。…

将列表中的各字符串sn连接成为一个字符串s使用;将各sn间隔开os.pathsep.join()

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 将列表中的各字符串sn 连接成为一个字符串s 使用;将各sn间隔开 os.pathsep.join() [太阳]选择题 下列说法中正确的是? import os paths ["/a", "/b/c", "/d&q…

Android开发修改为原生主题(在Android Studio开发环境下)

结构如下图&#xff1a; 修改方法&#xff1a;在Android模式目录下&#xff0c;将res下的values文下的themes.xml文件中的 &#xff1a; parent"Theme.Material3.DayNight.NoActionBar" 修改为&#xff1a; parent"Theme.MaterialComponents.DayNight.Bridge&…

Meta 推出Movie Gen

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

ChatGPT 更新 Canvas 深度测评:论文写作这样用它!

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 ChatGPT又又更新了&#xff1a;基于ChatGPT 4o模型的Canvas 写作和代码功能。目前&#xff0c;仅针对Plus和Team用户。是一个独立的模块&#xff0c;如下所示&#xff1a; 官方…

【Python】simplejson:Python 中的 JSON 编解码利器

simplejson 是一个高效且功能丰富的 Python JSON 编码和解码库。它能够快速地将 Python 数据结构转换为 JSON 格式&#xff08;序列化&#xff09;&#xff0c;或将 JSON 格式的字符串转换为 Python 对象&#xff08;反序列化&#xff09;。相比标准库中的 json 模块&#xff0…

数据结构实验二 顺序表的应用

数据结构实验二 顺序表的应用 一、实验目的 1、掌握建立顺序表的基本方法。 2、掌握顺序表的插入、删除算法的思想和实现&#xff0c;并能灵活运用 二、实验内容 用顺序表实现病历信息的管理与查询功能。具体要求如下: 1.利用教材中定义顺序表类型存储病人病历信息(病历号…

直立行走机器人技术概述

直立行走机器人技术作为现代机器人领域的重要分支&#xff0c;结合了机械工程、计算机科学、人工智能、传感技术和动态控制等领域的最新研究成果。随着技术的不断发展&#xff0c;直立行走机器人在救灾、医疗、家庭辅助等领域开始发挥重要作用。本文旨在对直立行走机器人的相关…

Java 注释新手教程一口气讲完!ヾ(≧▽≦*)o

Java 注释 Java面向对象设计 - Java注释 什么是注释&#xff1f; Java中的注释允许我们将元数据与程序元素相关联。 程序元素可以是包&#xff0c;类&#xff0c;接口&#xff0c;类的字段&#xff0c;局部变量&#xff0c;方法&#xff0c;方法的参数&#xff0c;枚举&…