Linux 8 下的容器引擎Podman概述

news2024/11/28 7:37:00

一、前言

在这里插入图片描述

最近在进行OS国产化交流中,了解到部分业务迁移到BClinux 8.2或Anolis 8.2时,原有docker业务需要迁移到新的容器平台:Podman,来完成容器的新的管理。Podman(全称 Pod Manager)是一款用于在 Linux® 系统上开发、管理和运行容器的开源工具。Podman 最初由红帽® 工程师联合开源社区一同开发,它可利用 lipod 库来管理整个容器生态系统。官方声称:Podman - The next generation of Linux container tools,它不仅可以管理 OCI 容器,还可以管理 pod 。
在这里插入图片描述

Podman 是一个 RedHat 公司发布的开源容器管理工具,初衷就是 Docker 的替代品,在使用上与 Docker 的相似,但又有着很大的不同。它与 Docker 的最大区别是架构,Docker 是以 C/S 架构运行的,我们平时使用的 docker 命令只是一个命令行前端,它需要调用 dockerd 来完成实际的操作,而 dockerd 默认是一个有 root 权限的守护进程。而Podman 不需要守护进程,直接通过 fork/exec 的形式启动容器,不需要 root 权限。这也是Podman其中一个较大优势,它采用了无守护进程的包容性架构,可以更安全、更简单地对容器进行管理,再加上 Buildah 和 Skopeo 等与之配套的工具和功能,开发人员能够按照自身需求来量身定制容器环境。 它实际与Docker扮演相同的角色,并且在很大程度上与 Docker 兼容,提供几乎相同的命令。总之,Podman是一个基于libpod库开发的容器运行时,用于在Linux操作系统上管理和运行容器。与传统的Docker容器运行时不同,Podman无需依赖Docker守护进程,它可以在不同的Linux发行版中独立运行。它支持常见的容器管理功能,如启动、停止、重启和删除容器,以及构建、推送和拉取容器镜像等。Podman还支持容器的网络和存储管理,可以使用CNI插件创建和管理容器的网络,支持使用多种存储驱动程序,如overlayfs、btrfs和zfs等。

Podman的一个显著特点是它使用的是rootless模式,这意味着它可以在普通用户权限下运行,而不需要root权限。这有助于提高容器运行的安全性和可移植性。同时,Podman支持通过Pods来管理一组相关的容器,这样可以方便地管理复杂的应用程序。

另外,Podman还支持使用systemd来管理容器,这使得它可以更好地集成到Linux系统中,与其他系统服务一起运行和管理。但无论怎样,它作为运行时,Podman的底层主要也是基于Linux的Cgroup和Namespace等技术。

Podman 可以帮助我能实现如下:

管理容器镜像和完整的容器生命周期,包括运行、联网、检查和下线。
为无根容器和容器集运行和隔离资源。
支持 OCI 和 Docker 镜像,以及与 Docker 兼容的 CLI。
打造一个无守护进程的环境,提高安全性并减少闲置资源消耗。
部署 REST API 来支持 Podman 的高级功能。
借助 checkpoint/restore in userspace(CRIU),实施面向 Linux 容器的检查点/恢复功能。CRIU 可以冻结正在运行的容器,并将其内存内容和状态保存到磁盘,以便容器化工作负载能够更快地重新启动。
自动更新容器。Podman 会检测更新的容器是否无法启动,并自动回滚到上一个工作版本。这可以将应用的可靠性提升到新的水平。

相关资料:containerd、Podman、Podman介绍、官网、Podman项目

二、架构和功能

2.1、运行时runtime

"运行时"就是​程序运行的时候,​也就是指令加载到内存并由CPU执行的时候,实际它就是一套比较底层的纯C语言API,是1个C语言库,包含了很多底层的C语言API,从而更好与Linux内核通信。与之相对应的是“​编译时​”,其指代码​编译的时候,也就是​C代码编译成可执行文件的时候,此时指令没有被CPU执行。对应的运行时库就是​程序运行的时候​所需要依赖的库。

每个环境都有自己的运行时,这里我们主要回顾容器的运行时(runtime),就是运行和管理容器进程、镜像的工具,可以把进程运行在容器中,并可通过SDK或命令来调用Linux的内核功能,从而创建出容器或其他关联容器底层的东西。runtime是在一个OCI(Open Container Initiative)组织中被明确定义的。OCI 发布了两个规范:runtime spec 和 image format spec;这样不同组织和厂商依据该规范开发的容器能够在不同的 runtime 上运行,保证了容器的可移植性和互操作性。 这个规范规定了容器之中应用被放到什么样的环境下、如何运行,比如说容器的根文件系统上哪个可执行文件会被执行,是用什么用户执行,需要什么样的 CPU,有什么样的内存资源、外置存储,还有什么样的共享需求等等。正如前文所述,runtime 就是容器(可理解就是一个独立的进程)真正运行的地方。整个过程中 需要跟操作系统 kernel 紧密协作,为容器提供运行环境。比如:那常见的Java环境举例,Java 程序就可看做是个容器,JVM 则好比是 runtime。JVM 为 Java 程序提供运行环境。同样的道理,容器只有在 runtime 中才能运行。

OCI规范概览:

镜像规范(常被称为“OCI 1.0 images")定义了容器镜像的内容
运行时规范( 常被称为“CRI(Container Runntime Interface) 1.0”或者容器运行时接口)表述了容器的”配置,运行环境和生命周期“。容器运行时接口(Container Runtime Interface, CRI),是指上层应用无需编译就可以支持多种容器运行时的插件接口,通过插件的切换方式应用不同封装的容器。
容器网络接口(CNI)描述了如何在容器内部配置网络接口,不过它是在CNCF下标准化的, 而不是OCI。

目前主流的有三种容器 runtime:

LXC 是 Linux 上老牌的容器 runtime。Docker 最初也是用 lxc 作为 runtime。lxc 是 lxd 的管理工具。

runc 是 Docker 自己开发的容器 runtime,符合 oci 规范,也是现在 Docker 的默认 runtime。Docker公司把其容器核心技术libcontainer捐给OCI(Open Container Intiative)后,更名为runC。Runc 的管理工具是 docker engine,docker engine 包含后台 deamon 和 cli 两部分,大家经常提到的 Docker 就是指的 docker engine。

rkt 是 CoreOS 开发的容器 runtime,符合 oci 规范,因而能够运行 Docker 的容器。Rkt 的管理工具是 rkt cli。

当前后来随着发展,也出现了其他runtime,比如Kata Container、CRI-O等;最先,Docker使用的是LXC但是层次隔离不太完整,所以后来Docker开发了libcontainer,最后演变为了runC。

Runtime 主 要 定 义 了 以 下 规 范 , 并 以 json 格 式 保 存 在/run/docker/runtime-runc/moby/容器 ID/state.json 文件,此文件会根据容器的状态实时更新内容:

版本信息:存放 OCI 标准的具体版本号。
容器 ID:通常是一个哈希值,可以在所有 state.json 文件中提取出容器 ID 对容器进行
批量操作(关闭、删除等),此文件在容器关闭后会被删除,容器启动后会自动生成。
PID:在容器中运行的首个进程在宿主机上的进程号,即将宿主机的那个进程设置为容
器的守护进程。
容器文件目录:存放容器 rootfs 及相应配置的目录,外部程序只需读取 state.json 就
可以定位到宿主机上的容器文件目录。
容器创建:创建包括文件系统、namespaces、cgroups、用户权限在内的各项内容。
容器进程的启动:运行容器启动进程,该文件在
/run/containerd/io.containerd.runtime.v1.linux/moby/容器 ID/config.json。
容器生命周期:容器进程可以被外部程序关停,runtime 规范定义了对容器操作信号的
捕获,并做相应资源回收的处理,避免僵尸进程的出现。

OCI 容器镜像主要包含以下内容:

文件系统:定义以 layer 保存的文件系统,在镜像里面是 layer.tar,每个 layer 保存了
和上层之间变化的部分,image format spec 定义了 layer 应该保存哪些文件,怎么表
示增加、修改和删除的文件等操作。
manifest 文件:描述有哪些 layer,tag 标签及 config 文件名称。
config 文件:是一个以 hash 命名的 json 文件,保存了镜像平台,容器运行时容
器运行时需要的一些信息,比如环境变量、工作目录、命令参数等。
index 文件:可选的文件,指向不同平台的 manifest 文件,这个文件能保证一个镜
像可以跨平台使用,每个平台拥有不同的 manifest 文件使用 index 作为索引。
父镜像:大多数层的元信息结构都包含一个 parent 字段,指向该镜像的父镜像。
参数:
ID:镜像 ID,每一层都有 ID
tag 标签:标签用于将用户指定的、具有描述性的名称对应到镜像 ID
仓库:Repository 镜像仓库
os:定义类型
architecture :定义 CPU 架构
author:作者信息
create:镜像创建日期

容器运行时具有掌控容器运行的整个生命周期,包括镜像的构建和管理、容器的运行和管理等功能。容器运行时接口(Container Runtime Interface, CRI),是指上层应用无需编译就可以支持多种容器运行时的插件接口,通过插件的切换方式应用不同封装的容器。容器运行时向上提供容器调用接口,包括容器生成与销毁的全生命周期管理的功能,向下提供调用接口,负责具体的容器操作事项,例如一个典型的Kubernetes集群中,Kubernetes对具体的容器类型不感知,而通过Kubernetes节点代理kubelet实现了 CRI客户端 API,可以使用任何实现 CRI 服务器 API的容器运行时来管理其节点上的容器和 Pod。
在这里插入图片描述

根据容器运行时提供功能,可以将容器运行时分为低层运行时和高层运行时。
在这里插入图片描述

1)低层运行时主要负责与宿主机操作系统打交道,根据指定的容器镜像在宿主机上运行容器的进程,并对容器的整个生命周期进行管理。而这个低层运行时,正是负责执行我们前面讲解过的设置容器 Namespace、Cgroups等基础操作的组件。常见的低层运行时种类有:

RunC:传统的运行时,基于Linux Namespace和Cgroups技术实现,代表实现Docker

RunV:基于虚拟机管理程序的运行时,通过虚拟化 guest kernel,将容器和主机隔离开来,使得其边界更加清晰,代表实现是Kata Container和Firecracker

Runsc:runc + safety ,通过拦截应用程序的所有系统调用,提供安全隔离的轻量级容器运行时沙箱,代表实现是谷歌的gVisor

2)高层运行时主要负责镜像的管理、转化等工作,为容器的运行做前提准备。主流的高层运行时主要containerd和CRI-O。

高层运行时与低层运行时各司其职,容器运行时一般先由高层运行时将容器镜像下载下来,并解压转换为容器运行需要的操作系统文件,再由低层运行时启动和管理容器。

另外这里还要注意的一个容器引擎containerd,2020年CNCF基金会宣布Kubernetes 1.20版本将不再仅支持Docker容器管理工具;早前Docker 1.11的Docker Engine里就包含了containerd,而现在则是把containerd从Docker Engine里彻底剥离出来,作为一个独立的开源项目独立发展,目标是提供一个更加开放、稳定的容器运行基础设施。在Docker Engine里containerd相比,独立的containerd将具有更多的功能,可以涵盖整个容器运行时管理的所有需求。另外独立之后containerd的特性演进可以和Docker Engine分开,专注容器运行时管理,可以更稳定。

Containerd是一个工业标准的容器运行时,重点是它简洁,健壮,便携,在Linux和window上可以作为一个守护进程运行,它可以管理主机系统上容器的完整的生命周期:镜像传输和存储,容器的执行和监控,低级别的存储和网络。每个containerd只负责一台机器,Pull镜像,对容器的操作(启动、停止等),网络,存储都是由containerd完成。具体运行容器由runC负责,实际上只要是符合OCI规范的容器都可以支持。

Containerd和docker不同,containerd重点是集成在大规模的系统中,例如kubernetes、Swarm、Mesos等【对于容器编排服务来说,运行时只需要使用containerd+runC,更加轻量,容易管理。】。Containerd 被设计成嵌入到一个更大的系统中,而不是直接由开发人员或终端用户使用。

2.2、Podman 是如何管理容器的?

用户可以通过命令行调用 Podman,从存储库拉取容器并运行它们。Podman 调用配置好的容器运行时来创建运行的容器。由于没有专门的守护进程,Podman 使用 systemd(一种用于 Linux 操作系统的系统和服务管理器)来进行更新并让容器在后台保持运行。通过将 systemd 和 Podman 集成,我们可以为容器生成控制单元,并通过自动启用 systemd 的前提下运行它们。

用户可以在系统上管理自有的存储库,也可通过 systemd 单元来控制自有容器的自动启动和管理。允许用户管理自己的资源并使容器以无根方式运行,可以阻止诸如使 /var/lib/containers 目录可被写入等不良做法,或防范可能会导致应用暴露于额外安全问题的其他系统管理做法。这样也可确保每一用户具有单独的容器和镜像集合,并可在同一主机上同步使用 Podman,而不会彼此干扰。用户完成自己的工作时,可将变更推送到共有的镜像仓库,将他们的镜像共享给其他人。

Podman 也可部署 RESTful API(REST API)来管理容器。REST 是表述性状态传递的英文缩写。REST API 是遵循 REST 架构规范的应用编程接口,支持与 RESTful Web 服务进行交互。借助 REST API,您可以从 cURL、Postman 和 Google 的 Advanced REST 客户端等许多平台调用 Podman。

三、部署配置

四、工具应用

4.1

4.2、Podman 桌面管理工具

Podman Desktop 使你能够轻松地使用本地环境中的容器,Podman Desktop 无守护进程,它利用 Podman Engine 提供轻量级且无守护程序的容器工具。该工具允许浏览、管理容器的生命周期、检查容器、来自不同容器引擎的镜像等。另,它专注于将 Podman 作为默认打包的容器引擎的同时,还兼容了其他容器引擎。Podman Desktop 具有以下一些特性:

  1. 管理容器:列出、搜索、检查、连接、运行和停止容器。
  2. 构建、拉取和推送镜像:从该工具构建镜像,通过管理仓库来拉取和推送镜像,从这些镜像运行容器。
  3. 管理 Podman 资源:查看分配的内存、CPU 和存储;如果需要,创建新机器
  4. 兼容Docker desktop扩展:指定 Docker desktop扩展的 OCI 镜像以将其导入。
  5. Podman Desktop 能够通过添加包装器来拦截 API 调用来使用 Docker Desktop UI 插件。通过添加 Docker Desktop 扩展,你可以扩展 Podman Desktop 的功能。还可以在后台使用插件来管理不同的容器引擎。通过添加新插件。

资源获取:二进制包

五、附录:

5.1、Containerd回顾

在这里插入图片描述

如上图所示,docker为我们提供了抽象的容器调用接口,而其内部功能的具体实现却是调用的contanierd;2016年,docker 把负责容器生命周期的模块 containerd拆分出来,并将其捐赠给了社区。
在这里插入图片描述

Containerd的特点:

简洁的基于 gRPC 的 API 和 client library。
完整的 OCI 支持(runtime 和 image spec)。
同时具备稳定性和高性能的定义良好的容器核心功能。
一个解耦的系统(让 image、filesystem、runtime 解耦合),实现插件式的扩展和重用。

Containerd的作用:

管理容器的生命周期(从创建容器到销毁容器)。
拉取/推送容器镜像。
存储管理(管理镜像及容器数据的存储)。
调用 runC 运行容器(与 runC 等容器运行时交互)。
管理容器网络接口及网络。
使用 bucketbench 对 Docker、crio 和 Containerd 的性能测试结果,包括启动、停止和删除容器,以比较它们所耗的时间,可以发现Containerd 在各个方面都表现良好,总体性能优于 Docker 和 crio。

Containerd架构:Containerd 采用标准的 C/S 架构:服务端通过 GRPC 协议提供稳定的 API;客户端通过调用服务端的 API 进行高级的操作。为了实现解耦,Containerd 将不同的职责划分给不同的组件,每个组件就相当于一个子系统(subsystem)。连接不同子系统的组件被称为模块。containerd 需要调用 runC,所以在安装 containerd 之前请先安装 runC。

containerd 的技术架构:
在这里插入图片描述

Containerd 被分为三个大块: Storage 、 Metadata 和 Runtime。

Containerd 两大子系统为:

Bundle : 在 Containerd 中,Bundle 包含了配置、元数据和根文件系统数据,你可以理解为 容器的文件系统。而 Bundle 子系统允许用户从镜像中提取和打包 Bundles。

Runtime : Runtime 子系统用来执行 Bundles,比如创建容器。其中,每一个子系统的行为都由一个或多个模块协作完成。

在这里插入图片描述

【几个概念】:

1)containerd 是一个高级容器运行时,又名容器管理器。简单来说,它是一个守护进程,在单个主机上管理完整的容器生命周期:创建、启动、停止容器、拉取和存储镜像、配置挂载、网络等。

2)ctr 是作为 containerd 项目的一部分提供的命令行客户端。该ctr界面 [显然] 与 Docker CLI不兼容,乍一看,可能看起来不太用户友好。因为它的主要受众是测试守护进程的容器开发人员。ctr + containerd比docker + dockerd更接近实际的容器。

3)nerdctl 是一个相对较新的containerd命令行客户端。与ctr不同,nerdctl的目标是用户友好和docker兼容。在某种程度上,nerdctl + containerd可以无缝地替代docker + dockerd。

4)crictl 是一个命令行客户端,用于 [kubernetes] CRI兼容的容器运行时。引入 Kubernetes 容器运行时接口 (CRI)以使 Kubernetes 容器运行时不可知。Kubernetes节点代理kubelet实现了 CRI客户端 API,可以使用任何实现 CRI 服务器 API的容器运行时来管理其节点上的容器和 Pod。

相关资源:containerd官网、containerd官方安装步骤

5.2、Docker、containerd的关系

1)就docker本身而言,包括docker client和dockerd,是一个客户端工具,用来把用户的请求发送给docker daemon(dockerd)。dockerd:dockerd是对容器相关操作的最上层封装,直接面向操作用户。Docker daemon,一般也会被称为docker engine。dockerd启动时会启动containerd 子进程。

containerd-shim是一个真实运行容器的载体,为了能够支持多种OCI Runtime,containerd内部使用containerd-shim,每启动一个容器都会起一个新的containerd-shim的进程。它通常指定三个因素:容器ID、bundle目录(对应某个容器生成的目录,一般位于:/var/run/docker/containerd/containerID)

2)containerd囊括了单机运行一个容器时所需要的一切;containerd是一个工业级别标准的容器运行时,它强调简单性、健壮性和可移植性,几乎囊括了单机运行一个容器运行时所需要的一切:执行、分发、监控、网络、构建、日志等。主要作用是:

1)、管理容器的生命周期(从创建容器到销毁容器)
2)、拉取/推送容器镜像
3)、存储管理(管理镜像及容器数据的存储)
4)、调用runC运行容器(与runC等容器运行时交互)
5)、管理容器网络接口及网络

dockerd实际真实调用的还是containerd的api接口,containerd是dockerd和runC之间的一个中间交流组件。runC是一个轻量级的工具,用来运行容器的,我们可以不用通过docker引擎,直接运行容器。

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

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

相关文章

MOS管的损耗分析

目的 1、MOS管的损耗分类: 开关损耗: 栅驱动损耗: 导通损耗: 主要内容 MOS管损耗主要有开关损耗(开通损耗和关断损耗,关注参数Cgd(Crss))、栅极驱动损耗(关注参数Qg)和…

面试流程解析:从初面到终面,程序员需要注意什么

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

RabbitMQ 的快速使用

docker部署rabbitmq # management才有管理页面 docker pull rabbitmq:management# 新建容器并运行 docker run \-e RABBITMQ_DEFAULT_USERadmin \ -e RABBITMQ_DEFAULT_PASSadmin \ -v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \-itd \ra…

客服系统哪个好用?

在当今竞争激烈的商业环境中,良好的客户服务是企业成功的关键因素之一。通过提供优质的客户服务,企业可以吸引、留住、回馈顾客,增加口碑宣传,提高产品或服务质量,同时还可以减少客户投诉率,从而为企业带来…

docker容器运行成功但无法访问,原因分析及对应解决方案(最新,以Tomcat为例,亲测有效)

原因分析: 是否能访问当运行docker容器虚拟机(主机)地址 虚拟机对应的端口号是否开启或者防墙是否关闭 端口映射是否正确(这个是我遇到的) tomcat下载的是最新版,docker运行后里面是没有东西的&am…

跨屏无界 | ZlongGames 携手 Google Play Games 打造无缝游戏体验

一款经典游戏,会在时间的沉淀中被每一代玩家所怀念,经久不衰。对于紫龙游戏来讲,他们就是这样一群怀揣着创作出经典游戏的初心而聚集在一起的团队,致力于研发出被广大玩家喜爱的作品。 从 2015 年团队成立,到 2019 年走…

DHCP实验

文章目录 一、实验背景与目的二、实验拓扑三、 实验需求四、实验解法1. R1配置IP地址部分2. 配置R1的DHCP服务3. 配置IP地址排除4. 配置PC3和PC4的IP地址为自动获取,然后可以自动获得192.168.1.0/24网段的IP地址。 摘要: 本实验旨在通过配置DHCP服务器和…

2023-8-30 Dijkstra 求最短路(一)

题目链接&#xff1a;Dijkstra求最短路 I #include <iostream> #include <cstring> #include <algorithm>using namespace std;const int N 510;int n, m; int g[N][N]; int dist[N]; bool st[N];int dijkstra() {memset(dist, 0x3f, sizeof dist);dist[1…

【力扣每日一题】2023.8.30 到家的最少跳跃次数

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 题目给我们一只跳蚤&#xff0c;我们可以操控它前跳 a 格或是后跳 b 格&#xff0c;不能跳到小于0的位置&#xff0c;有一些被禁止的点不…

Gradio入门(1)输入输出、表格、文本高亮

本文将会介绍gradio的入门使用&#xff0c;并结合大模型&#xff08;LLM&#xff09;&#xff0c;给出三个使用例子。   Gradio 是通过友好的 Web 界面演示机器学习模型的最快方式&#xff0c;以便任何人都可以在任何地方使用它。其官网网址为&#xff1a;https://www.gradio…

1978-2022年全国整体GDP平减指数计算模板(可任意调整基期)

1978-2022年全国整体GDP平减指数计算模板&#xff08;可任意调整基期&#xff09; 1、时间区间&#xff1a;1978-2022年 2、指标&#xff1a;名义GDP、实际GDP、GDP平减指数 3、中国GDP平减指数计算公式可以给定基期&#xff0c;自动计算平减指数&#xff0c;可根据需要任意…

易混淆的符号

C自学精简教程 目录(必读) &符号在C中有多个含义。 下面我们列出常见的3种&#xff0c;你都能分得清吗&#xff1f; #include <iostream> using namespace std;//传递引用类型的参数 pass by reference void fun(int& a)//(1) 这里的 & 表示参数a是引用类…

加速度传感器术语解析

一、加速度单位 g 一般用g表示加速度&#xff0c;g即为重力加速度9.8米/秒的平方 如上图表示了加速度传感器的量程范围&#xff0c;可选为2g&#xff0c;4g&#xff0c;8g&#xff0c;16g,即对应19.6米/秒的平方、39.2米/秒的平方、78.4米/秒的平方、156.8米/秒的平方。 二、…

k8s(kubernetes)介绍篇

一、Kubernetes 是什么 Kubernetes 是一个全新的基于容器技术的分布式架构解决方案&#xff0c;是 Google 开源的一个容器集群管理系统&#xff0c;Kubernetes 简称 K8S。 Kubernetes 是一个一站式的完备的分布式系统开发和支撑平台&#xff0c;更是一个开放平台&#xff0c;对…

docker linux(centos 7) 安装

这是个目录 1:安装1:手动安装(适用于centos7)之一2:手动安装(适用于centos7)之二3&#xff1a;一键安装docker4:二进制安装1&#xff1a;下载二进制包2&#xff1a;解压3&#xff1a;移动文件4&#xff1a;后台运行docker5&#xff1a;测试 dicker命令表999&#xff1a;遇到的问…

C语言每日一练--------Day(8)

本专栏为c语言练习专栏&#xff0c;适合刚刚学完c语言的初学者。本专栏每天会不定时更新&#xff0c;通过每天练习&#xff0c;进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字&#xff1a;图片整理 寻找数组下标 &#x1f493;博主csdn个人主页&#xff1a;小小…

二十、观察者模式

一、什么是观察者模式 观察者&#xff08;Observer&#xff09;模式的定义&#xff1a;指多个对象间存在一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式&…

苹果秋季发布会,北京时间9月13日

苹果公司宣布&#xff0c;将于当地时间9月12日&#xff08;北京时间9月13日&#xff09;召开新闻发布会&#xff0c;发布会将于美东时间下午1点&#xff08;北京时间凌晨1点&#xff09;在苹果官网上进行直播&#xff0c;预计苹果届时将在会上发布iPhone 15系列和新款苹果手表。…

如何制作并运行 jar 程序

以下是用 Intellij 制作 jar 程序&#xff0c;并运行的方法。 【1】新建工程&#xff0c;保持默认选项&#xff0c;Next 【2】保持默认选项&#xff0c;Next 【3】给工程命名&#xff0c;设置保存位置&#xff0c;Finish 【4】新建工程结束&#xff0c;进入开发界面 【5】展开…

Spring源码分析(七)不同作用域下Bean的创建

目录 1.1 单例模式的实例化1.1.1 从缓存中获取1.1.2 前置处理1.1.3 获取Bean1.1.4 后置处理1.1.5 加入缓存 1.2 原型模式实例化1.3 其他模式实例化 官网&#xff1a;Home参考书籍&#xff1a;Spring源码深度解析-郝佳编著-微信读书 上一篇文章我们分析到不同的作用域创建Bean&…