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

K8S 1.20 弃用 Docker 评估之 Docker 和 OCI 镜像格式的差别

背景

2020 年 12 月初,Kubernetes 在其最新的 Changelog 中宣布,自 Kubernetes 1.20 之后将弃用 Docker 作为容器运行时。

弃用 Docker 带来的,可能是一系列的改变,包括不限于:

  • 容器镜像构建工具
  • 容器 CLI
  • 容器镜像仓库
  • 容器运行时

专题文章《K8S 1.20 弃用 Docker 评估》会从多方面分析由此带来的变动和影响,今天先介绍镜像格式的改变。

Docker 镜像仍然可以使用吗?

是的,可以使用。Docker 较新版本生成的镜像实际上并不是特定于 Docker 的镜像,而是 OCI(Open Container Initiative)镜像。无论你使用什么工具构建镜像,任何符合 OCI 标准的镜像在 Kubernetes 看来都是一样的。containerd 和 CRI-O 都能够提取这些镜像并运行它们。所以您可以仍然使用 Docker 来构建容器镜像,并且可以继续在 containerd 和 CRI-O 上使用。

那为什么发现 Docker 镜像和 Containerd 镜像存在不兼容情况?

具体如下:在 K8S > 1.20 版本中,发现 containerd ctr 上传到镜像仓库的镜像与同版本的 docker 镜像间存在以下问题

  1. 不能被 docker 使用
  2. docker push不能覆盖

根本原因还是在于镜像格式的差别。下面做详细解释。

Docker 和 OCI 镜像格式的差别?

目前有以下几种容器镜像格式:

  • ❌已弃用:Docker Image V1
  • :warning:已弃用:Docker Image Manifest V2 Schema 1
  • Docker Image Manifest V2 Schema 2
  • Open Container Initiative (OCI) 规范

Docker V1 镜像

{% note danger %} ❌严重警告

Docker V1 格式早已弃用,请不要再使用!!! {% endnote %}

{% note info %} :book: 引用

  1. 版本 1.8.3 增加了一个标志(--disable-legacy-registry=false),用于阻止 docker 守护进程对 v1 镜像注册表进行拉、推和登录操作。尽管默认情况下是启用的,但这表示不赞成 v1 协议。
  2. 自 2017 年 2 月 28 日起,随着 Docker v1.13 的发布,Docker Engine 不再支持 v1 协议。
  3. 从 Docker 17.12 开始,对 V1 镜像注册表的支持已经被删除,并且 --disable-legacy-registry 标志不再使用,当设置该标志时 dockerd时将无法启动。 {% endnote %}

Docker V2 镜像简介

Docker V2 镜像清单(Image Manifest)是 Docker 的 V2 版本容器映像规范,它允许多架构镜像并支持内容可寻址映像。

从 2017 年 2 月 28 日开始,Docker V2 镜像注册表规范取代了 Docker V1 规范。Docker V1 规范已被弃用,并且 Docker V1 映像不能再用于 Container Registry。

为支持内容可寻址镜像并简化镜像图层的跟踪,Docker V2 对 Docker 镜像格式进行了一系列更改。 Docker V2 镜像清单包含镜像图层的所有内容地址(“摘要”),而 Docker V1 映像则不包含这些信息。

Docker Image Manifest V2 Schema 1

下面简单介绍下 V2 Schema 1 镜像清单的格式。V2 Schema 1 它是一个临时清单,提供与 V1 Image 格式的兼容性,V2 Schema 2 才是当前 Docker 镜像格式的最终格式。

{% note default %} :notebook: 备注

V2 Schema 1 由于需要与 V1 的向后兼容性原因,它比 V2.2(即 Docker Image Manifest V2 Schema 2) 更复杂。 {% endnote %}

镜像清单描述了一个 Docker 镜像的各种组成部分。镜像清单可以序列化为 JSON 格式与以下媒体类型:

清单类型(Manifest Type)媒体类型(Media Type)
manifest“application/vnd.docker.distribution.manifest.v1+json”
signed manifest“application/vnd.docker.distribution.manifest.v1+prettyjws”

清单格式不详细介绍,下面通过示例说明:

示例清单格式

{"name": "hello-world","tag": "latest","architecture": "amd64","fsLayers": [{"blobSum": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"},{"blobSum": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"},{"blobSum": "sha256:cc8567d70002e957612902a8e985ea129d831ebe04057d88fb644857caa45d11"},{"blobSum": "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"}],"history": [{"v1Compatibility": "{\"id\":\"e45a5af57b00862e5ef5782a9925979a02ba2b12dff832fd0991335f4a11e5c5\",\"parent\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"created\":\"2014-12-31T22:57:59.178729048Z\",\"container\":\"27b45f8fb11795b52e9605b686159729b0d9ca92f76d40fb4f05a62e19c46b4f\",\"container_config\":{\"Hostname\":\"8ce6509d66e2\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) CMD [/hello]\"],\"Image\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"SecurityOpt\":null,\"Labels\":null},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"8ce6509d66e2\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/hello\"],\"Image\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"SecurityOpt\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"},{"v1Compatibility": "{\"id\":\"e45a5af57b00862e5ef5782a9925979a02ba2b12dff832fd0991335f4a11e5c5\",\"parent\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"created\":\"2014-12-31T22:57:59.178729048Z\",\"container\":\"27b45f8fb11795b52e9605b686159729b0d9ca92f76d40fb4f05a62e19c46b4f\",\"container_config\":{\"Hostname\":\"8ce6509d66e2\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/bin/sh\",\"-c\",\"#(nop) CMD [/hello]\"],\"Image\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"SecurityOpt\":null,\"Labels\":null},\"docker_version\":\"1.4.1\",\"config\":{\"Hostname\":\"8ce6509d66e2\",\"Domainname\":\"\",\"User\":\"\",\"Memory\":0,\"MemorySwap\":0,\"CpuShares\":0,\"Cpuset\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"PortSpecs\":null,\"ExposedPorts\":null,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":[\"/hello\"],\"Image\":\"31cbccb51277105ba3ae35ce33c22b69c9e3f1002e76e4c736a2e8ebff9d7b5d\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":null,\"NetworkDisabled\":false,\"MacAddress\":\"\",\"OnBuild\":[],\"SecurityOpt\":null,\"Labels\":null},\"architecture\":\"amd64\",\"os\":\"linux\",\"Size\":0}\n"},],"schemaVersion": 1,"signatures": [{"header": {"jwk": {"crv": "P-256","kid": "OD6I:6DRK:JXEJ:KBM4:255X:NSAA:MUSF:E4VM:ZI6W:CUN2:L4Z6:LSF4","kty": "EC","x": "3gAwX48IQ5oaYQAYSxor6rYYc_6yjuLCjtQ9LUakg4A","y": "t72ge6kIA1XOjqjVoEOiPPAURltJFBMGDSQvEGVB010"},"alg": "ES256"},"signature": "XREm0L8WNn27Ga_iE_vRnTxVMhhYY0Zst_FfkKopg6gWSoTOZTuW4rK0fg_IqnKkEKlbD83tD46LKEGi5aIVFg","protected": "eyJmb3JtYXRMZW5ndGgiOjY2MjgsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAxNS0wNC0wOFQxODo1Mjo1OVoifQ"}]
}

{% note warning %} :warning: 注意

随着 Docker Image Manifest V2 Schema 2 的发布,Docker Image Manifest V2 Schema 1 已被弃用。这可能导致尚未更新到 Docker Image Manifest V2 Schema 2 的镜像存在兼容性和漏洞问题。 {% endnote %}

Docker Image Manifest V2 Schema 2

然后介绍 V2 Schema 2 的格式。

V2 Schema 2 版本有两个主要目标。第一种是允许多架构镜像,通过“胖清单”引用特定于平台版本的镜像的镜像清单。第二种方法是将 Docker 引擎转向可内容寻址的图像,方法是支持一个镜像模型,在该模型中,可以对镜像的配置进行哈希,以生成镜像的 ID。

清单列表(Manifest List)

清单列表是 Docker V2 Schema 2 和 OCI 镜像的一部分。

利用清单列表,您可以使用单个摘要或标记来表示映像的多种形式。

示例清单列表(Manifest List)

{"schemaVersion": 2,"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json","manifests": [{"mediaType": "application/vnd.docker.distribution.manifest.v2+json","size": 7143,"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f","platform": {"architecture": "ppc64le","os": "linux",}},{"mediaType": "application/vnd.docker.distribution.manifest.v2+json","size": 7682,"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270","platform": {"architecture": "amd64","os": "linux","features": ["sse4"]}}]
}
镜像清单

示例镜像清单

{"schemaVersion": 2,"mediaType": "application/vnd.docker.distribution.manifest.v2+json","config": {"mediaType": "application/vnd.docker.container.image.v1+json","size": 7023,"digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"},"layers": [{"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip","size": 32654,"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f"},{"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip","size": 16724,"digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b"},{"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip","size": 73109,"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"}]
}

如何将 Docker V1 或 Manifest V2 Schema 1 升级到:Docker Image Manifest V2 Schema 2 ?

  1. 将老的 Docker V1 或 Manifest V2 Schema 1 使用 docker pull 下来;
  2. 然后用新版本的 Docker docker push 到镜像仓库即可

这样做将自动将镜像转换为使用最新的镜像清单规范。

或者也可以这样升级:

  1. 可以通过更新 Dockerfile 中的 FROM 语句来重新 build 镜像。如果您的镜像清单过期了,那么从 Dockerfile 中的 from语句中提取的镜像也有可能过期。

OCI 格式

OCI 格式是基于 Docker Image Manifest Version 2 Schema 2 格式的容器镜像规范。该规范定义了如何创建 OCI Image(通常由构建系统完成),并输出镜像清单、文件系统(镜像层)序列化和镜像配置。下面简要拿镜像清单做一个和 Docker 的对比说明,更多就不详细展开了。

镜像索引(Image Index)

镜像索引(Image Index)相当于 OCI 映像中的清单列表(Manifest List)。

与清单列表一样,镜像索引清单指的是多个镜像清单。镜像索引对多平台镜像很有用。

示例镜像索引

{"schemaVersion": 2,"manifests": [{"mediaType": "application/vnd.oci.image.manifest.v1+json","size": 7143,"digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f","platform": {"architecture": "ppc64le","os": "linux"}},{"mediaType": "application/vnd.oci.image.manifest.v1+json","size": 7682,"digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270","platform": {"architecture": "amd64","os": "linux"}}],"annotations": {"com.example.key1": "value1","com.example.key2": "value2"}
}

镜像清单

示例镜像清单

{"schemaVersion": 2,"config": {"mediaType": "application/vnd.oci.image.config.v1+json","size": 7023,"digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7"},"layers": [{"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip","size": 32654,"digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"},{"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip","size": 16724,"digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b"},{"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip","size": 73109,"digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736"}],"annotations": {"com.example.key1": "value1","com.example.key2": "value2"}
}

镜像格式差别总结

首先是 Docker V1 镜像,这是非常老旧且已经弃用的镜像格式,是 Docker 刚出来的时候,没有考虑多架构多平台(如:x86 和 arm 镜像),所以通常 Docker V1 镜像只有 x86 平台的镜像。:warning: 注意:请不要再使用,如果使用,请尽快升级到 Docker Image Manifest V2 Schema 2 或 OCI 格式

然后是 Docker Image Manifest V2 Schema 1,这个是过过渡形态的格式,兼容 Docker V1 和 Docker Image Manifest V2 使得它更为复杂,它的作用也仅仅是为了过渡而非长期使用。:warning: 注意:请不要再使用,如果使用,请尽快升级到 Docker Image Manifest V2 Schema 2 或 OCI 格式

最后是 Docker Image Manifest V2 Schema 2 和 OCI 格式,OCI 主要参考的就是 Docker Image Manifest V2 Schema 2 格式,二者是兼容的,这也就回答了上文所说的:「Docker 镜像仍然可以使用吗?-- 是的,可以使用。」

但是二者在媒体类型(Media Type)、压缩方式等细节上存在不同,部分举例如:

  • 清单(manifest)上:
    • Docker Image Manifest V2 Schema 2 的 Media Type 是:"application/vnd.docker.distribution.manifest.list.v2+json"
    • 而 OCI 是:"application/vnd.oci.image.manifest.v1+json"
  • 每一层镜像层上:
    • Docker Image Manifest V2 Schema 2 的 Media Type 是:"application/vnd.docker.image.rootfs.diff.tar.gzip"
    • OCI 的 Media Type 是:application/vnd.oci.image.layer.v1.tar+gzipapplication/vnd.oci.image.layer.v1.tar 等类型。

也正是因为这些差异,最终导致即使是完全相同的镜像,二者的 digest、镜像大小不尽相同。

所以这也正好解释了「那为什么发现 Docker 镜像和 Containerd 镜像存在不兼容情况?」

  1. 「不能被 docker 使用?」 - 可能是 docker 版本过低导致的;
  2. 「docker push 不能覆盖?」- 因为即使是完全相同的镜像,二者的 digest、镜像大小不尽相同。所以无法覆盖。

我的建议

针对镜像,因为 OCI 主要参考了 Docker Image Manifest V2 Schema 2,而 Docker Image Manifest V2 Schema 2 是 OCI 的一种实现。所以 Docker 较新版本生成的镜像,containerd 和 CRI-O 都能够提取这些镜像并运行它们。

两种办法都可以:

  1. 镜像构建方式保持不变,仍然是采用 Docker 构建镜像(注意 Docker 版本要较新,确保构建的镜像是:Docker Image Manifest V2 Schema 2 格式)
  2. 变更镜像构建工具,不再使用 Docker,而是使用可以构建 OCI 格式的镜像构建工具。

具体您可以视实际情况进行选择。

三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.

相关文章:

K8S 1.20 弃用 Docker 评估之 Docker 和 OCI 镜像格式的差别

背景 2020 年 12 月初,Kubernetes 在其最新的 Changelog 中宣布,自 Kubernetes 1.20 之后将弃用 Docker 作为容器运行时。 弃用 Docker 带来的,可能是一系列的改变,包括不限于: 容器镜像构建工具容器 CLI容器镜像仓…...

Vue2和Vue3响应式的区别

数据响应式是什么? ​所谓 数据响应式 就是建立 响应式数据 与 依赖(调用了响应式数据的操作)之间的关系,当响应式数据发生变化时,可以通知那些使用了这些响应式数据的依赖操作进行相关更新操作,可以是DOM…...

模型实战(6)之Alex实现图像分类:模型原理+训练+预测(详细教程!)

Alex实现图像分类:模型原理+训练+预测 图像分类或者检索任务在浏览器中的搜索操作、爬虫搜图中应用较广,本文主要通过Alex模型实现猫狗分类,并且将可以复用的开源模型在文章中给出!!!数据集可以由此下载:Data本文将从以下内容做出讲述: 1.模型简介及环境搭建2.数据集准…...

【大数据】最全的大数据Hadoop|Yarn|Spark|Flink|Hive技术书籍分享/下载链接,持续更新中...

这里写目录标题Hadoop大数据处理Hadoop技术内幕:深入解析YARN架构设计与实现原理Hadoop 技术内幕:深入解析Hadoop Common 和HDFS 架构设计与实现原理Spark SQL内核剖析Hadoop 应用架构深度剖析Hadoop HDFSHadoop实战Hive编程指南Hadoop大数据处理 本书以…...

RIG Exploit Kit 仍然通过 IE 感染企业用户

RIG Exploit Kit 正处于最成功的时期,每天尝试大约 2000 次入侵并在大约 30% 的案例中成功,这是该服务长期运行历史中的最高比率。 通过利用相对较旧的 Internet Explorer 漏洞,RIG EK 已被发现分发各种恶意软件系列,包括 Dridex…...

GIS在地质灾害危险性评估与灾后重建中的实践技术应用及python机器学习灾害易发性评价模型建立与优化进阶

地质灾害是指全球地壳自然地质演化过程中,由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。由于降水、地震等自然作用下,地质灾害在世界范围内频繁发生。我国除滑坡灾害外,还包括崩塌、泥石流、地面沉…...

SQL SERVER中SCHEMA的詳解

SQL SERVER中SCHEMA的講解1. Introduction1.1 優勢1.2 內置schema2. Create Schema2.1 Parameters2.2 Sql3.Awakening1. Introduction 1.1 優勢 数据库模式为我们提供了在数据库中创建逻辑对象组的灵活性。如果多个团队使用同一个数据库,我们可以设计各种模式来分組…...

【LeetCode】剑指 Offer(13)

目录 题目:剑指 Offer 31. 栈的压入、弹出序列 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 写在最后: 题目:剑指 Offer 31. 栈…...

帮助小型企业实现业务增长的7种数字营销策略

数字营销一直在不断地变化和发展,在过去的几年里我们已经见识到了其迅猛的发展速度。虽然我们在数字营销中看到了一些新的趋势,但对于小型企业来说很难利用并发挥其优势。相比较大型企业,小型企业的预算和资源通常有限,所以他们很…...

互联网行业的高级产品经理和普通产品经理有哪些区别?

普通产品经理的一天可能是这样的。 早上到公司想一想,这几天有哪些事情要处理。打开记事本,按照上面要求的任务一条一条开始做。 这里有个需求,是要给产品的聊天模块增加历史记录。嗯,看一下常见的几款社交工具 APP,他…...

aardio - 【库】简单信息框

昨晚得知aardio作者一鹤的妻子病情严重,深感悲痛。今日给一鹤捐赠少许,望其妻能挺过难关,早日康复。 aardio是一个很好的编程工具,我非常喜欢,这两年也一直在用。虽然未曾用其获利,但其灵活的语法&#xff…...

程序员必备!最值得收藏的宝藏网站大盘点

做为程序员,没有收藏点宝藏网站都说不过去。 除了常见的大家熟知的知乎、谷歌、b站、CSDN、掘金等,今天将介绍一些其他更加实用的宝藏网站,程序员小伙伴们可以按需收藏哦~ 1.菜鸟教程:https://www.runoob.com/ 国内…...

Android 10.0 Settings 关掉开发者模式

1.概述 在系统Settings中,系统默认在关于手机里面点击五下版本号进入开发者模式,开启某些功能, 在进行项目定制中,要求去掉进入开发者模式的这个功能,就需要找到关于开启开发者模式的相关代码屏蔽掉就可以了 2.关于屏蔽掉开发者模式的相关核心代码 packages/apps/Settings…...

软件测试面试必杀篇:【2023软件测试面试八股文宝典】

800道软件测试面试真题,高清打印版打包带走,横扫软件测试面试高频问题,涵盖测试理论、Linux、MySQL、Web测试、接口测试、App测试、Python、Selenium、性能测试、LordRunner、计算机网络、数据结构与算法、逻辑思维、人力资源等模块面试题&am…...

原子级操作快速自制modbus协议

原子级操作手把手搞懂modbus协议文章目录[toc]1 modbus协议基础概念1.1 使用场所1.2 主从协议站1.3 modbus帧描述1.4 数据模式1.5 modbus状态机2 modbus协议2.1 功能码2.2 公共功能码2.3 数据域格式3 modbus从站程序设计3.1 接口初始化3.2 数据处理部分查表法设置超时时间3.2 主…...

大数据之Apache Doris_亚秒级响应_大数据处理分析_介绍_概述---大数据之Apache Doris工作笔记0001

可以看到这个Doris的介绍 MPP是大规模并行处理 这里的clickhouse ,greenplumn也是mpp,大规模并行处理数据库 应用场景 然后我们看一下doris的架构,可以看到,这里,左侧是数据来源,可以看到这个数据来源有 OLTP数据库,比如mysql,oracle等等这种数据库,还有就是enterprise appli…...

SpringCloud学习笔记 - 分布式系统全局事务管理 - Seata1.5.2+Nacos+OpenFeign

1. Seata 是什么? 由于业务和技术的发展,单体应用被拆分成微服务应用,原来的三个模块被拆分成三个独立的应用,分别使用三个独立的数据源,业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性由本地事务来保证, 但是全…...

LeetCode190_190. 颠倒二进制位

LeetCode190_190. 颠倒二进制位 一、描述 颠倒给定的 32 位无符号整数的二进制位。 提示: 请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型&…...

atomic 原子操作

atomic 原子操作前言atomic_t定义内核中的实现armv7的实现armv8的实现Exclusive monitor实现所处的位置External exclusive monitorAtomic指令的支持QA前言 修改一个变量会经过读、修改、写的操作序列。但有时该操作序列在执行完毕前会被其他任务或事件打断。 比如在多CPU体系…...

DataGear 制作基于Vue前端框架渲染的数据可视化看板

DataGear 在4.3.0版本新增了dg-dashboard-code特性&#xff0c;并在4.4.0版本进行了改进和增强&#xff0c;结合看板API&#xff0c;可以很方便地制作完全由Vue、React等前端框架渲染的数据可视化看板。 本文基于Vue2、Element UI前端框架的<el-container>、<el-head…...

JavaFX Scene Builder 下载安装

JavaFX Scene Builder 下载安装1. Scene Builder官网下载2. 安装3. Oracle官网下载Scene Builder 是创建漂亮的用户界面&#xff0c;并将您的设计转化为交互式原型。Scene Builder通过创建可以直接在JavaFX应用程序中使用的用户界面&#xff0c;缩小了设计人员和开发人员之间的…...

dva( 轻量级的应用框架 )

dva核心知识与实战运用 dva 首先是一个基于 redux 和 redux-saga 的数据流方案&#xff0c;然后为了简化开发体验&#xff0c;dva 还额外内置了 react-router 和 fetch&#xff0c;所以也可以理解为一个轻量级的应用框架! 介绍 | DvaJS 易学易用&#xff0c;仅有 6 个 api&…...

数据结构:堆的实现与建堆时间复杂度分析

目录 前言 一.堆的介绍 1.堆的本质 2.堆的分类 二.堆的实现(以小根堆为例) 1.关于二叉树的两组重要结论&#xff1a; 2.堆的物理存储结构框架(动态数组的简单构建) 3. 堆元素插入接口(以小根堆为例) 堆尾元素向上调整的算法接口: 4.堆元素插入接口测试 5.堆元素插入…...

对“车辆销售配置器”的认识与理解

概述 中国汽车市场转为存量阶段后&#xff0c;各车企开始从”以产品为中心“转型到”以客户为中心“&#xff0c;产品的个性化配置需求日益丰富。随着竞争的加剧&#xff0c;车企们不仅要提供出色的产品&#xff0c;而且需要提供更加个性化的产品配置和服务&#xff0c;例如&am…...

Linux编译器——gcc/g++(预处理、编译、汇编、链接)

目录 0.程序实现的两大环境 1.gcc如何完成 预处理 编译 汇编 链接 2.动态库与静态库 对比二者生成的文件大小 3. gcc常用选项 0.程序实现的两大环境 任何一个C程序的实现都要经过翻译环境与执行环境。 在翻译环境中又分为4个部分&#xff0c;预编译、编译、汇编与链…...

Java 操作图片进行缩放旋转翻转加水印

1 纯原生手写图片操作工具类 import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; import java.awt.image.BufferedImage; public class RotateImageUtil {public static BufferedImage rotateImage(BufferedImage bu…...

不能去演唱会现场就多听听耳机里的他们,教你用python来实现一个音乐播放器

前言 最近可以说大麦网很知名了&#xff0c;哈哈还有好多想要用Python来搞抢票脚本的 怎么说呢也不是不行&#xff0c;但是咱今天可不是来搞这个的&#xff0c;我可不抢票&#xff0c;抢了都去不了&#xff0c;上班搞钱啊铁铁们 咱就是说去不了现场&#xff0c;就多听听手机…...

CLion Debug 调试 Makefile 构建的 C 语言程序断点不起作用

最近在研究 jattach&#xff0c;打算在本地调试项目&#xff0c;发现 CLion 可以正常编译运行代码&#xff0c;却无法断点 Debug。由于笔者对 C/C 项目不熟悉&#xff0c;在此记录研究过程中遇到的一些基本问题与解决方法。 文章目录解决方式尝试过的手段【未解决】找 Native D…...

·神经网络

目录11神经网络demo112神经网络demo213神经网络demo320tensorflow2.0 安装教程,所有安装工具&#xff08;神经网络&#xff09;21神经网络-线性回归- demo122神经网络-线性回归- demo228神经网络-多层感知- demo1目录11神经网络demo1 package com.example.xxx; import java.ut…...

【Java 多线程学习】

多线程学习多线程1. 并行与并发2.进程和线程3. *****多线程的实现方式3.1 继承Thread类的方式进行实现3.2 实现Runnable接口方式进行实现3.3 利用Callable和Future接口方式实现3.4 设置获取线程名字4.获得线程对象5.线程休眠6.线程调度[线程的优先级]7.后台线程/守护线程多线程…...

福州网站快速排名/阳泉seo

6 命名空间的应用在C中&#xff0c;使用“命名空间”&#xff0c;是为了更好地管理代码。例如&#xff0c;程序员A定义了一个处理字符串的string类&#xff0c;程序员B定义了一个处理字符串的string类。那么&#xff0c;都是同样的类名string&#xff0c;但是&#xff0c;功能可…...

java+做网站后台/武汉关键词排名工具

众所周知&#xff0c;swap就是交换分区的意思。 但是什么是交换分区&#xff0c;你真的知道吗&#xff1f; SWAP就是LINUX下的虚拟内存分区, 它的作用是在物理内存使用完之后,将磁盘空间(也就是SWAP分区)虚拟成内存来使用.    它和Windows系统的交换文件作用类似&#xff0c;…...

英文书 影印版 网站开发/站长工具seo查询软件

在idea使用htmlcss 简单仿制QQ会员官网主页页面 附带登录页面 跳转登陆页面 导航栏设置固定 底部信息栏附加根据鼠标在页面滑动的距离设置自动隐藏和显示 登录页面在点击登录后&#xff0c;实现覆盖整个页面&#xff0c;保持固定在页面中央位置&#xff0c;背景半透明化 …...

php编程/推送者seo

java Spring Controller 获取请求参数的几种方法1、直接把表单的参数写在Controller相应的方法的形参中&#xff0c;适用于get方式提交&#xff0c;不适用于post方式提交。若"Content-Type""application/x-www-form-urlencoded",可用post提交url形式&#…...

wordpress h5模板/百度代做seo排名

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2022年安全员-C证试题是安全员-C证练习题高频考题覆盖&#xff01;2022安全员-C证考试题模拟考试题库及在线模拟考试依据安全员-C证考试教材。安全员-C证复审模拟考试通过安全生产模拟考试一点通上提前熟悉考试环境。…...

做微信表情的微信官方网站/搜索引擎营销方案

网址:http://cmder.net/ 如果vim乱码 命令行输入 set LC_ALLzh_CN.UTF8 添加cmder到鼠标右键 c://安装目录/Cmder.exe /REGISTER ALL 右键添加 Cmder here 选项 我们首先需要通过原来的cmd来到Cmder的目录下&#xff0c;然后运行相关的指令&#xff1a; Cmder.exe /REGISTER…...