RocketMQ部署单机版及集群版本(Docker部署)

news2024/11/24 14:32:38

目录

前言

单机版部署

1. 准备工作

2. 创建Docker网络

 3.启动NameServer

4.启动Broker

 5.启动RocketMQ控制台

集群版部署

1.启动NameServer

2.启动Broker

配置文件说明


前言

废话不多直接上干货,我负责踩坑,你负责验证。

单机版部署

1. 准备工作

确保Docker和Docker Compose已经安装。如果没有,请先进行安装。

2. 创建Docker网络
docker network create rocketmq-net

 查看Docker网络:

docker network ls

NETWORK ID     NAME               DRIVER    SCOPE
3ce16f0e7951   bridge             bridge    local
afe16f80ffc9   host               host      local
36892fa1b1bb   none               null      local
ce100504c410   rocketmq-network   bridge    local

 3.启动NameServer
docker run -d --name rmqnamesrv   --network rocketmq-network   -p 9876:9876   rocketmqinc/rocketmq   sh mqnamesrv

 输出结果:

Unable to find image 'rocketmqinc/rocketmq:latest' locally
latest: Pulling from rocketmqinc/rocketmq
a02a4930cb5d: Pull complete 
90eb47c86343: Pull complete 
43bf660f95f6: Pull complete 
7f5ca7a20245: Pull complete 
707a618112e3: Pull complete 
4b527473eafb: Pull complete 
fedd1d06c8ba: Pull complete 
27782fcf3aef: Pull complete 
Digest: sha256:b08556227ad8d169b7927f4c48335877cb10060e6781374ce5a644ea29f6fbe1
Status: Downloaded newer image for rocketmqinc/rocketmq:latest
332a6a49ef2f1caf3ec8fb597df49a03a7a91b3a552668f5bf762c19595c2a25

 参数解释:

docker run

  • docker run 命令用于创建并启动一个新的容器。
  • 在这个命令中,你可以指定容器的配置和运行时行为。

-d

  • -d 选项表示“分离模式”(detached mode),即在后台运行容器。
  • 容器启动后,你的终端不会被占用,容器会在后台继续运行。

--name rmqnamesrv

  • --name rmqnamesrv 为容器指定一个名称,这里将容器命名为 rmqnamesrv
  • 使用自定义名称可以更方便地管理和引用这个容器,比如通过名称启动、停止、查看日志等。

--network rocketmq-network

  • --network rocketmq-network 指定容器要连接的 Docker 网络,这里是 rocketmq-network
  • 这使得该容器可以通过网络中的名称(如 rmqnamesrv)与其他容器进行通信。
  • 使用自定义网络可以控制容器之间的连接范围,并启用 Docker 内置的 DNS 服务。

-p 9876:9876

  • -p 9876:9876 映射主机的端口和容器的端口。
  • 这意味着将主机的 9876 端口映射到容器的 9876 端口。
  • RocketMQ 的 NameServer 默认监听 9876 端口,因此通过这个映射,可以从主机直接访问 NameServer。

rocketmqinc/rocketmq

  • rocketmqinc/rocketmq 是所使用的 Docker 镜像名称。
  • 这个镜像包含了 RocketMQ 的安装和运行环境,官方维护的镜像通常会包含 NameServer、Broker 等组件的运行脚本。

sh mqnamesrv

  • sh mqnamesrv 是容器启动后要执行的命令。
  • 这个命令启动一个 sh 进程,并执行 mqnamesrv 脚本来启动 RocketMQ 的 NameServer。
  • mqnamesrv 是 RocketMQ 启动 NameServer 的命令。通常,RocketMQ 镜像包含这个命令,它会启动 NameServer 服务并监听在指定的端口(这里是 9876)。
4.启动Broker
docker run -d --name rmqbroker --network rocketmq-network \
  -p 10911:10911 \
  -e "NAMESRV_ADDR=rmqnamesrv:9876" \
  -v /opt/rocketmq/conf/broker.conf:/opt/rocketmq/conf/broker.conf \
  rocketmqinc/rocketmq \
  sh mqbroker -c /opt/rocketmq/conf/broker.conf

参数解释:

docker run

  • docker run 命令用于创建并启动一个新的容器。

-d

  • -d 选项表示“分离模式”(detached mode),即在后台运行容器。

--name rmqbroker

  • --name rmqbroker 为容器指定一个名称,这里将容器命名为 rmqbroker
  • 使用自定义名称可以方便地管理和引用该容器。

--network rocketmq-network

  • --network rocketmq-network 指定容器要连接的 Docker 网络,这里是 rocketmq-network
  • 这允许容器在这个网络中与其他容器(如 NameServer)通过容器名称进行通信。

 -p 10911:10911

  • -p 10911:10911 将主机的 10911 端口映射到容器的 10911 端口。
  • 10911 端口通常用于 RocketMQ Broker 的外部通信(如消息存储的物理 I/O 操作)。

-e "NAMESRV_ADDR=rmqnamesrv:9876"

  • -e 选项用于设置环境变量。在这里,设置了 NAMESRV_ADDR 环境变量。
  • NAMESRV_ADDR=rmqnamesrv:9876 指定了 NameServer 的地址为 rmqnamesrv:9876,其中 rmqnamesrv 是 NameServer 容器的名称,端口号为 9876
  • 这使得 Broker 容器可以在启动时注册到指定的 NameServer。

-v /opt/rocketmq/conf/broker.conf(主机文件路径):/opt/rocketmq/conf/broker.conf(容器文件路径)

  • -v 选项用于将主机文件或目录挂载到容器内。在这里,/opt/rocketmq/conf/broker.conf 文件被挂载到容器的相同路径。
  • 这意味着你可以在主机上编辑 broker.conf 文件,容器内的配置将会实时更新,避免了每次更改配置都要重新构建容器的麻烦。

rocketmqinc/rocketmq

  • rocketmqinc/rocketmq 是所使用的 Docker 镜像名称。
  • 这个镜像包含了 RocketMQ 的安装和运行环境,包括 Broker、NameServer 等组件。

sh mqbroker -c /opt/rocketmq/conf/broker.conf

  • sh mqbroker 是容器启动后要执行的命令,启动一个 sh 进程并执行 mqbroker 命令来启动 RocketMQ 的 Broker 服务。
  • -c /opt/rocketmq/conf/broker.conf 指定了 Broker 的配置文件路径为 /opt/rocketmq/conf/broker.conf。这个文件路径与通过 -v 选项挂载的配置文件一致。

注:在执行此指令之前我们需要创建Broker的配置文件,如果没有创建直接启动Broker 会报错,报错信息可以通过一下操作查看:

# 查看所有镜像
docker ps -a

# 输出结果
CONTAINER ID   IMAGE                      COMMAND                  CREATED         STATUS         PORTS                                                                                                                                                 NAMES
df6d3071e300   rocketmqinc/rocketmq       "sh mqbroker -c /opt…"   4 seconds ago   Up 3 seconds   9876/tcp, 10909/tcp, 0.0.0.0:10911->10911/tcp, :::10911->10911/tcp                                                                                    rmqbroker
332a6a49ef2f   rocketmqinc/rocketmq       "sh mqnamesrv"           7 minutes ago   Up 7 minutes   10909/tcp, 0.0.0.0:9876->9876/tcp, :::9876->9876/tcp, 10911/tcp   


# 查看Broker日志
docker logs df6d3071e300 (对应的镜像ID) 

在没有配置broker.conf前日志中会出现:

java.io.FileNotFoundException: /opt/rocketmq/conf/broker.conf
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(FileInputStream.java:195)
        at java.io.FileInputStream.<init>(FileInputStream.java:138)
        at java.io.FileInputStream.<init>(FileInputStream.java:93)
        at org.apache.rocketmq.broker.BrokerStartup.createBrokerController(BrokerStartup.java:128)
        at org.apache.rocketmq.broker.BrokerStartup.main(BrokerStartup.java:58)

配置broker.conf(如果已有则跳过此步骤):

# 创建所有缺少的目录
sudo mkdir -p /opt/rocketmq/conf

# 创建文件
sudo touch /opt/rocketmq/conf/broker.conf

vim /opt/rocketmq/conf/broker.conf


# 配置文件
# RocketMQ Broker配置文件
brokerClusterName=DefaultCluster
brokerName=broker-a
brokerId=0
#brokerIP1=127.0.0.1 推荐不设置 此ip可以为镜像名或者使用ping镜像名获取具体IP填写,并非为127.0.0.1
# NameServer地址
namesrvAddr=rmqnamesrv:9876
# 数据存储路径
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
# 设置 Broker ID 和集群名称
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC

在这里额外多说几句,大家可以看到,配置中namesrvAddr 的值按道理来说应该是具体的IP+PORT但是我这里却使用的是rmqnamesrv,其实仔细联系上下文可以发现,这里的rmqnamesrv就是nameServer的镜像名,那为什么在这里可以配置镜像名呢?这便涉及到了Docker的DNS解析如下:

Docker 网络的 DNS 解析

  1. Docker 内部 DNS 解析

    • Docker 的内置 DNS 服务器会自动为同一 Docker 网络中的容器提供名称解析。每个容器在其网络内部都可以使用其他容器的名字作为主机名。
    • 当你在容器的配置中指定 namesrvAddr=rmqnamesrv:9876 时,Docker 网络的 DNS 服务会解析 rmqnamesrv 为相应的容器的 IP 地址。
  2. 服务发现

    • 在 Docker 自定义网络中,Docker 会在网络内维护一个 DNS 解析服务,使容器可以通过名字互相发现和通信。容器名称(如 rmqnamesrv)实际上是网络中容器的主机名。
  3. 自动 IP 分配

    • 当你启动容器时,Docker 会自动为每个容器分配一个 IP 地址,并将容器的名字注册到 Docker 内部的 DNS 服务器。这样,其他容器可以通过名字直接访问这个 IP 地址。 
 5.启动RocketMQ控制台
docker run -d --name rmqconsole --network rocketmq-network -p 8080:8080 -e "NAMESRV_ADDR=rmqnamesrv:9876" styletang/rocketmq-console-ng

参数解释:

 --name rmqconsole

  • --name rmqconsole 为容器指定一个名称,这里将容器命名为 rmqconsole
  • 使用自定义名称可以方便地管理和引用该容器。

--network rocketmq-network

  • --network rocketmq-network 指定容器要连接的 Docker 网络,这里是 rocketmq-network
  • 这允许容器在这个网络中与其他容器(如 RocketMQ 的 NameServer 和 Broker)通过容器名称进行通信。

-p 8080:8080

  • -p 8080:8080 将主机的 8080 端口映射到容器的 8080 端口。
  • RocketMQ Console 默认在 8080 端口提供 Web 界面。通过这个映射,你可以从主机上访问 RocketMQ Console 的 Web 界面。

-e "NAMESRV_ADDR=rmqnamesrv:9876"

  • -e 选项用于设置环境变量。在这里,设置了 NAMESRV_ADDR 环境变量。
  • NAMESRV_ADDR=rmqnamesrv:9876 指定了 NameServer 的地址为 rmqnamesrv:9876,其中 rmqnamesrv 是 NameServer 容器的名称,端口号为 9876
  • RocketMQ Console 使用这个地址来连接和管理 RocketMQ 集群的 NameServer 和 Broker。

styletang/rocketmq-console-ng

  • styletang/rocketmq-console-ng 是所使用的 Docker 镜像名称。
  • 这个镜像包含了 RocketMQ Console 的安装和运行环境,它提供了一个 Web 界面,用于监控和管理 RocketMQ 集群,包括查看 Topic、Consumer、Producer 的状态等。

输出结果:

Unable to find image 'styletang/rocketmq-console-ng:latest' locally
latest: Pulling from styletang/rocketmq-console-ng
e12c678537ae: Pull complete 
8d9ed335b7db: Pull complete 
3318dd58ae60: Pull complete 
624ba6156166: Pull complete 
c7a02d193df7: Pull complete 
813b62320378: Pull complete 
49e2d6393f32: Extracting [=============>                                     ]  34.54MB/130.1MB
0a2b7222259b: Download complete 
478657249124: Download complete 
5f8636e9fbb7: Download complete 

 执行完成后便可以使用我们映射的8080端口进行访问控制台至此便已经搭建完成。

 

集群版部署

1.启动NameServer
# 启动nameServer 1
docker run -d --name rmqnamesrv1 \
  --network rocketmq-network \
  -p 9876:9876 \
  rocketmqinc/rocketmq \
  sh mqnamesrv
  
启动nameServer 2
docker run -d --name rmqnamesrv2 \
  --network rocketmq-network \
  -p 9877:9876 \
  rocketmqinc/rocketmq \
  sh mqnamesrv
2.启动Broker
docker run -d --name rmqbroker1 --network rocketmq-network \
  -p 10911:10911 \
  -e "NAMESRV_ADDR=rmqnamesrv1:9876;rmqnamesrv2:9877" \
  -v /opt/rocketmq/conf/broker1.conf:/opt/rocketmq/conf/broker1.conf \
  rocketmqinc/rocketmq \
  sh mqbroker -c /opt/rocketmq/conf/broker1.conf  
  
  
docker run -d --name rmqbroker2 --network rocketmq-network \
  -p 10912:10911 \
  -e "NAMESRV_ADDR=rmqnamesrv1:9876;rmqnamesrv2:9877" \
  -v /opt/rocketmq/conf/broker2.conf:/opt/rocketmq/conf/broker2.conf \
  rocketmqinc/rocketmq \
  sh mqbroker -c /opt/rocketmq/conf/broker2.conf 

配置broker.conf

broker1.con

ocketMQ Broker配置文件
brokerClusterName=DefaultCluster
brokerName=broker-a
# Master 的 brokerId 必须是 0 
# Slave 的 brokerId 必须是正整数,且唯一
brokerId=0 
brokerIP1=172.20.0.2
# NameServer地址
namesrvAddr=rmqnamesrv:9876;rmqnamesrv:9877
# 数据存储路径
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
# 设置 Broker ID 和集群名称
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC

broker2.conf

RocketMQ Broker配置文件
brokerClusterName=DefaultCluster
brokerName=broker-b
# Master 的 brokerId 必须是 0 
# Slave 的 brokerId 必须是正整数,且唯一
brokerId=1
brokerIP1=172.20.0.3
# NameServer地址
namesrvAddr=rmqnamesrv:9876;rmqnamesrv:9877
# 数据存储路径
storePathRootDir=/home/rocketmq/store
storePathCommitLog=/home/rocketmq/store/commitlog
# 设置 Broker ID 和集群名称
brokerRole=ASYNC_MASTER
flushDiskType=ASYNC

注:集群模式还存在一些问题,需要后期进行调整,时间关系就暂时记一个待办了,欢迎大家监督催更。 

配置文件说明

#所属集群名字
brokerClusterName=rocketmq-cluster
#broker名字,注意此处不同的配置文件填写的不一样
brokerName=broker-a
#0 表示 Master,>0 表示 Slave
brokerId=0
#nameServer地址,分号分割
namesrvAddr=rocketmq-nameserver1:9876;rocketmq-nameserver2:9876
#在发送消息时,自动创建服务器不存在的topic,默认创建的队列数
defaultTopicQueueNums=4
#是否允许 Broker 自动创建Topic,建议线下开启,线上关闭
autoCreateTopicEnable=true
#是否允许 Broker 自动创建订阅组,建议线下开启,线上关闭
autoCreateSubscriptionGroup=true
#Broker 对外服务的监听端口
listenPort=10911
#删除文件时间点,默认凌晨 4点
deleteWhen=04
#文件保留时间,默认 48 小时
fileReservedTime=120
#commitLog每个文件的大小默认1G
mapedFileSizeCommitLog=1073741824
#ConsumeQueue每个文件默认存30W条,根据业务情况调整
mapedFileSizeConsumeQueue=300000
#destroyMapedFileIntervalForcibly=120000
#redeleteHangedFileInterval=120000
#检测物理文件磁盘空间
diskMaxUsedSpaceRatio=88
#存储路径
storePathRootDir=/usr/local/rocketmq/store
#commitLog 存储路径
storePathCommitLog=/usr/local/rocketmq/store/commitlog
#消费队列存储路径存储路径
storePathConsumeQueue=/usr/local/rocketmq/store/consumequeue
#消息索引存储路径
storePathIndex=/usr/local/rocketmq/store/index
#checkpoint 文件存储路径
storeCheckpoint=/usr/local/rocketmq/store/checkpoint
#abort 文件存储路径
abortFile=/usr/local/rocketmq/store/abort
#限制的消息大小
maxMessageSize=65536
#flushCommitLogLeastPages=4
#flushConsumeQueueLeastPages=2
#flushCommitLogThoroughInterval=10000
#flushConsumeQueueThoroughInterval=60000
#Broker 的角色
#- ASYNC_MASTER 异步复制Master
#- SYNC_MASTER 同步双写Master
#- SLAVE
brokerRole=SYNC_MASTER
#刷盘方式
#- ASYNC_FLUSH 异步刷盘
#- SYNC_FLUSH 同步刷盘
flushDiskType=SYNC_FLUSH
#checkTransactionMessageEnable=false
#发消息线程池数量
#sendMessageThreadPoolNums=128
#拉消息线程池数量
#pullMessageThreadPoolNums=128
 

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

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

相关文章

DCMM数据管理能力成熟度评估模型解读

DCMM(GBT36073-2018)数据管理能力成熟度评估模型解读 DCMM标准的核心点在于通过八个核心能力域和五个成熟度等级的划分&#xff0c;全面评估企业的数据管理能力&#xff0c;并为企业提供提升数据管理能力的路径和方法&#xff0c;从而推动企业在信息化、数字化、智能化方面的发…

光伏设计中组串逆变和微型逆变是什么意思?有什么区别?

在光伏系统设计中&#xff0c;逆变器是核心组件之一&#xff0c;负责将太阳能电池板产生的直流电转换为交流电&#xff0c;以供家庭、商业或电网使用。根据设计和应用场景的不同&#xff0c;逆变器主要分为组串逆变器和微型逆变器两大类。 一、组串逆变器的定义 组串逆变器是太…

力扣面试经典算法150题:整数转罗马数字

整数转罗马数字 今天的题目是力扣面试经典150题中的数组的中等难度题&#xff1a; 整数转罗马数字。 题目链接&#xff1a;https://leetcode.cn/problems/integer-to-roman/description/?envTypestudy-plan-v2&envIdtop-interview-150 题目描述 七个不同的符号代表罗马…

【EI稳定检索】2024年第三届环境工程与可持续能源国际会议

2024年第三届环境工程与可持续能源国际会议&#xff08;EESE 2024&#xff09;将于12月20日至22日在长沙举行&#xff0c;由西安交通大学等支持&#xff0c;EI检索&#xff0c;投稿截止10月18日&#xff0c;AC学术中心提供技术支持和免费投稿系统。 2024年第三届环境工程与可持…

鸿蒙(API 12 Beta3版)【默认界面扫码】

基本概念 默认界面扫码能力提供系统级体验一致的扫码界面&#xff0c;Scan Kit对系统相机权限进行了预授权&#xff0c;调用接口时&#xff0c;无需开发者再次申请相机权限。适用于不同扫码场景的应用开发。 说明 通过默认界面扫码可以实现应用内的扫码功能&#xff0c;为了…

机器学习:TF-IDF算法原理及代码实现

TF-IDF是一种用于信息检索与文本挖掘的常用加权技术。它是一种统计方法&#xff0c;用以评估一个词语对于一个文件集或一个语料库中的其中一份文件的重要程度。它的主要思想是&#xff1a;如果某个词语在一篇文章中出现的频率高&#xff08;Term Frequency&#xff0c;TF&#…

路别走窄了,华为认证的这些方向,比数通值钱

华为认证作为全球领先的ICT技术认证之一&#xff0c;以其高标准和权威性在全球范围内受到认可。它不仅代表了专业技能的国际水平&#xff0c;更是IT专业人士职业生涯中的重要里程碑。但谈论起华为认证&#xff0c;似乎大家都默认首选数通。 不止在华为认证&#xff0c;而是在整…

10个伪原创软件,改写文章效率高

在内容为王的时代&#xff0c;高效地改写文章已成为许多创作者和营销人员必备的技能。伪原创软件作为提升工作效率的利器&#xff0c;可以帮助用户在短时间内生成质量上乘的全新内容。以下是10个备受推崇的伪原创软件&#xff0c;它们各具特色&#xff0c;能够助力创作者大幅提…

猫头虎 分享已解决Bug || ReferenceError: Can‘t find variable: React 解决方案

猫头虎 分享已解决Bug || ReferenceError: Cant find variable: React 解决方案 今天猫头虎要跟大家分享一个前端开发中常见的问题&#xff1a; ReferenceError: Cant find variable: React。这个错误常常出现在我们开发React项目时&#xff0c;特别是在新手刚接触React或者是团…

如何快速创建个性化视频二维码用于产品宣传

产品视频二维码营销推广在实际应用中具有广泛的用途&#xff0c;可以有效地帮助企业推广品牌、产品和服务。常见的应用场景有&#xff1a;产品广告和宣传材料、产品包装展示、展会和活动、店内展示、旅游和景点介绍等。 那么如何快速制作和创建带企业图标的产品视频二维码呢&am…

【香橙派系列教程】(十九) 使用文件编程实现开关盖的历史记录

【十九】使用文件编程实现开关盖的历史记录 我现在多了一个需求&#xff0c;我需要在每次识别垃圾时&#xff0c;将垃圾的种类记录下来&#xff0c;同时记录下时间。 Linux显示当前的时间&#xff1a;date指令 //打印当前的 “年-月-日-时-分-秒” date "%Y-%m-%d %H:%M:…

开环响应(频率响应+相移响应)+闭环响应(负反馈对带宽的影响+增益-带宽积)+正反馈与稳定性/补偿(选学)

2024-8-29&#xff0c;星期四&#xff0c;20:01&#xff0c;天气&#xff1a;晴&#xff0c;心情&#xff1a;晴。今天没什么事情发生&#xff0c;继续学习。 今天完成了第七章的学习&#xff0c;主要学习内容为&#xff1a;开环响应(频率响应相移响应)闭环响应(负反馈对带宽的…

鸿蒙开发入门day15-焦点事件

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;还请三连支持一波哇ヾ(&#xff20;^∇^&#xff20;)ノ&#xff09; 目录 焦点事件 基础概念与规范 基础概念 走焦规范 走焦算法 获焦/失…

Layer Normalization(层归一化)里的可学习的参数

参考pyttorch官方文档&#xff1a; LayerNorm — PyTorch 2.4 documentation 在深度学习模型中&#xff0c;层归一化&#xff08;Layer Normalization, 简称LN&#xff09;是一种常用的技术&#xff0c;用于稳定和加速神经网络的训练。层归一化通过对单个样本内的所有激活进行…

各种数据降维方法ICA、 ISOMAP、 LDA、LE、 LLE、MDS、 PCA、 KPCA、SPCA、SVD、 JADE

独立分量分析 ICA 等度量映射 ISOMAP 线性判别分析 LDA (拉普拉斯)数据降维方法 LE 局部线性嵌入 LLE 多维尺度变换MDS 主成分分析 PCA 核主成分分析 KPCA 稀疏主成分分析SPCA 奇异值分解SVD 特征矩阵的联合近似对角化 JADE 各种数据降维方法(matlab代码)代码获取戳此处代码获取…

一篇文章讲清楚Java中的反射

介绍 每个类都有一个 Class 对象&#xff0c;包含了与类有关的信息。当编译一个新类时&#xff0c;会产生一个同名的 .class 文件&#xff0c;该文件内容保存着 Class 对象。 类加载相当于 Class 对象的加载。类在第一次使用时才动态加载到 JVM 中&#xff0c;可以使用 Class…

组件通信 Vue3

1.props 1.child <template><div class"child"><h3>子组件</h3><h4>玩具&#xff1a;{{ toy }}</h4><h4>父给的车&#xff1a;{{ car }}</h4><button click"sendToy(toy)">把玩具给父亲</butt…

Python进阶03-闭包和装饰器

零、文章目录 Python进阶03-闭包和装饰器 1、作用域 &#xff08;1&#xff09;作用域 在Python代码中&#xff0c;作用域分为两种情况&#xff1a; 全局作用域局部作用域 &#xff08;2&#xff09;变量的作用域 随着函数的出现&#xff0c;作用域被划分为两种 在全局定…

江协科技STM32学习- P7 GPIO输入

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

docker安装AWVS15(网络拉取失败,提供百度云镜像下载)

一.背景 准备在服务器上安装AWVS15用于扫描&#xff0c;直接拉取一直提示网络错误&#xff0c;刚好本地上有容器&#xff0c;就直接将本地的AWVS容器打包上传了&#xff0c;顺带上传到百度云来避免今后直接拉取网络出错的情况。考虑到其他师傅可能也会遇到相似问题&#xff0c…