<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>IT技术文章分享 – 博客</title><link>https://sunqi.site/blog/</link><description>Recent content in 博客 on IT技术文章分享</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><atom:link href="https://sunqi.site/blog/index.xml" rel="self" type="application/rss+xml"/><item><title>使用Mock思想进行单元测试Python篇</title><link>https://sunqi.site/blog/use-mock-unittest-in-python/</link><pubDate>Sat, 03 Dec 2022 08:09:28 +0800</pubDate><guid>https://sunqi.site/blog/use-mock-unittest-in-python/</guid><description>
&lt;h2&gt;为什么使用Mock进行单元测试？&lt;span class="hx:absolute hx:-mt-20" id="为什么使用mock进行单元测试"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e4%bd%bf%e7%94%a8mock%e8%bf%9b%e8%a1%8c%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;从功能开发完成的定义来看，至少包括：代码本身、文档及单元测试。而往往在实际开发中，由于需求的不停的变化，导致文档及单元测试是开发过程中直接被忽略的内容。反观优秀的开源项目，在全球几千人合作开发的大项目中，仍然能保持代码的高质量，这其中文档和单元测试是必不可少的环节之一。&lt;/p&gt;
&lt;p&gt;不同于完整性测试或者冒烟测试，单元测试是为了证明你代码逻辑的正确性，所以必须由开发人员亲自完成，类似在证明“你爸是你爸”。单元测试能够屏蔽80%以上的低级错误，以及在协作开发过程中出现修改公共逻辑造成的潜在风险。一个伴随着单元测试出现的指标叫做覆盖率，即单元测试覆盖的代码行数，简单来说单元测试有没有覆盖代码执行过程中的每一行。每一个项目的代码覆盖率要求不同，需要寻找一个平衡点，过高的覆盖率会导致研发成本升高，过低的覆盖率又没有起到单元测试的目的。&lt;/p&gt;
&lt;p&gt;另外一个在单元测试经常出现的困扰点是环境依赖的问题，比如我们代码实现中需要调用外部某一系统的接口，那么我们在做单元测试时，是不是真的要搭建一套系统来满足我们测试的需要呢？显然是不可能的。这就和我们今天主题相关了，使用Mock思想进行单元测试。简而言之，不具备的条件使用Mock来进行模拟。还是接口调用的例子，我们在进行单元测试的时候，重点要测试时我们的逻辑，并不是那个接口的实现，我们关注的只是那个接口的正常或异常的返回，所以当我们的程序调用那个接口时，我们只需要Mock那个接口的返回即可，这样就可以专注于我们自身的逻辑测试了。&lt;/p&gt;
&lt;h2&gt;示例一：测试文件删除&lt;span class="hx:absolute hx:-mt-20" id="示例一测试文件删除"&gt;&lt;/span&gt;
&lt;a href="#%e7%a4%ba%e4%be%8b%e4%b8%80%e6%b5%8b%e8%af%95%e6%96%87%e4%bb%b6%e5%88%a0%e9%99%a4" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;本文中的一些示例来自：&lt;a href="https://www.toptal.com/python/an-introduction-to-mocking-in-python"target="_blank" rel="noopener"&gt;https://www.toptal.com/python/an-introduction-to-mocking-in-python&lt;/a&gt;
我们从例子来看一下如果利用Mock思想进行单元测试。先看看代码实现部分：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;按照传统的思想进行测试，一定会构建一个文件，然后调用函数进行删除后，判断文件是否存在。但是注意，这种测试方法其实不是在测试你的函数，而是在测试os.remove。这种思想并不是不可以，但是严重依赖于环境，如果我们现在测试对象是一个数据库或者上面提到的接口，我们构建单元测试的成本就非常高，甚至无法实现了。&lt;/p&gt;
&lt;p&gt;我们还是来看一下基于这种思想的测试用例实现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;实现在setUp中，随机新建了一个文件&lt;/li&gt;
&lt;li&gt;在test_rm中，调用我们的方法进行删除&lt;/li&gt;
&lt;li&gt;最终在assert中判断文件是否存在，如果存在，则抛出Failed to remove this file&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mymodule&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os.path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tempfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RmTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tmpfilepath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tempfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gettempdir&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tmp-testfile&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tmpfilepath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;wb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Delete me!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# remove the file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tmpfilepath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# test that it was actually removed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertFalse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tmpfilepath&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Failed to remove the file.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们使用Mock思想来重新分析一下：在代码中，我们实现其实是接受一个变量后，将变量传给os.remove，从Mock思想来看，我们只需要证明我们参数正确的传给了os.remove，并且os.remove是用我们这个参数执行的，这其实才是我们真正的逻辑，来看一下基于Mock是想的测试用例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用Mock时，我们不再需要依赖外部环境&lt;/li&gt;
&lt;li&gt;我们需要使用unittest中的mock.patch，即允许我们对某些模块的返回值进行模拟，比如这里我们对我们依赖的mymodule.os进行了Mock&lt;/li&gt;
&lt;li&gt;在测试用例中，当调用rm时，rm会使用我们Mock好的库进行调用，并不会触发真正的删除&lt;/li&gt;
&lt;li&gt;而在断言中，我们只需要证明os库被调用，且参数与我们传入一致即证明测试通过&lt;/li&gt;
&lt;li&gt;当然对于各种异常情况，我们也可以通过mock进行模拟，来捕获相关的异常是否符合我们的预期，在后面的示例中我们会看到&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mymodule&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;mock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RmTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.os&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# test that rm called os.remove with the right parameters&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_called_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这里需要注意的一点是我们mock的对象是mymodule.os并不是os，这与Python运行机制有关，在运行时mymodule会导入模块中的独立范围内，所以如果单纯mock os是无法实现上述测试的。&lt;/p&gt;
&lt;h2&gt;示例二：测试校验验证&lt;span class="hx:absolute hx:-mt-20" id="示例二测试校验验证"&gt;&lt;/span&gt;
&lt;a href="#%e7%a4%ba%e4%be%8b%e4%ba%8c%e6%b5%8b%e8%af%95%e6%a0%a1%e9%aa%8c%e9%aa%8c%e8%af%81" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在这个示例中，我们对源代码进行部分修改，增加对path存在的校验，我们在执行os.remove前，首先判断传入的参数是否为文件类型。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os.path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们直接使用Mock方式进行测试，测试用例增加的部分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;增加对mymodule.os.path进行Mock，Mock的目的是控制其返回值&lt;/li&gt;
&lt;li&gt;通过return_value来控制isfile的返回值为False
&lt;ul&gt;
&lt;li&gt;mock_path.isfile.return_value = False&lt;/li&gt;
&lt;li&gt;我们的测试的第一种情况是：当参数不是文件时，os.remove不会被调用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;再次通过return_value来控制isfile的返回值为True
&lt;ul&gt;
&lt;li&gt;mock_path.isfile.return_value = True&lt;/li&gt;
&lt;li&gt;我们测试的第二种情况是：当参数是文件时，os.remove会被调用同时使用参数&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mymodule&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;rm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;mock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RmTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.os.path&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.os&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# set up the mock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# test that the remove call was NOT called.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertFalse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;called&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Failed to not remove the file if not present.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# make the file &amp;#39;exist&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_called_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;示例三：对类进行测试&lt;span class="hx:absolute hx:-mt-20" id="示例三对类进行测试"&gt;&lt;/span&gt;
&lt;a href="#%e7%a4%ba%e4%be%8b%e4%b8%89%e5%af%b9%e7%b1%bb%e8%bf%9b%e8%a1%8c%e6%b5%8b%e8%af%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;首先我们将现有代码改造成类的方式，我们增加了RemovalService类，将原有方法变为类的方法&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os.path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RemovalService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;A service for removing objects from the filesystem.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们再次进行测试时，需要将类实例化后，在进行相关测试，这个测试与上面对单独函数的测试并没有太大差别&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mymodule&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RemovalService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;mock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RemovalServiceTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.os.path&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.os&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# instantiate our service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RemovalService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# set up the mock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# test that the remove call was NOT called.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertFalse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;called&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Failed to not remove the file if not present.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# make the file &amp;#39;exist&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_called_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们再次对代码进行改造，实现两个类。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我们保留了刚才构建了RemovalService，同时新增了一个UploadService使用RemovalService的rm方法&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os.path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RemovalService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;A service for removing objects from the filesystem.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UploadService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;removal_service&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;removal_service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;removal_service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;upload_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;removal_service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;根据刚刚我们强调的测试思想，此时再对UploadService进行测试时，我们无须再关注rm实现及测试，而是要关注upload_complete方法本身的测试，这里有两种Mock测试方法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对RemovalService.rm进行Mock&lt;/li&gt;
&lt;li&gt;在UploadService中完全Mock一个RemovalService&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Mock RemovalService.rm&lt;span class="hx:absolute hx:-mt-20" id="mock-removalservicerm"&gt;&lt;/span&gt;
&lt;a href="#mock-removalservicerm" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在这种测试方式下，测试方法类似我们之前的测试，只要保证我们的UploadService中是否被正确调用及参数传递是否正确即可。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mymodule&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RemovalService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UploadService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;mock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RemovalServiceTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.os.path&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.os&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# instantiate our service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RemovalService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# set up the mock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# test that the remove call was NOT called.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertFalse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;called&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Failed to not remove the file if not present.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# make the file &amp;#39;exist&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_called_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UploadServiceTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch.object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RemovalService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rm&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_upload_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_rm&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# build our dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;removal_service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RemovalService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UploadService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;removal_service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# call upload_complete, which should, in turn, call `rm`:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upload_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my uploaded file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# check that it called the rm method of any RemovalService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_rm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_called_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my uploaded file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# check that it called the rm method of _our_ removal_service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;removal_service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_called_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my uploaded file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Mock UploadService&lt;span class="hx:absolute hx:-mt-20" id="mock-uploadservice"&gt;&lt;/span&gt;
&lt;a href="#mock-uploadservice" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在本示例中，我们直接对UploadService进行自动Mock：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用mock.create_autospec(RemovalService)&lt;/li&gt;
&lt;li&gt;测试的case仍然是对调用参数及调用过程进行检验&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ch"&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mymodule&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RemovalService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UploadService&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;mock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RemovalServiceTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.os.path&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.os&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# instantiate our service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RemovalService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# set up the mock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# test that the remove call was NOT called.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertFalse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;called&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Failed to not remove the file if not present.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# make the file &amp;#39;exist&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_called_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;any path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UploadServiceTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_upload_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# build our dependencies&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_removal_service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_autospec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RemovalService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UploadService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mock_removal_service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# call upload_complete, which should, in turn, call `rm`:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;reference&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upload_complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my uploaded file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# test that it called the rm method&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_removal_service&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_called_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my uploaded file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;mock.create_autospec 方法为所提供的类创建一个功能等效的实例。如果在使用过程中，例如：传递参数错误发生，则会导致异常。这在代码重构时，会帮助我们检查到相关调整可能导致的异常。&lt;/p&gt;
&lt;h2&gt;Mock常用方法&lt;span class="hx:absolute hx:-mt-20" id="mock常用方法"&gt;&lt;/span&gt;
&lt;a href="#mock%e5%b8%b8%e7%94%a8%e6%96%b9%e6%b3%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;Mock Patch顺序&lt;span class="hx:absolute hx:-mt-20" id="mock-patch顺序"&gt;&lt;/span&gt;
&lt;a href="#mock-patch%e9%a1%ba%e5%ba%8f" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Mock的顺序与使用顺序相反，例如下面的例子中：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.sys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.os&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mymodule.os.path&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_os_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_sys&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;pass&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们看到在函数参数中，顺序与mock的顺序相反，这与Python自身机制有关&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;patch_sys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;patch_os&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;patch_os_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_something&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Mock和MagicMock&lt;span class="hx:absolute hx:-mt-20" id="mock和magicmock"&gt;&lt;/span&gt;
&lt;a href="#mock%e5%92%8cmagicmock" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Mock和MagicMock都可以模拟对象所有属性和方法，并且灵活设定存储和返回的内容。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;unittest.mock&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MagicMock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;thing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ProductionClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;thing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MagicMock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;return_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;thing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;value&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;thing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_called_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;value&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;使用mock side_effect模拟异常&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;side_effect&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="ne"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="ne"&gt;KeyError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;side_effect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;side_effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;side_effect&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;b&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;side_effect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Mock API请求&lt;span class="hx:absolute hx:-mt-20" id="mock-api请求"&gt;&lt;/span&gt;
&lt;a href="#mock-api%e8%af%b7%e6%b1%82" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;使用各种SDK调用不同平台的API接口，是基于云开发的时候常用的形态。此时，Mock测试对于这种形态的调用是绝佳的测试方案，特别是一些异常情况，非常容易模拟。
该示例是调用Facebook API发送消息的接口实例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在本示例中，我们封装了一个类&lt;/li&gt;
&lt;li&gt;post_message可以发送一条动态，我们需要对此进行测试&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;facebook&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleFacebook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;oauth_token&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;facebook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GraphAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;oauth_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Posts a message to the Facebook wall.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;me&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;feed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;来看一下这个测试用例：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;通过mock.patch.object对facbook.GraphAPI中的put_object进行Mock&lt;/li&gt;
&lt;li&gt;用simple_facebook构建一个Mock Token，用于类的初始化&lt;/li&gt;
&lt;li&gt;最后对Mock后进行调用及传参的校验&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;facebook&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;simple_facebook&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;mock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleFacebookTestCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@mock.patch.object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;facebook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GraphAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;put_object&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;autospec&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_post_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mock_put_object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;simple_facebook&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SimpleFacebook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;fake oauth token&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Hello World!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# verify&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;mock_put_object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_called_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Hello World!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;参考链接&lt;span class="hx:absolute hx:-mt-20" id="参考链接"&gt;&lt;/span&gt;
&lt;a href="#%e5%8f%82%e8%80%83%e9%93%be%e6%8e%a5" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Python unittest: &lt;a href="https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.assert_called_with"target="_blank" rel="noopener"&gt;https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.assert_called_with&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>从Notion迁移至语雀的图片问题</title><link>https://sunqi.site/blog/migrate-notion-to-yuque/</link><pubDate>Mon, 28 Nov 2022 08:40:27 +0800</pubDate><guid>https://sunqi.site/blog/migrate-notion-to-yuque/</guid><description>
&lt;h2&gt;为什么要迁移&lt;span class="hx:absolute hx:-mt-20" id="为什么要迁移"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e8%bf%81%e7%a7%bb" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Notion是一款非常优秀的笔记软件，在此之前我一直是印象笔记的拥趸，但是随着Notion这种全新概念的、符合程序员使用习惯的笔记软件出现后，完全撬动了印象笔记的市场。但是由于Notion服务器主要存储于国外，图片主要在AWS S3上，国内使用的速度上的用户体验较差。&lt;/p&gt;
&lt;p&gt;从2013年创业开始，一直在寻求一款团队内部的知识共享平台，从早期自建Mediawiki、Remine再到后来的Teakki，几经辗转，最后终于将全部的知识共享移动到语雀上，目前语雀的功能几乎满足了团队协作中的全部需求，从最基本的基于Markdown文档共享、编辑、历史版本，再到PlantUML时序图绘制能力，再到画板，完美覆盖了原有全部知识体系软件的功能。所以，为了统一知识共享软件，最后决定将自有的Notion文档全部切换至语雀上。&lt;/p&gt;
&lt;h2&gt;迁移遇到了哪些问题&lt;span class="hx:absolute hx:-mt-20" id="迁移遇到了哪些问题"&gt;&lt;/span&gt;
&lt;a href="#%e8%bf%81%e7%a7%bb%e9%81%87%e5%88%b0%e4%ba%86%e5%93%aa%e4%ba%9b%e9%97%ae%e9%a2%98" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Notion本身提供了较为强大的导出功能，可以在任意页面将全部子页面一次性全部导出成zip文件，包含了全部的图片，这个功能还是非常良心的，用户无须担心自己软件锁定。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-11-28-08-49-22.png" alt="2022-11-28-08-49-22" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;而语雀方面，也提供了较为完整的导入功能，不旦可以导入某一个文件，还支持zip包的整体导入，这样从Notion导出的包可以直接在语雀中导入，从而实现快速迁移。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-11-28-08-49-41.png" alt="2022-11-28-08-49-41" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;但美中不足的是，不知道是不是语雀的Bug，并不是所有的图片都被正确的导入。如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-11-28-08-49-58.png" alt="2022-11-28-08-49-58" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;如何解决这些问题&lt;span class="hx:absolute hx:-mt-20" id="如何解决这些问题"&gt;&lt;/span&gt;
&lt;a href="#%e5%a6%82%e4%bd%95%e8%a7%a3%e5%86%b3%e8%bf%99%e4%ba%9b%e9%97%ae%e9%a2%98" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;目前还没有从任何公开文档中找到相关问题的解释或解决方案，如果有读者了解到相关更便捷的方法，可以告知一下。&lt;/p&gt;
&lt;p&gt;目前在浏览器中的支持粘贴图片的编辑器，通常需要直接访问图片地址，也就是图片必须有公网直接访问的，所以我的基本思路为：&lt;/p&gt;
&lt;p&gt;首先，通过Notion导出功能，将文档导出为HTML格式包;&lt;/p&gt;
&lt;p&gt;第二，如果文档较多，且只有一部分为有图片的文档，可以先尝试用Markdown格式导入后，再单独修复有图片的文档；&lt;/p&gt;
&lt;p&gt;第三，在任意公有云的对象存储服务中，新建一个存储桶，权限为“公有读私有写”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-11-28-08-50-23.png" alt="2022-11-28-08-50-23" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;第四，将我们的文件目录直接上传&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-11-28-08-50-30.png" alt="2022-11-28-08-50-30" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;第五，上传完成后，回到文件列表，找到要导入文档的HTML文件的详情，复制链接后直接在浏览器打开&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-11-28-08-50-38.png" alt="2022-11-28-08-50-38" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;第六，此时你应该可以在浏览器中看到完整的文档，你需要做的需要全选后复制，直接粘贴到你语雀的文档后，图片就会正常的显示了。&lt;/p&gt;</description></item><item><title>Serverless奇亚币(Chia)挖矿与成本分析</title><link>https://sunqi.site/blog/linux%E5%A5%87%E4%BA%9A%E5%B8%81-chia-%E6%8C%96%E7%9F%BF%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/</link><pubDate>Fri, 29 Apr 2022 13:09:39 +0000</pubDate><guid>https://sunqi.site/blog/linux%E5%A5%87%E4%BA%9A%E5%B8%81-chia-%E6%8C%96%E7%9F%BF%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/</guid><description>
&lt;p&gt;奇亚币Chia是最近非常火的新币种，火爆到什么程度呢？火爆到大容量的硬盘都被卖光了。另外一点Chia的创始人就是BT的创始人，依靠的是硬盘容量挖矿，号称绿色挖矿。虽然一直对区块链行业不是很了解，但是仍然想凑个热闹，想尝试一下Serverless是不是能挖矿。&lt;/p&gt;
&lt;p&gt;目前挖矿这件事情在国内还是有所禁忌的，毕竟是有违低碳环保的宗旨，同时，也有人质疑虚拟货币是不是一场资本骗局。笔者对于这些问题并没有太多研究，本文主要从技术维度对Serverless挖矿的技术实现和成本进行分析。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;Chia架构分析&lt;span class="hx:absolute hx:-mt-20" id="chia架构分析"&gt;&lt;/span&gt;
&lt;a href="#chia%e6%9e%b6%e6%9e%84%e5%88%86%e6%9e%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;之前确实没有太关注过币圈，只是简单的了解区块链的基本概念，也不曾参与过挖矿，只是简单的知道比特币必须要依靠性能强大的GPU能力。而Chia币恰好相反，不必依赖昂贵的显卡能力，而单纯消耗的存储能力。公有云的存储，特别是对象存储一向具有很大的价格优势，所以这也为公有云资源进行挖矿提供了可能性。&lt;/p&gt;
&lt;p&gt;先来简单分析一下Chia的架构，通过分析可知对于竞猜过程，并不需要钱包参与，因为对于plot数据，创建时已经指定了两个公钥，也就是plot已经是专属“彩票”,兑奖时,直接打给的彩票的创建公钥对应的账户地址(待稍后测试确认)，对于Wallet并没有参与竞猜,所以不需要部署，对于farmer部分只需要部署，Full node，Farmer， Harvester三种，具体每个服务部署多少，取决于负载，也就是 plots的数量级。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-227.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;Chia云主机架构挖矿&lt;span class="hx:absolute hx:-mt-20" id="chia云主机架构挖矿"&gt;&lt;/span&gt;
&lt;a href="#chia%e4%ba%91%e4%b8%bb%e6%9c%ba%e6%9e%b6%e6%9e%84%e6%8c%96%e7%9f%bf" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;部署架构&lt;span class="hx:absolute hx:-mt-20" id="部署架构"&gt;&lt;/span&gt;
&lt;a href="#%e9%83%a8%e7%bd%b2%e6%9e%b6%e6%9e%84" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;之前看到过利用公有云进行挖矿的案例，甚至AWS官方竟然推出了标准化文档。这些解决方案中主要利用的是云主机加上本地的NVMe存储实现高性能挖矿。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-232.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;在这个方案中，临时空间使用的是NVMe本地盘，而最终的持久化空间则是利用对象存储，但是由于对象存储的访问接口限制，需要利用用户态模块将对象存储以文件目录挂载给各个节点，用于最终数据的写入。但是在实际测试中，用户态的模块其实并不稳定，经常出现Input/Output Error的情况，经过与云商工单系统确认，该问题属于硬伤，只能再增加一层缓存层（比如NAS），利用对象存储的上传工具上传。&lt;/p&gt;
&lt;h3&gt;时间分析&lt;span class="hx:absolute hx:-mt-20" id="时间分析"&gt;&lt;/span&gt;
&lt;a href="#%e6%97%b6%e9%97%b4%e5%88%86%e6%9e%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;分享一下实际的测试结果，我们云主机的规格4核32G，本地NVMe磁盘894G，最大的IOPS可以达到250000。为了测试准确性，我们使用k=32，其他为默认参数进行验证。总体生成耗时8.8小时，拷贝至最终存储11.6分钟，转存至对象存储大约耗时14分钟，总体耗时为9小时12分钟。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;Approximate working space used (without final file): 269.315 GiB
Final File size: 101.340 GiB
Total time = 31748.852 seconds. CPU (117.300%) Wed May 12 14:27:27 2021
Copied final file from &amp;#34;/plots-tmp/plot-k32-2021-05-12-05-38-79875f7a80d07fb658c68fd441e3c3befec4a30e2c6c9c21ee79fe815d0c4e36.plot.2.tmp&amp;#34; to &amp;#34;/plots-final/plot-k32-2021-05-12-05-38-79875f7a80d07fb658c68fd441e3c3befec4a30e2c6c9c21ee79fe815d0c4e36.plot.2.tmp&amp;#34;
Copy time = 692.271 seconds. CPU (27.600%) Wed May 12 14:39:00 2021&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;资源消耗&lt;span class="hx:absolute hx:-mt-20" id="资源消耗"&gt;&lt;/span&gt;
&lt;a href="#%e8%b5%84%e6%ba%90%e6%b6%88%e8%80%97" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;我们看一下监控数据，在单任务并发的情况下，我们可以看到，远远没有达到NVMe的极限速度。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-228.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;CPU利用率方面基本没有超过25%，而网络利用率我们看到，在挖矿过程中并没有太多的网络消耗。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-231.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-230.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;资源成本&lt;span class="hx:absolute hx:-mt-20" id="资源成本"&gt;&lt;/span&gt;
&lt;a href="#%e8%b5%84%e6%ba%90%e6%88%90%e6%9c%ac" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;测试过程中使用的是按量计费，Plots过程中主要涉及的云资源包括主机和云盘，费用分别为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;云主机 0.44 元/小时（账单内是将存储和计算资源分别计算，购买时时在一起）&lt;/li&gt;
&lt;li&gt;云硬盘 2.92 元/小时&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以本次挖矿过程中产生的成本约为31元。对象存储1TB保存1个月数据的时间约为111元。&lt;/p&gt;
&lt;h2&gt;Chia Serverless架构挖矿&lt;span class="hx:absolute hx:-mt-20" id="chia-serverless架构挖矿"&gt;&lt;/span&gt;
&lt;a href="#chia-serverless%e6%9e%b6%e6%9e%84%e6%8c%96%e7%9f%bf" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;部署架构&lt;span class="hx:absolute hx:-mt-20" id="部署架构-1"&gt;&lt;/span&gt;
&lt;a href="#%e9%83%a8%e7%bd%b2%e6%9e%b6%e6%9e%84-1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;公有云目前都提供基于容器的实例，这种实例是按照CPU和内存的使用时间来计费，也就是如果你的CPU没有使用，则无须付费。但是目前公有云中无法将NVMe类型的磁盘直接给容器使用，我们只能将性能最佳的云盘挂载给容器的方式。另外在测试过程中，如果直接使用对象存储作为持久化存储，最终拷贝过程会出现input/output error的异常，所以在测试过程中仍然借用NAS存储作为临时性最终存储。以下为部署架构：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-233.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;我们将挖矿的所有节点运行在Kubernetes（Serverless）中，而Full Node放在一台低配置云主机（云主机和OSS通过内部网络通讯不收费）甚至本地环境，通过文件方式挂载使用。&lt;/p&gt;
&lt;p&gt;本次选择的临时存储为最高性能的云硬盘，IOPS最高可达14300，缓存存储选择了普通的云盘（也可以使用NAS，成本接近），最终的数据仍然存放在对象存储。&lt;/p&gt;
&lt;h3&gt;时间分析&lt;span class="hx:absolute hx:-mt-20" id="时间分析-1"&gt;&lt;/span&gt;
&lt;a href="#%e6%97%b6%e9%97%b4%e5%88%86%e6%9e%90-1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;容器最大可使用的规格诶4C8G，云盘最大IOPS为14300。我们仍然使用k=32，其他为默认参数进行验证。总体生成耗时10.6小时，拷贝至最终存储14.5分钟，转存至对象存储大约耗时14分钟，总体耗时为11小时6分钟左右。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;Approximate working space used (without final file): 269.379 GiB
Final File size: 101.374 GiB
Total time = 38470.562 seconds. CPU (110.440%) Thu May 13 14:06:05 2021
Copied final file from &amp;#34;/plots-tmp/plot-k32-2021-05-13-03-24-598167f5cc365884a79d55b3c0a68d5339f223f7708a5fec1108caf2e42d3f55.plot.2.tmp&amp;#34; to &amp;#34;/plots-final/plot-k32-2021-05-13-03-24-598167f5cc365884a79d55b3c0a68d5339f223f7708a5fec1108caf2e42d3f55.plot.2.tmp&amp;#34;
Copy time = 870.129 seconds. CPU (18.280%) Thu May 13 14:20:36 2021&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;资源消耗&lt;span class="hx:absolute hx:-mt-20" id="资源消耗-1"&gt;&lt;/span&gt;
&lt;a href="#%e8%b5%84%e6%ba%90%e6%b6%88%e8%80%97-1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;从磁盘性能损耗来看，也仍然没有达到云盘的极限性能。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-235.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;内存利用率上，由于最高上限的限制，使用率应该不会超过4G，CPU利用率相对来说比较稳定，并没有超过200%。&lt;/p&gt;
&lt;p&gt;11点监控
&lt;img src="https://sunqi.site/images/pasted-236.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;15点监控
&lt;img src="https://sunqi.site/images/pasted-237.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;21点监控
&lt;img src="https://sunqi.site/images/pasted-238.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;资源成本&lt;span class="hx:absolute hx:-mt-20" id="资源成本-1"&gt;&lt;/span&gt;
&lt;a href="#%e8%b5%84%e6%ba%90%e6%88%90%e6%9c%ac-1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;容器实例：0.52 元/小时&lt;/li&gt;
&lt;li&gt;云硬盘：0.6元/小时&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以本次挖矿过程中的成本约为12.3元左右。&lt;/p&gt;
&lt;h2&gt;总结&lt;span class="hx:absolute hx:-mt-20" id="总结"&gt;&lt;/span&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;从监控数据可以看到，Chia币在挖矿中虽然非常依赖于硬盘，但是单任务运行时并没有完全把硬盘性能榨干（曾经调试过Thread参数但是结果差不多，如果有其他参数请告知），只能通过提高并发性来压榨硬盘。对于Serverless，根据监控可以适当降低磁盘规格来达到进一步降低成本的目的。同时，对于CPU利用率和内存的利用也不会占用太高，2核4G基本可以满足需求（有内存不足的风险，内存默认上限为3389，可以限制）。&lt;/p&gt;
&lt;p&gt;通过以上的实验数据可以看到，在公有云上挖矿有不同的组合方案，
每一种组合的成本是完全不同的。如果以单一Plots比较，Serverless方式确实有比较明显的优势。但是，由于NVMe卓越性能可以通过提高并发方式实现成本最优。根据下表中临时空间占用，在刚刚规格配置的云主机上可以实现并发3个同时挖矿的效果。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-234.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;同时Serverless在扩展的灵活性上要优于云主机的方案，通过适当的自动化手段，可以做到成本最优的效果。以上单纯的是从技术上对云主机挖矿的可行性进行分析，有兴趣的朋友可以入群讨论。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-239.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;如果加群失败，请添加个人微信号入群&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-240.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;</description></item><item><title>Restic原理分析</title><link>https://sunqi.site/blog/restic-analysis/</link><pubDate>Fri, 22 Apr 2022 18:23:33 +0800</pubDate><guid>https://sunqi.site/blog/restic-analysis/</guid><description>
&lt;h2&gt;创建存储库&lt;span class="hx:absolute hx:-mt-20" id="创建存储库"&gt;&lt;/span&gt;
&lt;a href="#%e5%88%9b%e5%bb%ba%e5%ad%98%e5%82%a8%e5%ba%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;初始化存储库（本地）&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;restic init --repo ./restic_repo&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;回车后，需要输入密码&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;enter password for new repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;enter password again&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;created restic repository 56f6f17938 at ./restic_repo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;Please note that knowledge of your password is required to access&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;the repository. Losing your password means that your data is&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;irrecoverably lost.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;查看生成的目录结构&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;├── config&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;├── data&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;│   ├── 00&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;│   ├── 01&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;│   ├── 02&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;...&lt;/span&gt;&lt;span class="l"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;│   ├── fd&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;│   ├── fe&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;│   └── ff&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;├── index&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;├── keys&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;│   └── a1147718095f6ecc356caaae676932f78159a8332bf6ea36aed5ff4763205042&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;├── locks&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;└── snapshots&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;261&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;directories, 2 files&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;data目录结构&lt;span class="hx:absolute hx:-mt-20" id="data目录结构"&gt;&lt;/span&gt;
&lt;a href="#data%e7%9b%ae%e5%bd%95%e7%bb%93%e6%9e%84" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;此时生成了restic存储库的结构，从目录结构上可以很清楚的和设计原理对应。在data目录下，根据十六进制从00一直生成到ff个目录，用于blob的存储。&lt;/p&gt;
&lt;h3&gt;config文件&lt;span class="hx:absolute hx:-mt-20" id="config文件"&gt;&lt;/span&gt;
&lt;a href="#config%e6%96%87%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;由于config采用加密方式存储，无法直接查看，需要使用restic命令查看具体内容。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;restic cat -r restic_repo config&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;输出结果为&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;repository 56f6f179 opened successfully, password is correct&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;version&amp;#34;: &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;id&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;56f6f17938d86e6a4718d8d5a31ea6503a8bf24606e022c4ac2c2aae75ed52e2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;chunker_polynomial&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;25fe60909e1433&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;根据restic设计原理，初始化后版本为1，id为存储库的唯一ID，&lt;code&gt;chunker_polynomial&lt;/code&gt;字段包含一个参数，用于将大文件分割成更小的块。&lt;/p&gt;
&lt;h3&gt;keys目录&lt;span class="hx:absolute hx:-mt-20" id="keys目录"&gt;&lt;/span&gt;
&lt;a href="#keys%e7%9b%ae%e5%bd%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;而文件部分，在初始化的结构上只存在keys下的文件和config两个文件。其中config文件为加密存储，而keys文件是明文存储，可以直接查看。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;python -mjson.tool restic_repo/keys/a1147718095&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;格式化输出内容为：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;created&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2022-03-23T10:31:42.819697576+08:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;username&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;hostname&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ray-dev&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;kdf&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;scrypt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;N&amp;#34;: &lt;/span&gt;&lt;span class="m"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;r&amp;#34;: &lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;p&amp;#34;: &lt;/span&gt;&lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;salt&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;aziDQSzuuAet1SPMaEcgSLphDb9UyLZ8D/mry7QBMbnL60LTU/sjwXXEctGQNIATe6XeAy+Lgojcej7CV959Gg==&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;data&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;YCG8jYsnxaj2YyF5jc82q7mWPF6YsNNbhISXrsZGab7bsMlFe/dBPbnCUzyigac73cMFdirzrb2n9was+0wcGiTc3TIdQ9op5sbgaqAaCRHzR28zDjq/6b8PCl39rDm0fhwSPT+TrvJ8d9EX7FcnxIltJ2Xio4dsnHmr+2KxIyXhAyPaad4KEDKiTZEhtdw+dorofFB1aDKiTYBysRW1RA==&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;当打开restic存储库时，会提示用户输入存储库密码。然后将其与 &lt;code&gt;scrypt&lt;/code&gt;、密钥派生函数 (KDF) 和提供的参数（&lt;code&gt;N&lt;/code&gt;、&lt;code&gt;r&lt;/code&gt;、&lt;code&gt;p&lt;/code&gt; 和&lt;code&gt;salt&lt;/code&gt;）一起派生64个密钥字节。前32个字节用于加密密钥（用于 AES-256），最后32个字节用作消息验证密钥（用于 Poly1305-AES）。这最后32个字节被分成一个16字节的AES密钥“k”，然后是16个字节的密钥“r”。然后将密钥&lt;code&gt;r&lt;/code&gt;屏蔽，与 Poly1305 一起使用（有关详细信息，请参阅论文）。&lt;/p&gt;
&lt;p&gt;这些消息身份验证密钥（&lt;code&gt;k&lt;/code&gt; 和 &lt;code&gt;r&lt;/code&gt;）用于计算MAC，使用 JSON 中 &lt;code&gt;data&lt;/code&gt;字段包含的字节（在删除 Base64 编码并且不包括最后32个字节之后）。如果密码不正确或密钥文件被篡改，则计算出的 MAC将与数据的最后 16 个字节不匹配，restic 会报错退出。否则，将使用从scrypt派生的加密密钥解密数据。这将生成一个JSON，其中包含此存储库的主加密和消息鉴权密钥（以 Base64 编码）。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;restic cat masterkey -r restic_repo&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;查看信息&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;repository 56f6f179 opened successfully, password is correct&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;mac&amp;#34;: &lt;/span&gt;{&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;k&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DLMpuMFKlvonh3rpul5yMQ==&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;r&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DU06C/h5Jg+UAzoLuBsRDA==&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;encrypt&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;H6tU0t5Sbo5hjux3kj9BapWtEqIo63UyyBhcbwBnP+M=&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;存储库中的所有数据都使用这些主密钥进行加密和验证。 对于加密，使用计数器模式下的 AES-256 算法。 对于消息认证，如上所述使用 Poly1305-AES。&lt;/p&gt;
&lt;p&gt;存储库可以有多个不同的密码，每个密码都有一个密钥文件。 这样，无需重新加密所有数据即可更改密码。&lt;/p&gt;
&lt;h2&gt;小文件备份&lt;span class="hx:absolute hx:-mt-20" id="小文件备份"&gt;&lt;/span&gt;
&lt;a href="#%e5%b0%8f%e6%96%87%e4%bb%b6%e5%a4%87%e4%bb%bd" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;为了测试方便，我们创建一个文本类型文件，该文件只包含一个字符，例如0。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;cat demo.txt&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;内容如下：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;查看文件的大小：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;stat demo.txt&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;输出为：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;File&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;‘demo.txt’&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;Size: 2 Blocks: 8 IO Block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;regular file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Device: 803h/2051d Inode: 878940853 Links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;( 0/ root)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Access&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ld"&gt;2022-03-23 14:39:15.857514408 +0800&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Modify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ld"&gt;2022-03-23 14:39:13.157444776 +0800&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Change&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ld"&gt;2022-03-23 14:39:13.157444776 +0800&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;Birth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;此时我们的目录结构为&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;source_dir&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;demo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;directories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们使用restic进行备份&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;restic -r restic_repo --verbose backup source_dir/demo.txt&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;输入正确的密码后备份成功&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;repository 56f6f179 opened successfully, password is correct&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;lock repository&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;load index files&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kc"&gt;no&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;parent snapshot found, will read all files&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;start scan on [source_dir/demo.txt]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;start backup on [source_dir/demo.txt]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;scan finished in 0.204s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;files, 2 B&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new, 0 changed, 0 unmodified&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Dirs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new, 0 changed, 0 unmodified&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Data Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Tree Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Added to the repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;750&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;B&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;processed 1 files, 2 B in 0:00&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;snapshot 6ca52f2f saved&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;此时，我们回到restic存储库中来检查一下文件增加的情况，为了方便查看，我用git将初始化的信息进行了commit，这样就能看到本次备份后的文件变化情况。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;23&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;data/62/62f89d280ebdf875ef6f0d12e4d90d0e807a48506e60064ecb4d58a2c733177a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;23&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;data/b3/b3346e2e87eee7a8d1a17052ce1d1d09784c072b949205f3c632dd503b867096&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;549&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;index/701f1ff24a647a51ebfadfaf973721075b62819408f3ac647e7a757e147de059&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;251&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;snapshots/6ca52f2f0978fbcfa16fdade23b2f20ba4f5a4a71882bb63cc0d4bec2970161a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们来分析一下文件的变化情况，我们发现在data目录下增加了两个文件，而index和snapshots下分别增加了一个文件。&lt;/p&gt;
&lt;h3&gt;包（Packs）&lt;span class="hx:absolute hx:-mt-20" id="包packs"&gt;&lt;/span&gt;
&lt;a href="#%e5%8c%85packs" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;很明显restic在存储文件时是根据文件名称前两位决定将文件存放在哪个目录下，比如62f89d280ebdf875ef6f0d12e4d90d0e807a48506e60064ecb4d58a2c733177a就存放在data/62下面。&lt;/p&gt;
&lt;p&gt;在data目录下增加的两个文件就是restic的包，我们通过list命令可以查询存储库中包的列表&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;restic&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;restic_repo&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="n"&gt;packs&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;返回所有包的信息，与目录中的内容对应&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="n"&gt;f89d280ebdf875ef6f0d12e4d90d0e807a48506e60064ecb4d58a2c733177a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;b3346e2e87eee7a8d1a17052ce1d1d09784c072b949205f3c632dd503b867096&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;虽然在cat中提供了查看pack内容，但是由于加密的原因，无法查看其中的内容，与直接执行cat返回内容一致&lt;/p&gt;
&lt;h3&gt;索引&lt;span class="hx:absolute hx:-mt-20" id="索引"&gt;&lt;/span&gt;
&lt;a href="#%e7%b4%a2%e5%bc%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;查看index情况，和snapshots一样使用目录下的id进行查询&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;restic&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;restic_repo&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="mi"&gt;701&lt;/span&gt;&lt;span class="n"&gt;f1ff24a647a51ebfadfaf973721075b62819408f3ac647e7a757e147de059&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mjson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;通过返回数据，我们可以看到packs与blobs的对应关系，通过返回，我们可以得知pack 62f89d280ebdf875ef6f0d12e4d90d0e807a48506e60064ecb4d58a2c733177a中包含的是实际数据，而另外一个pack包含的则是tree，即目录结构，虽然原理文档对于offset和length的计算有介绍，但是单从描述的方式上还不足以理解，需要对源码进行分析。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;packs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;62f89d280ebdf875ef6f0d12e4d90d0e807a48506e60064ecb4d58a2c733177a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;blobs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;b3346e2e87eee7a8d1a17052ce1d1d09784c072b949205f3c632dd503b867096&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;blobs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;5dbab6dedd6e621d742e9e2327e8e8da6198ed188321d68b6cc5ec1dc9ebafc2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tree&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;407&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;e8a97749d4bdd53506bd5979dec630d8606cc98e46ed6c07432242592382b322&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tree&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;405&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Blob&lt;span class="hx:absolute hx:-mt-20" id="blob"&gt;&lt;/span&gt;
&lt;a href="#blob" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;我们进一步通过cat blob命令进行查询，我们先来查看数据类型&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;restic&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;restic_repo&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="n"&gt;a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;返回的结果就是我们的实际内容&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们再来查看tree类型&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;restic&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;restic_repo&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;dbab6dedd6e621d742e9e2327e8e8da6198ed188321d68b6cc5ec1dc9ebafc2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mjson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;此时，返回的是我们的第一级目录&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;nodes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;source_dir&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;dir&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2147484141&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mtime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2022-03-23T14:39:13.157444776+08:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;atime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2022-03-23T14:39:13.157444776+08:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ctime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2022-03-23T14:39:13.157444776+08:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;gid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;group&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;inode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;878936120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;device_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2051&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;subtree&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;e8a97749d4bdd53506bd5979dec630d8606cc98e46ed6c07432242592382b322&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这里包含subtree，就是我们的子目录，我们进一步查询&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;restic&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;restic_repo&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="n"&gt;e8a97749d4bdd53506bd5979dec630d8606cc98e46ed6c07432242592382b322&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mjson&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tool&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;此时content的内容指向了数据blob 9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa，即我们的文件内容&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;nodes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;demo.txt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;420&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mtime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2022-03-23T14:39:13.157444776+08:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;atime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2022-03-23T14:39:13.157444776+08:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ctime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2022-03-23T14:39:13.157444776+08:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;gid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;group&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;inode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;878940853&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;device_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2051&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;links&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;快照&lt;span class="hx:absolute hx:-mt-20" id="快照"&gt;&lt;/span&gt;
&lt;a href="#%e5%bf%ab%e7%85%a7" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;再来查看一下snapshots的情况，直接使用snapshots下面的6ca52f2f0978fbcfa16fdade23b2f20ba4f5a4a71882bb63cc0d4bec2970161a进行查询&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;restic&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;restic_repo&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;ca52f2f0978fbcfa16fdade23b2f20ba4f5a4a71882bb63cc0d4bec2970161a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;从返回的数据看，snapshots指向了tree，而tree实质上就是最顶层的目录blob&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2022-03-23T14:44:52.064414778+08:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;tree&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;5dbab6dedd6e621d742e9e2327e8e8da6198ed188321d68b6cc5ec1dc9ebafc2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;paths&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;/root/workspace/restic_test/source_dir/demo.txt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;hostname&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ray-dev&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;username&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;从以上一个备份过程上，我们不难理解restic是如何进行的备份，那么我们再来测试一下，当达到restic对blob文件进行切割后，如何进行的存储。&lt;/p&gt;
&lt;h2&gt;大于8MB文件备份&lt;span class="hx:absolute hx:-mt-20" id="大于8mb文件备份"&gt;&lt;/span&gt;
&lt;a href="#%e5%a4%a7%e4%ba%8e8mb%e6%96%87%e4%bb%b6%e5%a4%87%e4%bb%bd" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;根据原理文档描述，restic针对512 KB以下文件不切分，对于512KB到8MB的文件会保留原有大小，只有大于8MB才会切分，所以我们构建一个10MB文件，为了便于后续观察，我们按照递增方式从1向上增加，每一行为一个数字，即&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;101&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;102&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;使用如下命令生成&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mf"&gt;1..1450000&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="n"&gt;do&lt;/span&gt; &lt;span class="n"&gt;echo&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="n"&gt;mb_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;直接对文件进行备份&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;restic&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;restic_repo&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt; &lt;span class="n"&gt;backup&lt;/span&gt; &lt;span class="n"&gt;source_dir&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="n"&gt;mb_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;输出详情为&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;repository&lt;/span&gt; &lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="n"&gt;f6f179&lt;/span&gt; &lt;span class="n"&gt;opened&lt;/span&gt; &lt;span class="n"&gt;successfully&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;correct&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;load&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="nb"&gt;all&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="n"&gt;scan&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;source_dir&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="n"&gt;mb_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="n"&gt;backup&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;source_dir&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="n"&gt;mb_file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;scan&lt;/span&gt; &lt;span class="n"&gt;finished&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="mf"&gt;0.206&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;10.003&lt;/span&gt; &lt;span class="n"&gt;MiB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;unmodified&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Dirs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;unmodified&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="n"&gt;Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Tree&lt;/span&gt; &lt;span class="n"&gt;Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Added&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;10.004&lt;/span&gt; &lt;span class="n"&gt;MiB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;processed&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;10.003&lt;/span&gt; &lt;span class="n"&gt;MiB&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;snapshot&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="n"&gt;b965346&lt;/span&gt; &lt;span class="n"&gt;saved&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;通过输出可以看到：restic发现了一个新的文件，同时生成了6个新的数据Blobs，其中Tree Blobs为2个。通过观察restic repo内的文件变化情况，没有文件被修改，新增了6个文件（无修改文件）：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mf"&gt;1.3&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;****&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;347&lt;/span&gt;&lt;span class="n"&gt;f0dd64113d6fd4cc47dc085405fbff605e942a7a18f92c77aab0bd480e069&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ab&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ab69b131e8262286a726f65b12462657259961a58ca7adbac480321e9a091565&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;be1e14a1ec2b41ea3e7d02ab985ff99e764a8f5de6c13aaac6ba9180f5ce81cd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mf"&gt;4.2&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;be4b589501ccd0c6da460659faf5db477b541e6fb46bf5909af5927b03f19ca8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mf"&gt;1.3&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;d40932add8acb5cfdd1deae551d59a85deab190b55a578243860fbf71aeb08d0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="mi"&gt;255&lt;/span&gt; &lt;span class="n"&gt;snapshots&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="n"&gt;b9653468c30e7943f5d068c2a0210069eab03ca56d8b787c2883be06be2b116&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;从输出的结果上来看，本次生成的文件中snapshots文件与第一次备份一致，因为仅仅指向blob，所以文件大小没有显著增加，而index文件则比之前大了一倍，从549直接增加到1.3K。&lt;/p&gt;
&lt;h3&gt;索引&lt;span class="hx:absolute hx:-mt-20" id="索引-1"&gt;&lt;/span&gt;
&lt;a href="#%e7%b4%a2%e5%bc%95-1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;我们仍然通过命令，查看一下索引内的变化情况&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;restic&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;restic_repo&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;d40932add8acb5cfdd1deae551d59a85deab190b55a578243860fbf71aeb08d0&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;jq&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;从生成的结果来看，与备份的标准输出相对应，index文件中总共包含了6个Blobs，其中四个为数据型，两个为目录型，我们直接对数据型blobs进行分析，看看restic是如何对文件进行的拆分。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;packs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;be1e14a1ec2b41ea3e7d02ab985ff99e764a8f5de6c13aaac6ba9180f5ce81cd&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;blobs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;df59490249716895dd8b67dfe4af369f21dde033b51489ab4ccb3af5d064e65f&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;708813&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;6e837f4efe3effa79c1db760a83dc4a4ed9e8feb0a03d0c3358612248fd6bfd6&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;708813&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2344049&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ab69b131e8262286a726f65b12462657259961a58ca7adbac480321e9a091565&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;blobs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;7d2fc5c4b2b7d183c94460eb6418a4b3a8898d769951281708cf7cf430f99dcd&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1482607&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;d20d76c1a8e128707d094207f63d3e54bdd34c2f7dbb9bef19bfba9b408232cc&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1482607&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1616191&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;be4b589501ccd0c6da460659faf5db477b541e6fb46bf5909af5927b03f19ca8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;blobs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2df049910612d58b07727115601f8a2bf6412ebc036d087a233d26d677290415&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1837173&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2500255&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;5e137b93f71fca42a5710a5b7e16c75d75c0c4b63b8bc8aab8f334a34c65b4ae&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;data&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1837173&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;347f0dd64113d6fd4cc47dc085405fbff605e942a7a18f92c77aab0bd480e069&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;blobs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;005bdcba00bd7ad8f1aa1f7db1aaa8b8539f1839061c40709a519de1b25e4b89&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tree&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;752&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;067835a81002764d000d0e2dd36ea942d9ef176586d80a03878c373777608958&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;tree&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;offset&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;752&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;length&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Blob&lt;span class="hx:absolute hx:-mt-20" id="blob-1"&gt;&lt;/span&gt;
&lt;a href="#blob-1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;我们分别对每个Blob进行cat查询，可以清楚看到每一个文件切分的位置，这里不再赘述，这里只列出切割的位置(根据上面输出索引的顺序)，及Blob对应的id。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Blob ID&lt;/th&gt;
&lt;th&gt;文件起始行&lt;/th&gt;
&lt;th&gt;结尾&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;df59490249716895dd8b67dfe4af369f21dde033b51489ab4ccb3af5d064e65f&lt;/td&gt;
&lt;td&gt;824978&lt;/td&gt;
&lt;td&gt;92#&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6e837f4efe3effa79c1db760a83dc4a4ed9e8feb0a03d0c3358612248fd6bfd6&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;35073#&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7d2fc5c4b2b7d183c94460eb6418a4b3a8898d769951281708cf7cf430f99dcd&lt;/td&gt;
&lt;td&gt;181&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;613182&lt;/td&gt;
&lt;td&gt;824977#&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;d20d76c1a8e128707d094207f63d3e54bdd34c2f7dbb9bef19bfba9b408232cc&lt;/td&gt;
&lt;td&gt;6232&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;926233&lt;/td&gt;
&lt;td&gt;1137472&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1#&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2df049910612d58b07727115601f8a2bf6412ebc036d087a233d26d677290415&lt;/td&gt;
&lt;td&gt;137473&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1137474&lt;/td&gt;
&lt;td&gt;1450000&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5e137b93f71fca42a5710a5b7e16c75d75c0c4b63b8bc8aab8f334a34c65b4ae&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;350733&lt;/td&gt;
&lt;td&gt;613180&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;613#&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;从输出结果来看，我们不难看到restic切割的痕迹和每个Blob的关系，那么restic又是如何管理其中的顺序呢？答案就是最后subtree的contents字段。&lt;/p&gt;
&lt;p&gt;最后，我们来通过查看子树的信息来观察contents的排列。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;restic&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;restic_repo&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="n"&gt;blob&lt;/span&gt; &lt;span class="mi"&gt;005&lt;/span&gt;&lt;span class="n"&gt;bdcba00bd7ad8f1aa1f7db1aaa8b8539f1839061c40709a519de1b25e4b89&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;jq&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;通过观察contents的排列顺序恰好是我们上述表格内正确的顺序，这样在还原备份时，restic就可以对文件进行重组。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;nodes&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;10mb_file.txt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;420&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;mtime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2022-03-24T07:00:32.751188252+08:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;atime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2022-03-24T07:00:32.751188252+08:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;ctime&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2022-03-24T07:01:26.38858041+08:00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;uid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;gid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;group&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;root&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;inode&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1377358062&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;device_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2051&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;size&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10488896&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;links&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;content&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;6e837f4efe3effa79c1db760a83dc4a4ed9e8feb0a03d0c3358612248fd6bfd6&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;5e137b93f71fca42a5710a5b7e16c75d75c0c4b63b8bc8aab8f334a34c65b4ae&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;7d2fc5c4b2b7d183c94460eb6418a4b3a8898d769951281708cf7cf430f99dcd&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;df59490249716895dd8b67dfe4af369f21dde033b51489ab4ccb3af5d064e65f&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;d20d76c1a8e128707d094207f63d3e54bdd34c2f7dbb9bef19bfba9b408232cc&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;2df049910612d58b07727115601f8a2bf6412ebc036d087a233d26d677290415&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;小文件修改后备份&lt;span class="hx:absolute hx:-mt-20" id="小文件修改后备份"&gt;&lt;/span&gt;
&lt;a href="#%e5%b0%8f%e6%96%87%e4%bb%b6%e4%bf%ae%e6%94%b9%e5%90%8e%e5%a4%87%e4%bb%bd" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在本次备份前，先来尝试修改小文件，我们将原有小文件的内容从0变为1，进行备份。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;restic -r restic_repo --verbose backup source_dir/demo.txt&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;此时restic发现有一个文件进行了改变，增加了一个Data Blob，增加了746字节&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;repository 56f6f179 opened successfully, password is correct&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;lock repository&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;load index files&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;using parent snapshot 6ca52f2f&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;start scan on [source_dir/demo.txt]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;start backup on [source_dir/demo.txt]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;scan finished in 0.219s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;files, 2 B&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new, 1 changed, 0 unmodified&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Dirs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new, 1 changed, 0 unmodified&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Data Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Tree Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Added to the repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;746&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;B&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;processed 1 files, 2 B in 0:00&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;snapshot 4e2aa2b0 saved&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们看一下存储库内的实际变化情况，虽然只修改了一个字符，但是restic存储库增加了1901个字节。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;107&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;data/30/30b15f86b4797676aa3b15b7b39094887fa5ebc23faeb0005a1de3db3cb5a99e&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;918&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;data/b8/b83c8903968a1754a4b935937c80588ca6415bc765b3ac67da3c1b5d99181545&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;549&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;index/35a11e5dfa5a4dd5a94ef7865993161e637c6e594b945b91a819c2cbbad5437f&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;327&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;snapshots/4e2aa2b01e6c253bff413e80c4838338342eb3cdf21adaee6399e0d196efef24&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;因为存储库的变化情况与上述相似，这里不再赘述。&lt;/p&gt;
&lt;h2&gt;大文件修改后备份&lt;span class="hx:absolute hx:-mt-20" id="大文件修改后备份"&gt;&lt;/span&gt;
&lt;a href="#%e5%a4%a7%e6%96%87%e4%bb%b6%e4%bf%ae%e6%94%b9%e5%90%8e%e5%a4%87%e4%bb%bd" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我们接下来看看如果是大文件变化，restic的同步情况，我们将我们构造的10MB文件的第一行进行从1修改为a。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;restic -r restic_repo --verbose backup source_dir/10mb_file.txt&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;输出内容，增加了一个1个新的数据blob，增加容量为2.236MB。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;repository 56f6f179 opened successfully, password is correct&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;lock repository&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;load index files&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;using parent snapshot 3568a27c&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;start scan on [source_dir/10mb_file.txt]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;start backup on [source_dir/10mb_file.txt]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;scan finished in 0.208s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;files, 10.003 MiB&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new, 1 changed, 0 unmodified&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Dirs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new, 1 changed, 0 unmodified&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Data Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Tree Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Added to the repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2.236&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;MiB&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;processed 1 files, 10.003 MiB in 0:00&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;snapshot 7505e3f0 saved&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;看一下存储库的实际变化情况，增加的总大小大约为2.3MB。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;2.&lt;/span&gt;&lt;span class="l"&gt;3M data/b0/b0b147233fd6514fa14229231aa346bb321698e091fd5d2ca2aeb39590d96180&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;1.&lt;/span&gt;&lt;span class="l"&gt;3K data/ed/edbf5390498ef9459e359eff4c03da82ee46c1f302a7ef6ec7410af25c825ae1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;554&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;index/10001235dbd9f406ae7bd4030ad3feaf7dbdcddc32da05c125371a0780c578aa&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="m"&gt;332&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;snapshots/7505e3f009775ad74c00ca09aa57a854957d7f761a14e72ecd0d5fef9d7e9623&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们再将第100行，修改为aaa。我们看到在同一blob内，每次修改同步的大小是一样的。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;repository 56f6f179 opened successfully, password is correct&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;lock repository&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;load index files&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;using parent snapshot 7505e3f0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;start scan on [source_dir/10mb_file.txt]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;start backup on [source_dir/10mb_file.txt]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;scan finished in 0.205s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;files, 10.003 MiB&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new, 1 changed, 0 unmodified&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Dirs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new, 1 changed, 0 unmodified&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Data Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Tree Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Added to the repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2.236&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;MiB&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;processed 1 files, 10.003 MiB in 0:00&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;snapshot 98f81417 saved&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;如果我们增加行数会发生什么呢？根据blob的分割记录，我们大概追加30000行到文件内，此时文件大小情况为&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;File&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;‘10mb_file.txt’&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;Size: 10657790 Blocks: 53248 IO Block&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;regular file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Device: 803h/2051d Inode: 1377358062 Links&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;( 0/ root)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Access&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ld"&gt;2022-03-24 15:05:36.102065592 +0800&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Modify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ld"&gt;2022-03-24 15:11:54.259081906 +0800&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Change&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ld"&gt;2022-03-24 15:11:54.259081906 +0800&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;Birth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;本次同步后，可能是未达到边界值，所以同步的大小为2.5MB左右。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;repository 56f6f179 opened successfully, password is correct&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;lock repository&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;load index files&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;using parent snapshot 98f81417&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;start scan on [source_dir/10mb_file.txt]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;start backup on [source_dir/10mb_file.txt]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;scan finished in 0.214s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;files, 10.164 MiB&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new, 1 changed, 0 unmodified&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Dirs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new, 1 changed, 0 unmodified&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Data Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Tree Blobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;Added to the repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2.547&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;MiB&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;processed 1 files, 10.164 MiB in 0:00&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;snapshot 84bb70fa saved&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;总结&lt;span class="hx:absolute hx:-mt-20" id="总结"&gt;&lt;/span&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;通过以上使用测试，首先我们应该了解restic的目录管理逻辑&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;index目录下的文件记录了每一次备份的完整组织结构，指向packs&lt;/li&gt;
&lt;li&gt;snapshots则直接指向了最顶层的blob&lt;/li&gt;
&lt;li&gt;data目录中的id是packs id，而packs中可能包含多个blob&lt;/li&gt;
&lt;li&gt;blob包含tree和data两种类型，blob记录了大量与文件有关的metadata信息&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>AWS Certified Solutions Architect - Associate Exam(Q1-Q100)</title><link>https://sunqi.site/blog/2019-12-31-aws-certified-solutions-architect-associate-exam/</link><pubDate>Thu, 31 Mar 2022 09:11:55 +0000</pubDate><guid>https://sunqi.site/blog/2019-12-31-aws-certified-solutions-architect-associate-exam/</guid><description>
&lt;p&gt;参考链接：https://www.examtopics.com/exams/amazon/aws-certified-solutions-architect-associate/view/&lt;/p&gt;
&lt;p&gt;一直对AWS情有独钟，也想尝试考取最高认证，但是苦于无法集中精力学习。2019年由于和AWS合作的原因，所以痛下决心一定要考取AWS各种认证。另外，在AWS的学习过程中，也逐渐帮我梳理了以前在OpenStack开发过程中不是很清晰的设计理念。并且AWS的文档和最佳实践堪称各个公有云的典范，非常具有学习价值。考试不是最终的目的，学以致用才是。&lt;/p&gt;
&lt;p&gt;由于备考AWS ACA考试，所以从网上看到这套模拟试题，在学习过程中对试题进行系统性分析和记录。发现有很多问题答案并非十分准确，所以也尝试做出分析和更正。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;A Solutions Architect is designing an application that will encrypt all data in an Amazon Redshift cluster. Which action will encrypt the data at rest?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-an-application-that-will-encrypt-all-data-in-an-amazon-redshift-cluster-which-action-will-encrypt-the-data-at-rest"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-an-application-that-will-encrypt-all-data-in-an-amazon-redshift-cluster-which-action-will-encrypt-the-data-at-rest" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Place the Redshift cluster in a private subnet.
B. Use the AWS KMS Default Customer master key.
C. Encrypt the Amazon EBS volumes.
D. Encrypt the data using SSL/TLS.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;参考链接：https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-db-encryption.html&lt;/li&gt;
&lt;li&gt;分析：Amazon Redshift 使用加密密钥层次结构来加密数据库。您可以使用 AWS Key Management Service (AWS KMS) 或硬件安全模块 (HSM) 来管理该层次结构中的顶级加密密钥。Amazon Redshift 用于加密的流程因您管理密钥的方式而异。Amazon Redshift 自动与 AWS KMS 集成，而不与 HSM 集成。当您使用 HSM 时，必须使用客户端和服务器证书在 Amazon Redshift 和 HSM 之间配置受信任的连接。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A website experiences unpredictable traffic. During peak traffic times, the database is unable to keep up with the write request. Which AWS service will help decouple the web application from the database?&lt;span class="hx:absolute hx:-mt-20" id="a-website-experiences-unpredictable-traffic-during-peak-traffic-times-the-database-is-unable-to-keep-up-with-the-write-request-which-aws-service-will-help-decouple-the-web-application-from-the-database"&gt;&lt;/span&gt;
&lt;a href="#a-website-experiences-unpredictable-traffic-during-peak-traffic-times-the-database-is-unable-to-keep-up-with-the-write-request-which-aws-service-will-help-decouple-the-web-application-from-the-database" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon SQS
B. Amazon EFS
C. Amazon S3
D. AWS Lambda&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;参考链接：https://aws.amazon.com/cn/sqs/faqs/&lt;/li&gt;
&lt;li&gt;分析：关键词是unpredictable traffic, keep up with write request, decouple the web application, 所以通过消息队列服务可以让写入请求排队，从而实现前端应用和后端数据库的解耦。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A legacy application needs to interact with local storage using iSCSI. A team needs to design a reliable storage solution to provision all new storage on AWS. Which storage solution meets the legacy application requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-legacy-application-needs-to-interact-with-local-storage-using-iscsi-a-team-needs-to-design-a-reliable-storage-solution-to-provision-all-new-storage-on-aws-which-storage-solution-meets-the-legacy-application-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-legacy-application-needs-to-interact-with-local-storage-using-iscsi-a-team-needs-to-design-a-reliable-storage-solution-to-provision-all-new-storage-on-aws-which-storage-solution-meets-the-legacy-application-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. AWS Snowball storage for the legacy application until the application can be re-architected.
B. AWS Storage Gateway in cached mode for the legacy application storage to write data to Amazon S3.
C. AWS Storage Gateway in stored mode for the legacy application storage to write data to Amazon S3.
D. An Amazon S3 volume mounted on the legacy application server locally using the File Gateway service.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：关键词是local stroage with iSCSI, 并且需要将所有新的存储用AWS提供，所以排除A选项；因为用到了iSCSI协议，所以S3使用文件网关方式也不适用，排除D；剩下的B和C区别在于存储模式，因为需要本地应用请求，所以需要使用存储模式，而不能用缓存模式，所以最终选择C。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is designing an architecture for a mobile gaming application. The application is expected to be very popular. The Architect needs to prevent the Amazon RDS MySQL database from becoming a bottleneck due to frequently accessed queries. Which service or feature should the Architect add to prevent a bottleneck?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-an-architecture-for-a-mobile-gaming-application-the-application-is-expected-to-be-very-popular-the-architect-needs-to-prevent-the-amazon-rds-mysql-database-from-becoming-a-bottleneck-due-to-frequently-accessed-queries-which-service-or-feature-should-the-architect-add-to-prevent-a-bottleneck"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-an-architecture-for-a-mobile-gaming-application-the-application-is-expected-to-be-very-popular-the-architect-needs-to-prevent-the-amazon-rds-mysql-database-from-becoming-a-bottleneck-due-to-frequently-accessed-queries-which-service-or-feature-should-the-architect-add-to-prevent-a-bottleneck" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Multi-AZ feature on the RDS MySQL Database
B. ELB Classic Load Balancer in front of the web application tier
C. Amazon SQS in front of RDS MySQL Database
D. Amazon ElastiCache in front of the RDS MySQL Database&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：该问题的关键在于bottleneck due to frequently accessed queries，查询变成瓶颈，可以使用ElastiCache服务作为缓存，降低读取频率解决问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company is launching an application that it expects to be very popular. The company needs a database that can scale with the rest of the application. The schema will change frequently. The application cannot afford any downtime for database changes. Which AWS service allows the company to achieve these objectives?&lt;span class="hx:absolute hx:-mt-20" id="a-company-is-launching-an-application-that-it-expects-to-be-very-popular-the-company-needs-a-database-that-can-scale-with-the-rest-of-the-application-the-schema-will-change-frequently-the-application-cannot-afford-any-downtime-for-database-changes-which-aws-service-allows-the-company-to-achieve-these-objectives"&gt;&lt;/span&gt;
&lt;a href="#a-company-is-launching-an-application-that-it-expects-to-be-very-popular-the-company-needs-a-database-that-can-scale-with-the-rest-of-the-application-the-schema-will-change-frequently-the-application-cannot-afford-any-downtime-for-database-changes-which-aws-service-allows-the-company-to-achieve-these-objectives" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon Redshift
B. Amazon DynamoDB
C. Amazon RDS MySQL
D. Amazon Aurora&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：原网站给出的答案是A，但是经过分析觉得有些问题，这道题的几个关键词：scale with the rest of the application, schema will change frequently, cannot afford any downtime for database changes. 首先，schema总是变更，所以这里需要的非关系型数据库，排除C和D。Redshift是数据仓库，其实也是数据仓库，从第一点上就可以排除。另外从这个链接（http://braindump2go.hatenablog.com/entry/2019/11/05/123057）分析上，还有一点除了DynamoDB可以真正做到scale时候zero downtime，其他的都不行。所以原网站给出的答案是错误的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solution Architect is designing a disaster recovery solution for a 5 TB Amazon Redshift cluster. The recovery site must be at least 500 miles (805 kilometers) from the live site. How should the Architect meet these requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-solution-architect-is-designing-a-disaster-recovery-solution-for-a-5-tb-amazon-redshift-cluster-the-recovery-site-must-be-at-least-500-miles-805-kilometers-from-the-live-site-how-should-the-architect-meet-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-solution-architect-is-designing-a-disaster-recovery-solution-for-a-5-tb-amazon-redshift-cluster-the-recovery-site-must-be-at-least-500-miles-805-kilometers-from-the-live-site-how-should-the-architect-meet-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Use AWS CloudFormation to deploy the cluster in a second region.
B. Take a snapshot of the cluster and copy it to another Availability Zone.
C. Modify the Redshift cluster to span two regions.
D. Enable cross-region snapshots to a different region.&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;参考链接：https://aws.amazon.com/cn/blogs/aws/automated-cross-region-snapshot-copy-for-amazon-redshift/&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A customer has written an application that uses Amazon S3 exclusively as a data store. The application works well until the customer increases the rate at which the application is updating information. The customer now reports that outdated data occasionally appears when the application accesses objects in Amazon S3. What could be the problem, given that the application logic is otherwise correct?&lt;span class="hx:absolute hx:-mt-20" id="a-customer-has-written-an-application-that-uses-amazon-s3-exclusively-as-a-data-store-the-application-works-well-until-the-customer-increases-the-rate-at-which-the-application-is-updating-information-the-customer-now-reports-that-outdated-data-occasionally-appears-when-the-application-accesses-objects-in-amazon-s3-what-could-be-the-problem-given-that-the-application-logic-is-otherwise-correct"&gt;&lt;/span&gt;
&lt;a href="#a-customer-has-written-an-application-that-uses-amazon-s3-exclusively-as-a-data-store-the-application-works-well-until-the-customer-increases-the-rate-at-which-the-application-is-updating-information-the-customer-now-reports-that-outdated-data-occasionally-appears-when-the-application-accesses-objects-in-amazon-s3-what-could-be-the-problem-given-that-the-application-logic-is-otherwise-correct" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. The application is reading parts of objects from Amazon S3 using a range header.
B. The application is reading objects from Amazon S3 using parallel object requests.
C. The application is updating records by writing new objects with unique keys.
D. The application is updating records by overwriting existing objects with the same keys.&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题也是争论很大的一道题，原网站答案为A。问题简单描述为客户端访问不到最新的数据，发生的时间点在于应用上传信息时候速率提高导致的，所以问题应该出现在写入的时候，这样排除A和B读取的问题。因为S3同一object永远是覆盖，所以最有可能的问题是在same key的情况下，所以选择D。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is designing a new social media application. The application must provide a secure method for uploading profile photos. Each user should be able to upload a profile photo into a shared storage location for one week after their profile is created. Which approach will meet all of these requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-new-social-media-application-the-application-must-provide-a-secure-method-for-uploading-profile-photos-each-user-should-be-able-to-upload-a-profile-photo-into-a-shared-storage-location-for-one-week-after-their-profile-is-created-which-approach-will-meet-all-of-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-new-social-media-application-the-application-must-provide-a-secure-method-for-uploading-profile-photos-each-user-should-be-able-to-upload-a-profile-photo-into-a-shared-storage-location-for-one-week-after-their-profile-is-created-which-approach-will-meet-all-of-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Use Amazon Kinesis with AWS CloudTrail for auditing the specific times when profile photos are uploaded.
B. Use Amazon EBS volumes with IAM policies restricting user access to specific time periods.
C. Use Amazon S3 with the default private access policy and generate pre-signed URLs each time a new site profile is created.
D. Use Amazon CloudFront with AWS CloudTrail for auditing the specific times when profile photos are uploaded.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;An application requires block storage for file updates. The data is 500 GB and must continuously sustain 100 MiB/s of aggregate read/write operations. Which storage option is appropriate for this application?&lt;span class="hx:absolute hx:-mt-20" id="an-application-requires-block-storage-for-file-updates-the-data-is-500-gb-and-must-continuously-sustain-100-mibs-of-aggregate-readwrite-operations-which-storage-option-is-appropriate-for-this-application"&gt;&lt;/span&gt;
&lt;a href="#an-application-requires-block-storage-for-file-updates-the-data-is-500-gb-and-must-continuously-sustain-100-mibs-of-aggregate-readwrite-operations-which-storage-option-is-appropriate-for-this-application" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon S3
B. Amazon EFS
C. Amazon EBS
D. Amazon Glacier&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：没想到这道题原网站给出的答案是B，争议比较大，但是从题目描述需要Block Storage角度来看，选择C才是最合理的。这道题还需要进一步确认一下。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A mobile application serves scientific articles from individual files in an Amazon S3 bucket. Articles older than 30 days are rarely read. Articles older than 60 days no longer need to be available through the application, but the application owner would like to keep them for historical purposes. Which cost-effective solution BEST meets these requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-mobile-application-serves-scientific-articles-from-individual-files-in-an-amazon-s3-bucket-articles-older-than-30-days-are-rarely-read-articles-older-than-60-days-no-longer-need-to-be-available-through-the-application-but-the-application-owner-would-like-to-keep-them-for-historical-purposes-which-cost-effective-solution-best-meets-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-mobile-application-serves-scientific-articles-from-individual-files-in-an-amazon-s3-bucket-articles-older-than-30-days-are-rarely-read-articles-older-than-60-days-no-longer-need-to-be-available-through-the-application-but-the-application-owner-would-like-to-keep-them-for-historical-purposes-which-cost-effective-solution-best-meets-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create a Lambda function to move files older than 30 days to Amazon EBS and move files older than 60 days to Amazon Glacier.
B. Create a Lambda function to move files older than 30 days to Amazon Glacier and move files older than 60 days to Amazon EBS.
C. Create lifecycle rules to move files older than 30 days to Amazon S3 Standard Infrequent Access and move files older than 60 days to Amazon Glacier.
D. Create lifecycle rules to move files older than 30 days to Amazon Glacier and move files older than 60 days to Amazon S3 Standard Infrequent Access.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：很明显的排除A和B，S3可以自定义规则，那么问题就是30天后和60天后需要哪种存储的问题了，根据题目C是明显正确的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;An organization is currently hosting a large amount of frequently accessed data consisting of key-value pairs and semi-structured documents in their data center. They are planning to move this data to AWS. Which of one of the following services MOST effectively meets their needs?&lt;span class="hx:absolute hx:-mt-20" id="an-organization-is-currently-hosting-a-large-amount-of-frequently-accessed-data-consisting-of-key-value-pairs-and-semi-structured-documents-in-their-data-center-they-are-planning-to-move-this-data-to-aws-which-of-one-of-the-following-services-most-effectively-meets-their-needs"&gt;&lt;/span&gt;
&lt;a href="#an-organization-is-currently-hosting-a-large-amount-of-frequently-accessed-data-consisting-of-key-value-pairs-and-semi-structured-documents-in-their-data-center-they-are-planning-to-move-this-data-to-aws-which-of-one-of-the-following-services-most-effectively-meets-their-needs" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon Redshift
B. Amazon RDS
C. Amazon DynamoDB
D. Amazon Aurora&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;A Lambda function must execute a query against an Amazon RDS database in a private subnet. Which steps are required to allow the Lambda function to access the Amazon RDS database? (Select two.)&lt;span class="hx:absolute hx:-mt-20" id="a-lambda-function-must-execute-a-query-against-an-amazon-rds-database-in-a-private-subnet-which-steps-are-required-to-allow-the-lambda-function-to-access-the-amazon-rds-database-select-two"&gt;&lt;/span&gt;
&lt;a href="#a-lambda-function-must-execute-a-query-against-an-amazon-rds-database-in-a-private-subnet-which-steps-are-required-to-allow-the-lambda-function-to-access-the-amazon-rds-database-select-two" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create a VPC Endpoint for Amazon RDS.
B. Create the Lambda function within the Amazon RDS VPC.
C. Change the ingress rules of Lambda security group, allowing the Amazon RDS security group.
D. Change the ingress rules of the Amazon RDS security group, allowing the Lambda security group.
E. Add an Internet Gateway (IGW) to the VPC, route the private subnet to the IGW.&lt;/p&gt;
&lt;p&gt;Answer: BD&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：又是原网站一道错题，原网站答案为AD。D选项是允许Lambda服务访问RDS，所以在进方向允许。&lt;/li&gt;
&lt;li&gt;目前VPC支持Endpoint的服务：https://docs.aws.amazon.com/zh_cn/vpc/latest/userguide/vpc-endpoints.html&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Amazon API Gateway
Amazon AppStream 2.0
AWS App Mesh
Amazon Athena
AWS CloudFormation
AWS CloudTrail
Amazon CloudWatch
Amazon CloudWatch Events
Amazon CloudWatch Logs
AWS CodeBuild
AWS CodeCommit
AWS CodePipeline
AWS Config
AWS DataSync
Amazon EC2 API
Elastic Load Balancing
Amazon Elastic Container Registry
Amazon Elastic Container Service
AWS Glue
AWS Key Management Service
Amazon Kinesis Data Firehose
Amazon Kinesis Data Streams
Amazon Rekognition
Amazon SageMaker 和 Amazon SageMaker 运行时
Amazon SageMaker 笔记本
AWS Secrets Manager
AWS Security Token Service
AWS Service Catalog
Amazon SNS
Amazon SQS
AWS Systems Manager
AWS Storage Gateway
AWS Transfer for SFTP
其他 AWS 账户托管的终端节点服务&lt;/p&gt;
&lt;p&gt;网关终端节点是一个网关，作为您在路由表中指定的路由的目标，用于发往受支持的 AWS 服务的流量。支持以下 AWS 服务：
Amazon S3
DynamoDB&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;(待实际环境验证)A Solutions Architect needs to build a resilient data warehouse using Amazon Redshift. The Architect needs to rebuild the Redshift cluster in another region. Which approach can the Architect take to address this requirement?&lt;span class="hx:absolute hx:-mt-20" id="待实际环境验证a-solutions-architect-needs-to-build-a-resilient-data-warehouse-using-amazon-redshift-the-architect-needs-to-rebuild-the-redshift-cluster-in-another-region-which-approach-can-the-architect-take-to-address-this-requirement"&gt;&lt;/span&gt;
&lt;a href="#%e5%be%85%e5%ae%9e%e9%99%85%e7%8e%af%e5%a2%83%e9%aa%8c%e8%af%81a-solutions-architect-needs-to-build-a-resilient-data-warehouse-using-amazon-redshift-the-architect-needs-to-rebuild-the-redshift-cluster-in-another-region-which-approach-can-the-architect-take-to-address-this-requirement" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Modify the Redshift cluster and configure cross-region snapshots to the other region.
B. Modify the Redshift cluster to take snapshots of the Amazon EBS volumes each day, sharing those snapshots with the other region.
C. Modify the Redshift cluster and configure the backup and specify the Amazon S3 bucket in the other region.
D. Modify the Redshift cluster to use AWS Snowball in export mode with data delivered to the other region.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：又是一道错题，Redhift备份是通过S3实现的, 所以不存在B的情况，我个人有点倾向于C，但是A确实是Redshift在快照时默认的格式，可能是更容易恢复吧，这道题需要在实际环境进行一下验证。另外国际版本的Redshift和国内的应该比国内的高很多。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;问：Amazon Redshift 如何备份数据？ 如何从备份中还原我的集群？&lt;/p&gt;
&lt;p&gt;在加载数据时，Amazon Redshift 会复制数据仓库集群内的所有数据并将其连续备份至 S3。Amazon Redshift 始终尝试维持至少三份数据（计算节点上的正本数据、副本数据和 Amazon S3 上的备份数据）。Redshift 还能将您的快照异步复制到另一个区域的 S3 中进行灾难恢复。&lt;/p&gt;
&lt;p&gt;默认情况下，Amazon Redshift 以一天的保留期启用数据仓库群集的自动化备份。您可将其配置为 35 天之久。&lt;/p&gt;
&lt;p&gt;免费备份存储受限于数据仓库群集中节点上的总存储大小，并仅适用于已激活的数据仓库群集。例如，如果您有 8TB 的数据仓库总存储大小，那么我们将提供最多 8TB 的备份存储而不另外收费。如果您想将备份保留期延长为超过一天，那么您可以使用 AWS 管理控制台或 Amazon Redshift API 来实现这一目的。有关自动快照的更多信息，请参阅《Amazon Redshift 管理指南》。Amazon Redshift 仅备份已更改的数据，因此大多数快照仅占用少量的免费备份存储。&lt;/p&gt;
&lt;p&gt;如果您需要还原备份，则可以在备份保留期内访问所有自动备份。在您选择某个要还原的备份后，我们将预置一个新的数据仓库集群并将数据还原至此集群中。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A popular e-commerce application runs on AWS. The application encounters performance issues. The database is unable to handle the amount of queries and load during peak times. The database is running on the RDS Aurora engine on the largest instance size available. What should an administrator do to improve performance?&lt;span class="hx:absolute hx:-mt-20" id="a-popular-e-commerce-application-runs-on-aws-the-application-encounters-performance-issues-the-database-is-unable-to-handle-the-amount-of-queries-and-load-during-peak-times-the-database-is-running-on-the-rds-aurora-engine-on-the-largest-instance-size-available-what-should-an-administrator-do-to-improve-performance"&gt;&lt;/span&gt;
&lt;a href="#a-popular-e-commerce-application-runs-on-aws-the-application-encounters-performance-issues-the-database-is-unable-to-handle-the-amount-of-queries-and-load-during-peak-times-the-database-is-running-on-the-rds-aurora-engine-on-the-largest-instance-size-available-what-should-an-administrator-do-to-improve-performance" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Convert the database to Amazon Redshift.
B. Create a CloudFront distribution.
C. Convert the database to use EBS Provisioned IOPS.
D. Create one or more read replicas.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题我最开始选择的是D，但是评论区的一种解释有一定的道理：这个网站应用类型为电商，原题中没有很清楚说明queris and load的压力有多大，很可能我们建立了read replicas只能临时性解决问题，并不是一劳永逸的方式。并且根据https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Replication.html&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;因此，所有 Aurora 副本均返回相同的查询结果数据，且副本滞后时间非常短 - 通常远远少于主实例写入更新后的 100 毫秒。副本滞后因数据库更改速率而异。也就是说，在对数据库执行大量写入操作期间，您可能发现副本滞后时间变长。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;如果读副本在这个延时上，很可能对业务系统造成很大的影响。&lt;/p&gt;
&lt;h2&gt;A Solutions Architect is designing the architecture for a new three-tier web-based e-commerce site that must be available 24/7. Requests are expected to range from 100 to 10,000 each minute. Usage can vary depending on time of day, holidays, and promotions. The design should be able to handle these volumes, with the ability to handle higher volumes if necessary. How should the Architect design the architecture to ensure the web tier is cost-optimized and can handle the expected traffic? (Select two.)&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-the-architecture-for-a-new-three-tier-web-based-e-commerce-site-that-must-be-available-247-requests-are-expected-to-range-from-100-to-10000-each-minute-usage-can-vary-depending-on-time-of-day-holidays-and-promotions-the-design-should-be-able-to-handle-these-volumes-with-the-ability-to-handle-higher-volumes-if-necessary-how-should-the-architect-design-the-architecture-to-ensure-the-web-tier-is-cost-optimized-and-can-handle-the-expected-traffic-select-two"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-the-architecture-for-a-new-three-tier-web-based-e-commerce-site-that-must-be-available-247-requests-are-expected-to-range-from-100-to-10000-each-minute-usage-can-vary-depending-on-time-of-day-holidays-and-promotions-the-design-should-be-able-to-handle-these-volumes-with-the-ability-to-handle-higher-volumes-if-necessary-how-should-the-architect-design-the-architecture-to-ensure-the-web-tier-is-cost-optimized-and-can-handle-the-expected-traffic-select-two" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Launch Amazon EC2 instances in an Auto Scaling group behind an ELB.
B. Store all static files in a multi-AZ Amazon Aurora database.
C. Create an CloudFront distribution pointing to static content in Amazon S3.
D. Use Amazon Route 53 to route traffic to the correct region.
E. Use Amazon S3 multi-part uploads to improve upload times.&lt;/p&gt;
&lt;p&gt;Answer: AC&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：A是很明显的，弹性伸缩，节约成本，其他几项和题干没有太多关系，所以选的C。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solution Architect is designing a three-tier web application. The Architect wants to restrict access to the database tier to accept traffic from the application servers only. However, these application servers are in an Auto Scaling group and may vary in quantity. How should the Architect configure the database servers to meet the requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-solution-architect-is-designing-a-three-tier-web-application-the-architect-wants-to-restrict-access-to-the-database-tier-to-accept-traffic-from-the-application-servers-only-however-these-application-servers-are-in-an-auto-scaling-group-and-may-vary-in-quantity-how-should-the-architect-configure-the-database-servers-to-meet-the-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-solution-architect-is-designing-a-three-tier-web-application-the-architect-wants-to-restrict-access-to-the-database-tier-to-accept-traffic-from-the-application-servers-only-however-these-application-servers-are-in-an-auto-scaling-group-and-may-vary-in-quantity-how-should-the-architect-configure-the-database-servers-to-meet-the-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Configure the database security group to allow database traffic from the application server IP addresses.
B. Configure the database security group to allow database traffic from the application server security group.
C. Configure the database subnet network ACL to deny all inbound non-database traffic from the application-tier subnet.
D. Configure the database subnet network ACL to allow inbound database traffic from the application-tier subnet.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这好像又是一道错题，原给出的答案是C。首先要明确的一点是SG是工作在instance级别，NACL是在子网级别，SG默认全部Deny，NACL默认全部Allow。A不对的原因是insance在Auto Scaling里，IP地址是不固定的。D不对的原因是NACL默认全都是Allow的。其实本质上考察的是如何选择安全组还是网络防火墙的问题。不选择C的原因是因为配置NACL规则至少需要阻止和允许，而通过安全组只需要配置一条即可。但是也有一种声音认为题目中关键词restrict意味着需要deny流量。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;问：VPC 中的安全组和 VPC 中的网络 ACL 有什么区别？&lt;/p&gt;
&lt;p&gt;VPC 中的安全组指定允许传入或传出 Amazon EC2 实例的流量。网络 ACL 则在子网级别上运作，评估进出某个子网的流量。网络 ACL 可通过设置允许和拒绝规则来进行使用。Network ACL 不能筛选同一子网中实例之间的流量。此外，网络 ACL 执行无状态筛选，而安全组则执行有状态筛选。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;An Internet-facing multi-tier web application must be highly available. An ELB Classic Load Balancer is deployed in front of the web tier. Amazon EC2 instances at the web application tier are deployed evenly across two Availability Zones. The database is deployed using RDS Multi-AZ. A NAT instance is launched for Amazon EC2 instances and database resources to access the Internet. These instances are not assigned with public IP addresses. Which component poses a potential single point of failure in this architecture?&lt;span class="hx:absolute hx:-mt-20" id="an-internet-facing-multi-tier-web-application-must-be-highly-available-an-elb-classic-load-balancer-is-deployed-in-front-of-the-web-tier-amazon-ec2-instances-at-the-web-application-tier-are-deployed-evenly-across-two-availability-zones-the-database-is-deployed-using-rds-multi-az-a-nat-instance-is-launched-for-amazon-ec2-instances-and-database-resources-to-access-the-internet-these-instances-are-not-assigned-with-public-ip-addresses-which-component-poses-a-potential-single-point-of-failure-in-this-architecture"&gt;&lt;/span&gt;
&lt;a href="#an-internet-facing-multi-tier-web-application-must-be-highly-available-an-elb-classic-load-balancer-is-deployed-in-front-of-the-web-tier-amazon-ec2-instances-at-the-web-application-tier-are-deployed-evenly-across-two-availability-zones-the-database-is-deployed-using-rds-multi-az-a-nat-instance-is-launched-for-amazon-ec2-instances-and-database-resources-to-access-the-internet-these-instances-are-not-assigned-with-public-ip-addresses-which-component-poses-a-potential-single-point-of-failure-in-this-architecture" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon EC2
B. NAT instance
C. ELB Classic Load Balancer
D. Amazon RDS&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题竟然给出了C的答案，很意外。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://aws.amazon.com/articles/high-availability-for-amazon-vpc-nat-instances-an-example/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/articles/high-availability-for-amazon-vpc-nat-instances-an-example/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Instances in a private subnet can access the Internet without exposing their private IP address by routing their traffic through a Network Address Translation (NAT) instance in a public subnet. A NAT instance, however, can introduce a single point of failure to your VPC&amp;rsquo;s outbound traffic. This situation is depicted in the diagram below.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A call center application consists of a three-tier application using Auto Scaling groups to automatically scale resources as needed. Users report that every morning at 9:00 AM the system becomes very slow for about 15 minutes. A Solution Architect determines that a large percentage of the call center staff starts work at 9:00 AM, so Auto Scaling does not have enough time to scale out to meet demand. How can the Architect fix the problem?&lt;span class="hx:absolute hx:-mt-20" id="a-call-center-application-consists-of-a-three-tier-application-using-auto-scaling-groups-to-automatically-scale-resources-as-needed-users-report-that-every-morning-at-900-am-the-system-becomes-very-slow-for-about-15-minutes-a-solution-architect-determines-that-a-large-percentage-of-the-call-center-staff-starts-work-at-900-am-so-auto-scaling-does-not-have-enough-time-to-scale-out-to-meet-demand-how-can-the-architect-fix-the-problem"&gt;&lt;/span&gt;
&lt;a href="#a-call-center-application-consists-of-a-three-tier-application-using-auto-scaling-groups-to-automatically-scale-resources-as-needed-users-report-that-every-morning-at-900-am-the-system-becomes-very-slow-for-about-15-minutes-a-solution-architect-determines-that-a-large-percentage-of-the-call-center-staff-starts-work-at-900-am-so-auto-scaling-does-not-have-enough-time-to-scale-out-to-meet-demand-how-can-the-architect-fix-the-problem" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Change the Auto Scaling group&amp;rsquo;s scale out event to scale based on network utilization.
B. Create an Auto Scaling scheduled action to scale out the necessary resources at 8:30 AM every morning.
C. Use Reserved Instances to ensure the system has reserved the right amount of capacity for the scale-up events.
D. Permanently keep a steady state of instances that is needed at 9:00 AM to guarantee available resources, but leverage Spot Instances.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：竟然又是一道错题，记得在AWS听过这道题的分析。原答案是A，但是可能并不是由于网络引起的访问缓慢。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;An e-commerce application is hosted in AWS. The last time a new product was launched, the application experienced a performance issue due to an enormous spike in traffic. Management decided that capacity must be doubled the week after the product is launched. Which is the MOST efficient way for management to ensure that capacity requirements are met?&lt;span class="hx:absolute hx:-mt-20" id="an-e-commerce-application-is-hosted-in-aws-the-last-time-a-new-product-was-launched-the-application-experienced-a-performance-issue-due-to-an-enormous-spike-in-traffic-management-decided-that-capacity-must-be-doubled-the-week-after-the-product-is-launched-which-is-the-most-efficient-way-for-management-to-ensure-that-capacity-requirements-are-met"&gt;&lt;/span&gt;
&lt;a href="#an-e-commerce-application-is-hosted-in-aws-the-last-time-a-new-product-was-launched-the-application-experienced-a-performance-issue-due-to-an-enormous-spike-in-traffic-management-decided-that-capacity-must-be-doubled-the-week-after-the-product-is-launched-which-is-the-most-efficient-way-for-management-to-ensure-that-capacity-requirements-are-met" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Add a Step Scaling policy.
B. Add a Dynamic Scaling policy.
C. Add a Scheduled Scaling action.
D. Add Amazon EC2 Spot Instances.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：又是一道争议比较大的题目，争议最大的是C选项，因为题目中有几个词在暗示时间，但是又不明确。既然现有性能上无法应对高峰访问，那么从这个角度还是通过Dynamic配置一个规则进行动态规则最为有效。所以还是选择B。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A customer owns a simple API for their website that receives about 1,000 requests each day and has an average response time of 50 ms. It is currently hosted on one c4.large instance. Which changes to the architecture will provide high availability at the LOWEST cost?&lt;span class="hx:absolute hx:-mt-20" id="a-customer-owns-a-simple-api-for-their-website-that-receives-about-1000-requests-each-day-and-has-an-average-response-time-of-50-ms-it-is-currently-hosted-on-one-c4large-instance-which-changes-to-the-architecture-will-provide-high-availability-at-the-lowest-cost"&gt;&lt;/span&gt;
&lt;a href="#a-customer-owns-a-simple-api-for-their-website-that-receives-about-1000-requests-each-day-and-has-an-average-response-time-of-50-ms-it-is-currently-hosted-on-one-c4large-instance-which-changes-to-the-architecture-will-provide-high-availability-at-the-lowest-cost" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create an Auto Scaling group with a minimum of one instance and a maximum of two instances, then use an Application Load Balancer to balance the traffic.
B. Recreate the API using Amazon API Gateway and use AWS Lambda as the service backend.
C. Create an Auto Scaling group with a maximum of two instances, then use an Application Load Balancer to balance the traffic.
D. Recreate the API using Amazon API Gateway and integrate the new API with the existing backend service.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题有个陷阱，Simple API，确实如果在不考虑开发的前提下B确实是最佳选项，但是重构也是要花成本的。所以我坚持选A。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solution Architect is designing an application that uses Amazon EBS volumes. The volumes must be backed up to a different region. How should the Architect meet this requirement?&lt;span class="hx:absolute hx:-mt-20" id="a-solution-architect-is-designing-an-application-that-uses-amazon-ebs-volumes-the-volumes-must-be-backed-up-to-a-different-region-how-should-the-architect-meet-this-requirement"&gt;&lt;/span&gt;
&lt;a href="#a-solution-architect-is-designing-an-application-that-uses-amazon-ebs-volumes-the-volumes-must-be-backed-up-to-a-different-region-how-should-the-architect-meet-this-requirement" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create EBS snapshots directly from one region to another.
B. Move the data to an Amazon S3 bucket and enable cross-region replication.
C. Create EBS snapshots and then copy them to the desired region.
D. Use a script to copy data from the current Amazon EBS volume to the destination Amazon EBS volume.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;A company is using an Amazon S3 bucket located in us-west-2 to serve videos to their customers. Their customers are located all around the world and the videos are requested a lot during peak hours. Customers in Europe complain about experiencing slow downloaded speeds, and during peak hours, customers in all locations report experiencing HTTP 500 errors. What can a Solutions Architect do to address these issues?&lt;span class="hx:absolute hx:-mt-20" id="a-company-is-using-an-amazon-s3-bucket-located-in-us-west-2-to-serve-videos-to-their-customers-their-customers-are-located-all-around-the-world-and-the-videos-are-requested-a-lot-during-peak-hours-customers-in-europe-complain-about-experiencing-slow-downloaded-speeds-and-during-peak-hours-customers-in-all-locations-report-experiencing-http-500-errors-what-can-a-solutions-architect-do-to-address-these-issues"&gt;&lt;/span&gt;
&lt;a href="#a-company-is-using-an-amazon-s3-bucket-located-in-us-west-2-to-serve-videos-to-their-customers-their-customers-are-located-all-around-the-world-and-the-videos-are-requested-a-lot-during-peak-hours-customers-in-europe-complain-about-experiencing-slow-downloaded-speeds-and-during-peak-hours-customers-in-all-locations-report-experiencing-http-500-errors-what-can-a-solutions-architect-do-to-address-these-issues" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Place an elastic load balancer in front of the Amazon S3 bucket to distribute the load during peak hours.
B. Cache the web content with Amazon CloudFront and use all Edge locations for content delivery.
C. Replicate the bucket in eu-west-1 and use an Amazon Route 53 failover routing policy to determine which bucket it should serve the request to.
D. Use an Amazon Route 53 weighted routing policy for the CloudFront domain name to distribute the GET request between CloudFront and the Amazon S3 bucket directly.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：网站给出的答案竟然是D，但是B很明显是正确的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is designing a solution that includes a managed VPN connection. To monitor whether the VPN connection is up or down, the Architect should use:&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-solution-that-includes-a-managed-vpn-connection-to-monitor-whether-the-vpn-connection-is-up-or-down-the-architect-should-use"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-solution-that-includes-a-managed-vpn-connection-to-monitor-whether-the-vpn-connection-is-up-or-down-the-architect-should-use" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. an external service to ping the VPN endpoint from outside the VPC.
B. AWS CloudTrail to monitor the endpoint.
C. the CloudWatch TunnelState Metric.
D. an AWS Lambda function that parses the VPN connection logs.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Monitoring VPN Tunnels Using Amazon CloudWatch(&lt;a href="https://docs.aws.amazon.com/vpn/latest/s2svpn/monitoring-cloudwatch-vpn.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/vpn/latest/s2svpn/monitoring-cloudwatch-vpn.html&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A social networking portal experiences latency and throughput issues due to an increased number of users. Application servers use very large datasets from an Amazon RDS database, which creates a performance bottleneck on the database. Which AWS service should be used to improve performance?&lt;span class="hx:absolute hx:-mt-20" id="a-social-networking-portal-experiences-latency-and-throughput-issues-due-to-an-increased-number-of-users-application-servers-use-very-large-datasets-from-an-amazon-rds-database-which-creates-a-performance-bottleneck-on-the-database-which-aws-service-should-be-used-to-improve-performance"&gt;&lt;/span&gt;
&lt;a href="#a-social-networking-portal-experiences-latency-and-throughput-issues-due-to-an-increased-number-of-users-application-servers-use-very-large-datasets-from-an-amazon-rds-database-which-creates-a-performance-bottleneck-on-the-database-which-aws-service-should-be-used-to-improve-performance" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Auto Scaling
B. Amazon SQS
C. Amazon ElastiCache
D. ELB Application Load Balancer&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;A Solutions Architect is designing network architecture for an application that has compliance requirements. The application will be hosted on Amazon EC2 instances in a private subnet and will be using Amazon S3 for storing data. The compliance requirements mandate that the data cannot traverse the public Internet. What is the MOST secure way to satisfy this requirement?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-network-architecture-for-an-application-that-has-compliance-requirements-the-application-will-be-hosted-on-amazon-ec2-instances-in-a-private-subnet-and-will-be-using-amazon-s3-for-storing-data-the-compliance-requirements-mandate-that-the-data-cannot-traverse-the-public-internet-what-is-the-most-secure-way-to-satisfy-this-requirement"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-network-architecture-for-an-application-that-has-compliance-requirements-the-application-will-be-hosted-on-amazon-ec2-instances-in-a-private-subnet-and-will-be-using-amazon-s3-for-storing-data-the-compliance-requirements-mandate-that-the-data-cannot-traverse-the-public-internet-what-is-the-most-secure-way-to-satisfy-this-requirement" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Use a NAT Instance.
B. Use a NAT Gateway.
C. Use a VPC endpoint.
D. Use a Virtual Private Gateway.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;New – VPC Endpoint for Amazon S3(&lt;a href="https://aws.amazon.com/cn/blogs/aws/new-vpc-endpoint-for-amazon-s3/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/cn/blogs/aws/new-vpc-endpoint-for-amazon-s3/&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Developers are creating a new online transaction processing (OLTP) application for a small database that is very read-write intensive. A single table in the database is updated continuously throughout the day, and the developers want to ensure that the database performance is consistent. Which Amazon EBS storage option will achieve the MOST consistent performance to help maintain application performance?&lt;span class="hx:absolute hx:-mt-20" id="developers-are-creating-a-new-online-transaction-processing-oltp-application-for-a-small-database-that-is-very-read-write-intensive-a-single-table-in-the-database-is-updated-continuously-throughout-the-day-and-the-developers-want-to-ensure-that-the-database-performance-is-consistent-which-amazon-ebs-storage-option-will-achieve-the-most-consistent-performance-to-help-maintain-application-performance"&gt;&lt;/span&gt;
&lt;a href="#developers-are-creating-a-new-online-transaction-processing-oltp-application-for-a-small-database-that-is-very-read-write-intensive-a-single-table-in-the-database-is-updated-continuously-throughout-the-day-and-the-developers-want-to-ensure-that-the-database-performance-is-consistent-which-amazon-ebs-storage-option-will-achieve-the-most-consistent-performance-to-help-maintain-application-performance" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Provisioned IOPS SSD
B. General Purpose SSD
C. Cold HDD
D. Throughput Optimized HDD&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;h2&gt;A Solutions Architect is designing a log-processing solution that requires storage that supports up to 500 MB/s throughput. The data is sequentially accessed by an Amazon EC2 instance. Which Amazon storage type satisfies these requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-log-processing-solution-that-requires-storage-that-supports-up-to-500-mbs-throughput-the-data-is-sequentially-accessed-by-an-amazon-ec2-instance-which-amazon-storage-type-satisfies-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-log-processing-solution-that-requires-storage-that-supports-up-to-500-mbs-throughput-the-data-is-sequentially-accessed-by-an-amazon-ec2-instance-which-amazon-storage-type-satisfies-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. EBS Provisioned IOPS SSD (io1)
B. EBS General Purpose SSD (gp2)
C. EBS Throughput Optimized HDD (st1)
D. EBS Cold HDD (sc1)&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;A company&amp;rsquo;s development team plans to create an Amazon S3 bucket that contains millions of images. The team wants to maximize the read performance of&lt;span class="hx:absolute hx:-mt-20" id="a-companys-development-team-plans-to-create-an-amazon-s3-bucket-that-contains-millions-of-images-the-team-wants-to-maximize-the-read-performance-of"&gt;&lt;/span&gt;
&lt;a href="#a-companys-development-team-plans-to-create-an-amazon-s3-bucket-that-contains-millions-of-images-the-team-wants-to-maximize-the-read-performance-of" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Amazon S3. Which naming scheme should the company use?&lt;/p&gt;
&lt;p&gt;A. Add a date as the prefix.
B. Add a sequential id as the suffix.
C. Add a hexadecimal hash as the suffix.
D. Add a hexadecimal hash as the prefix.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题的旧答案是D，不过根据最新文档档案为A。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/dev/optimizing-performance.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/AmazonS3/latest/dev/optimizing-performance.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For example, previously Amazon S3 performance guidelines recommended randomizing prefix naming with hashed characters to optimize performance for frequent data retrievals. You no longer have to randomize prefix naming for performance, and can use sequential date-based naming for your prefixes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;什么是Prefix?&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;For example, your application can achieve at least 3,500 PUT/COPY/POST/DELETE and 5,500 GET/HEAD requests per second per prefix in a bucket. There are no limits to the number of prefixes in a bucket. You can increase your read or write performance by parallelizing reads. For example, if you create 10 prefixes in an Amazon S3 bucket to parallelize reads, you could scale your read performance to 55,000 read requests per second.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;However, if the new limits are not sufficient, prefixes would need to be used. A prefix has no fixed number of characters. It is any string between a bucket name and an object name, for example:
bucket/folder1/sub1/file
bucket/folder1/sub2/file
bucket/1/file
bucket/2/file
Prefixes of the object &amp;lsquo;file&amp;rsquo; would be: /folder1/sub1/ , /folder1/sub2/, /1/, /2/.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A Solutions Architect needs to design a solution that will enable a security team to detect, review, and perform root cause analysis of security incidents that occur in a cloud environment. The Architect must provide a centralized view of all API events for current and future AWS regions. How should the Architect accomplish this task?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-needs-to-design-a-solution-that-will-enable-a-security-team-to-detect-review-and-perform-root-cause-analysis-of-security-incidents-that-occur-in-a-cloud-environment-the-architect-must-provide-a-centralized-view-of-all-api-events-for-current-and-future-aws-regions-how-should-the-architect-accomplish-this-task"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-needs-to-design-a-solution-that-will-enable-a-security-team-to-detect-review-and-perform-root-cause-analysis-of-security-incidents-that-occur-in-a-cloud-environment-the-architect-must-provide-a-centralized-view-of-all-api-events-for-current-and-future-aws-regions-how-should-the-architect-accomplish-this-task" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Enable AWS CloudTrail logging in each individual region. Repeat this for all future regions.
B. Enable Amazon CloudWatch logs for all AWS services across all regions and aggregate them in a single Amazon S3 bucket.
C. Enable AWS Trusted Advisor security checks and report all security incidents for all regions.
D. Enable AWS CloudTrail by creating a new trail and apply the trail to all regions.&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题肯定使用CloudTrail，区别在于设定范围。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://aws.amazon.com/cn/about-aws/whats-new/2015/12/turn-on-cloudtrail-across-all-regions-and-support-for-multiple-trails/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/cn/about-aws/whats-new/2015/12/turn-on-cloudtrail-across-all-regions-and-support-for-multiple-trails/&lt;/a&gt;
You can now turn on a trail across all regions for your AWS account. CloudTrail will deliver log files from all regions to the Amazon S3 bucket and an optional CloudWatch Logs log group you specified. Additionally, when AWS launches a new region, CloudTrail will create the same trail in the new region. As a result, you will receive log files containing API activity for the new region without taking any action. Using the CloudTrail console, you can specify that a trail applies to all regions. For more details, refer to the Applying a trail to all regions section of the CloudTrail FAQ.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A company has a legacy application using a proprietary file system and plans to migrate the application to AWS. Which storage service should the company use?&lt;span class="hx:absolute hx:-mt-20" id="a-company-has-a-legacy-application-using-a-proprietary-file-system-and-plans-to-migrate-the-application-to-aws-which-storage-service-should-the-company-use"&gt;&lt;/span&gt;
&lt;a href="#a-company-has-a-legacy-application-using-a-proprietary-file-system-and-plans-to-migrate-the-application-to-aws-which-storage-service-should-the-company-use" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon DynamoDB
B. Amazon S3
C. Amazon EBS
D. Amazon EFS&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题有点蒙人，关键词在proprietary（专有的），EFS未必支持，只有EBS才能100%满足。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company plans to use AWS for all new batch processing workloads. The company&amp;rsquo;s developers use Docker containers for the new batch processing. The system design must accommodate critical and non-critical batch processing workloads 24/7. How should a Solutions Architect design this architecture in a cost-efficient manner?&lt;span class="hx:absolute hx:-mt-20" id="a-company-plans-to-use-aws-for-all-new-batch-processing-workloads-the-companys-developers-use-docker-containers-for-the-new-batch-processing-the-system-design-must-accommodate-critical-and-non-critical-batch-processing-workloads-247-how-should-a-solutions-architect-design-this-architecture-in-a-cost-efficient-manner"&gt;&lt;/span&gt;
&lt;a href="#a-company-plans-to-use-aws-for-all-new-batch-processing-workloads-the-companys-developers-use-docker-containers-for-the-new-batch-processing-the-system-design-must-accommodate-critical-and-non-critical-batch-processing-workloads-247-how-should-a-solutions-architect-design-this-architecture-in-a-cost-efficient-manner" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Purchase Reserved Instances to run all containers. Use Auto Scaling groups to schedule jobs.
B. Host a container management service on Spot Instances. Use Reserved Instances to run Docker containers.
C. Use Amazon ECS orchestration and Auto Scaling groups: one with Reserve Instances, one with Spot Instances.
D. Use Amazon ECS to manage container orchestration. Purchase Reserved Instances to run all batch workloads at the same time.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：绕嘴，多读两遍。主要是应对两种不同类型的任务。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company is evaluating Amazon S3 as a data storage solution for their daily analyst reports. The company has implemented stringent requirements concerning the security of the data at rest. Specifically, the CISO asked for the use of envelope encryption with separate permissions for the use of an envelope key, automated rotation of the encryption keys, and visibility into when an encryption key was used and by whom. Which steps should a Solutions Architect take to satisfy the security requirements requested by the CISO?&lt;span class="hx:absolute hx:-mt-20" id="a-company-is-evaluating-amazon-s3-as-a-data-storage-solution-for-their-daily-analyst-reports-the-company-has-implemented-stringent-requirements-concerning-the-security-of-the-data-at-rest-specifically-the-ciso-asked-for-the-use-of-envelope-encryption-with-separate-permissions-for-the-use-of-an-envelope-key-automated-rotation-of-the-encryption-keys-and-visibility-into-when-an-encryption-key-was-used-and-by-whom-which-steps-should-a-solutions-architect-take-to-satisfy-the-security-requirements-requested-by-the-ciso"&gt;&lt;/span&gt;
&lt;a href="#a-company-is-evaluating-amazon-s3-as-a-data-storage-solution-for-their-daily-analyst-reports-the-company-has-implemented-stringent-requirements-concerning-the-security-of-the-data-at-rest-specifically-the-ciso-asked-for-the-use-of-envelope-encryption-with-separate-permissions-for-the-use-of-an-envelope-key-automated-rotation-of-the-encryption-keys-and-visibility-into-when-an-encryption-key-was-used-and-by-whom-which-steps-should-a-solutions-architect-take-to-satisfy-the-security-requirements-requested-by-the-ciso" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create an Amazon S3 bucket to store the reports and use Server-Side Encryption with Customer-Provided Keys (SSE-C).
B. Create an Amazon S3 bucket to store the reports and use Server-Side Encryption with Amazon S3-Managed Keys (SSE-S3).
C. Create an Amazon S3 bucket to store the reports and use Server-Side Encryption with AWS KMS-Managed Keys (SSE-KMS).
D. Create an Amazon S3 bucket to store the reports and use Amazon s3 versioning with Server-Side Encryption with Amazon S3-Managed Keys (SSE-S3).&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：用S3 + KMS服务。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;(争议)A customer has a production application that frequently overwrites and deletes data, the application requires the most up-to-date version of the data every time it is requested. Which storage should a Solutions Architect recommend to bet accommodate this use case?&lt;span class="hx:absolute hx:-mt-20" id="争议a-customer-has-a-production-application-that-frequently-overwrites-and-deletes-data-the-application-requires-the-most-up-to-date-version-of-the-data-every-time-it-is-requested-which-storage-should-a-solutions-architect-recommend-to-bet-accommodate-this-use-case"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-customer-has-a-production-application-that-frequently-overwrites-and-deletes-data-the-application-requires-the-most-up-to-date-version-of-the-data-every-time-it-is-requested-which-storage-should-a-solutions-architect-recommend-to-bet-accommodate-this-use-case" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon S3
B. Amazon RDS
C. Amazon RedShift
D. AWS Storage Gateway&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题的争议点在答案B，因为S3提供eventual consistency for overwirte PUTS and DELETES，可能会导致无法获取最新数据的问题。不确定该问题是否会考到，暂时没有找到更合理的解释。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Amazon S3 Data Consistency Model(&lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/dev/Introduction.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/AmazonS3/latest/dev/Introduction.html&lt;/a&gt;)
Amazon S3 provides read-after-write consistency for PUTS of new objects in your S3 bucket in all Regions with one caveat. The caveat is that if you make a HEAD or GET request to the key name (to find if the object exists) before creating the object, Amazon S3 provides eventual consistency for read-after-write.&lt;/p&gt;
&lt;p&gt;Amazon S3 offers eventual consistency for overwrite PUTS and DELETES in all Regions.&lt;/p&gt;
&lt;p&gt;Updates to a single key are atomic. For example, if you PUT to an existing key, a subsequent read might return the old data or the updated data, but it never returns corrupted or partial data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A Solutions Architect is designing a photo application on AWS. Every time a user uploads a photo to Amazon S3, the Architect must insert a new item to a&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-photo-application-on-aws-every-time-a-user-uploads-a-photo-to-amazon-s3-the-architect-must-insert-a-new-item-to-a"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-photo-application-on-aws-every-time-a-user-uploads-a-photo-to-amazon-s3-the-architect-must-insert-a-new-item-to-a" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;DynamoDB table. Which AWS-managed service is the BEST fit to insert the item?&lt;/p&gt;
&lt;p&gt;A. Lambda@Edge
B. AWS Lambda
C. Amazon API Gateway
D. Amazon EC2 instances&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;参考链接：https://aws.amazon.com/cn/blogs/machine-learning/build-your-own-face-recognition-service-using-amazon-rekognition/&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;An application relies on messages being sent and received in order. The volume will never exceed more than 300 transactions each second. Which service should be used?&lt;span class="hx:absolute hx:-mt-20" id="an-application-relies-on-messages-being-sent-and-received-in-order-the-volume-will-never-exceed-more-than-300-transactions-each-second-which-service-should-be-used"&gt;&lt;/span&gt;
&lt;a href="#an-application-relies-on-messages-being-sent-and-received-in-order-the-volume-will-never-exceed-more-than-300-transactions-each-second-which-service-should-be-used" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon SQS
B. Amazon SNS
C. Amazon ECS
D. AWS STS&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;问：Amazon SNS 与 Amazon SQS 有何不同？&lt;/p&gt;
&lt;p&gt;Amazon Simple Queue Service (SQS) 和 Amazon SNS 都是 AWS 中的消息收发服务，但为开发人员提供了不同的优势。Amazon SNS 允许应用程序通过“推送”机制向多个订阅者发送时间关键型消息，并且无需定期检查或“轮询”更新。Amazon SQS 是一种供分布式应用程序使用的消息队列服务，通过轮询模式交换消息，可用于分离收发组件。Amazon SQS 使应用程序的分布式组件可以灵活地收发消息，并且不要求每个组件同时可用。&lt;/p&gt;
&lt;p&gt;一种常见的模式是使用 SNS 将消息发布到 Amazon SQS 队列，进而以可靠的方式将消息异步发送到一个或多个系统组件。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A Solutions Architect is designing an application on AWS that uses persistent block storage. Data must be encrypted at rest. Which solution meets the requirement?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-an-application-on-aws-that-uses-persistent-block-storage-data-must-be-encrypted-at-rest-which-solution-meets-the-requirement"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-an-application-on-aws-that-uses-persistent-block-storage-data-must-be-encrypted-at-rest-which-solution-meets-the-requirement" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Enable SSL on Amazon EC2 instances.
B. Encrypt Amazon EBS volumes on Amazon EC2 instances.
C. Enable server-side encryption on Amazon S3.
D. Encrypt Amazon EC2 Instance Storage.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New EBS Encryption for Additional Data Protection(&lt;a href="https://aws.amazon.com/cn/blogs/aws/protect-your-data-with-new-ebs-encryption/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/cn/blogs/aws/protect-your-data-with-new-ebs-encryption/&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;(争议)A company is launching a static website using the zone apex (mycompany.com). The company wants to use Amazon Route 53 for DNS. Which steps should the company perform to implement a scalable and cost-effective solution? (Choose two.)&lt;span class="hx:absolute hx:-mt-20" id="争议a-company-is-launching-a-static-website-using-the-zone-apex-mycompanycom-the-company-wants-to-use-amazon-route-53-for-dns-which-steps-should-the-company-perform-to-implement-a-scalable-and-cost-effective-solution-choose-two"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-company-is-launching-a-static-website-using-the-zone-apex-mycompanycom-the-company-wants-to-use-amazon-route-53-for-dns-which-steps-should-the-company-perform-to-implement-a-scalable-and-cost-effective-solution-choose-two" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Host the website on an Amazon EC2 instance with ELB and Auto Scaling, and map a Route 53 alias record to the ELB endpoint.
B. Host the website using AWS Elastic Beanstalk, and map a Route 53 alias record to the Beanstalk stack.
C. Host the website on an Amazon EC2 instance, and map a Route 53 alias record to the public IP address of the Amazon EC2 instance.
D. Serve the website from an Amazon S3 bucket, and map a Route 53 alias record to the website endpoint.
E. Create a Route 53 hosted zone, and set the NS records of the domain to use Route 53 name servers.&lt;/p&gt;
&lt;p&gt;Answer: DE&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：又是一道争议非常大的题，原来的答案是CD，从cost-effective的角度说C确实不够经济。参考AWS如何构建静态网站的最佳实践：https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;(争议)A manufacturing company captures data from machines running at customer sites. Currently, thousands of machines send data every 5 minutes, and this is expected to grow to hundreds of thousands of machines in the near future. The data is logged with the intent to be analyzed in the future as needed. What is the SIMPLEST method to store this streaming data at scale?&lt;span class="hx:absolute hx:-mt-20" id="争议a-manufacturing-company-captures-data-from-machines-running-at-customer-sites-currently-thousands-of-machines-send-data-every-5-minutes-and-this-is-expected-to-grow-to-hundreds-of-thousands-of-machines-in-the-near-future-the-data-is-logged-with-the-intent-to-be-analyzed-in-the-future-as-needed-what-is-the-simplest-method-to-store-this-streaming-data-at-scale"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-manufacturing-company-captures-data-from-machines-running-at-customer-sites-currently-thousands-of-machines-send-data-every-5-minutes-and-this-is-expected-to-grow-to-hundreds-of-thousands-of-machines-in-the-near-future-the-data-is-logged-with-the-intent-to-be-analyzed-in-the-future-as-needed-what-is-the-simplest-method-to-store-this-streaming-data-at-scale" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create an Amazon Kinesis Firehouse delivery stream to store the data in Amazon S3.
B. Create an Auto Scaling group of Amazon EC2 servers behind ELBs to write the data into Amazon RDS.
C. Create an Amazon SQS queue, and have the machines write to the queue.
D. Create an Amazon EC2 server farm behind an ELB to store the data in Amazon EBS Cold HDD volumes.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：很奇怪为什么原有答案给出B，这道题明显是暗指实时计算Kinesis服务。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A bank is writing new software that is heavily dependent upon the database transactions for write consistency. The application will also occasionally generate reports on data in the database, and will do joins across multiple tables. The database must automatically scale as the amount of data grows. Which AWS service should be used to run the database?&lt;span class="hx:absolute hx:-mt-20" id="a-bank-is-writing-new-software-that-is-heavily-dependent-upon-the-database-transactions-for-write-consistency-the-application-will-also-occasionally-generate-reports-on-data-in-the-database-and-will-do-joins-across-multiple-tables-the-database-must-automatically-scale-as-the-amount-of-data-grows-which-aws-service-should-be-used-to-run-the-database"&gt;&lt;/span&gt;
&lt;a href="#a-bank-is-writing-new-software-that-is-heavily-dependent-upon-the-database-transactions-for-write-consistency-the-application-will-also-occasionally-generate-reports-on-data-in-the-database-and-will-do-joins-across-multiple-tables-the-database-must-automatically-scale-as-the-amount-of-data-grows-which-aws-service-should-be-used-to-run-the-database" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon S3
B. Amazon Aurora
C. Amazon DynamoDB
D. Amazon Redshift&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：很明显需要关系型数据库。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is designing a new application that needs to access data in a different AWS account located within the same region. The data must not be accessed over the Internet. Which solution will meet these requirements with the LOWEST cost?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-new-application-that-needs-to-access-data-in-a-different-aws-account-located-within-the-same-region-the-data-must-not-be-accessed-over-the-internet-which-solution-will-meet-these-requirements-with-the-lowest-cost"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-new-application-that-needs-to-access-data-in-a-different-aws-account-located-within-the-same-region-the-data-must-not-be-accessed-over-the-internet-which-solution-will-meet-these-requirements-with-the-lowest-cost" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Add rules to the security groups in each account.
B. Establish a VPC Peering connection between accounts.
C. Configure Direct Connect in each account.
D. Add a NAT Gateway to the data account.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：B的方案是成本最低的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is designing a mobile application that will capture receipt images to track expenses. The Architect wants to store the images on Amazon S3. However, uploading images through the web server will create too much traffic. What is the MOST efficient method to store images from a mobile application on Amazon S3?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-mobile-application-that-will-capture-receipt-images-to-track-expenses-the-architect-wants-to-store-the-images-on-amazon-s3-however-uploading-images-through-the-web-server-will-create-too-much-traffic-what-is-the-most-efficient-method-to-store-images-from-a-mobile-application-on-amazon-s3"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-mobile-application-that-will-capture-receipt-images-to-track-expenses-the-architect-wants-to-store-the-images-on-amazon-s3-however-uploading-images-through-the-web-server-will-create-too-much-traffic-what-is-the-most-efficient-method-to-store-images-from-a-mobile-application-on-amazon-s3" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Upload directly to S3 using a pre-signed URL.
B. Upload to a second bucket, and have a Lambda event copy the image to the primary bucket.
C. Upload to a separate Auto Scaling group of servers behind an ELB Classic Load Balancer, and have them write to the Amazon S3 bucket.
D. Expand the web server fleet with Spot Instances to provide the resources to handle the images.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：A选项相较于题目中描述的并没有本质区别。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;A presigned URL gives you access to the object identified in the URL, provided that the creator of the presigned URL has permissions to access that object. That is, if you receive a presigned URL to upload an object, you can upload the object only if the creator of the presigned URL has the necessary permissions to upload that object.&lt;/p&gt;
&lt;p&gt;All objects and buckets by default are private. The presigned URLs are useful if you want your user/customer to be able to upload a specific object to your bucket, but you don&amp;rsquo;t require them to have AWS security credentials or permissions. When you create a presigned URL, you must provide your security credentials and then specify a bucket name, an object key, an HTTP method (PUT for uploading objects), and an expiration date and time. The presigned URLs are valid only for the specified duration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A company requires that the source, destination, and protocol of all IP packets be recorded when traversing a private subnet. What is the MOST secure and reliable method of accomplishing this goal.&lt;span class="hx:absolute hx:-mt-20" id="a-company-requires-that-the-source-destination-and-protocol-of-all-ip-packets-be-recorded-when-traversing-a-private-subnet-what-is-the-most-secure-and-reliable-method-of-accomplishing-this-goal"&gt;&lt;/span&gt;
&lt;a href="#a-company-requires-that-the-source-destination-and-protocol-of-all-ip-packets-be-recorded-when-traversing-a-private-subnet-what-is-the-most-secure-and-reliable-method-of-accomplishing-this-goal" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create VPC flow logs on the subnet.
B. Enable source destination check on private Amazon EC2 instances.
C. Enable AWS CloudTrail logging and specify an Amazon S3 bucket for storing log files.
D. Create an Amazon CloudWatch log to capture packet information.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：启动VPC流表日志, CloudTrail没有此能力&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect has a multi-layer application running in Amazon VPC. The application has an ELB Classic Load Balancer as the front end in a public subnet, and an Amazon EC2-based reverse proxy that performs content-based routing to two backend Amazon EC2 instances hosted in a private subnet. The Architect sees tremendous traffic growth and is concerned that the reverse proxy and current backend set up will be insufficient. Which actions should the Architect take to achieve a cost-effective solution that ensures the application automatically scales to meet traffic demand? (Select two.)&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-has-a-multi-layer-application-running-in-amazon-vpc-the-application-has-an-elb-classic-load-balancer-as-the-front-end-in-a-public-subnet-and-an-amazon-ec2-based-reverse-proxy-that-performs-content-based-routing-to-two-backend-amazon-ec2-instances-hosted-in-a-private-subnet-the-architect-sees-tremendous-traffic-growth-and-is-concerned-that-the-reverse-proxy-and-current-backend-set-up-will-be-insufficient-which-actions-should-the-architect-take-to-achieve-a-cost-effective-solution-that-ensures-the-application-automatically-scales-to-meet-traffic-demand-select-two"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-has-a-multi-layer-application-running-in-amazon-vpc-the-application-has-an-elb-classic-load-balancer-as-the-front-end-in-a-public-subnet-and-an-amazon-ec2-based-reverse-proxy-that-performs-content-based-routing-to-two-backend-amazon-ec2-instances-hosted-in-a-private-subnet-the-architect-sees-tremendous-traffic-growth-and-is-concerned-that-the-reverse-proxy-and-current-backend-set-up-will-be-insufficient-which-actions-should-the-architect-take-to-achieve-a-cost-effective-solution-that-ensures-the-application-automatically-scales-to-meet-traffic-demand-select-two" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Replace the Amazon EC2 reverse proxy with an ELB internal Classic Load Balancer.
B. Add Auto Scaling to the Amazon EC2 backend fleet.
C. Add Auto Scaling to the Amazon EC2 reverse proxy layer.
D. Use t2 burstable instance types for the backend fleet.
E. Replace both the frontend and reverse proxy layers with an ELB Application Load Balancer.&lt;/p&gt;
&lt;p&gt;Answer: BE&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：又是一道错题，原答案是AB。根据题目分析，出现瓶颈的地方来自于两处：反向代理和后端服务。后端服务的扩展没有什么争议，所以B很明显是正确的。最大的争议来自于是使用什么方式替代目前成为瓶颈的反向代理EC2。原题里反向代理EC2作为content-based routing，那么问题的关键就是CLB、ELB谁能做content-based routing了。根据目前最新的内容，所以需要使用Application Load Balancer来提供content-based routing了。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;There are three types of Elastic Load Balancer (ELB) on AWS:&lt;/p&gt;
&lt;p&gt;Classic Load Balancer (CLB) – this is the oldest of the three and provides basic load balancing at both layer 4 and layer 7.&lt;/p&gt;
&lt;p&gt;Application Load Balancer (ALB) – layer 7 load balancer that routes connections based on the content of the request.&lt;/p&gt;
&lt;p&gt;Network Load Balancer (NLB) – layer 4 load balancer that routes connections based on IP protocol data.&lt;/p&gt;
&lt;p&gt;Note: The Classic Load Balancer may be phased out over time and Amazon are promoting the ALB and NLB for most use cases within VPC.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Introducing Amazon EC2 Fleet
Posted On: May 2, 2018&lt;/p&gt;
&lt;p&gt;Amazon EC2 Fleet is a new feature that simplifies the provisioning of Amazon EC2 capacity across different Amazon EC2 instance types, Availability Zones and across On-Demand, Amazon EC2 Reserved Instances (RI) and Amazon EC2 Spot purchase models. With a single API call, now you can provision capacity across EC2 instance types and across purchase models to achieve desired scale, performance and cost.&lt;/p&gt;
&lt;p&gt;You can create an EC2 Fleet specification defining target capacity, which EC2 instance types work for you, and how much of your fleet should be filled using On-Demand, RI and Spot purchase models. You can also indicate whether EC2 Fleet should take into account the number of cores and amount of memory on each instance or consider all instances equal when scaling. EC2 Fleet then launches the lowest price combination of instances to meet the target capacity based on these preferences. EC2 fleet enables you to use multiple instance types and purchase models to provision capacity cost effectively, with just a few clicks in the AWS Management Console.&lt;/p&gt;
&lt;p&gt;Amazon EC2 Fleet is now available in all public Regions. To learn more about simplifying the provisioning of Amazon EC2 capacity across different Amazon EC2 instance types, AWS Availability Zones and across On-Demand, RI and Spot purchase models using Amazon EC2 Fleet, visit this blog. To learn more about Amazon EC2 pricing models, visit this page.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;EC2 Fleet – Manage Thousands of On-Demand and Spot Instances with One Request(&lt;a href="https://amazonaws-china.com/blogs/aws/ec2-fleet-manage-thousands-of-on-demand-and-spot-instances-with-one-request/"target="_blank" rel="noopener"&gt;https://amazonaws-china.com/blogs/aws/ec2-fleet-manage-thousands-of-on-demand-and-spot-instances-with-one-request/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;New – Advanced Request Routing for AWS Application Load Balancers(&lt;a href="https://amazonaws-china.com/blogs/aws/new-advanced-request-routing-for-aws-application-load-balancers/"target="_blank" rel="noopener"&gt;https://amazonaws-china.com/blogs/aws/new-advanced-request-routing-for-aws-application-load-balancers/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;ELASTIC LOAD BALANCING(&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/compute/elastic-load-balancing/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/compute/elastic-load-balancing/&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company is launching a marketing campaign on their website tomorrow and expects a significant increase in traffic. The website is designed as a multi-tiered web architecture, and the increase in traffic could potentially overwhelm the current design. What should a Solutions Architect do to minimize the effects from a potential failure in one or more of the tiers?&lt;span class="hx:absolute hx:-mt-20" id="a-company-is-launching-a-marketing-campaign-on-their-website-tomorrow-and-expects-a-significant-increase-in-traffic-the-website-is-designed-as-a-multi-tiered-web-architecture-and-the-increase-in-traffic-could-potentially-overwhelm-the-current-design-what-should-a-solutions-architect-do-to-minimize-the-effects-from-a-potential-failure-in-one-or-more-of-the-tiers"&gt;&lt;/span&gt;
&lt;a href="#a-company-is-launching-a-marketing-campaign-on-their-website-tomorrow-and-expects-a-significant-increase-in-traffic-the-website-is-designed-as-a-multi-tiered-web-architecture-and-the-increase-in-traffic-could-potentially-overwhelm-the-current-design-what-should-a-solutions-architect-do-to-minimize-the-effects-from-a-potential-failure-in-one-or-more-of-the-tiers" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Migrate the database to Amazon RDS.
B. Set up DNS failover to a statistic website.
C. Use Auto Scaling to keep up with the demand.
D. Use both a SQL and a NoSQL database in the design.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：明天就上线了，改啥都来不及了，还是价格Auto scaling策略吧。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A web application experiences high compute costs due to serving a high amount of static web content. How should the web server architecture be designed to be the MOST cost-efficient?&lt;span class="hx:absolute hx:-mt-20" id="a-web-application-experiences-high-compute-costs-due-to-serving-a-high-amount-of-static-web-content-how-should-the-web-server-architecture-be-designed-to-be-the-most-cost-efficient"&gt;&lt;/span&gt;
&lt;a href="#a-web-application-experiences-high-compute-costs-due-to-serving-a-high-amount-of-static-web-content-how-should-the-web-server-architecture-be-designed-to-be-the-most-cost-efficient" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create an Auto Scaling group to scale out based on average CPU usage.
B. Create an Amazon CloudFront distribution to pull static content from an Amazon S3 bucket.
C. Leverage Reserved Instances to add additional capacity at a significantly lower price.
D. Create a multi-region deployment using an Amazon Route 53 geolocation routing policy.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;A web application experiences high compute costs due to serving a high amount of static web content. How should the web server architecture be designed to be the MOST cost-efficient?&lt;span class="hx:absolute hx:-mt-20" id="a-web-application-experiences-high-compute-costs-due-to-serving-a-high-amount-of-static-web-content-how-should-the-web-server-architecture-be-designed-to-be-the-most-cost-efficient-1"&gt;&lt;/span&gt;
&lt;a href="#a-web-application-experiences-high-compute-costs-due-to-serving-a-high-amount-of-static-web-content-how-should-the-web-server-architecture-be-designed-to-be-the-most-cost-efficient-1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create an Auto Scaling group to scale out based on average CPU usage.
B. Create an Amazon CloudFront distribution to pull static content from an Amazon S3 bucket.
C. Leverage Reserved Instances to add additional capacity at a significantly lower price.
D. Create a multi-region deployment using an Amazon Route 53 geolocation routing policy.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;A Solutions Architect plans to migrate NAT instances to NAT gateway. The Architect has NAT instances with scripts to manage high availability. What is the MOST efficient method to achieve similar high availability with NAT gateway?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-plans-to-migrate-nat-instances-to-nat-gateway-the-architect-has-nat-instances-with-scripts-to-manage-high-availability-what-is-the-most-efficient-method-to-achieve-similar-high-availability-with-nat-gateway"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-plans-to-migrate-nat-instances-to-nat-gateway-the-architect-has-nat-instances-with-scripts-to-manage-high-availability-what-is-the-most-efficient-method-to-achieve-similar-high-availability-with-nat-gateway" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Remove source/destination check on NAT instances.
B. Launch a NAT gateway in each Availability Zone.
C. Use a mix of NAT instances and NAT gateway.
D. Add an ELB Application Load Balancer in front of NAT gateway.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NAT 实例与 NAT 网关的比较(&lt;a href="https://docs.aws.amazon.com/zh_cn/vpc/latest/userguide/vpc-nat-comparison.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/zh_cn/vpc/latest/userguide/vpc-nat-comparison.html&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;每个 NAT 网关都在特定可用区中创建，并在该可用区进行冗余实施。您可以在一个可用区中创建的 NAT 网关存在数量限制。有关更多信息，请参阅 Amazon VPC 限制。&lt;/p&gt;
&lt;p&gt;注意:
如果您在多个可用区中拥有资源，并且它们共享一个 NAT 网关，则在该 NAT 网关的可用区不可用时，其他可用区中的资源将无法访问 Internet。要创建不依赖于可用区的架构，请在每个可用区中都创建一个 NAT 网关，并配置路由以确保这些资源使用自身可用区中的 NAT 网关。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A Solutions Architect is designing a solution to store a large quantity of event data in Amazon S3. The Architect anticipates that the workload will consistently exceed 100 requests each second. What should the Architect do in Amazon S3 to optimize performance?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-solution-to-store-a-large-quantity-of-event-data-in-amazon-s3-the-architect-anticipates-that-the-workload-will-consistently-exceed-100-requests-each-second-what-should-the-architect-do-in-amazon-s3-to-optimize-performance"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-solution-to-store-a-large-quantity-of-event-data-in-amazon-s3-the-architect-anticipates-that-the-workload-will-consistently-exceed-100-requests-each-second-what-should-the-architect-do-in-amazon-s3-to-optimize-performance" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Randomize a key name prefix.
B. Store the event data in separate buckets.
C. Randomize the key name suffix.
D. Use Amazon S3 Transfer Acceleration.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题和上面有道题类似，目前S3建议使用时间作为prefix，原来是建议使用hash方式。&lt;/li&gt;
&lt;li&gt;最佳实践设计模式：优化 Amazon S3 性能(&lt;a href="https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/dev/optimizing-performance.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/dev/optimizing-performance.html&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;下面的主题介绍的最佳实践准则和设计模式用于优化使用 Amazon S3 的应用程序的性能。本指南的优先级高于之前有关优化 Amazon S3 的性能的任何指南。例如，以前的 Amazon S3 性能指南建议用哈希字符来随机化前缀命名，以便优化频繁数据检索的性能。现在，您不再需要为了提高性能随机化前缀命名，而是可以对前缀使用基于顺序日期的命名方式。有关对 Amazon S3 进行性能优化的最新信息，请参阅Amazon S3 的性能准则和Amazon S3 的性能设计模式。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A user is testing a new service that receives location updates from 3,600 rental cars every hour. Which service will collect data and automatically scale to accommodate production workload?&lt;span class="hx:absolute hx:-mt-20" id="a-user-is-testing-a-new-service-that-receives-location-updates-from-3600-rental-cars-every-hour-which-service-will-collect-data-and-automatically-scale-to-accommodate-production-workload"&gt;&lt;/span&gt;
&lt;a href="#a-user-is-testing-a-new-service-that-receives-location-updates-from-3600-rental-cars-every-hour-which-service-will-collect-data-and-automatically-scale-to-accommodate-production-workload" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon EC2
B. Amazon Kinesis Firehose
C. Amazon EBS
D. Amazon API Gateway&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：又是一道争议题，大部分给出的答案是B，就应用场景上看Kinesis更适合实时计算场景。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is designing a web application. The web and application tiers need to access the Internet, but they cannot be accessed from the Internet. Which of the following steps is required?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-web-application-the-web-and-application-tiers-need-to-access-the-internet-but-they-cannot-be-accessed-from-the-internet-which-of-the-following-steps-is-required"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-web-application-the-web-and-application-tiers-need-to-access-the-internet-but-they-cannot-be-accessed-from-the-internet-which-of-the-following-steps-is-required" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Attach an Elastic IP address to each Amazon EC2 instance and add a route from the private subnet to the public subnet.
B. Launch a NAT gateway in the public subnet and add a route to it from the private subnet.
C. Launch Amazon EC2 instances in the public subnet and change the security group to allow outbound traffic on port 80.
D. Launch a NAT gateway in the private subnet and deploy a NAT instance in the private subnet.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;An application stack includes an Elastic Load Balancer in a public subnet, a fleet of Amazon EC2 instances in an Auto Scaling group, and an Amazon RDS MySQL cluster. Users connect to the application from the Internet. The application servers and database must be secure. How should a Solutions Architect perform this task?&lt;span class="hx:absolute hx:-mt-20" id="an-application-stack-includes-an-elastic-load-balancer-in-a-public-subnet-a-fleet-of-amazon-ec2-instances-in-an-auto-scaling-group-and-an-amazon-rds-mysql-cluster-users-connect-to-the-application-from-the-internet-the-application-servers-and-database-must-be-secure-how-should-a-solutions-architect-perform-this-task"&gt;&lt;/span&gt;
&lt;a href="#an-application-stack-includes-an-elastic-load-balancer-in-a-public-subnet-a-fleet-of-amazon-ec2-instances-in-an-auto-scaling-group-and-an-amazon-rds-mysql-cluster-users-connect-to-the-application-from-the-internet-the-application-servers-and-database-must-be-secure-how-should-a-solutions-architect-perform-this-task" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create a private subnet for the Amazon EC2 instances and a public subnet for the Amazon RDS cluster.
B. Create a private subnet for the Amazon EC2 instances and a private subnet for the Amazon RDS cluster.
C. Create a public subnet for the Amazon EC2 instances and a private subnet for the Amazon RDS cluster.
D. Create a public subnet for the Amazon EC2 instances and a public subnet for the Amazon RDS cluster.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：答案给出的是C，有多种方式证明这个答案是错误的。&lt;/li&gt;
&lt;li&gt;How do I connect a public-facing load balancer to EC2 instances that have private IP addresses?(&lt;a href="https://amazonaws-china.com/premiumsupport/knowledge-center/public-load-balancer-private-ec2/"target="_blank" rel="noopener"&gt;https://amazonaws-china.com/premiumsupport/knowledge-center/public-load-balancer-private-ec2/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;AWS Best Practices: 3-Tier Infrastructure(&lt;a href="https://blog.stratus10.com/aws-best-practices-3-tier-infrastructure"target="_blank" rel="noopener"&gt;https://blog.stratus10.com/aws-best-practices-3-tier-infrastructure&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is designing a solution for a media company that will stream large amounts of data from an Amazon EC2 instance. The data streams are typically large and sequential, and must be able to support up to 500 MB/s. Which storage type will meet the performance requirements of this application?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-solution-for-a-media-company-that-will-stream-large-amounts-of-data-from-an-amazon-ec2-instance-the-data-streams-are-typically-large-and-sequential-and-must-be-able-to-support-up-to-500-mbs-which-storage-type-will-meet-the-performance-requirements-of-this-application"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-solution-for-a-media-company-that-will-stream-large-amounts-of-data-from-an-amazon-ec2-instance-the-data-streams-are-typically-large-and-sequential-and-must-be-able-to-support-up-to-500-mbs-which-storage-type-will-meet-the-performance-requirements-of-this-application" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. EBS Provisioned IOPS SSD
B. EBS General Purpose SSD
C. EBS Cold HDD
D. EBS Throughput Optimized HDD&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;h2&gt;(争议)A legacy application running in premises requires a Solutions Architect to be able to open a firewall to allow access to several Amazon S3 buckets. The Architect has a VPN connection to AWS in place. How should the Architect meet this requirement?&lt;span class="hx:absolute hx:-mt-20" id="争议a-legacy-application-running-in-premises-requires-a-solutions-architect-to-be-able-to-open-a-firewall-to-allow-access-to-several-amazon-s3-buckets-the-architect-has-a-vpn-connection-to-aws-in-place-how-should-the-architect-meet-this-requirement"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-legacy-application-running-in-premises-requires-a-solutions-architect-to-be-able-to-open-a-firewall-to-allow-access-to-several-amazon-s3-buckets-the-architect-has-a-vpn-connection-to-aws-in-place-how-should-the-architect-meet-this-requirement" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create an IAM role that allows access from the corporate network to Amazon S3.
B. Configure a proxy on Amazon EC2 and use an Amazon S3 VPC endpoint.
C. Use Amazon API Gateway to do IP whitelisting.
D. Configure IP whitelisting on the customer&amp;rsquo;s gateway.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：争议较大的一道题，这里采用了这个解释：https://d0.awsstatic.com/aws-answers/Accessing_VPC_Endpoints_from_Remote_Networks.pdf&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is designing a database solution that must support a high rate of random disk reads and writes. It must provide consistent performance, and requires long-term persistence. Which storage solution BEST meets these requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-database-solution-that-must-support-a-high-rate-of-random-disk-reads-and-writes-it-must-provide-consistent-performance-and-requires-long-term-persistence-which-storage-solution-best-meets-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-database-solution-that-must-support-a-high-rate-of-random-disk-reads-and-writes-it-must-provide-consistent-performance-and-requires-long-term-persistence-which-storage-solution-best-meets-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. An Amazon EBS Provisioned IOPS volume
B. An Amazon EBS General Purpose volume
C. An Amazon EBS Magnetic volume
D. An Amazon EC2 Instance Store&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;h2&gt;A Solutions Architect is designing solution with AWS Lambda where different environments require different database passwords. What should the Architect do to accomplish this in a secure and scalable way?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-solution-with-aws-lambda-where-different-environments-require-different-database-passwords-what-should-the-architect-do-to-accomplish-this-in-a-secure-and-scalable-way"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-solution-with-aws-lambda-where-different-environments-require-different-database-passwords-what-should-the-architect-do-to-accomplish-this-in-a-secure-and-scalable-way" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create a Lambda function for each individual environment.
B. Use Amazon DynamoDB to store environmental variables.
C. Use encrypted AWS Lambda environmental variables.
D. Implement a dedicated Lambda function for distributing variables.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;A news organization plans to migrate their 20 TB video archive to AWS. The files are rarely accessed, but when they are, a request is made in advance and a 3 to 5-hour retrieval time frame is acceptable. However, when there is a breaking news story, the editors require access to archived footage within minutes. Which storage solution meets the needs of this organization while providing the LOWEST cost of storage?&lt;span class="hx:absolute hx:-mt-20" id="a-news-organization-plans-to-migrate-their-20-tb-video-archive-to-aws-the-files-are-rarely-accessed-but-when-they-are-a-request-is-made-in-advance-and-a-3-to-5-hour-retrieval-time-frame-is-acceptable-however-when-there-is-a-breaking-news-story-the-editors-require-access-to-archived-footage-within-minutes-which-storage-solution-meets-the-needs-of-this-organization-while-providing-the-lowest-cost-of-storage"&gt;&lt;/span&gt;
&lt;a href="#a-news-organization-plans-to-migrate-their-20-tb-video-archive-to-aws-the-files-are-rarely-accessed-but-when-they-are-a-request-is-made-in-advance-and-a-3-to-5-hour-retrieval-time-frame-is-acceptable-however-when-there-is-a-breaking-news-story-the-editors-require-access-to-archived-footage-within-minutes-which-storage-solution-meets-the-needs-of-this-organization-while-providing-the-lowest-cost-of-storage" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Store the archive in Amazon S3 Reduced Redundancy Storage.
B. Store the archive in Amazon Glacier and use standard retrieval for all content.
C. Store the archive in Amazon Glacier and pay the additional charge for expedited retrieval when needed.
D. Store the archive in Amazon S3 with a lifecycle policy to move this to S3 Infrequent Access after 30 days.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;问：从 Amazon S3 Glacier 检索数据如何收费？&lt;/p&gt;
&lt;p&gt;从 Amazon S3 Glacier 检索数据的方式有三种：加急、标准和批量检索。每种方式具有不同的每 GB 检索费和每存档请求费（即请求一个存档计为一个请求）。有关不同 AWS 区域的 S3 Glacier 定价的详细信息，请访问 Amazon S3 Glacier 定价页面。&lt;/p&gt;
&lt;p&gt;定价标准： &lt;a href="https://amazonaws-china.com/cn/glacier/pricing/"target="_blank" rel="noopener"&gt;https://amazonaws-china.com/cn/glacier/pricing/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A Solutions Architect is building a multi-tier website. The web servers will be in a public subnet, and the database servers will be in a private subnet. Only the web servers can be accessed from the Internet. The database servers must have Internet access for software updates. Which solution meets the requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-building-a-multi-tier-website-the-web-servers-will-be-in-a-public-subnet-and-the-database-servers-will-be-in-a-private-subnet-only-the-web-servers-can-be-accessed-from-the-internet-the-database-servers-must-have-internet-access-for-software-updates-which-solution-meets-the-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-building-a-multi-tier-website-the-web-servers-will-be-in-a-public-subnet-and-the-database-servers-will-be-in-a-private-subnet-only-the-web-servers-can-be-accessed-from-the-internet-the-database-servers-must-have-internet-access-for-software-updates-which-solution-meets-the-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Assign Elastic IP addresses to the database instances.
B. Allow Internet traffic on the private subnet through the network ACL.
C. Use a NAT Gateway.
D. Use an egress-only Internet Gateway.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;A Solutions Architect is designing a Lambda function that calls an API to list all running Amazon RDS instances. How should the request be authorized?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-lambda-function-that-calls-an-api-to-list-all-running-amazon-rds-instances-how-should-the-request-be-authorized"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-lambda-function-that-calls-an-api-to-list-all-running-amazon-rds-instances-how-should-the-request-be-authorized" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create an IAM access and secret key, and store it in the Lambda function.
B. Create an IAM role to the Lambda function with permissions to list all Amazon RDS instances.
C. Create an IAM role to Amazon RDS with permissions to list all Amazon RDS instances.
D. Create an IAM access and secret key, and store it in an encrypted RDS database.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;教程：配置 Lambda 函数以访问 Amazon VPC 中的 Amazon RDS&lt;/p&gt;
&lt;p&gt;打开 IAM 控制台中的“角色”页面。
选择 Create role (创建角色)。
创建具有以下属性的角色。
Trusted entity (可信任的实体) – Lambda.
权限 – AWSLambdaVPCAccessExecutionRole。
角色名称 (角色名称) – lambda-vpc-role。
AWSLambdaVPCAccessExecutionRole 具有函数管理与 VPC 的网络连接所需的权限。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A Solutions Architect is building an application on AWS that will require 20,000 IOPS on a particular volume to support a media event. Once the event ends, the IOPS need is no longer required. The marketing team asks the Architect to build the platform to optimize storage without incurring downtime. How should the Architect design the platform to meet these requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-building-an-application-on-aws-that-will-require-20000-iops-on-a-particular-volume-to-support-a-media-event-once-the-event-ends-the-iops-need-is-no-longer-required-the-marketing-team-asks-the-architect-to-build-the-platform-to-optimize-storage-without-incurring-downtime-how-should-the-architect-design-the-platform-to-meet-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-building-an-application-on-aws-that-will-require-20000-iops-on-a-particular-volume-to-support-a-media-event-once-the-event-ends-the-iops-need-is-no-longer-required-the-marketing-team-asks-the-architect-to-build-the-platform-to-optimize-storage-without-incurring-downtime-how-should-the-architect-design-the-platform-to-meet-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Change the Amazon EC2 instant types.
B. Change the EBS volume type to Provisioned IOPS.
C. Stop the Amazon EC2 instance and provision IOPS for the EBS volume.
D. Enable an API Gateway to change the endpoints for the Amazon EC2 instances.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;打开 Amazon EC2 控制台 &lt;a href="https://console.aws.amazon.com/ec2/"target="_blank" rel="noopener"&gt;https://console.aws.amazon.com/ec2/&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;选择 Volumes，选择要修改的卷，然后依次选择 Actions、Modify Volume。&lt;/p&gt;
&lt;p&gt;Modify Volume 窗口显示卷 ID 和卷的当前配置，包括类型、大小和 IOPS。您可以在单个操作中更改任何或所有这些设置。设置新的配置值，如下所述：&lt;/p&gt;
&lt;p&gt;要修改类型，请为 Volume Type 选择一个值。&lt;/p&gt;
&lt;p&gt;要修改大小，请为 Size 输入一个允许的整数值。&lt;/p&gt;
&lt;p&gt;如果选择预配置 IOPS SSD (io1) 作为卷类型，请为 IOPS 输入一个允许的整数值。&lt;/p&gt;
&lt;p&gt;完成更改卷设置后，请选择 Modify (修改)。当系统提示您确认时，请选择 Yes。&lt;/p&gt;
&lt;p&gt;在扩展卷的文件系统以使用新的存储容量之前，修改卷大小没有实际效果。有关更多信息，请参阅调整卷大小后扩展 Linux 文件系统。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A Solutions Architect is building a new feature using a Lambda to create metadata when a user uploads a picture to Amazon S3. All metadata must be indexed. Which AWS service should the Architect use to store this metadata?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-building-a-new-feature-using-a-lambda-to-create-metadata-when-a-user-uploads-a-picture-to-amazon-s3-all-metadata-must-be-indexed-which-aws-service-should-the-architect-use-to-store-this-metadata"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-building-a-new-feature-using-a-lambda-to-create-metadata-when-a-user-uploads-a-picture-to-amazon-s3-all-metadata-must-be-indexed-which-aws-service-should-the-architect-use-to-store-this-metadata" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon S3
B. Amazon DynamoDB
C. Amazon Kinesis
D. Amazon EFC&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Building and Maintaining an Amazon S3 Metadata Index without Servers(&lt;a href="https://amazonaws-china.com/cn/blogs/big-data/building-and-maintaining-an-amazon-s3-metadata-index-without-servers"target="_blank" rel="noopener"&gt;https://amazonaws-china.com/cn/blogs/big-data/building-and-maintaining-an-amazon-s3-metadata-index-without-servers&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;In this post, I walk through an approach for building such an index using Amazon DynamoDB and AWS Lambda. With these technologies, you can create a high performance, low-cost index that scales and remains highly available without the need to maintain traditional servers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;An interactive, dynamic website runs on Amazon EC2 instances in a single subnet behind an ELB Classic Load Balancer. Which design changes will make the site more highly available?&lt;span class="hx:absolute hx:-mt-20" id="an-interactive-dynamic-website-runs-on-amazon-ec2-instances-in-a-single-subnet-behind-an-elb-classic-load-balancer-which-design-changes-will-make-the-site-more-highly-available"&gt;&lt;/span&gt;
&lt;a href="#an-interactive-dynamic-website-runs-on-amazon-ec2-instances-in-a-single-subnet-behind-an-elb-classic-load-balancer-which-design-changes-will-make-the-site-more-highly-available" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Move some Amazon EC2 instances to a subnet in a different way(different AZ).
B. Move the website to Amazon S3.
C. Change the ELB to an Application Load Balancer.
D. Move some Amazon EC2 instances to a subnet in the same Availability Zone.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题的选项A可能是写错了，根据评论区是different AZ，那么选择A就比较容易理解了。评论区有一种声音是选择C，但是从高可用性上讲，C选项并没有实质的价值。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is designing a web application that is running on an Amazon EC2 instance. The application stores data in DynamoDB. The Architect needs to secure access to the DynamoDB table. What combination of steps does AWS recommend to achieve secure authorization? (Select two.)&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-web-application-that-is-running-on-an-amazon-ec2-instance-the-application-stores-data-in-dynamodb-the-architect-needs-to-secure-access-to-the-dynamodb-table-what-combination-of-steps-does-aws-recommend-to-achieve-secure-authorization-select-two"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-web-application-that-is-running-on-an-amazon-ec2-instance-the-application-stores-data-in-dynamodb-the-architect-needs-to-secure-access-to-the-dynamodb-table-what-combination-of-steps-does-aws-recommend-to-achieve-secure-authorization-select-two" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Store an access key on the Amazon EC2 instance with rights to the Dynamo DB table.
B. Attach an IAM user to the Amazon EC2 instance.
C. Create an IAM role with permissions to write to the DynamoDB table.
D. Attach an IAM role to the Amazon EC2 instance.
E. Attach an IAM policy to the Amazon EC2 instance.&lt;/p&gt;
&lt;p&gt;Answer: CD&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：AWS一向重视安全性，所以更推荐使用STS方式进行接口调用&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;(争议)A Solutions Architect is about to deploy an API on multiple EC2 instances in an Auto Scaling group behind an ELB. The support team has the following operational requirements:&lt;span class="hx:absolute hx:-mt-20" id="争议a-solutions-architect-is-about-to-deploy-an-api-on-multiple-ec2-instances-in-an-auto-scaling-group-behind-an-elb-the-support-team-has-the-following-operational-requirements"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-solutions-architect-is-about-to-deploy-an-api-on-multiple-ec2-instances-in-an-auto-scaling-group-behind-an-elb-the-support-team-has-the-following-operational-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;1 They get an alert when the requests per second go over 50,000
2 They get an alert when latency goes over 5 seconds
3 They can validate how many times a day users call the API requesting highly-sensitive data
Which combination of steps does the Architect need to take to satisfy these operational requirements? (Select two.)&lt;/p&gt;
&lt;p&gt;A. Ensure that CloudTrail is enabled.
B. Create a custom CloudWatch metric to monitor the API for data access.
C. Configure CloudWatch alarms for any metrics the support team requires.
D. Ensure that detailed monitoring for the EC2 instances is enabled.
E. Create an application to export and save CloudWatch metrics for longer term trending analysis.&lt;/p&gt;
&lt;p&gt;Answer: BC&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：原题给出的答案是BD，但是EC2的详细监控其实并没有包含API级别的监控，ELB的监控才包含了API访问的监控。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;(争议)A Solutions Architect is designing a highly-available website that is served by multiple web servers hosted outside of AWS. If an instance becomes unresponsive, the Architect needs to remove it from the rotation. What is the MOST efficient way to fulfill this requirement?&lt;span class="hx:absolute hx:-mt-20" id="争议a-solutions-architect-is-designing-a-highly-available-website-that-is-served-by-multiple-web-servers-hosted-outside-of-aws-if-an-instance-becomes-unresponsive-the-architect-needs-to-remove-it-from-the-rotation-what-is-the-most-efficient-way-to-fulfill-this-requirement"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-solutions-architect-is-designing-a-highly-available-website-that-is-served-by-multiple-web-servers-hosted-outside-of-aws-if-an-instance-becomes-unresponsive-the-architect-needs-to-remove-it-from-the-rotation-what-is-the-most-efficient-way-to-fulfill-this-requirement" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Use Amazon CloudWatch to monitor utilization.
B. Use Amazon API Gateway to monitor availability.
C. Use an Amazon Elastic Load Balancer.
D. Use Amazon Route 53 health checks.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：不同网站给出不同答案，原网站给出的答案是C，但是从题目分析关键词是the Architect needs to remove it，所以看起来A更合理一些。但是ELB增加health check之后应该可以自动的将不可用节点移除掉。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company hosts a popular web application. The web application connects to a database running in a private VPC subnet. The web servers must be accessible only to customers on an SSL connection. The RDS MySQL database server must be accessible only from the web servers. How should the Architect design a solution to meet the requirements without impacting running applications?&lt;span class="hx:absolute hx:-mt-20" id="a-company-hosts-a-popular-web-application-the-web-application-connects-to-a-database-running-in-a-private-vpc-subnet-the-web-servers-must-be-accessible-only-to-customers-on-an-ssl-connection-the-rds-mysql-database-server-must-be-accessible-only-from-the-web-servers-how-should-the-architect-design-a-solution-to-meet-the-requirements-without-impacting-running-applications"&gt;&lt;/span&gt;
&lt;a href="#a-company-hosts-a-popular-web-application-the-web-application-connects-to-a-database-running-in-a-private-vpc-subnet-the-web-servers-must-be-accessible-only-to-customers-on-an-ssl-connection-the-rds-mysql-database-server-must-be-accessible-only-from-the-web-servers-how-should-the-architect-design-a-solution-to-meet-the-requirements-without-impacting-running-applications" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create a network ACL on the web server&amp;rsquo;s subnet, and allow HTTPS inbound and MySQL outbound. Place both database and web servers on the same subnet.
B. Open an HTTPS port on the security group for web servers and set the source to 0.0.0.0/0. Open the MySQL port on the database security group and attach it to the MySQL instance. Set the source to Web Server Security Group.
C. Create a network ACL on the web server&amp;rsquo;s subnet, and allow HTTPS inbound, and specify the source as 0.0.0.0/0. Create a network ACL on a database subnet, allow MySQL port inbound for web servers, and deny all outbound traffic.
D. Open the MySQL port on the security group for web servers and set the source to 0.0.0.0/0. Open the HTTPS port on the database security group and attach it to the MySQL instance. Set the source to Web Server Security Group.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;Which service should an organization use if it requires an easily managed and scalable platform to host its web application running on Nginx?&lt;span class="hx:absolute hx:-mt-20" id="which-service-should-an-organization-use-if-it-requires-an-easily-managed-and-scalable-platform-to-host-its-web-application-running-on-nginx"&gt;&lt;/span&gt;
&lt;a href="#which-service-should-an-organization-use-if-it-requires-an-easily-managed-and-scalable-platform-to-host-its-web-application-running-on-nginx" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. AWS Lambda
B. Auto Scaling
C. AWS Elastic Beanstalk
D. Elastic Load Balancing&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;AWS Elastic Beanstalk 是一项易于使用的服务，用于在熟悉的服务器（例如 Apache 、Nginx、Passenger 和 IIS ）上部署和扩展使用 Java、.NET、PHP、Node.js、Python、Ruby、GO 和 Docker 开发的 Web 应用程序和服务。
您只需上传代码，Elastic Beanstalk 即可自动处理包括容量预配置、负载均衡、自动扩展和应用程序运行状况监控在内的部署工作。同时，您能够完全控制为应用程序提供支持的 AWS 资源，并可以随时访问底层资源。
Elastic Beanstalk 不额外收费 – 您只需为存储和运行应用程序所需的 AWS 资源付费。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;An Administrator is hosting an application on a single Amazon EC2 instance, which users can access by the public hostname. The administrator is adding a second instance, but does not want users to have to decide between many public hostnames. Which AWS service will decouple the users from specific Amazon EC2 instances?&lt;span class="hx:absolute hx:-mt-20" id="an-administrator-is-hosting-an-application-on-a-single-amazon-ec2-instance-which-users-can-access-by-the-public-hostname-the-administrator-is-adding-a-second-instance-but-does-not-want-users-to-have-to-decide-between-many-public-hostnames-which-aws-service-will-decouple-the-users-from-specific-amazon-ec2-instances"&gt;&lt;/span&gt;
&lt;a href="#an-administrator-is-hosting-an-application-on-a-single-amazon-ec2-instance-which-users-can-access-by-the-public-hostname-the-administrator-is-adding-a-second-instance-but-does-not-want-users-to-have-to-decide-between-many-public-hostnames-which-aws-service-will-decouple-the-users-from-specific-amazon-ec2-instances" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon SQS
B. Auto Scaling group
C. Amazon EC2 security group
D. Amazon ELB&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题原网站给出答案是B，但是明显应该是D&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is designing a microservices-based application using Amazon ECS. The application includes a WebSocket component, and the traffic needs to be distributed between microservices based on the URL. Which service should the Architect choose to distribute the workload?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-microservices-based-application-using-amazon-ecs-the-application-includes-a-websocket-component-and-the-traffic-needs-to-be-distributed-between-microservices-based-on-the-url-which-service-should-the-architect-choose-to-distribute-the-workload"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-microservices-based-application-using-amazon-ecs-the-application-includes-a-websocket-component-and-the-traffic-needs-to-be-distributed-between-microservices-based-on-the-url-which-service-should-the-architect-choose-to-distribute-the-workload" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. ELB Classic Load Balancer
B. Amazon Route 53 DNS
C. ELB Application Load Balancer
D. Amazon CloudFront&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;参考链接：https://docs.aws.amazon.com/aws-technical-content/latest/microservices-on-aws/microservices-on-aws.pdf?icmpid=link_from_whitepapers_page&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is designing the storage layer for a production relational database. The database will run on Amazon EC2. The database is accessed by an application that performs intensive reads and writes, so the database requires the LOWEST random I/O latency. Which data storage method fulfills the above requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-the-storage-layer-for-a-production-relational-database-the-database-will-run-on-amazon-ec2-the-database-is-accessed-by-an-application-that-performs-intensive-reads-and-writes-so-the-database-requires-the-lowest-random-io-latency-which-data-storage-method-fulfills-the-above-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-the-storage-layer-for-a-production-relational-database-the-database-will-run-on-amazon-ec2-the-database-is-accessed-by-an-application-that-performs-intensive-reads-and-writes-so-the-database-requires-the-lowest-random-io-latency-which-data-storage-method-fulfills-the-above-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Store data in a filesystem backed by Amazon Elastic File System (EFS).
B. Store data in Amazon S3 and use a third-party solution to expose Amazon S3 as a filesystem to the database server.
C. Store data in Amazon Dynamo DB and emulate relational database semantics.
D. Stripe data across multiple Amazon EBS volumes using RAID 0.&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;h2&gt;A Solutions Architect is designing a VPC. Instances in a private subnet must be able to establish IPv6 traffic to the Internet. The design must scale automatically and not incur any additional cost. This can be accomplished with:&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-vpc-instances-in-a-private-subnet-must-be-able-to-establish-ipv6-traffic-to-the-internet-the-design-must-scale-automatically-and-not-incur-any-additional-cost-this-can-be-accomplished-with"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-vpc-instances-in-a-private-subnet-must-be-able-to-establish-ipv6-traffic-to-the-internet-the-design-must-scale-automatically-and-not-incur-any-additional-cost-this-can-be-accomplished-with" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. an egress-only internet gateway
B. a NAT gateway
C. a custom NAT instance
D. a VPC endpoint&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;参考链接：https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Scenario2.html&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;An egress-only Internet gateway. This enables instances in the private subnet to send requests to the Internet over IPv6 (for example, for software updates). An egress-only Internet gateway is necessary if you want instances in the private subnet to be able to initiate communication with the Internet over IPv6. For more information, see Egress-Only Internet Gateways.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A web application stores all data in an Amazon RDS Aurora database instance. A Solutions Architect wants to provide access to the data for a detailed report for the Marketing team, but is concerned that the additional load on the database will affect the performance of the web application. How can the report be created without affecting the performance of the application?&lt;span class="hx:absolute hx:-mt-20" id="a-web-application-stores-all-data-in-an-amazon-rds-aurora-database-instance-a-solutions-architect-wants-to-provide-access-to-the-data-for-a-detailed-report-for-the-marketing-team-but-is-concerned-that-the-additional-load-on-the-database-will-affect-the-performance-of-the-web-application-how-can-the-report-be-created-without-affecting-the-performance-of-the-application"&gt;&lt;/span&gt;
&lt;a href="#a-web-application-stores-all-data-in-an-amazon-rds-aurora-database-instance-a-solutions-architect-wants-to-provide-access-to-the-data-for-a-detailed-report-for-the-marketing-team-but-is-concerned-that-the-additional-load-on-the-database-will-affect-the-performance-of-the-web-application-how-can-the-report-be-created-without-affecting-the-performance-of-the-application" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create a read replica of the database.
B. Provision a new RDS instance as a secondary master.
C. Configure the database to be in multiple regions.
D. Increase the number of provisioned storage IOPS.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：原有网站给出的答案是B，明显是A，搞这么复杂干啥&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company has an application that stores sensitive data. The company is required by government regulations to store multiple copies of its data. What would be the MOST resilient and cost-effective option to meet this requirement?&lt;span class="hx:absolute hx:-mt-20" id="a-company-has-an-application-that-stores-sensitive-data-the-company-is-required-by-government-regulations-to-store-multiple-copies-of-its-data-what-would-be-the-most-resilient-and-cost-effective-option-to-meet-this-requirement"&gt;&lt;/span&gt;
&lt;a href="#a-company-has-an-application-that-stores-sensitive-data-the-company-is-required-by-government-regulations-to-store-multiple-copies-of-its-data-what-would-be-the-most-resilient-and-cost-effective-option-to-meet-this-requirement" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon EFS
B. Amazon RDS
C. AWS Storage Gateway
D. Amazon S3&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;h2&gt;A company is using AWS Key Management Service (AWS KMS) to secure their Amazon RDS databases. An auditor has recommended that the company log all use of their AWS KMS keys. What is the SIMPLEST solution?&lt;span class="hx:absolute hx:-mt-20" id="a-company-is-using-aws-key-management-service-aws-kms-to-secure-their-amazon-rds-databases-an-auditor-has-recommended-that-the-company-log-all-use-of-their-aws-kms-keys-what-is-the-simplest-solution"&gt;&lt;/span&gt;
&lt;a href="#a-company-is-using-aws-key-management-service-aws-kms-to-secure-their-amazon-rds-databases-an-auditor-has-recommended-that-the-company-log-all-use-of-their-aws-kms-keys-what-is-the-simplest-solution" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Associate AWS KMS metrics with Amazon CloudWatch.
B. Use AWS CloudTrail to log AWS KMS key usage.
C. Deploy a monitoring agent on the RDS instances.
D. Poll AWS KMS periodically with a scheduled job.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;A Solutions Architect is designing a stateful web application that will run for one year (24/7) and then be decommissioned. Load on this platform will be constant, using a number of r4.8xlarge instances. Key drivers for this system include high availability, but elasticity is not required. What is the MOST cost-effective way to purchase compute for this platform?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-stateful-web-application-that-will-run-for-one-year-247-and-then-be-decommissioned-load-on-this-platform-will-be-constant-using-a-number-of-r48xlarge-instances-key-drivers-for-this-system-include-high-availability-but-elasticity-is-not-required-what-is-the-most-cost-effective-way-to-purchase-compute-for-this-platform"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-stateful-web-application-that-will-run-for-one-year-247-and-then-be-decommissioned-load-on-this-platform-will-be-constant-using-a-number-of-r48xlarge-instances-key-drivers-for-this-system-include-high-availability-but-elasticity-is-not-required-what-is-the-most-cost-effective-way-to-purchase-compute-for-this-platform" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Scheduled Reserved Instances
B. Convertible Reserved Instances
C. Standard Reserved Instances
D. Spot Instances&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：根据题目要求7*24小时不停机，所以需要排除A和D两个选项, B选项在这个场景下并不需要，所以选C&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Exchanging Convertible Reserved Instances: You can exchange one or more Convertible Reserved Instances for another Convertible Reserved Instance with a different configuration, including instance family, operating system, and tenancy. There are no limits to how many times you perform an exchange, as long as the target Convertible Reserved Instance is of an equal or higher value than the Convertible Reserved Instances that you are exchanging.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A media company asked a Solutions Architect to design a highly available storage solution to serve as a centralized document store for their Amazon EC2 instances. The storage solution needs to be POSIX-compliant, scale dynamically, and be able to serve up to 100 concurrent EC2 instances. Which solution meets these requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-media-company-asked-a-solutions-architect-to-design-a-highly-available-storage-solution-to-serve-as-a-centralized-document-store-for-their-amazon-ec2-instances-the-storage-solution-needs-to-be-posix-compliant-scale-dynamically-and-be-able-to-serve-up-to-100-concurrent-ec2-instances-which-solution-meets-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-media-company-asked-a-solutions-architect-to-design-a-highly-available-storage-solution-to-serve-as-a-centralized-document-store-for-their-amazon-ec2-instances-the-storage-solution-needs-to-be-posix-compliant-scale-dynamically-and-be-able-to-serve-up-to-100-concurrent-ec2-instances-which-solution-meets-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create an Amazon S3 bucket and store all of the documents in this bucket.
B. Create an Amazon EBS volume and allow multiple users to mount that volume to their EC2 instance(s).
C. Use Amazon Glacier to store all of the documents.
D. Create an Amazon Elastic File System (Amazon EFS) to store and share the documents.&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：需要文件接口，并且同时访问，那么只有EFS能够满足&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solution Architect has a two-tier application with a single Amazon EC2 instance web server and Amazon RDS MySQL Multi-AZ DB instances. The Architect is re-architecting the application for high availability by adding instances in a second Availability Zone. Which additional services will improve the availability of the application? (Choose two.)&lt;span class="hx:absolute hx:-mt-20" id="a-solution-architect-has-a-two-tier-application-with-a-single-amazon-ec2-instance-web-server-and-amazon-rds-mysql-multi-az-db-instances-the-architect-is-re-architecting-the-application-for-high-availability-by-adding-instances-in-a-second-availability-zone-which-additional-services-will-improve-the-availability-of-the-application-choose-two"&gt;&lt;/span&gt;
&lt;a href="#a-solution-architect-has-a-two-tier-application-with-a-single-amazon-ec2-instance-web-server-and-amazon-rds-mysql-multi-az-db-instances-the-architect-is-re-architecting-the-application-for-high-availability-by-adding-instances-in-a-second-availability-zone-which-additional-services-will-improve-the-availability-of-the-application-choose-two" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Auto Scaling group
B. AWS CloudTrail
C. ELB Classic Load Balancer
D. Amazon DynamoDB
E. Amazon ElastiCache&lt;/p&gt;
&lt;p&gt;Answer: AC&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：原网站给出的答案是AE，E显然没什么用对于目标&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company is migrating its data center to AWS. As part of this migration, there is a three-tier web application that has strict data-at-rest encryption requirements. The customer deploys this application on Amazon EC2 using Amazon EBS, and now must provide encryption at-rest. How can this requirement be met without changing the application?&lt;span class="hx:absolute hx:-mt-20" id="a-company-is-migrating-its-data-center-to-aws-as-part-of-this-migration-there-is-a-three-tier-web-application-that-has-strict-data-at-rest-encryption-requirements-the-customer-deploys-this-application-on-amazon-ec2-using-amazon-ebs-and-now-must-provide-encryption-at-rest-how-can-this-requirement-be-met-without-changing-the-application"&gt;&lt;/span&gt;
&lt;a href="#a-company-is-migrating-its-data-center-to-aws-as-part-of-this-migration-there-is-a-three-tier-web-application-that-has-strict-data-at-rest-encryption-requirements-the-customer-deploys-this-application-on-amazon-ec2-using-amazon-ebs-and-now-must-provide-encryption-at-rest-how-can-this-requirement-be-met-without-changing-the-application" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Use AWS Key Management Service and move the encrypted data to Amazon S3.
B. Use an application-specific encryption API with AWS server-side encryption.
C. Use encrypted EBS storage volumes with AWS-managed keys.
D. Use third-party tools to encrypt the EBS data volumes with Key Management Service Bring Your Own Keys.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;A Solutions Architect is developing software on AWS that requires access to multiple AWS services, including an Amazon EC2 instance. This is a security sensitive application, and AWS credentials such as Access Key ID and Secret Access Key need to be protected and cannot be exposed anywhere in the system. What security measure would satisfy these requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-developing-software-on-aws-that-requires-access-to-multiple-aws-services-including-an-amazon-ec2-instance-this-is-a-security-sensitive-application-and-aws-credentials-such-as-access-key-id-and-secret-access-key-need-to-be-protected-and-cannot-be-exposed-anywhere-in-the-system-what-security-measure-would-satisfy-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-developing-software-on-aws-that-requires-access-to-multiple-aws-services-including-an-amazon-ec2-instance-this-is-a-security-sensitive-application-and-aws-credentials-such-as-access-key-id-and-secret-access-key-need-to-be-protected-and-cannot-be-exposed-anywhere-in-the-system-what-security-measure-would-satisfy-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Store the AWS Access Key ID/Secret Access Key combination in software comments.
B. Assign an IAM user to the Amazon EC2 instance.
C. Assign an IAM role to the Amazon EC2 instance.
D. Enable multi-factor authentication for the AWS root account.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;An AWS workload in a VPC is running a legacy database on an Amazon EC2 instance. Data is stored on a 200GB Amazon EBS (gp2) volume. At peak load times, logs show excessive wait time. What solution should be implemented to improve database performance using persistent storage?&lt;span class="hx:absolute hx:-mt-20" id="an-aws-workload-in-a-vpc-is-running-a-legacy-database-on-an-amazon-ec2-instance-data-is-stored-on-a-200gb-amazon-ebs-gp2-volume-at-peak-load-times-logs-show-excessive-wait-time-what-solution-should-be-implemented-to-improve-database-performance-using-persistent-storage"&gt;&lt;/span&gt;
&lt;a href="#an-aws-workload-in-a-vpc-is-running-a-legacy-database-on-an-amazon-ec2-instance-data-is-stored-on-a-200gb-amazon-ebs-gp2-volume-at-peak-load-times-logs-show-excessive-wait-time-what-solution-should-be-implemented-to-improve-database-performance-using-persistent-storage" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Migrate the data on the Amazon EBS volume to an SSD-backed volume.
B. Change the EC2 instance type to one with EC2 instance store volumes.
C. Migrate the data on the EBS volume to provisioned IOPS SSD (io1).
D. Change the EC2 instance type to one with burstable performance.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：原有答案给出的是D，但是从性能角度看C明显是正确的&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company&amp;rsquo;s website receives 50,000 requests each second, and the company wants to use multiple applications to analyze the navigation patterns of the users on their website so that the experience can be personalized. What can a Solutions Architect use to collect page clicks for the website and process them sequentially for each user?&lt;span class="hx:absolute hx:-mt-20" id="a-companys-website-receives-50000-requests-each-second-and-the-company-wants-to-use-multiple-applications-to-analyze-the-navigation-patterns-of-the-users-on-their-website-so-that-the-experience-can-be-personalized-what-can-a-solutions-architect-use-to-collect-page-clicks-for-the-website-and-process-them-sequentially-for-each-user"&gt;&lt;/span&gt;
&lt;a href="#a-companys-website-receives-50000-requests-each-second-and-the-company-wants-to-use-multiple-applications-to-analyze-the-navigation-patterns-of-the-users-on-their-website-so-that-the-experience-can-be-personalized-what-can-a-solutions-architect-use-to-collect-page-clicks-for-the-website-and-process-them-sequentially-for-each-user" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon Kinesis Stream
B. Amazon SQS standard queue
C. Amazon SQS FIFO queue
D. AWS CloudTrail trail&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create real-time clickstream sessions and run analytics with Amazon Kinesis Data Analytics, AWS Glue, and Amazon Athena(&lt;a href="https://aws.amazon.com/cn/blogs/big-data/create-real-time-clickstream-sessions-and-run-analytics-with-amazon-kinesis-data-analytics-aws-glue-and-amazon-athena/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/cn/blogs/big-data/create-real-time-clickstream-sessions-and-run-analytics-with-amazon-kinesis-data-analytics-aws-glue-and-amazon-athena/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Amazon Kinesis – Real-Time Processing of Streaming Big Data(&lt;a href="https://aws.amazon.com/cn/blogs/aws/amazon-kinesis-real-time-processing-of-streamed-data/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/cn/blogs/aws/amazon-kinesis-real-time-processing-of-streamed-data/&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company wants to migrate a highly transactional database to AWS. Requirements state that the database has more than 6 TB of data and will grow exponentially. Which solution should a Solutions Architect recommend?&lt;span class="hx:absolute hx:-mt-20" id="a-company-wants-to-migrate-a-highly-transactional-database-to-aws-requirements-state-that-the-database-has-more-than-6-tb-of-data-and-will-grow-exponentially-which-solution-should-a-solutions-architect-recommend"&gt;&lt;/span&gt;
&lt;a href="#a-company-wants-to-migrate-a-highly-transactional-database-to-aws-requirements-state-that-the-database-has-more-than-6-tb-of-data-and-will-grow-exponentially-which-solution-should-a-solutions-architect-recommend" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon Aurora
B. Amazon Redshift
C. Amazon DynamoDB
D. Amazon RDS MySQL&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：A和D的区别没有找到合适的解释，Aurora的扩展性更好，而且是AWS云原生的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;(争议)A company hosts a two-tier application that consists of a publicly accessible web server that communicates with a private database. Only HTTPS port 443 traffic to the web server must be allowed from the Internet. Which of the following options will achieve these requirements? (Choose two.)&lt;span class="hx:absolute hx:-mt-20" id="争议a-company-hosts-a-two-tier-application-that-consists-of-a-publicly-accessible-web-server-that-communicates-with-a-private-database-only-https-port-443-traffic-to-the-web-server-must-be-allowed-from-the-internet-which-of-the-following-options-will-achieve-these-requirements-choose-two"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-company-hosts-a-two-tier-application-that-consists-of-a-publicly-accessible-web-server-that-communicates-with-a-private-database-only-https-port-443-traffic-to-the-web-server-must-be-allowed-from-the-internet-which-of-the-following-options-will-achieve-these-requirements-choose-two" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Security group rule that allows inbound Internet traffic for port 443.
B. Security group rule that denies all inbound Internet traffic except port 443.
C. Network ACL rule that allows port 443 inbound and all ports outbound for Internet traffic.
D. Security group rule that allows Internet traffic for port 443 in both inbound and outbound.
E. Network ACL rule that allows port 443 for both inbound and outbound for all Internet traffic.&lt;/p&gt;
&lt;p&gt;Answer: AC&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：答案给出的是AE，根据Network ACL的描述，默认情况为白名单，是无状态性的，返回的端口不会自动允许，所以需要C选项打开所有返回的端口。&lt;/li&gt;
&lt;li&gt;临时端口(&lt;a href="https://docs.aws.amazon.com/zh_cn/vpc/latest/userguide/vpc-network-acls.html#nacl-ephemeral-ports"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/zh_cn/vpc/latest/userguide/vpc-network-acls.html#nacl-ephemeral-ports&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;临时端口
上一个部分中的网络 ACL 实例使用了临时端口范围 32768-65535。但是，您可能需要根据自己使用的或作为通信目标的客户端的类型为网络 ACL 使用不同的范围。
发起请求的客户端会选择临时端口范围。根据客户端的操作系统不同，范围也随之更改。
许多 Linux 内核（包括 Amazon Linux 内核）使用端口 32768-61000。
生成自 Elastic Load Balancing 的请求使用端口 1024-65535。
Windows 操作系统通过 Windows Server 2003 使用端口 1025-5000。
Windows Server 2008 及更高版本使用端口 49152-65535。
NAT 网关使用端口 1024 - 65535。
AWS Lambda 函数使用端口 1024-65535。
例如，如果一个来自 Internet 上的 Windows XP 客户端的请求到达您的 VPC 中的 Web 服务器，则您的网络 ACL 必须有相应的出站规则，以支持目标为端口 1025-5000 的数据流。
如果您的 VPC 中的一个实例是发起请求的客户端，则您的网络 ACL 必须有入站规则来支持发送到实例类型（Amazon Linux、Windows Server 2008 等）特有的临时端口的数据流。
在实际中，为使不同客户端类型可以启动流量进入您 VPC 中的公有实例，您可以开放临时端口 1024-65535。但是，您也可以在 ACL 中添加规则以拒绝任何在此范围内的来自恶意端口的数据流。请务必将拒绝 规则放在表的较前端，先于开放一系列临时端口的允许 规则。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A Solutions Architect is designing an Amazon VPC. Applications in the VPC must have private connectivity to Amazon DynamoDB in the same AWS Region. The design should route DynamoDB traffic through:&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-an-amazon-vpc-applications-in-the-vpc-must-have-private-connectivity-to-amazon-dynamodb-in-the-same-aws-region-the-design-should-route-dynamodb-traffic-through"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-an-amazon-vpc-applications-in-the-vpc-must-have-private-connectivity-to-amazon-dynamodb-in-the-same-aws-region-the-design-should-route-dynamodb-traffic-through" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. VPC peering connection.
B. NAT gateway
C. VPC endpoint
D. AWS Direct Connect&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;A Solutions Architect is architecting a workload that requires a performant object-based storage system that must be shared with multiple Amazon EC2 instances. Which AWS service meets this requirement?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-architecting-a-workload-that-requires-a-performant-object-based-storage-system-that-must-be-shared-with-multiple-amazon-ec2-instances-which-aws-service-meets-this-requirement"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-architecting-a-workload-that-requires-a-performant-object-based-storage-system-that-must-be-shared-with-multiple-amazon-ec2-instances-which-aws-service-meets-this-requirement" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon EFS
B. Amazon S3
C. Amazon EBS
D. Amazon ElastiCache&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题给出的答案竟然是A，不明白这个网站是不是专门负责坑人的。object-based storage system，很明显是S3.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is developing a solution for sharing files in an organization. The solution must allow multiple users to access the storage service at once from different virtual machines and scale automatically. It must also support file-level locking. Which storage service meets the requirements of this use case?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-developing-a-solution-for-sharing-files-in-an-organization-the-solution-must-allow-multiple-users-to-access-the-storage-service-at-once-from-different-virtual-machines-and-scale-automatically-it-must-also-support-file-level-locking-which-storage-service-meets-the-requirements-of-this-use-case"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-developing-a-solution-for-sharing-files-in-an-organization-the-solution-must-allow-multiple-users-to-access-the-storage-service-at-once-from-different-virtual-machines-and-scale-automatically-it-must-also-support-file-level-locking-which-storage-service-meets-the-requirements-of-this-use-case" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon S3
B. Amazon EFS
C. Amazon EBS
D. Cached Volumes&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;A company runs a legacy application with a single-tier architecture on an Amazon EC2 instance. Disk I/O is low, with occasional small spikes during business hours. The company requires the instance to be stopped from 8 PM to 8 AM daily. Which storage option is MOST appropriate for this workload?&lt;span class="hx:absolute hx:-mt-20" id="a-company-runs-a-legacy-application-with-a-single-tier-architecture-on-an-amazon-ec2-instance-disk-io-is-low-with-occasional-small-spikes-during-business-hours-the-company-requires-the-instance-to-be-stopped-from-8-pm-to-8-am-daily-which-storage-option-is-most-appropriate-for-this-workload"&gt;&lt;/span&gt;
&lt;a href="#a-company-runs-a-legacy-application-with-a-single-tier-architecture-on-an-amazon-ec2-instance-disk-io-is-low-with-occasional-small-spikes-during-business-hours-the-company-requires-the-instance-to-be-stopped-from-8-pm-to-8-am-daily-which-storage-option-is-most-appropriate-for-this-workload" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon EC2 instance storage
B. Amazon EBS General Purpose SSD (gp2) storage
C. Amazon S3
D. Amazon EBS Provision IOPS SSD (io1) storage&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：原始答案给出的是C，一个legcy application为什么会用S3呢？这可是需要应用改造的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;(争议)As part of securing an API layer built on Amazon API gateway, a Solutions Architect has to authorize users who are currently authenticated by an existing identity provider. The users must be denied access for a period of one hour after three unsuccessful attempts. How can the Solutions Architect meet these requirements?&lt;span class="hx:absolute hx:-mt-20" id="争议as-part-of-securing-an-api-layer-built-on-amazon-api-gateway-a-solutions-architect-has-to-authorize-users-who-are-currently-authenticated-by-an-existing-identity-provider-the-users-must-be-denied-access-for-a-period-of-one-hour-after-three-unsuccessful-attempts-how-can-the-solutions-architect-meet-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aeas-part-of-securing-an-api-layer-built-on-amazon-api-gateway-a-solutions-architect-has-to-authorize-users-who-are-currently-authenticated-by-an-existing-identity-provider-the-users-must-be-denied-access-for-a-period-of-one-hour-after-three-unsuccessful-attempts-how-can-the-solutions-architect-meet-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Use AWS IAM authorization and add least-privileged permissions to each respective IAM role.
B. Use an API Gateway custom authorizer to invoke an AWS Lambda function to validate each user&amp;rsquo;s identity.
C. Use Amazon Cognito user pools to provide built-in user management.
D. Use Amazon Cognito user pools to integrate with external identity providers.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：正义点在答案D，参考链接：https://serverless-stack.com/chapters/cognito-user-pool-vs-identity-pool.html&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;An organization runs an online media site, hosted on-premises. An employee posted a product review that contained videos and pictures. The review went viral and the organization needs to handle the resulting spike in website traffic. What action would provide an immediate solution?&lt;span class="hx:absolute hx:-mt-20" id="an-organization-runs-an-online-media-site-hosted-on-premises-an-employee-posted-a-product-review-that-contained-videos-and-pictures-the-review-went-viral-and-the-organization-needs-to-handle-the-resulting-spike-in-website-traffic-what-action-would-provide-an-immediate-solution"&gt;&lt;/span&gt;
&lt;a href="#an-organization-runs-an-online-media-site-hosted-on-premises-an-employee-posted-a-product-review-that-contained-videos-and-pictures-the-review-went-viral-and-the-organization-needs-to-handle-the-resulting-spike-in-website-traffic-what-action-would-provide-an-immediate-solution" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Redesign the website to use Amazon API Gateway, and use AWS Lambda to deliver content.
B. Add server instances using Amazon EC2 and use Amazon Route 53 with a failover routing policy.
C. Serve the images and videos via an Amazon CloudFront distribution created using the news site as the origin.
D. Use Amazon ElasticCache for Redis for caching and reducing the load requests from the origin.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;A client notices that their engineers often make mistakes when creating Amazon SQS queues for their backend system. Which action should a Solutions Architect recommend to improve this process?&lt;span class="hx:absolute hx:-mt-20" id="a-client-notices-that-their-engineers-often-make-mistakes-when-creating-amazon-sqs-queues-for-their-backend-system-which-action-should-a-solutions-architect-recommend-to-improve-this-process"&gt;&lt;/span&gt;
&lt;a href="#a-client-notices-that-their-engineers-often-make-mistakes-when-creating-amazon-sqs-queues-for-their-backend-system-which-action-should-a-solutions-architect-recommend-to-improve-this-process" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Use the AWS CLI to create queues using AWS IAM Access Keys.
B. Write a script to create the Amazon SQS queue using AWS Lambda.
C. Use AWS Elastic Beanstalk to automatically create the Amazon SQS queues.
D. Use AWS CloudFormation Templates to manage the Amazon SQS queue creation.&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;教程：创建 Amazon SQS 队列(&lt;a href="https://docs.aws.amazon.com/zh_cn/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html#create-queue-cloudformation"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/zh_cn/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-create-queue.html#create-queue-cloudformation&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;(争议)A development team is building an application with front-end and backend application tiers. Each tier consists of Amazon EC2 instances behind an ELB Classic Load Balancer. The instances run in Auto Scaling groups across multiple Availability Zones. The network team has allocated the 10.0.0.0/24 address space for this application. Only the front-end load balancer should be exposed to the Internet. There are concerns about the limited size of the address space and the ability of each tier to scale. What should the VPC subnet design be in each Availability Zone?&lt;span class="hx:absolute hx:-mt-20" id="争议a-development-team-is-building-an-application-with-front-end-and-backend-application-tiers-each-tier-consists-of-amazon-ec2-instances-behind-an-elb-classic-load-balancer-the-instances-run-in-auto-scaling-groups-across-multiple-availability-zones-the-network-team-has-allocated-the-1000024-address-space-for-this-application-only-the-front-end-load-balancer-should-be-exposed-to-the-internet-there-are-concerns-about-the-limited-size-of-the-address-space-and-the-ability-of-each-tier-to-scale-what-should-the-vpc-subnet-design-be-in-each-availability-zone"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-development-team-is-building-an-application-with-front-end-and-backend-application-tiers-each-tier-consists-of-amazon-ec2-instances-behind-an-elb-classic-load-balancer-the-instances-run-in-auto-scaling-groups-across-multiple-availability-zones-the-network-team-has-allocated-the-1000024-address-space-for-this-application-only-the-front-end-load-balancer-should-be-exposed-to-the-internet-there-are-concerns-about-the-limited-size-of-the-address-space-and-the-ability-of-each-tier-to-scale-what-should-the-vpc-subnet-design-be-in-each-availability-zone" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. One public subnet for the load balancer tier, one public subnet for the front-end tier, and one private subnet for the backend tier.
B. One shared public subnet for all tiers of the application.
C. One public subnet for the load balancer tier and one shared private subnet for the application tiers.
D. One shared private subnet for all tiers of the application.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：答案给出的是A，但是题目中说道only the front-end load balancer should be exposed to the internet，所以A答案中为front-end tier一个公网subnet有点多余了&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect must select the storage type for a big data application that requires very high sequential I/O. The data must persist if the instance is stopped. Which of the following storage types will provide the best fit at the LOWEST cost for the application?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-must-select-the-storage-type-for-a-big-data-application-that-requires-very-high-sequential-io-the-data-must-persist-if-the-instance-is-stopped-which-of-the-following-storage-types-will-provide-the-best-fit-at-the-lowest-cost-for-the-application"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-must-select-the-storage-type-for-a-big-data-application-that-requires-very-high-sequential-io-the-data-must-persist-if-the-instance-is-stopped-which-of-the-following-storage-types-will-provide-the-best-fit-at-the-lowest-cost-for-the-application" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. An Amazon EC2 instance store local SSD volume.
B. An Amazon EBS provisioned IOPS SSD volume.
C. An Amazon EBS throughput optimized HDD volume.
D. An Amazon EBS general purpose SSD volume.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题需要高顺序I/O和低成本，显然C正确&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Two Auto Scaling applications, Application A and Application B, currently run within a shared set of subnets. A Solutions Architect wants to make sure that Application A can make requests to Application B, but Application B should be denied from making requests to Application A. Which is the SIMPLEST solution to achieve this policy?&lt;span class="hx:absolute hx:-mt-20" id="two-auto-scaling-applications-application-a-and-application-b-currently-run-within-a-shared-set-of-subnets-a-solutions-architect-wants-to-make-sure-that-application-a-can-make-requests-to-application-b-but-application-b-should-be-denied-from-making-requests-to-application-a-which-is-the-simplest-solution-to-achieve-this-policy"&gt;&lt;/span&gt;
&lt;a href="#two-auto-scaling-applications-application-a-and-application-b-currently-run-within-a-shared-set-of-subnets-a-solutions-architect-wants-to-make-sure-that-application-a-can-make-requests-to-application-b-but-application-b-should-be-denied-from-making-requests-to-application-a-which-is-the-simplest-solution-to-achieve-this-policy" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Using security groups that reference the security groups of the other application
B. Using security groups that reference the application server&amp;rsquo;s IP addresses
C. Using Network Access Control Lists to allow/deny traffic based on application IP addresses
D. Migrating the applications to separate subnets from each other&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;h2&gt;Legacy applications currently send messages through a single Amazon EC2 instance, which then routes the messages to the appropriate destinations. The Amazon EC2 instance is a bottleneck and single point of failure, so the company would like to address these issues. Which services could address this architectural use case? (Choose two.)&lt;span class="hx:absolute hx:-mt-20" id="legacy-applications-currently-send-messages-through-a-single-amazon-ec2-instance-which-then-routes-the-messages-to-the-appropriate-destinations-the-amazon-ec2-instance-is-a-bottleneck-and-single-point-of-failure-so-the-company-would-like-to-address-these-issues-which-services-could-address-this-architectural-use-case-choose-two"&gt;&lt;/span&gt;
&lt;a href="#legacy-applications-currently-send-messages-through-a-single-amazon-ec2-instance-which-then-routes-the-messages-to-the-appropriate-destinations-the-amazon-ec2-instance-is-a-bottleneck-and-single-point-of-failure-so-the-company-would-like-to-address-these-issues-which-services-could-address-this-architectural-use-case-choose-two" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon SNS
B. AWS STS
C. Amazon SQS
D. Amazon Route 53
E. AWS Glue&lt;/p&gt;
&lt;p&gt;Answer: AC&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：根据题目是要解决消息的问题，消息服务有两种SNS和SQS，因为题目里并没有说消息模式，所以这两种也许能解决需求。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect needs to design an architecture for a new, mission-critical batch processing billing application. The application is required to run Monday, Wednesday, and Friday from 5 AM to 11 AM. Which is the MOST cost-effective Amazon EC2 pricing model?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-needs-to-design-an-architecture-for-a-new-mission-critical-batch-processing-billing-application-the-application-is-required-to-run-monday-wednesday-and-friday-from-5-am-to-11-am-which-is-the-most-cost-effective-amazon-ec2-pricing-model"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-needs-to-design-an-architecture-for-a-new-mission-critical-batch-processing-billing-application-the-application-is-required-to-run-monday-wednesday-and-friday-from-5-am-to-11-am-which-is-the-most-cost-effective-amazon-ec2-pricing-model" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon EC2 Spot Instances
B. On-Demand Amazon EC2 Instances
C. Scheduled Reserved Instances
D. Dedicated Amazon EC2 Instances&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;A workload consists of downloading an image from an Amazon S3 bucket, processing the image, and moving it to another Amazon S3 bucket. An Amazon EC2 instance runs a scheduled task every hour to perform the operation. How should a Solutions Architect redesign the process so that it is highly available?&lt;span class="hx:absolute hx:-mt-20" id="a-workload-consists-of-downloading-an-image-from-an-amazon-s3-bucket-processing-the-image-and-moving-it-to-another-amazon-s3-bucket-an-amazon-ec2-instance-runs-a-scheduled-task-every-hour-to-perform-the-operation-how-should-a-solutions-architect-redesign-the-process-so-that-it-is-highly-available"&gt;&lt;/span&gt;
&lt;a href="#a-workload-consists-of-downloading-an-image-from-an-amazon-s3-bucket-processing-the-image-and-moving-it-to-another-amazon-s3-bucket-an-amazon-ec2-instance-runs-a-scheduled-task-every-hour-to-perform-the-operation-how-should-a-solutions-architect-redesign-the-process-so-that-it-is-highly-available" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Change the Amazon EC2 instance to compute optimized.
B. Launch a second Amazon EC2 instance to monitor the health of the first.
C. Trigger a Lambda function when a new object is uploaded.
D. Initially copy the images to an attached Amazon EBS volume.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：Lambda的触发器很适合做这个&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;An application is running on an Amazon EC2 instance in a private subnet. The application needs to read and write data onto Amazon Kinesis Data Streams, and corporate policy requires that this traffic should not go to the internet. How can these requirements be met?&lt;span class="hx:absolute hx:-mt-20" id="an-application-is-running-on-an-amazon-ec2-instance-in-a-private-subnet-the-application-needs-to-read-and-write-data-onto-amazon-kinesis-data-streams-and-corporate-policy-requires-that-this-traffic-should-not-go-to-the-internet-how-can-these-requirements-be-met"&gt;&lt;/span&gt;
&lt;a href="#an-application-is-running-on-an-amazon-ec2-instance-in-a-private-subnet-the-application-needs-to-read-and-write-data-onto-amazon-kinesis-data-streams-and-corporate-policy-requires-that-this-traffic-should-not-go-to-the-internet-how-can-these-requirements-be-met" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Configure a NAT gateway in a public subnet and route all traffic to Amazon Kinesis through the NAT gateway.
B. Configure a gateway VPC endpoint for Kinesis and route all traffic to Kinesis through the gateway VPC endpoint.
C. Configure an interface VPC endpoint for Kinesis and route all traffic to Kinesis through the gateway VPC endpoint.
D. Configure an AWS Direct Connect private virtual interface for Kinesis and route all traffic to Kinesis through the virtual interface.&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：误选了B，从题目说是Kinesis需要读取EC2的数据，所以应该是在VPC interface上建立一个endpoint&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is building an application that stores object data. Compliance requirements state that the data stored is immutable. Which service meets these requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-building-an-application-that-stores-object-data-compliance-requirements-state-that-the-data-stored-is-immutable-which-service-meets-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-building-an-application-that-stores-object-data-compliance-requirements-state-that-the-data-stored-is-immutable-which-service-meets-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon S3
B. Amazon Glacier
C. Amazon EFS
D. AWS Storage Gateway&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Data stored in Amazon Glacier is immutable, meaning that after an archive is created it cannot be updated. This ensures that data such as compliance and regulatory records cannot be altered after they have been archived.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;分析：从这道题我们可以看出，考试的时候选中文的重要性，不会因为一个单词意思不明确导致整个题目判断失误，关键词是immutalbe，不可改变的&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;(争议)A Solutions Architect is defining a shared Amazon S3 bucket where corporate applications will save objects. How can the Architect ensure that when an application uploads an object to the Amazon S3 bucket, the object is encrypted?&lt;span class="hx:absolute hx:-mt-20" id="争议a-solutions-architect-is-defining-a-shared-amazon-s3-bucket-where-corporate-applications-will-save-objects-how-can-the-architect-ensure-that-when-an-application-uploads-an-object-to-the-amazon-s3-bucket-the-object-is-encrypted"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-solutions-architect-is-defining-a-shared-amazon-s3-bucket-where-corporate-applications-will-save-objects-how-can-the-architect-ensure-that-when-an-application-uploads-an-object-to-the-amazon-s3-bucket-the-object-is-encrypted" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Set a CORS configuration.
B. Set a bucket policy to encrypt all Amazon S3 objects.
C. Enable default encryption on the bucket.
D. Set permission for users.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：争议点在于答案C，从界面操作上看BC好像是在做同一件事情&lt;/li&gt;
&lt;li&gt;如何为 Amazon S3 存储桶启用默认加密？(&lt;a href="https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/user-guide/default-bucket-encryption.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/user-guide/default-bucket-encryption.html&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;How to Prevent Uploads of Unencrypted Objects to Amazon S3(&lt;a href="https://aws.amazon.com/cn/blogs/security/how-to-prevent-uploads-of-unencrypted-objects-to-amazon-s3/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/cn/blogs/security/how-to-prevent-uploads-of-unencrypted-objects-to-amazon-s3/&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;An application tier currently hosts two web services on the same set of instances, listening on different ports. Which AWS service should a Solutions Architect use to route traffic to the service based on the incoming request path?&lt;span class="hx:absolute hx:-mt-20" id="an-application-tier-currently-hosts-two-web-services-on-the-same-set-of-instances-listening-on-different-ports-which-aws-service-should-a-solutions-architect-use-to-route-traffic-to-the-service-based-on-the-incoming-request-path"&gt;&lt;/span&gt;
&lt;a href="#an-application-tier-currently-hosts-two-web-services-on-the-same-set-of-instances-listening-on-different-ports-which-aws-service-should-a-solutions-architect-use-to-route-traffic-to-the-service-based-on-the-incoming-request-path" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. AWS Application Load Balancer
B. Amazon CloudFront
C. Amazon Classic Load Balancer
D. Amazon Route 53&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;h2&gt;A data analytics startup company asks a Solutions Architect to recommend an AWS data store options for indexed data. The data processing engine will generate and input more than 64 TB of processed data every day, with item sizes reaching up to 300 KB. The startup is flexible with data storage and is more interested in a database that requires minimal effort to scale with a growing dataset size. Which AWS data store service should the Architect recommend?&lt;span class="hx:absolute hx:-mt-20" id="a-data-analytics-startup-company-asks-a-solutions-architect-to-recommend-an-aws-data-store-options-for-indexed-data-the-data-processing-engine-will-generate-and-input-more-than-64-tb-of-processed-data-every-day-with-item-sizes-reaching-up-to-300-kb-the-startup-is-flexible-with-data-storage-and-is-more-interested-in-a-database-that-requires-minimal-effort-to-scale-with-a-growing-dataset-size-which-aws-data-store-service-should-the-architect-recommend"&gt;&lt;/span&gt;
&lt;a href="#a-data-analytics-startup-company-asks-a-solutions-architect-to-recommend-an-aws-data-store-options-for-indexed-data-the-data-processing-engine-will-generate-and-input-more-than-64-tb-of-processed-data-every-day-with-item-sizes-reaching-up-to-300-kb-the-startup-is-flexible-with-data-storage-and-is-more-interested-in-a-database-that-requires-minimal-effort-to-scale-with-a-growing-dataset-size-which-aws-data-store-service-should-the-architect-recommend" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon RDS
B. Amazon Redshift
C. Amazon DynamoDB
D. Amazon S3&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;(争议)A Solutions Architect needs to allow developers to have SSH connectivity to web servers. The requirements are as follows:&lt;span class="hx:absolute hx:-mt-20" id="争议a-solutions-architect-needs-to-allow-developers-to-have-ssh-connectivity-to-web-servers-the-requirements-are-as-follows"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-solutions-architect-needs-to-allow-developers-to-have-ssh-connectivity-to-web-servers-the-requirements-are-as-follows" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;✑ Limit access to users origination from the corporate network.
✑ Web servers cannot have SSH access directly from the Internet.
✑ Web servers reside in a private subnet.
Which combination of steps must the Architect complete to meet these requirements? (Choose two.)&lt;/p&gt;
&lt;p&gt;A. Create a bastion host that authenticates users against the corporate directory.
B. Create a bastion host with security group rules that only allow traffic from the corporate network.
C. Attach an IAM role to the bastion host with relevant permissions.
D. Configure the web servers&amp;rsquo; security group to allow SSH traffic from a bastion host.
E. Deny all SSH traffic from the corporate network in the inbound network ACL.&lt;/p&gt;
&lt;p&gt;Answer: BD&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：原有答案给出的是AC，感觉并不能完全解决该问题&lt;/li&gt;
&lt;li&gt;How to Record SSH Sessions Established Through a Bastion Host(&lt;a href="https://aws.amazon.com/blogs/security/how-to-record-ssh-sessions-established-through-a-bastion-host/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/blogs/security/how-to-record-ssh-sessions-established-through-a-bastion-host/&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>AWS Certified Solutions Architecture Associate Practice</title><link>https://sunqi.site/blog/2020-01-30-aws-certified-solutions-architecture-associate-practice/</link><pubDate>Wed, 30 Mar 2022 21:35:00 +0000</pubDate><guid>https://sunqi.site/blog/2020-01-30-aws-certified-solutions-architecture-associate-practice/</guid><description>
&lt;p&gt;该模拟题出自AWS Practice，是付费后的模拟题，一共25道题，相对来说答案比较准确，答题正确率在76%，看中文的命题相对来说对理解题目内容更简单。&lt;/p&gt;
&lt;p&gt;总得分: 76%
主题得分:
1.0. Design Resilient Architectures 89%
2.0. Define Performant Architectures 71%
3.0. Specify Secure Applications and Architectures 50%
4.0. Design Cost-Optimized Architectures 100%
5.0. Define Operationally Excellent Architectures 100%&lt;/p&gt;
&lt;p&gt;个人感觉，对于网络题目还是有些晕的，因为和OpenStack的SDN还是有一些区别，特别涉及到安全组、网络ACL特别含糊；另外一类题就是服务之间的互联互通时会比较晕。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;(*)您在us-west-2中运行一个应用程序，它需要始终运行6个EC2实例。&lt;span class="hx:absolute hx:-mt-20" id="您在us-west-2中运行一个应用程序它需要始终运行6个ec2实例"&gt;&lt;/span&gt;
&lt;a href="#%e6%82%a8%e5%9c%a8us-west-2%e4%b8%ad%e8%bf%90%e8%a1%8c%e4%b8%80%e4%b8%aa%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%ae%83%e9%9c%80%e8%a6%81%e5%a7%8b%e7%bb%88%e8%bf%90%e8%a1%8c6%e4%b8%aaec2%e5%ae%9e%e4%be%8b" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;该区域有三个可用区（us-west-2a，us-west-2b和us-west-2c)可以使用，如果us-west-2中的任何可用区变得不可用，以下哪种部署可以提供容错功能？（选择两顶◊)
A. 在us-west-2a中有2个EC2实例，在us-west-2b中有2个EC2实例，在us-west-2c中有2个EC2实例
B. 在 us- west- 2 a中有3个 EC2实例，在us-west-2b中有3个 EC2实例，在us-west-2c中没有EC2实例
C. 在us-west-2a中有4个 EC2实例，在us-west-2b中有2个 EC2实例，在us-west-2c中有2个 EC2实例
D. 在 us- west- 2 a中有6个 EC2实例，在us-west-2b中有6个 EC2实例，在us-west-2c中没有EC2实例
E. 在us-west-2a中有3个 EC2实例，在us-west-2b中有3个 EC2实例，在us-west-2c中有3个 EC2实例&lt;/p&gt;
&lt;p&gt;Answer: DE&lt;/p&gt;
&lt;p&gt;该道题的重点是始终运行6个EC2实例，所以当一个区Down掉，仍然能保证有6台实例的答案为正确答案。&lt;/p&gt;
&lt;h2&gt;一家咨询公司反复使用来自很多AMS服务（包括IAM，Amazon EC2, Amazon RDS，DynamoDB和Amazon VPC)的AMS资源为客户构建大型标准化架构。顾问们有每个架构的架构图，但让他们感到沮丧的是，无法使用这些架构图自动创建资源。 哪种服务会立即为组织带来好处?&lt;span class="hx:absolute hx:-mt-20" id="一家咨询公司反复使用来自很多ams服务包括iamamazon-ec2-amazon-rdsdynamodb和amazon-vpc的ams资源为客户构建大型标准化架构顾问们有每个架构的架构图但让他们感到沮丧的是无法使用这些架构图自动创建资源-哪种服务会立即为组织带来好处"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e5%ae%b6%e5%92%a8%e8%af%a2%e5%85%ac%e5%8f%b8%e5%8f%8d%e5%a4%8d%e4%bd%bf%e7%94%a8%e6%9d%a5%e8%87%aa%e5%be%88%e5%a4%9aams%e6%9c%8d%e5%8a%a1%e5%8c%85%e6%8b%aciamamazon-ec2-amazon-rdsdynamodb%e5%92%8camazon-vpc%e7%9a%84ams%e8%b5%84%e6%ba%90%e4%b8%ba%e5%ae%a2%e6%88%b7%e6%9e%84%e5%bb%ba%e5%a4%a7%e5%9e%8b%e6%a0%87%e5%87%86%e5%8c%96%e6%9e%b6%e6%9e%84%e9%a1%be%e9%97%ae%e4%bb%ac%e6%9c%89%e6%af%8f%e4%b8%aa%e6%9e%b6%e6%9e%84%e7%9a%84%e6%9e%b6%e6%9e%84%e5%9b%be%e4%bd%86%e8%ae%a9%e4%bb%96%e4%bb%ac%e6%84%9f%e5%88%b0%e6%b2%ae%e4%b8%a7%e7%9a%84%e6%98%af%e6%97%a0%e6%b3%95%e4%bd%bf%e7%94%a8%e8%bf%99%e4%ba%9b%e6%9e%b6%e6%9e%84%e5%9b%be%e8%87%aa%e5%8a%a8%e5%88%9b%e5%bb%ba%e8%b5%84%e6%ba%90-%e5%93%aa%e7%a7%8d%e6%9c%8d%e5%8a%a1%e4%bc%9a%e7%ab%8b%e5%8d%b3%e4%b8%ba%e7%bb%84%e7%bb%87%e5%b8%a6%e6%9d%a5%e5%a5%bd%e5%a4%84" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Elastic Beanstalk
B. CloudFormation
C. AMS CodeBuild
D. AMS CodeDeploy&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;解决方案架构师正在设计一种解决方案以存储和存档公司文档，并确定Amazon Glacier是正确的解决方案。必须在发出检索请求后的10分钟内提供数据。&lt;span class="hx:absolute hx:-mt-20" id="解决方案架构师正在设计一种解决方案以存储和存档公司文档并确定amazon-glacier是正确的解决方案必须在发出检索请求后的10分钟内提供数据"&gt;&lt;/span&gt;
&lt;a href="#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e6%9e%b6%e6%9e%84%e5%b8%88%e6%ad%a3%e5%9c%a8%e8%ae%be%e8%ae%a1%e4%b8%80%e7%a7%8d%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e4%bb%a5%e5%ad%98%e5%82%a8%e5%92%8c%e5%ad%98%e6%a1%a3%e5%85%ac%e5%8f%b8%e6%96%87%e6%a1%a3%e5%b9%b6%e7%a1%ae%e5%ae%9aamazon-glacier%e6%98%af%e6%ad%a3%e7%a1%ae%e7%9a%84%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e5%bf%85%e9%a1%bb%e5%9c%a8%e5%8f%91%e5%87%ba%e6%a3%80%e7%b4%a2%e8%af%b7%e6%b1%82%e5%90%8e%e7%9a%8410%e5%88%86%e9%92%9f%e5%86%85%e6%8f%90%e4%be%9b%e6%95%b0%e6%8d%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Amazon Glacier中的哪种功能可以帮助满足该要求？
A. 文件库锁定
B. 加速检索
c. 批量检索
D. 标准检索&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;问：如何从该服务检索数据？&lt;/p&gt;
&lt;p&gt;当您请求从 S3 Glacier 检索数据时，即表示您启动了一个存档检索作业。当检索作业完成后，您的数据将在 24 小时内可供下载或通过 Amazon Elastic Compute Cloud (Amazon EC2) 访问。有三种方式可以检索数据，每种具有不同的访问时间和成本：加急、标准和批量检索。&lt;/p&gt;
&lt;p&gt;问：什么是加急检索？&lt;/p&gt;
&lt;p&gt;当您偶尔需要加急请求档案子集时，可以使用加急检索来快速访问您的数据。除了最大的存档 (250MB+) 以外，对于使用加急检索方式访问的所有数据，通常在 1-5 分钟内即可使用。有两种加急检索：按需和预置。当我们可以在 1-5 分钟内完成检索时，就可以实施按需检索。所提供的请求将确保在您需要时能够获得加急检索的能力。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;(*)一个组织的安全策略要求应用程序在写入到磁盘之前加密数据。&lt;span class="hx:absolute hx:-mt-20" id="一个组织的安全策略要求应用程序在写入到磁盘之前加密数据"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e4%b8%aa%e7%bb%84%e7%bb%87%e7%9a%84%e5%ae%89%e5%85%a8%e7%ad%96%e7%95%a5%e8%a6%81%e6%b1%82%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%9c%a8%e5%86%99%e5%85%a5%e5%88%b0%e7%a3%81%e7%9b%98%e4%b9%8b%e5%89%8d%e5%8a%a0%e5%af%86%e6%95%b0%e6%8d%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;该组织应使用哪种解决方案以满足该要求？
A. AMS KMS API
B. AMS Certificate Manager
C. 具有 STS 的 API Gateway
D. IAM访问密钥&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;问：什么是 Amazon EBS 加密？&lt;/p&gt;
&lt;p&gt;Amazon EBS 加密提供 EBS 数据卷、引导卷和快照的无缝加密，无需构建和维护安全密钥管理基础设施。EBS 加密可使用 Amazon 托管的密钥或您使用 AWS Key Management Service (KMS) 创建和管理的密钥来给您的数据加密，从而保障静态数据的安全性。加密还发生在托管 EC2 实例的服务器上，当数据在 EC2 实例和 EBS 存储之间移动时提供数据加密。有关详细信息，请参阅 Amazon EC2 用户指南中的“Amazon EBS”加密。&lt;/p&gt;
&lt;p&gt;问：什么是 AWS Key Management Service (KMS)？&lt;/p&gt;
&lt;p&gt;AWS KMS 是一项托管服务，可让您轻松创建和控制加密数据所用的加密密钥。AWS Key Management Service 可与其他 AWS 服务集成，包括 Amazon EBS、Amazon S3 和 Amazon Redshift，可让您轻松使用您管理的加密密钥加密您的数据。AWS Key Management Service 还能与 AWS CloudTrail 集成，从而为您提供所有密钥的使用记录，帮助您满足监管和合规性要求。要了解有关 KMS 的更多信息，请访问 AWS Key Management Service 产品页面。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;(*)一家零售商每天将其交易数据库中的数据导出到S3存储捅中。该零售商的数据仓库团队希望将这些数据导入到VPC中的现有Amazon Redshift群集◊公司安全策略规定只能在VPC中传输这些数据。&lt;span class="hx:absolute hx:-mt-20" id="一家零售商每天将其交易数据库中的数据导出到s3存储捅中该零售商的数据仓库团队希望将这些数据导入到vpc中的现有amazon-redshift群集公司安全策略规定只能在vpc中传输这些数据"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e5%ae%b6%e9%9b%b6%e5%94%ae%e5%95%86%e6%af%8f%e5%a4%a9%e5%b0%86%e5%85%b6%e4%ba%a4%e6%98%93%e6%95%b0%e6%8d%ae%e5%ba%93%e4%b8%ad%e7%9a%84%e6%95%b0%e6%8d%ae%e5%af%bc%e5%87%ba%e5%88%b0s3%e5%ad%98%e5%82%a8%e6%8d%85%e4%b8%ad%e8%af%a5%e9%9b%b6%e5%94%ae%e5%95%86%e7%9a%84%e6%95%b0%e6%8d%ae%e4%bb%93%e5%ba%93%e5%9b%a2%e9%98%9f%e5%b8%8c%e6%9c%9b%e5%b0%86%e8%bf%99%e4%ba%9b%e6%95%b0%e6%8d%ae%e5%af%bc%e5%85%a5%e5%88%b0vpc%e4%b8%ad%e7%9a%84%e7%8e%b0%e6%9c%89amazon-redshift%e7%be%a4%e9%9b%86%e5%85%ac%e5%8f%b8%e5%ae%89%e5%85%a8%e7%ad%96%e7%95%a5%e8%a7%84%e5%ae%9a%e5%8f%aa%e8%83%bd%e5%9c%a8vpc%e4%b8%ad%e4%bc%a0%e8%be%93%e8%bf%99%e4%ba%9b%e6%95%b0%e6%8d%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;以下哪种步骤组合满足安全策略要求？（选择两顶)
A. 启用 Amazon Redshift 增强 VPC 路由。
B. 创建集群安全组以允许Amazon Redshift集群访问Amazon S3
C. 在公有子网中创建NAT网关以允许Amazon Redshift集群访问Amazon S3
D. 创建并配置Amazon S3 VPC终端节点
E. 在私有子网中设置NAT网关以允许Amazon Redshift集群访问AmazonS3&lt;/p&gt;
&lt;p&gt;Answer: AD&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/zh_cn/redshift/latest/mgmt/enhanced-vpc-working-with-endpoints.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/zh_cn/redshift/latest/mgmt/enhanced-vpc-working-with-endpoints.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;使用 VPC 终端节点
可以使用 VPC 终端节点创建 VPC 中的 Amazon Redshift 集群与 Amazon Simple Storage Service (Amazon S3) 之间的托管连接。在执行此操作时，您的集群与 Amazon S3 数据之间的 COPY 和 UNLOAD 流量将保留在您的 Amazon VPC 中。可以将终端节点策略附加到您的终端节点，以便更严格地管理对数据的访问。例如，可以向 VPC 终端节点添加策略以仅允许将数据上传到您账户中的特定 Amazon S3 存储桶。&lt;/p&gt;
&lt;p&gt;重要
目前，Amazon Redshift 仅支持连接到 Amazon S3 的 VPC 终端节点。当 Amazon VPC 添加对其他 AWS 服务的支持以使用 VPC 终端节点时，Amazon Redshift 也将支持这些 VPC 终端节点连接。要使用 VPC 终端节点连接到 Amazon S3 存储桶，Amazon Redshift 集群与其连接到的 Amazon S3 存储桶必须在同一个 AWS 区域中。&lt;/p&gt;
&lt;p&gt;要使用 VPC 终端节点，请为集群所在的 VPC 创建 VPC 终端节点，然后为集群启用增强型 VPC 路由。可以在 VPC 中创建集群时启用增强型 VPC 路由，也可以修改 VPC 中的集群以使用增强型 VPC 路由。&lt;/p&gt;
&lt;p&gt;VPC 终端节点使用路由表来控制 VPC 中的集群和 Amazon S3 之间的流量路由。与指定路由表关联的子网中的所有集群会自动使用该终端节点来访问服务。&lt;/p&gt;
&lt;p&gt;您的 VPC 使用与集群流量匹配的最具体的/最严格的路由来决定路由流量的方式。例如，假设路由表中有一条路由用于所有指向 Internet 网关和 Amazon S3 终端节点的 Internet 流量 (0.0.0.0/0)。在这种情况下，对所有传送到 Amazon S3 的流量优先使用终端节点路由。这是因为 Amazon S3 服务的 IP 地址范围比 0.0.0.0/0 更具体。在此示例中，所有其他 Internet 流量（包括定位到其他 AWS 区域内的 Amazon S3 存储桶的流量）将流向 Internet 网关。&lt;/p&gt;
&lt;p&gt;有关创建终端节点的更多信息，请参阅 Amazon VPC 用户指南 中的 VPC 终端节点。&lt;/p&gt;
&lt;p&gt;您使用终端节点策略控制从集群到包含数据文件的 Amazon S3 存储桶的访问。默认情况下，创建终端节点向导会附加一个终端节点策略，该策略不会进一步限制来自 VPC 中的任何用户或服务的访问。要实现更具体的控制，您可以选择附加一个自定义终端节点策略。有关更多信息，请参阅 Amazon VPC 用户指南 中的使用终端节点策略。&lt;/p&gt;
&lt;p&gt;使用终端节点不收取任何额外费用。采用标准的数据传输和资源使用计费方式。有关定价的更多信息，请参阅 Amazon EC2 定价。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.amazonaws.cn/redshift/latest/mgmt/enhanced-vpc-routing.html"target="_blank" rel="noopener"&gt;https://docs.amazonaws.cn/redshift/latest/mgmt/enhanced-vpc-routing.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Amazon Redshift 增强型 VPC 路由&lt;/p&gt;
&lt;p&gt;在使用 Amazon Redshift 增强型 VPC 路由时，Amazon Redshift 会强制通过您的 Amazon VPC 路由集群和数据存储库之间的所有 COPY 和 UNLOAD 流量。通过使用增强型 VPC 路由，您可以使用标准 VPC 功能，例如 VPC 安全组、网络访问控制列表 (ACL)、VPC 终端节点、VPC 终端节点策略、Internet 网关和域名系统 (DNS) 服务器，如 Amazon VPC 用户指南 中所述。 您可以使用这些功能来严格管理 Amazon Redshift 集群与其他资源之间的数据流。在使用增强型 VPC 路由通过您的 VPC 路由流量时，也可以使用 VPC 流日志来监视 COPY 和 UNLOAD 流量。&lt;/p&gt;
&lt;p&gt;如果未启用增强型 VPC 路由，则 Amazon Redshift 会通过 Internet 路由流量，包括至 AWS 网络中的其他服务的流量。&lt;/p&gt;
&lt;p&gt;重要
由于增强型 VPC 路由影响了 Amazon Redshift 访问其他资源的方式，因此，除非您正确配置 VPC，否则 COPY 和 UNLOAD 命令可能会失败。您必须专门在集群的 VPC 和数据资源之间创建网络路径，如下所述。&lt;/p&gt;
&lt;p&gt;在对已启用增强型 VPC 路由的集群执行 COPY 或 UNLOAD 命令时，您的 VPC 会使用最严格 或最具体的可用网络路径来将流量路由到指定资源。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;一家公司正在生成包含数百万行的大型数据集，必须能按列对这些数据集进行汇总◊将使用现有的商业智能工具生成日常报告。&lt;span class="hx:absolute hx:-mt-20" id="一家公司正在生成包含数百万行的大型数据集必须能按列对这些数据集进行汇总将使用现有的商业智能工具生成日常报告"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e5%ae%b6%e5%85%ac%e5%8f%b8%e6%ad%a3%e5%9c%a8%e7%94%9f%e6%88%90%e5%8c%85%e5%90%ab%e6%95%b0%e7%99%be%e4%b8%87%e8%a1%8c%e7%9a%84%e5%a4%a7%e5%9e%8b%e6%95%b0%e6%8d%ae%e9%9b%86%e5%bf%85%e9%a1%bb%e8%83%bd%e6%8c%89%e5%88%97%e5%af%b9%e8%bf%99%e4%ba%9b%e6%95%b0%e6%8d%ae%e9%9b%86%e8%bf%9b%e8%a1%8c%e6%b1%87%e6%80%bb%e5%b0%86%e4%bd%bf%e7%94%a8%e7%8e%b0%e6%9c%89%e7%9a%84%e5%95%86%e4%b8%9a%e6%99%ba%e8%83%bd%e5%b7%a5%e5%85%b7%e7%94%9f%e6%88%90%e6%97%a5%e5%b8%b8%e6%8a%a5%e5%91%8a" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;哪种存储服务可满足这些要求？
A. Amazon Redshift
B. Amazon RDS
C. ElastiCache
D. DynamoDB&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;h2&gt;解决方案架构师正在设计一个活动注册网页；每次用户注册活动时，需要使用一个托管服务向用户发送文本消息。&lt;span class="hx:absolute hx:-mt-20" id="解决方案架构师正在设计一个活动注册网页每次用户注册活动时需要使用一个托管服务向用户发送文本消息"&gt;&lt;/span&gt;
&lt;a href="#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e6%9e%b6%e6%9e%84%e5%b8%88%e6%ad%a3%e5%9c%a8%e8%ae%be%e8%ae%a1%e4%b8%80%e4%b8%aa%e6%b4%bb%e5%8a%a8%e6%b3%a8%e5%86%8c%e7%bd%91%e9%a1%b5%e6%af%8f%e6%ac%a1%e7%94%a8%e6%88%b7%e6%b3%a8%e5%86%8c%e6%b4%bb%e5%8a%a8%e6%97%b6%e9%9c%80%e8%a6%81%e4%bd%bf%e7%94%a8%e4%b8%80%e4%b8%aa%e6%89%98%e7%ae%a1%e6%9c%8d%e5%8a%a1%e5%90%91%e7%94%a8%e6%88%b7%e5%8f%91%e9%80%81%e6%96%87%e6%9c%ac%e6%b6%88%e6%81%af" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;架构师应使用哪种AWS服务来实现该目的？
A. Amazon STS
B. Amazon SQS
C. Lambda
D. Amazon SNS&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Amazon Simple Notification Service (SNS) 是一种高度可用、持久、安全、完全托管的发布/订阅消息收发服务，可以轻松分离微服务、分布式系统和无服务器应用程序。Amazon SNS 提供了面向高吞吐量、多对多推送式消息收发的主题。借助 Amazon SNS 主题，发布系统可以向大量订阅终端节点（包括 Amazon SQS 队列、AWS Lambda 函数和 HTTP/S Webhook 等）扇出消息，从而实现并行处理。此外，SNS 可用于使用移动推送、短信和电子邮件向最终用户扇出通知。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;(*)解决方案架构师正在设计一个共享服务，以便在Amazon ECS上托管来自很多客户的容器。这些容器将使用很多AWS服务。一个客户的容器无法访问其他客户的数据。&lt;span class="hx:absolute hx:-mt-20" id="解决方案架构师正在设计一个共享服务以便在amazon-ecs上托管来自很多客户的容器这些容器将使用很多aws服务一个客户的容器无法访问其他客户的数据"&gt;&lt;/span&gt;
&lt;a href="#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e6%9e%b6%e6%9e%84%e5%b8%88%e6%ad%a3%e5%9c%a8%e8%ae%be%e8%ae%a1%e4%b8%80%e4%b8%aa%e5%85%b1%e4%ba%ab%e6%9c%8d%e5%8a%a1%e4%bb%a5%e4%be%bf%e5%9c%a8amazon-ecs%e4%b8%8a%e6%89%98%e7%ae%a1%e6%9d%a5%e8%87%aa%e5%be%88%e5%a4%9a%e5%ae%a2%e6%88%b7%e7%9a%84%e5%ae%b9%e5%99%a8%e8%bf%99%e4%ba%9b%e5%ae%b9%e5%99%a8%e5%b0%86%e4%bd%bf%e7%94%a8%e5%be%88%e5%a4%9aaws%e6%9c%8d%e5%8a%a1%e4%b8%80%e4%b8%aa%e5%ae%a2%e6%88%b7%e7%9a%84%e5%ae%b9%e5%99%a8%e6%97%a0%e6%b3%95%e8%ae%bf%e9%97%ae%e5%85%b6%e4%bb%96%e5%ae%a2%e6%88%b7%e7%9a%84%e6%95%b0%e6%8d%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;架构师应使用哪种解决方案以满足这些要求？
A. 任务的IAM角色
B. EC2实例的 IAM角色
C. EC2实例的 IAM实例配置文件
D. 安全组规则&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/zh_cn/AmazonECS/latest/developerguide/task-iam-roles.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/zh_cn/AmazonECS/latest/developerguide/task-iam-roles.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;借助 Amazon ECS 任务的 IAM 角色，您可以指定一个可由任务中的容器使用的 IAM 角色。应用程序必须使用 AWS 凭证签署其 AWS API 请求，并且此功能提供了一个管理凭证的策略以供应用程序使用，类似于 Amazon EC2 实例配置文件为 EC2 实例提供凭证的方式。您可以将 IAM 角色与 ECS 任务定义或 RunTask API 操作关联，而不是为容器创建和分配 AWS 凭证或使用 EC2 实例的角色。之后，任务的容器中的应用程序可以使用 AWS 开发工具包或 CLI 向授权的 AWS 服务发出 API 请求。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;一家公司正在将本地10 TB MySQL数据库迁移到AWS，该公司预计数据库大小将增加3倍，业务要求是副本的滯后时间必须保持在100毫秒以内。&lt;span class="hx:absolute hx:-mt-20" id="一家公司正在将本地10-tb-mysql数据库迁移到aws该公司预计数据库大小将增加3倍业务要求是副本的滯后时间必须保持在100毫秒以内"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e5%ae%b6%e5%85%ac%e5%8f%b8%e6%ad%a3%e5%9c%a8%e5%b0%86%e6%9c%ac%e5%9c%b010-tb-mysql%e6%95%b0%e6%8d%ae%e5%ba%93%e8%bf%81%e7%a7%bb%e5%88%b0aws%e8%af%a5%e5%85%ac%e5%8f%b8%e9%a2%84%e8%ae%a1%e6%95%b0%e6%8d%ae%e5%ba%93%e5%a4%a7%e5%b0%8f%e5%b0%86%e5%a2%9e%e5%8a%a03%e5%80%8d%e4%b8%9a%e5%8a%a1%e8%a6%81%e6%b1%82%e6%98%af%e5%89%af%e6%9c%ac%e7%9a%84%e6%bb%af%e5%90%8e%e6%97%b6%e9%97%b4%e5%bf%85%e9%a1%bb%e4%bf%9d%e6%8c%81%e5%9c%a8100%e6%af%ab%e7%a7%92%e4%bb%a5%e5%86%85" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;哪种Amazon RDS引擎满足这些要求？
A. MySQL
B. Microsoft SQL Server
C. Oracle
D. Amazon Aurora&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://amazonaws-china.com/cn/rds/aurora/faqs/?nc=sn&amp;amp;loc=6"target="_blank" rel="noopener"&gt;https://amazonaws-china.com/cn/rds/aurora/faqs/?nc=sn&amp;loc=6&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Amazon Aurora 副本复制是毫秒级别，而MySQL是秒级别&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;管理员在AWS中运行一个高可用应用程序。管理员需要使用一个文件存储层，它可以在实例之间共享并能更轻松地扩展该应用平台。&lt;span class="hx:absolute hx:-mt-20" id="管理员在aws中运行一个高可用应用程序管理员需要使用一个文件存储层它可以在实例之间共享并能更轻松地扩展该应用平台"&gt;&lt;/span&gt;
&lt;a href="#%e7%ae%a1%e7%90%86%e5%91%98%e5%9c%a8aws%e4%b8%ad%e8%bf%90%e8%a1%8c%e4%b8%80%e4%b8%aa%e9%ab%98%e5%8f%af%e7%94%a8%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e7%ae%a1%e7%90%86%e5%91%98%e9%9c%80%e8%a6%81%e4%bd%bf%e7%94%a8%e4%b8%80%e4%b8%aa%e6%96%87%e4%bb%b6%e5%ad%98%e5%82%a8%e5%b1%82%e5%ae%83%e5%8f%af%e4%bb%a5%e5%9c%a8%e5%ae%9e%e4%be%8b%e4%b9%8b%e9%97%b4%e5%85%b1%e4%ba%ab%e5%b9%b6%e8%83%bd%e6%9b%b4%e8%bd%bb%e6%9d%be%e5%9c%b0%e6%89%a9%e5%b1%95%e8%af%a5%e5%ba%94%e7%94%a8%e5%b9%b3%e5%8f%b0" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;哪种AMS服务可以执行该操作？
A. Amazon EBS
B. Amazon EFS
C. Amazon S3
D. Amazon EC2实例存储&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;一家公司托管一个流行的Web应用程序，它连接到在私有VPC子网中运行的Amazon RDS MySQL数据库实例，该子网是使用默认ACL设置创建的。仅允许使用SSL连接的客户访问Web服务器◊仅公有子网中的Web服务器可以访问该数据库。&lt;span class="hx:absolute hx:-mt-20" id="一家公司托管一个流行的web应用程序它连接到在私有vpc子网中运行的amazon-rds-mysql数据库实例该子网是使用默认acl设置创建的仅允许使用ssl连接的客户访问web服务器仅公有子网中的web服务器可以访问该数据库"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e5%ae%b6%e5%85%ac%e5%8f%b8%e6%89%98%e7%ae%a1%e4%b8%80%e4%b8%aa%e6%b5%81%e8%a1%8c%e7%9a%84web%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%ae%83%e8%bf%9e%e6%8e%a5%e5%88%b0%e5%9c%a8%e7%a7%81%e6%9c%89vpc%e5%ad%90%e7%bd%91%e4%b8%ad%e8%bf%90%e8%a1%8c%e7%9a%84amazon-rds-mysql%e6%95%b0%e6%8d%ae%e5%ba%93%e5%ae%9e%e4%be%8b%e8%af%a5%e5%ad%90%e7%bd%91%e6%98%af%e4%bd%bf%e7%94%a8%e9%bb%98%e8%ae%a4acl%e8%ae%be%e7%bd%ae%e5%88%9b%e5%bb%ba%e7%9a%84%e4%bb%85%e5%85%81%e8%ae%b8%e4%bd%bf%e7%94%a8ssl%e8%bf%9e%e6%8e%a5%e7%9a%84%e5%ae%a2%e6%88%b7%e8%ae%bf%e9%97%aeweb%e6%9c%8d%e5%8a%a1%e5%99%a8%e4%bb%85%e5%85%ac%e6%9c%89%e5%ad%90%e7%bd%91%e4%b8%ad%e7%9a%84web%e6%9c%8d%e5%8a%a1%e5%99%a8%e5%8f%af%e4%bb%a5%e8%ae%bf%e9%97%ae%e8%af%a5%e6%95%b0%e6%8d%ae%e5%ba%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;哪种解决方案可满足这些要求而不会影响其他运行的应用程序？（选择两顶)
A. 在Web服务器的子网上创建一个网络ACL，允许HTTPS端口 443入站流量，并将源指定为0.0.0.0/0。
B. 创建一个允许来自Anywhere (0.0.0.0/0)的 HTTPS端口 443入站流量的Web服务器安全组，并将其应用于Web服务器。
C. 创建一个允许MySQL端口 3306入站流量的数据库服务器安全组，并将源指定为一个Web服务器安全组。
D. 在数据库子网上创建一个网络ACL，允许Web服务器的MySQL端口 3306入站流量，并拒绝所有出站流量。
E. 创建一个允许HTTPS端口 443入站流量的数据库服务器安全组，并将源指定为一个Web服务器安全组。&lt;/p&gt;
&lt;p&gt;Answer: BC&lt;/p&gt;
&lt;h2&gt;一个应用程序当前在Amazon EBS卷上存储所有数据。必须在多个可用区中永久备份所有EBS卷。&lt;span class="hx:absolute hx:-mt-20" id="一个应用程序当前在amazon-ebs卷上存储所有数据必须在多个可用区中永久备份所有ebs卷"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e4%b8%aa%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%bd%93%e5%89%8d%e5%9c%a8amazon-ebs%e5%8d%b7%e4%b8%8a%e5%ad%98%e5%82%a8%e6%89%80%e6%9c%89%e6%95%b0%e6%8d%ae%e5%bf%85%e9%a1%bb%e5%9c%a8%e5%a4%9a%e4%b8%aa%e5%8f%af%e7%94%a8%e5%8c%ba%e4%b8%ad%e6%b0%b8%e4%b9%85%e5%a4%87%e4%bb%bd%e6%89%80%e6%9c%89ebs%e5%8d%b7" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;备份这些卷的最灵活方法是什么？
A. 定期创建EBS快照。
B. 启用EBS卷加密。
C. 创建脚本以将数据复制到EC2实例存储。
D. 在两个EBS卷之间镜像数据。&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;h2&gt;解决方案架构师正在开发一个文档共享应用程序，并需要使用一个存储层。该存储应提供自动版本控制支持，以便用户可以轻松回滚到以前的版本或恢复删除的文档。&lt;span class="hx:absolute hx:-mt-20" id="解决方案架构师正在开发一个文档共享应用程序并需要使用一个存储层该存储应提供自动版本控制支持以便用户可以轻松回滚到以前的版本或恢复删除的文档"&gt;&lt;/span&gt;
&lt;a href="#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e6%9e%b6%e6%9e%84%e5%b8%88%e6%ad%a3%e5%9c%a8%e5%bc%80%e5%8f%91%e4%b8%80%e4%b8%aa%e6%96%87%e6%a1%a3%e5%85%b1%e4%ba%ab%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%b9%b6%e9%9c%80%e8%a6%81%e4%bd%bf%e7%94%a8%e4%b8%80%e4%b8%aa%e5%ad%98%e5%82%a8%e5%b1%82%e8%af%a5%e5%ad%98%e5%82%a8%e5%ba%94%e6%8f%90%e4%be%9b%e8%87%aa%e5%8a%a8%e7%89%88%e6%9c%ac%e6%8e%a7%e5%88%b6%e6%94%af%e6%8c%81%e4%bb%a5%e4%be%bf%e7%94%a8%e6%88%b7%e5%8f%af%e4%bb%a5%e8%bd%bb%e6%9d%be%e5%9b%9e%e6%bb%9a%e5%88%b0%e4%bb%a5%e5%89%8d%e7%9a%84%e7%89%88%e6%9c%ac%e6%88%96%e6%81%a2%e5%a4%8d%e5%88%a0%e9%99%a4%e7%9a%84%e6%96%87%e6%a1%a3" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;哪种AMS服务可满足这些要求？
A. Amazon S3
B. Amazon EBS
C. Amazon EFS
D. Amazon Storage Gateway VTL&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;h2&gt;AWS中的一个数据处理应用程序必须从Internet服务中提取数据。解决方案架构师必须设计一种高可用解决方案以访问数据，并且不会对应用程序流量施加带宽限制。&lt;span class="hx:absolute hx:-mt-20" id="aws中的一个数据处理应用程序必须从internet服务中提取数据解决方案架构师必须设计一种高可用解决方案以访问数据并且不会对应用程序流量施加带宽限制"&gt;&lt;/span&gt;
&lt;a href="#aws%e4%b8%ad%e7%9a%84%e4%b8%80%e4%b8%aa%e6%95%b0%e6%8d%ae%e5%a4%84%e7%90%86%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%bf%85%e9%a1%bb%e4%bb%8einternet%e6%9c%8d%e5%8a%a1%e4%b8%ad%e6%8f%90%e5%8f%96%e6%95%b0%e6%8d%ae%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e6%9e%b6%e6%9e%84%e5%b8%88%e5%bf%85%e9%a1%bb%e8%ae%be%e8%ae%a1%e4%b8%80%e7%a7%8d%e9%ab%98%e5%8f%af%e7%94%a8%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e4%bb%a5%e8%ae%bf%e9%97%ae%e6%95%b0%e6%8d%ae%e5%b9%b6%e4%b8%94%e4%b8%8d%e4%bc%9a%e5%af%b9%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e6%b5%81%e9%87%8f%e6%96%bd%e5%8a%a0%e5%b8%a6%e5%ae%bd%e9%99%90%e5%88%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;哪种解决方案能满足这些要求？
A. 启动一个NAT网关并为0.0.0.0/0添加路由
B. 附加一个VPC终端节点并为0.0.0.0/0添加路由
C. 附加一个Internet网关并为0.0.0.0/0添加路由
D. 在公有子网中部署NAT实例并为0.0.0.0/0添加路由&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/zh_cn/vpc/latest/userguide/VPC_Internet_Gateway.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/zh_cn/vpc/latest/userguide/VPC_Internet_Gateway.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Internet 网关是一种横向扩展、支持冗余且高度可用的 VPC 组件，可实现 VPC 中的实例与 Internet 之间的通信。因此它不会对网络流量造成可用性风险或带宽限制。&lt;/p&gt;
&lt;p&gt;NAT 网关
您可以使用网络地址转换 (NAT) 网关允许私有子网中的实例连接到 Internet 或其他 AWS 服务，但阻止 Internet 发起与这些实例的连接。有关 NAT 的更多信息，请参阅NAT。
您在账户中创建和使用 NAT 网关会产生费用。NAT 网关小时使用费率和数据处理费率适用于此。Amazon EC2 数据传输费同样适用。有关更多信息，请参阅 Amazon VPC 定价。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;(待确认)在审查您的应用程序的Auto Scaling事件时，您注意到应用程序在同一小时内扩展和缩减多次。&lt;span class="hx:absolute hx:-mt-20" id="待确认在审查您的应用程序的auto-scaling事件时您注意到应用程序在同一小时内扩展和缩减多次"&gt;&lt;/span&gt;
&lt;a href="#%e5%be%85%e7%a1%ae%e8%ae%a4%e5%9c%a8%e5%ae%a1%e6%9f%a5%e6%82%a8%e7%9a%84%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e7%9a%84auto-scaling%e4%ba%8b%e4%bb%b6%e6%97%b6%e6%82%a8%e6%b3%a8%e6%84%8f%e5%88%b0%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%9c%a8%e5%90%8c%e4%b8%80%e5%b0%8f%e6%97%b6%e5%86%85%e6%89%a9%e5%b1%95%e5%92%8c%e7%bc%a9%e5%87%8f%e5%a4%9a%e6%ac%a1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;您可以选择哪种设计选顶以在保持弹性的同时优化成本？（选择两顶)
A. 修改Auto Scaling组终止策略以先终止最老的实例。
B. 修改Auto Scaling组终止策略以先终止最新的实例。
C. 修改Auto Scaling组冷却计时器。
D. 修改Auto Scaling策略以使用计划的缩放操作。
E. 修改触发Auto Scaling缩减策略的CloudWatch警报周期。&lt;/p&gt;
&lt;p&gt;Answer: BC&lt;/p&gt;
&lt;p&gt;这道题目前纠结点在于AB两个选项，从文档中可知有一种策略结束类型叫ClosestToNextInstanceHour类型更适合该题目。如果从这个角度说，新的实例好像更靠近最近计费时间点这个选项。&lt;/p&gt;
&lt;h2&gt;对于以下哪种工作负载，解决方案架构师应考虑使用Elastic Beanstalk?(选择两顶)&lt;span class="hx:absolute hx:-mt-20" id="对于以下哪种工作负载解决方案架构师应考虑使用elastic-beanstalk选择两顶"&gt;&lt;/span&gt;
&lt;a href="#%e5%af%b9%e4%ba%8e%e4%bb%a5%e4%b8%8b%e5%93%aa%e7%a7%8d%e5%b7%a5%e4%bd%9c%e8%b4%9f%e8%bd%bd%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e6%9e%b6%e6%9e%84%e5%b8%88%e5%ba%94%e8%80%83%e8%99%91%e4%bd%bf%e7%94%a8elastic-beanstalk%e9%80%89%e6%8b%a9%e4%b8%a4%e9%a1%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. 使用Amazon RDS的Web应用程序
B. 企业数据仓库
C. 长时间运行的工作进程
D. 静态网站
E. 每晚运行一次的管理任务&lt;/p&gt;
&lt;p&gt;Answer: AD&lt;/p&gt;
&lt;h2&gt;一家公司在AMS上运行一个服务，以便为笔记本电脑和手机上的图像提供异地备份。该解决方案必须支持数百万个客户，每个客户有数千张图像，很少会检索这些图像，但必须可以立即检索这些图像。&lt;span class="hx:absolute hx:-mt-20" id="一家公司在ams上运行一个服务以便为笔记本电脑和手机上的图像提供异地备份该解决方案必须支持数百万个客户每个客户有数千张图像很少会检索这些图像但必须可以立即检索这些图像"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e5%ae%b6%e5%85%ac%e5%8f%b8%e5%9c%a8ams%e4%b8%8a%e8%bf%90%e8%a1%8c%e4%b8%80%e4%b8%aa%e6%9c%8d%e5%8a%a1%e4%bb%a5%e4%be%bf%e4%b8%ba%e7%ac%94%e8%ae%b0%e6%9c%ac%e7%94%b5%e8%84%91%e5%92%8c%e6%89%8b%e6%9c%ba%e4%b8%8a%e7%9a%84%e5%9b%be%e5%83%8f%e6%8f%90%e4%be%9b%e5%bc%82%e5%9c%b0%e5%a4%87%e4%bb%bd%e8%af%a5%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e5%bf%85%e9%a1%bb%e6%94%af%e6%8c%81%e6%95%b0%e7%99%be%e4%b8%87%e4%b8%aa%e5%ae%a2%e6%88%b7%e6%af%8f%e4%b8%aa%e5%ae%a2%e6%88%b7%e6%9c%89%e6%95%b0%e5%8d%83%e5%bc%a0%e5%9b%be%e5%83%8f%e5%be%88%e5%b0%91%e4%bc%9a%e6%a3%80%e7%b4%a2%e8%bf%99%e4%ba%9b%e5%9b%be%e5%83%8f%e4%bd%86%e5%bf%85%e9%a1%bb%e5%8f%af%e4%bb%a5%e7%ab%8b%e5%8d%b3%e6%a3%80%e7%b4%a2%e8%bf%99%e4%ba%9b%e5%9b%be%e5%83%8f" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;哪种是满足这些要求的最经济高效的存储选顶？
A. 具有加速检索的Amazon Glacier
B. Amazon S3标准-低频率访问
C. Amazon EFS
D. Amazon S3 标准&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;一个带有150 GB大小的关系数据库的应用程序在EC2实例上运行。该应用程序很少使用，但在早上和晚上会出现很小的高峰。&lt;span class="hx:absolute hx:-mt-20" id="一个带有150-gb大小的关系数据库的应用程序在ec2实例上运行该应用程序很少使用但在早上和晚上会出现很小的高峰"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e4%b8%aa%e5%b8%a6%e6%9c%89150-gb%e5%a4%a7%e5%b0%8f%e7%9a%84%e5%85%b3%e7%b3%bb%e6%95%b0%e6%8d%ae%e5%ba%93%e7%9a%84%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%9c%a8ec2%e5%ae%9e%e4%be%8b%e4%b8%8a%e8%bf%90%e8%a1%8c%e8%af%a5%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%be%88%e5%b0%91%e4%bd%bf%e7%94%a8%e4%bd%86%e5%9c%a8%e6%97%a9%e4%b8%8a%e5%92%8c%e6%99%9a%e4%b8%8a%e4%bc%9a%e5%87%ba%e7%8e%b0%e5%be%88%e5%b0%8f%e7%9a%84%e9%ab%98%e5%b3%b0" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;最经济高效的存储类型是什么？
A. Amazon EBS 预置 IOPS SSD
B. Amazon EBS吞吐量优化HDD
C. Amazon EBS 通用型 SSD
D. Amazon EFS&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;一个应用程序允许生产站点上传文件。然后，处理每个3 GB大小的文件以提取元数据，处理每个文件需要几秒钟的时间◊更新频率是无法预铡的-可能几小时内没有更新，然后同时上传几个文件。&lt;span class="hx:absolute hx:-mt-20" id="一个应用程序允许生产站点上传文件然后处理每个3-gb大小的文件以提取元数据处理每个文件需要几秒钟的时间更新频率是无法预铡的-可能几小时内没有更新然后同时上传几个文件"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e4%b8%aa%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%85%81%e8%ae%b8%e7%94%9f%e4%ba%a7%e7%ab%99%e7%82%b9%e4%b8%8a%e4%bc%a0%e6%96%87%e4%bb%b6%e7%84%b6%e5%90%8e%e5%a4%84%e7%90%86%e6%af%8f%e4%b8%aa3-gb%e5%a4%a7%e5%b0%8f%e7%9a%84%e6%96%87%e4%bb%b6%e4%bb%a5%e6%8f%90%e5%8f%96%e5%85%83%e6%95%b0%e6%8d%ae%e5%a4%84%e7%90%86%e6%af%8f%e4%b8%aa%e6%96%87%e4%bb%b6%e9%9c%80%e8%a6%81%e5%87%a0%e7%a7%92%e9%92%9f%e7%9a%84%e6%97%b6%e9%97%b4%e6%9b%b4%e6%96%b0%e9%a2%91%e7%8e%87%e6%98%af%e6%97%a0%e6%b3%95%e9%a2%84%e9%93%a1%e7%9a%84-%e5%8f%af%e8%83%bd%e5%87%a0%e5%b0%8f%e6%97%b6%e5%86%85%e6%b2%a1%e6%9c%89%e6%9b%b4%e6%96%b0%e7%84%b6%e5%90%8e%e5%90%8c%e6%97%b6%e4%b8%8a%e4%bc%a0%e5%87%a0%e4%b8%aa%e6%96%87%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;哪种架构能以最经济高效的方式处理该工作负载？
A. 使用Kinesis数据传输流存储文件，并使用Uirtoda进行处理。
B. 使用SQS队列存储文件，然后，一组EC2实例访问该文件。
C. 将文件存储在EBS卷中，然后，其他EC2实例可以访问该文件以进行处理。
D. 将文件存储在S3存储捅中，并使用Amazon S3事件通知调用Lambda函数以处理该文件。&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;h2&gt;一家网站在ELB应用程序负载均衡器后面的多个EC2实例上运行。这些实例在跨多个可用区的Auto Scaling组中运行◊这些实例提供一些很大的文件（图像，PDF等)，这些文件存储在共享的Amazon EFS文件系统上。每次用户请求这些数字资产时，该公司需要避免从EC2实例中提供这些文件。&lt;span class="hx:absolute hx:-mt-20" id="一家网站在elb应用程序负载均衡器后面的多个ec2实例上运行这些实例在跨多个可用区的auto-scaling组中运行这些实例提供一些很大的文件图像pdf等这些文件存储在共享的amazon-efs文件系统上每次用户请求这些数字资产时该公司需要避免从ec2实例中提供这些文件"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e5%ae%b6%e7%bd%91%e7%ab%99%e5%9c%a8elb%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e8%b4%9f%e8%bd%bd%e5%9d%87%e8%a1%a1%e5%99%a8%e5%90%8e%e9%9d%a2%e7%9a%84%e5%a4%9a%e4%b8%aaec2%e5%ae%9e%e4%be%8b%e4%b8%8a%e8%bf%90%e8%a1%8c%e8%bf%99%e4%ba%9b%e5%ae%9e%e4%be%8b%e5%9c%a8%e8%b7%a8%e5%a4%9a%e4%b8%aa%e5%8f%af%e7%94%a8%e5%8c%ba%e7%9a%84auto-scaling%e7%bb%84%e4%b8%ad%e8%bf%90%e8%a1%8c%e8%bf%99%e4%ba%9b%e5%ae%9e%e4%be%8b%e6%8f%90%e4%be%9b%e4%b8%80%e4%ba%9b%e5%be%88%e5%a4%a7%e7%9a%84%e6%96%87%e4%bb%b6%e5%9b%be%e5%83%8fpdf%e7%ad%89%e8%bf%99%e4%ba%9b%e6%96%87%e4%bb%b6%e5%ad%98%e5%82%a8%e5%9c%a8%e5%85%b1%e4%ba%ab%e7%9a%84amazon-efs%e6%96%87%e4%bb%b6%e7%b3%bb%e7%bb%9f%e4%b8%8a%e6%af%8f%e6%ac%a1%e7%94%a8%e6%88%b7%e8%af%b7%e6%b1%82%e8%bf%99%e4%ba%9b%e6%95%b0%e5%ad%97%e8%b5%84%e4%ba%a7%e6%97%b6%e8%af%a5%e5%85%ac%e5%8f%b8%e9%9c%80%e8%a6%81%e9%81%bf%e5%85%8d%e4%bb%8eec2%e5%ae%9e%e4%be%8b%e4%b8%ad%e6%8f%90%e4%be%9b%e8%bf%99%e4%ba%9b%e6%96%87%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;该公司应釆取哪些措施以改进网站的用户体验？
A. 将数字资产移到到Amazon Glacier中。
B. 使用CloudFront缓存静态内容。
C. 调整图像以使其变小。
D. 使用保留的EC2实例。&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;您正在Amazon EC2上部署一个应用程序，它必须调用AMS API。&lt;span class="hx:absolute hx:-mt-20" id="您正在amazon-ec2上部署一个应用程序它必须调用ams-api"&gt;&lt;/span&gt;
&lt;a href="#%e6%82%a8%e6%ad%a3%e5%9c%a8amazon-ec2%e4%b8%8a%e9%83%a8%e7%bd%b2%e4%b8%80%e4%b8%aa%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%ae%83%e5%bf%85%e9%a1%bb%e8%b0%83%e7%94%a8ams-api" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;应使用哪种方法可将凭证安全地传送到该应用程序？
A. 使用实例用户数据将API凭证传送到实例。
B. 将API凭证作为对象存储在Amazon S3中。
C. 将API凭证嵌入到JAR文件中。
D. 将IAM角色分配给EC2实例。&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;h2&gt;一个组织在AWS上托管着一个多语言网站◊该网站是使用CloudFront提供服务的◊语言是在HTTP请求中指定的:&lt;span class="hx:absolute hx:-mt-20" id="一个组织在aws上托管着一个多语言网站该网站是使用cloudfront提供服务的语言是在http请求中指定的"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e4%b8%aa%e7%bb%84%e7%bb%87%e5%9c%a8aws%e4%b8%8a%e6%89%98%e7%ae%a1%e7%9d%80%e4%b8%80%e4%b8%aa%e5%a4%9a%e8%af%ad%e8%a8%80%e7%bd%91%e7%ab%99%e8%af%a5%e7%bd%91%e7%ab%99%e6%98%af%e4%bd%bf%e7%94%a8cloudfront%e6%8f%90%e4%be%9b%e6%9c%8d%e5%8a%a1%e7%9a%84%e8%af%ad%e8%a8%80%e6%98%af%e5%9c%a8http%e8%af%b7%e6%b1%82%e4%b8%ad%e6%8c%87%e5%ae%9a%e7%9a%84" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;• &lt;a href="http://dllllllabcdef8.cloudfront.net/main.html?language=de"target="_blank" rel="noopener"&gt;http://dllllllabcdef8.cloudfront.net/main.html?language=de&lt;/a&gt;
• &lt;a href="http://dllllllabcdef8.cloudfront.net/main.html?language=en"target="_blank" rel="noopener"&gt;http://dllllllabcdef8.cloudfront.net/main.html?language=en&lt;/a&gt;
• &lt;a href="http://dllllllabcdef8.cloudfront.net/main.html?language=es"target="_blank" rel="noopener"&gt;http://dllllllabcdef8.cloudfront.net/main.html?language=es&lt;/a&gt;
应如何配置CloudFront以使用正确的语言提供缓存的数据？
A. 将Cookie转发到原始地址。
B. 基于查询字符串参数。
C. 在原始地址中缓存对象。
D. 提供动态内容。&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/QueryStringParameters.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/QueryStringParameters.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;一些 Web 应用程序使用查询字符串将信息发送到源。查询字符串是 Web 请求的一部分，显示在 ? 字符之后；该字符串可以包含一个或多个使用 &amp;amp; 字符分隔的参数。在以下示例中，查询字符串包括两个参数 color=red 和 size=large：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;解决方案架构师正在设计一个可高度扩展的系统以跟踪记录。记录必须保留三个月以便可立即下载，然后必须删除记录。&lt;span class="hx:absolute hx:-mt-20" id="解决方案架构师正在设计一个可高度扩展的系统以跟踪记录记录必须保留三个月以便可立即下载然后必须删除记录"&gt;&lt;/span&gt;
&lt;a href="#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88%e6%9e%b6%e6%9e%84%e5%b8%88%e6%ad%a3%e5%9c%a8%e8%ae%be%e8%ae%a1%e4%b8%80%e4%b8%aa%e5%8f%af%e9%ab%98%e5%ba%a6%e6%89%a9%e5%b1%95%e7%9a%84%e7%b3%bb%e7%bb%9f%e4%bb%a5%e8%b7%9f%e8%b8%aa%e8%ae%b0%e5%bd%95%e8%ae%b0%e5%bd%95%e5%bf%85%e9%a1%bb%e4%bf%9d%e7%95%99%e4%b8%89%e4%b8%aa%e6%9c%88%e4%bb%a5%e4%be%bf%e5%8f%af%e7%ab%8b%e5%8d%b3%e4%b8%8b%e8%bd%bd%e7%84%b6%e5%90%8e%e5%bf%85%e9%a1%bb%e5%88%a0%e9%99%a4%e8%ae%b0%e5%bd%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;最适合该使用案例的决策是什么？
A. 将文件存储在Amazon EBS上，并创建一个生命周期策略以在三个月后删除这些文件。
B. 将文件存储在Amazon S3中，并创建一个生命周期策略以在三个月后删除这些文件。
C. 将文件存储在Amazon Glacier中，并创建一个生命周期策略以在三个月后删除这些文件。
D. 将文件存储在Amazon EFS上，并创建一个生命周期策略以在三个月后删除这些文件。&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;一个团队正在创建一个应用程序，它必须在高可用的数据存储中永久保存JSON文件并编制索引。尽管应用程序流量很高，但数据访问延迟必须保持一致。&lt;span class="hx:absolute hx:-mt-20" id="一个团队正在创建一个应用程序它必须在高可用的数据存储中永久保存json文件并编制索引尽管应用程序流量很高但数据访问延迟必须保持一致"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e4%b8%aa%e5%9b%a2%e9%98%9f%e6%ad%a3%e5%9c%a8%e5%88%9b%e5%bb%ba%e4%b8%80%e4%b8%aa%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%ae%83%e5%bf%85%e9%a1%bb%e5%9c%a8%e9%ab%98%e5%8f%af%e7%94%a8%e7%9a%84%e6%95%b0%e6%8d%ae%e5%ad%98%e5%82%a8%e4%b8%ad%e6%b0%b8%e4%b9%85%e4%bf%9d%e5%ad%98json%e6%96%87%e4%bb%b6%e5%b9%b6%e7%bc%96%e5%88%b6%e7%b4%a2%e5%bc%95%e5%b0%bd%e7%ae%a1%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e6%b5%81%e9%87%8f%e5%be%88%e9%ab%98%e4%bd%86%e6%95%b0%e6%8d%ae%e8%ae%bf%e9%97%ae%e5%bb%b6%e8%bf%9f%e5%bf%85%e9%a1%bb%e4%bf%9d%e6%8c%81%e4%b8%80%e8%87%b4" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;该团队应该选择哪种服务？
A. Amazon EFS
B. Amazon RedShift
C. DynamoDB
D. AWS CloudFormation&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;h2&gt;(*)一个应用程序在S3存储桶中读取和写入小对象。在完全部署该应用程序后，读取/写入流量会非常高。&lt;span class="hx:absolute hx:-mt-20" id="一个应用程序在s3存储桶中读取和写入小对象在完全部署该应用程序后读取写入流量会非常高"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e4%b8%aa%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%9c%a8s3%e5%ad%98%e5%82%a8%e6%a1%b6%e4%b8%ad%e8%af%bb%e5%8f%96%e5%92%8c%e5%86%99%e5%85%a5%e5%b0%8f%e5%af%b9%e8%b1%a1%e5%9c%a8%e5%ae%8c%e5%85%a8%e9%83%a8%e7%bd%b2%e8%af%a5%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%90%8e%e8%af%bb%e5%8f%96%e5%86%99%e5%85%a5%e6%b5%81%e9%87%8f%e4%bc%9a%e9%9d%9e%e5%b8%b8%e9%ab%98" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;架构师应如何最大限度地提高Amazon S3性能？
A. 在每个对象名称前面添加随机字符串。
B. 使用STANDARD_IA存储类
C. 在每个对象名称前面添加当前日期。
D. 在S3存储桶上启用版本控制。&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/dev/optimizing-performance.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/dev/optimizing-performance.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;当从 Amazon S3 上传和检索存储时，您的应用程序可以轻松地实现每秒数千个事务的请求性能。Amazon S3 会自动扩展至高请求速率。例如，您的应用程序可以在存储桶中实现至少每秒每个前缀 3,500 个 PUT/COPY/POST/DELETE 请求和 5,500 个 GET/HEAD 请求。对存储桶中的前缀数量没有限制。您可以通过并行读取来增加读取或写入性能。例如，如果您在 Amazon S3 存储桶中创建 10 个前缀以并行处理读取，则可以将读取性能扩展到每秒 55,000 个读取请求。
下面的主题介绍的最佳实践准则和设计模式用于优化使用 Amazon S3 的应用程序的性能。本指南的优先级高于之前有关优化 Amazon S3 的性能的任何指南。例如，以前的 Amazon S3 性能指南建议用哈希字符来随机化前缀命名，以便优化频繁数据检索的性能。现在，您不再需要为了提高性能随机化前缀命名，而是可以对前缀使用基于顺序日期的命名方式。有关对 Amazon S3 进行性能优化的最新信息，请参阅Amazon S3 的性能准则和Amazon S3 的性能设计模式。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;2018年7月17日 Amazon S3 宣布提高请求速率性能(&lt;a href="https://amazonaws-china.com/cn/about-aws/whats-new/2018/07/amazon-s3-announces-increased-request-rate-performance/"target="_blank" rel="noopener"&gt;https://amazonaws-china.com/cn/about-aws/whats-new/2018/07/amazon-s3-announces-increased-request-rate-performance/&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Amazon S3 现在提供了更高的性能，支持每秒至少 3500 个数据添加请求、每秒 5500 个数据检索请求，而且无需额外费用，这可以节省大量处理时间。每个 S3 前缀均支持这些请求速率，因此可以轻松实现显著的性能提升。&lt;/p&gt;
&lt;p&gt;目前在 Amazon S3 上运行的应用程序均可享受此性能改进，而无需实施任何更改；在 S3 上构建新应用程序的客户无需进行任何应用程序自定义即可享受此性能。Amazon S3 对并行请求的支持意味着您可以按照计算集群的系数扩展 S3 性能，而无需对应用程序进行任何自定义。性能按前缀扩展，因此您可以并行使用尽可能多的前缀，从而实现所需的吞吐量。前缀的数量没有限制。&lt;/p&gt;
&lt;p&gt;在这种 S3 请求速率性能提升推出后，先前任何为加速性能而随机化对象前缀的指南均被淘汰。也就是说，您现在可以在 S3 对象命名中使用逻辑或顺序命名模式，而不会产生任何性能影响。所有 AWS 区域现在均已提供此改进。有关更多信息，请访问 Amazon S3 开发人员指南。&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>Restic设计原理</title><link>https://sunqi.site/blog/restic-design/</link><pubDate>Wed, 23 Mar 2022 07:40:36 +0800</pubDate><guid>https://sunqi.site/blog/restic-design/</guid><description>
&lt;p&gt;Restic(&lt;a href="https://github.com/restic/restic"target="_blank" rel="noopener"&gt;https://github.com/restic/restic&lt;/a&gt;)一款开源文件备份工具，存储文件前将文件切割成对象进行存储，可以支持多种存储后端，包括本地目录、SFTP、HTTP Server和多种云平台的对象存储。Restic支持快照等备份常用功能，同时兼顾数据存储的安全性。&lt;/p&gt;
&lt;p&gt;本文主要讲解Restic设计原理，内容来源于Restic官方文档的Design篇(&lt;a href="https://restic.readthedocs.io/en/latest/100_references.html#design"target="_blank" rel="noopener"&gt;https://restic.readthedocs.io/en/latest/100_references.html#design&lt;/a&gt;)。&lt;/p&gt;
&lt;h2&gt;术语&lt;span class="hx:absolute hx:-mt-20" id="术语"&gt;&lt;/span&gt;
&lt;a href="#%e6%9c%af%e8%af%ad" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这一节主要介绍文档中使用的专业术语。&lt;/p&gt;
&lt;p&gt;存储库（Repository）：备份过程中生成的所有数据都以结构化形式发送并存储在存储库中，例如：存储在文件系统中，文件系统中可以创建多级目录。作为存储库，必须具备多种操作能力，例如列出内容。&lt;/p&gt;
&lt;p&gt;Blob: Blob是将数据与识别信息（如数据的 SHA-256 哈希值及其长度）组合在一起。&lt;/p&gt;
&lt;p&gt;包（Pack）: 一个Pack将多个Blobs进行组合，例如在一个文件中&lt;/p&gt;
&lt;p&gt;快照（Snapshot）: 一个快照是文件和目录在某个备份时间点的状态。状态的含义是内容以及元数据（metadata）信息，例如：文件或目录及其内容的名称、修改时间。&lt;/p&gt;
&lt;p&gt;存储ID（Storage ID）：存储ID是存储库中存放内容的SHA-256。只有得到此ID才能从存储库中加载文件。&lt;/p&gt;
&lt;h2&gt;存储库格式&lt;span class="hx:absolute hx:-mt-20" id="存储库格式"&gt;&lt;/span&gt;
&lt;a href="#%e5%ad%98%e5%82%a8%e5%ba%93%e6%a0%bc%e5%bc%8f" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;所有数据存放在restic存储库中。存储库可以存储不同类型的数据，可以根据ID获取。”Storage ID”是文件内容的SHA-256哈希值。存储库内所有文件仅仅写入一次，后续不再修改。这可以让多个客户端并发访问，甚至是写入到存储库中。仅仅只有删除操作将数据从存储库中移除。&lt;/p&gt;
&lt;p&gt;在撰写本文时，仅仅实现的存储库后端是基于文件系统的目录和文件。可以在同一系统或者内置的SFTP客户端（或者其他的后端方式）访问存储库。两种访问方法的目录布局相同。存储库类型会在后续详细描述。&lt;/p&gt;
&lt;p&gt;存储库由多个目录和一个名为 config 的文件组成。 对于存储库中的其他所有文件，文件的名称是存储 ID 的小写十六进制表示，即文件内容的 SHA-256 哈希。 通过简单地运行程序 sha256sum 并将其输出与文件名进行比较，轻松验证文件是否有意外修改，例如磁盘读取错误。 如果文件名的前缀在同一目录中是唯一的，则可以使用前缀代替完整的文件名。&lt;/p&gt;
&lt;p&gt;除了存储在 &lt;code&gt;keys&lt;/code&gt; 目录中的文件外，所有文件都在计数器模式 (CTR) 下使用 AES-256 进行加密。 加密数据的完整性由 Poly1305-AES 消息验证码（有时也称为“签名”）保护。&lt;/p&gt;
&lt;p&gt;在每个加密文件的前 16 个字节中，存储了初始化向量 (IV)。 其后是加密数据并由 16 字节 MAC 结尾。 格式为：&lt;code&gt;IV || 密文 || MAC&lt;/code&gt;。 完整的加密开销为 32 个字节。 对于每个文件，都会选择一个新的随机 IV。&lt;/p&gt;
&lt;p&gt;文件 &lt;code&gt;config&lt;/code&gt; 以这种方式加密，并包含如下 JSON 文档：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;5956a3f67a6230d4a92cefb29529f10196c7d92582ec305fd71ff6d331d6271b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;chunker_polynomial&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;25b468838dcb75&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;解密后，restic 首先检查版本字段是否包含它可以理解的版本号，否则会中止。 此时，版本预计为 1。字段 &lt;code&gt;id&lt;/code&gt; 包含一个由 32 个随机字节组成的唯一 ID，以十六进制编码。 无论是通过 SFTP 还是在本地访问它，这都会唯一标识存储库。 &lt;code&gt;chunker_polynomial&lt;/code&gt; 字段包含一个参数，用于将大文件分割成更小的块（见下文）。&lt;/p&gt;
&lt;p&gt;restic 存储库的基本布局如下所示：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;restic&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;├──&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="mi"&gt;2159&lt;/span&gt;&lt;span class="n"&gt;dd48f8a24f33c307b750592773f8b71ff8d11452132a7b2e2a6a01611be1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="n"&gt;ea976bc30771cebad8285cd99120ac8786f9ffd42141d452458089985043a5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="mi"&gt;59&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="mi"&gt;59&lt;/span&gt;&lt;span class="n"&gt;fe4bcde59bd6222eba87795e35a90d82cd2f138a27b6835032b7b58173a426&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="mi"&gt;73&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="mi"&gt;73&lt;/span&gt;&lt;span class="n"&gt;d04e6125cf3c28a299cc2f3cca3b78ceac396e4fcf9575e34536b26782413c&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;c38f5fb68307c6a3e3aa945d556e325dc38f5fb68307c6a3e3aa945d556e325d&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;ca171b1b7394d90d330b265d90f506f9984043b342525f019788f97e745c71fd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;b02de829beeb3c01a63e6b25cbd421a98fef144f03b9a02e46eff9e2ca3f0bd7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;locks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;snapshots&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="n"&gt;a5af1bdc6e616f8a29579458c49627e01b32210d09adb288d1ecda7c5711ec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;存储库可以使用restic init命令初始化，例如：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;restic&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;restic&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;包（Pack）格式&lt;span class="hx:absolute hx:-mt-20" id="包pack格式"&gt;&lt;/span&gt;
&lt;a href="#%e5%8c%85pack%e6%a0%bc%e5%bc%8f" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;除 Key 和 Pack 文件外，存储库中的所有文件仅包含原始数据，存储为&lt;code&gt;IV || 密文 || MAC&lt;/code&gt;。 包文件可能包含一个或多个 Blob 数据。&lt;/p&gt;
&lt;p&gt;一个包的结构如下：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;EncryptedBlob1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;EncryptedBlobN&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;EncryptedHeader&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;Header_Length&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Pack 文件的末尾是header，它描述了内容。header经过加密和身份验证。 &lt;code&gt;Header_Length&lt;/code&gt; 是加密头的长度，使用四字节整数little-endian编码。将header放置在文件末尾，目的是为了在备份过程中，读取blob后立即将他们写入连续的流中。这降低了代码的复杂度，并且避免了在包完成后，在已知内容和header长度后重复写入文件的问题。&lt;/p&gt;
&lt;p&gt;所有 blob（&lt;code&gt;EncryptedBlob1&lt;/code&gt;、``EncryptedBlobN` 等）都经过独立鉴权和加密。存储库可以在无需解密Blob情况下，进行重组。此外，还可以进行高效的索引，因为只需要读取header，找出Pack中包含哪些Blob。因为header是经过鉴权的，因此可以检查header的真实性，而无需读取完整的Pack。&lt;/p&gt;
&lt;p&gt;解密后，Pack 的头部由以下元素组成：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Type_Blob1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EncryptedBlob1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="n"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Plaintext_Blob1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Type_BlobN&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EncryptedBlobN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="n"&gt;Hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Plaintext_Blobn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这足以计算Pack中所有 Blob 的偏移量。 长度是 Blob 的长度，它是 little-endian 格式的四字节整数。 type 字段是一个单字节字段，根据下表标记 blob 的内容：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;tree&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;所有其他类型均无效，未来可能会添加更多类型。&lt;/p&gt;
&lt;p&gt;为了重建索引或解析没有索引的Pack，首先必须读取最后四个字节才能找到header的长度。 之后，可以读取和解析header，这会产生所有已包含的 blob 的明文哈希、类型、偏移量和长度。&lt;/p&gt;
&lt;h2&gt;索引（indexing）&lt;span class="hx:absolute hx:-mt-20" id="索引indexing"&gt;&lt;/span&gt;
&lt;a href="#%e7%b4%a2%e5%bc%95indexing" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;索引文件包含有关数据和树Blob树及其所在Pack的信息，并将此信息存储在存储库中。 当本地缓存索引不再可用时，可以下载索引文件并重建索引。 这些文件像数据和Blob树同样经过加密和鉴权，因此外部结构仍然是 IV || 密文 || Mac。 明文由如下 JSON 文档组成：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;{
&amp;#34;supersedes&amp;#34;: [
&amp;#34;ed54ae36197f4745ebc4b54d10e0f623eaaaedd03013eb7ae90df881b7781452&amp;#34;
],
&amp;#34;packs&amp;#34;: [
{
&amp;#34;id&amp;#34;: &amp;#34;73d04e6125cf3c28a299cc2f3cca3b78ceac396e4fcf9575e34536b26782413c&amp;#34;,
&amp;#34;blobs&amp;#34;: [
{
&amp;#34;id&amp;#34;: &amp;#34;3ec79977ef0cf5de7b08cd12b874cd0f62bbaf7f07f3497a5b1bbcc8cb39b1ce&amp;#34;,
&amp;#34;type&amp;#34;: &amp;#34;data&amp;#34;,
&amp;#34;offset&amp;#34;: 0,
&amp;#34;length&amp;#34;: 25
},{
&amp;#34;id&amp;#34;: &amp;#34;9ccb846e60d90d4eb915848add7aa7ea1e4bbabfc60e573db9f7bfb2789afbae&amp;#34;,
&amp;#34;type&amp;#34;: &amp;#34;tree&amp;#34;,
&amp;#34;offset&amp;#34;: 38,
&amp;#34;length&amp;#34;: 100
},
{
&amp;#34;id&amp;#34;: &amp;#34;d3dc577b4ffd38cc4b32122cabf8655a0223ed22edfd93b353dc0c3f2b0fdf66&amp;#34;,
&amp;#34;type&amp;#34;: &amp;#34;data&amp;#34;,
&amp;#34;offset&amp;#34;: 150,
&amp;#34;length&amp;#34;: 123
}
]
}, [...]
]
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;此 JSON 文档列出了Packs和其中包含的 blob。 在此示例中，Pack &lt;code&gt;73d04e61&lt;/code&gt; 包含两个数据 Blob 和一个 Blob树，明文哈希随后列出。&lt;/p&gt;
&lt;p&gt;字段 &lt;code&gt;supersedes&lt;/code&gt; 列出了已被当前索引文件替换的索引文件的存储 ID。 这发生在重新打包索引文件时，例如删除旧快照并重新组合包时。&lt;/p&gt;
&lt;p&gt;可能有任意数量的索引文件，其中包含关于不相交的Pack集合的信息。 选择在单一文件中描述的Packs数量，让文件大小保持在8MiB一下。&lt;/p&gt;
&lt;h2&gt;密钥（Keys），加密和MAC&lt;span class="hx:absolute hx:-mt-20" id="密钥keys加密和mac"&gt;&lt;/span&gt;
&lt;a href="#%e5%af%86%e9%92%a5keys%e5%8a%a0%e5%af%86%e5%92%8cmac" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;所有存放在restic存储库中的数据使用计数器模式AES-256加密，鉴权使用Poly1305-AES。为了加密新数据，从密码安全的伪随机数生成器中读取前 16 个字节作为随机随机数。这既用作计数器模式的 IV，也用作 Poly1305 的随机数。该操作需要三个密钥：用于加密的 AES-256 的 32 字节、用于 Poly1305 的 16 字节的 AES 密钥和 16 字节的密钥。有关详细信息，请参阅 Dan Bernstein 的原始论文 &lt;a href="http://cr.yp.to/mac/poly1305-20050329.pdf"target="_blank" rel="noopener"&gt;The Poly1305-AES 消息身份验证代码&lt;/a&gt;。然后使用 AES-256 对数据进行加密，然后在密文上计算消息验证码 (MAC)，然后将所有内容存储为 IV || 密文 || MAC。&lt;/p&gt;
&lt;p&gt;目录 &lt;code&gt;keys&lt;/code&gt; 包含密钥文件。这些是简单的 JSON 格式文档，包含从用户密码派生存储库的主加密和消息身份验证密钥所需的所有数据。例如，可以使用 Python 模块 &lt;code&gt;json&lt;/code&gt;（缩短以提高可读性）来优化打印存储库中的 JSON 文档：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ python -mjson.tool /tmp/restic-repo/keys/b02de82*
{
&amp;#34;hostname&amp;#34;: &amp;#34;kasimir&amp;#34;,
&amp;#34;username&amp;#34;: &amp;#34;fd0&amp;#34;
&amp;#34;kdf&amp;#34;: &amp;#34;scrypt&amp;#34;,
&amp;#34;N&amp;#34;: 65536,
&amp;#34;r&amp;#34;: 8,
&amp;#34;p&amp;#34;: 1,
&amp;#34;created&amp;#34;: &amp;#34;2015-01-02T18:10:13.48307196&amp;#43;01:00&amp;#34;,
&amp;#34;data&amp;#34;: &amp;#34;tGwYeKoM0C4j4/9DFrVEmMGAldvEn/&amp;#43;iKC3te/QE/6ox/V4qz58FUOgMa0Bb1cIJ6asrypCx/Ti/pRXCPHLDkIJbNYd2ybC&amp;#43;fLhFIJVLCvkMS&amp;#43;trdywsUkglUbTbi&amp;#43;7&amp;#43;Ldsul5jpAj9vTZ25ajDc&amp;#43;4FKtWEcCWL5ICAOoTAxnPgT&amp;#43;Lh8ByGQBH6KbdWabqamLzTRWxePFoYuxa7yXgmj9A==&amp;#34;,
&amp;#34;salt&amp;#34;: &amp;#34;uW4fEI1&amp;#43;IOzj7ED9mVor&amp;#43;yTSJFd68DGlGOeLgJELYsTU5ikhG/83/&amp;#43;jGd4KKAaQdSrsfzrdOhAMftTSih5Ux6w==&amp;#34;,
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;当打开restic存储库时，会提示用户输入存储库密码。然后将其与 &lt;code&gt;scrypt&lt;/code&gt;、密钥派生函数 (KDF) 和提供的参数（&lt;code&gt;N&lt;/code&gt;、&lt;code&gt;r&lt;/code&gt;、&lt;code&gt;p&lt;/code&gt; 和&lt;code&gt;salt&lt;/code&gt;）一起派生 64 个密钥字节。前 32 个字节用于加密密钥（用于 AES-256），最后 32 个字节用作消息验证密钥（用于 Poly1305-AES）。这最后 32 个字节被分成一个 16 字节的 AES 密钥“k”，然后是 16 个字节的密钥“r”。然后将密钥&lt;code&gt; r&lt;/code&gt; 屏蔽，与 Poly1305 一起使用（有关详细信息，请参阅论文）。&lt;/p&gt;
&lt;p&gt;这些消息身份验证密钥（&lt;code&gt;k&lt;/code&gt; 和 &lt;code&gt;r&lt;/code&gt;）用于计算MAC，使用 JSON 中 &lt;code&gt;data&lt;/code&gt;字段包含的字节（在删除 Base64 编码并且不包括最后 32 个字节之后）。如果密码不正确或密钥文件被篡改，则计算出的 MAC 将与数据的最后 16 个字节不匹配，restic 会报错退出。否则，将使用从 scrypt 派生的加密密钥解密数据。这将生成一个 JSON ，其中包含此存储库的主加密和消息鉴权密钥（以 Base64 编码）。 &lt;code&gt;restic cat masterkey&lt;/code&gt; 命令可用于解密和格式化打印主密钥：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ restic -r /tmp/restic-repo cat masterkey
{
&amp;#34;mac&amp;#34;: {
&amp;#34;k&amp;#34;: &amp;#34;evFWd9wWlndL9jc501268g==&amp;#34;,
&amp;#34;r&amp;#34;: &amp;#34;E9eEDnSJZgqwTOkDtOp&amp;#43;Dw==&amp;#34;
},
&amp;#34;encrypt&amp;#34;: &amp;#34;UQCqa0lKZ94PygPxMRqkePTZnHRYh1k1pX2k2lM2v3Q=&amp;#34;,
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;存储库中的所有数据都使用这些主密钥进行加密和验证。 对于加密，使用计数器模式下的 AES-256 算法。 对于消息认证，如上所述使用 Poly1305-AES。&lt;/p&gt;
&lt;p&gt;存储库可以有多个不同的密码，每个密码都有一个密钥文件。 这样，无需重新加密所有数据即可更改密码。&lt;/p&gt;
&lt;h2&gt;快照（Snapshots）&lt;span class="hx:absolute hx:-mt-20" id="快照snapshots"&gt;&lt;/span&gt;
&lt;a href="#%e5%bf%ab%e7%85%a7snapshots" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;快照表示在特定时间点包含所有文件和子目录的目录。 对于所做的每个备份，都会创建一个新快照。 快照使用JSON文件描述，存储在存储库中“snapshots”目录下的加密文件。 文件名是存储 ID。 此字符串是唯一的，并在 restic 中用于唯一标识快照。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;restic cat snapshot&lt;/code&gt; 命令可用于解密和格式化打印快照文件的内容：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ restic -r /tmp/restic-repo cat snapshot 22a5af1b
enter passwordfor repository:
{
&amp;#34;time&amp;#34;: &amp;#34;2015-01-02T18:10:50.895208559&amp;#43;01:00&amp;#34;,
&amp;#34;tree&amp;#34;: &amp;#34;2da81727b6585232894cfbb8f8bdab8d1eccd3d8f7c92bc934d62e62e618ffdf&amp;#34;,
&amp;#34;dir&amp;#34;: &amp;#34;/tmp/testdata&amp;#34;,
&amp;#34;hostname&amp;#34;: &amp;#34;kasimir&amp;#34;,
&amp;#34;username&amp;#34;: &amp;#34;fd0&amp;#34;,
&amp;#34;uid&amp;#34;: 1000,
&amp;#34;gid&amp;#34;: 100
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;在这里可以看出，这个快照代表了目录&lt;code&gt;/tmp/testdata&lt;/code&gt;的内容。 最重要的字段是&lt;code&gt;tree&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;restic 存储库中的所有内容都根据其 SHA-256 哈希值进行引用。 在保存之前，每个文件都被分割成可变大小的数据块。 所有 Blob 的 SHA-256 哈希值都保存在有序列表中，代表文件的内容。&lt;/p&gt;
&lt;p&gt;为了将这些明文哈希与 Pack 文件中的实际位置相关联，使用了索引。 如果索引不可用，则可以读取所有数据 Blob 的header。&lt;/p&gt;
&lt;h2&gt;树（Tree）和数据（Data）&lt;span class="hx:absolute hx:-mt-20" id="树tree和数据data"&gt;&lt;/span&gt;
&lt;a href="#%e6%a0%91tree%e5%92%8c%e6%95%b0%e6%8d%aedata" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;快照通过JSON中SHA-256哈希引用树，代表其内容树和数据保存在目录“data”的子目录中的Pack文件中。&lt;/p&gt;
&lt;p&gt;命令 &lt;code&gt;restic cat tree&lt;/code&gt; 可用于检查上面引用的树：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ restic -r /tmp/restic-repo cat tree b8138ab08a4722596ac89c917827358da4672eac68e3c03a8115b88dbf4bfb59
enter passwordfor repository:
{
&amp;#34;nodes&amp;#34;: [
{
&amp;#34;name&amp;#34;: &amp;#34;testdata&amp;#34;,
&amp;#34;type&amp;#34;: &amp;#34;dir&amp;#34;,
&amp;#34;mode&amp;#34;: 493,
&amp;#34;mtime&amp;#34;: &amp;#34;2014-12-22T14:47:59.912418701&amp;#43;01:00&amp;#34;,
&amp;#34;atime&amp;#34;: &amp;#34;2014-12-06T17:49:21.748468803&amp;#43;01:00&amp;#34;,
&amp;#34;ctime&amp;#34;: &amp;#34;2014-12-22T14:47:59.912418701&amp;#43;01:00&amp;#34;,
&amp;#34;uid&amp;#34;: 1000,
&amp;#34;gid&amp;#34;: 100,
&amp;#34;user&amp;#34;: &amp;#34;fd0&amp;#34;,
&amp;#34;inode&amp;#34;: 409704562,
&amp;#34;content&amp;#34;: null,
&amp;#34;subtree&amp;#34;: &amp;#34;b26e315b0988ddcd1cee64c351d13a100fedbc9fdbb144a67d1b765ab280b4dc&amp;#34;
}
]
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;树包包含一组节点（在“node”字段中），其中包含名称和时间戳等元数据。 当节点指向目录时，字段“subtree”包含另一个树对象的ID。&lt;/p&gt;
&lt;p&gt;当使用命令“restic cat tree”时，需要存储哈希来显示树。 上面引用的树可以展开输出为：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ restic -r /tmp/restic-repo cat tree 8b238c8811cc362693e91a857460c78d3acf7d9edb2f111048691976803cf16e
enter passwordfor repository:
{
&amp;#34;nodes&amp;#34;: [
{
&amp;#34;name&amp;#34;: &amp;#34;testfile&amp;#34;,
&amp;#34;type&amp;#34;: &amp;#34;file&amp;#34;,
&amp;#34;mode&amp;#34;: 420,
&amp;#34;mtime&amp;#34;: &amp;#34;2014-12-06T17:50:23.34513538&amp;#43;01:00&amp;#34;,
&amp;#34;atime&amp;#34;: &amp;#34;2014-12-06T17:50:23.338468713&amp;#43;01:00&amp;#34;,
&amp;#34;ctime&amp;#34;: &amp;#34;2014-12-06T17:50:23.34513538&amp;#43;01:00&amp;#34;,
&amp;#34;uid&amp;#34;: 1000,
&amp;#34;gid&amp;#34;: 100,
&amp;#34;user&amp;#34;: &amp;#34;fd0&amp;#34;,
&amp;#34;inode&amp;#34;: 416863351,
&amp;#34;size&amp;#34;: 1234,
&amp;#34;links&amp;#34;: 1,
&amp;#34;content&amp;#34;: [
&amp;#34;50f77b3b4291e8411a027b9f9b9e64658181cc676ce6ba9958b95f268cb1109d&amp;#34;
]
},
[...]
]
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;该树包含一个文件。 这一次，&lt;code&gt;subtree&lt;/code&gt; 字段不存在，&lt;code&gt;content&lt;/code&gt; 字段包含一个 SHA-256 哈希的列表。&lt;/p&gt;
&lt;p&gt;命令 &lt;code&gt;restic cat data&lt;/code&gt; 可用于提取和解密指定明文 ID 的数据，例如 对于上述数据：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ restic -r /tmp/restic-repo cat blob 50f77b3b4291e8411a027b9f9b9e64658181cc676ce6ba9958b95f268cb1109d | sha256sum
enter passwordfor repository:
50f77b3b4291e8411a027b9f9b9e64658181cc676ce6ba9958b95f268cb1109d -&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;从 sha256sum 的输出可以看出，哈希与上面树中包含的映射的明文哈希匹配，因此返回了正确的数据。&lt;/p&gt;
&lt;h2&gt;锁（Locks）&lt;span class="hx:absolute hx:-mt-20" id="锁locks"&gt;&lt;/span&gt;
&lt;a href="#%e9%94%81locks" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;restic 存储库设计方式是允许并发访问，甚至并行写入。 但是，有些功能工作效率要求更高，甚至需要对存储库进行独占访问。 为了实现这些功能，需要restic进程在执行任何操作之前，在存储库上创建一个锁。&lt;/p&gt;
&lt;p&gt;锁有两种类型：排他锁和非排他锁。 一个进程最多可以在存储库上拥有一个独占锁，并且在此期间不得有任何其他锁（独占和非独占）。 对于排它锁，可能并行存在多个。&lt;/p&gt;
&lt;p&gt;锁是子目录&lt;code&gt;locks&lt;/code&gt;中的文件，其文件名是内容的存储ID。 它的加密和鉴权方式与存储库中的其他文件相同，并包含以下 JSON 结构：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;{
&amp;#34;time&amp;#34;: &amp;#34;2015-06-27T12:18:51.759239612&amp;#43;02:00&amp;#34;,
&amp;#34;exclusive&amp;#34;: false,
&amp;#34;hostname&amp;#34;: &amp;#34;kasimir&amp;#34;,
&amp;#34;username&amp;#34;: &amp;#34;fd0&amp;#34;,
&amp;#34;pid&amp;#34;: 13607,
&amp;#34;uid&amp;#34;: 1000,
&amp;#34;gid&amp;#34;: 100
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;字段 &lt;code&gt;exclusive&lt;/code&gt; 定义了锁的类型。 当要创建新锁时，restic 会检查存储库中的所有锁。 找到锁时，会测试锁是否超时，默认时间为大于30分钟以上。 如果锁是在同一台机器上创建的，即使对于没有达到超时时间的锁，它也会通过向它发送信号来测试进程是否还活着。 如果失败，restic 假定进程已死，并认为锁是无用的。&lt;/p&gt;
&lt;p&gt;当要创建一个新锁并且没有检测到与其他冲突锁时，restic 创建一个新锁，等待并检查存储库中是否出现其他锁。 根据其他锁的类型和要创建的锁，restic 要么继续，要么失败。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;备份和重复数据删除&lt;/strong&gt;&lt;span class="hx:absolute hx:-mt-20" id="备份和重复数据删除"&gt;&lt;/span&gt;
&lt;a href="#%e5%a4%87%e4%bb%bd%e5%92%8c%e9%87%8d%e5%a4%8d%e6%95%b0%e6%8d%ae%e5%88%a0%e9%99%a4" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;为了创建备份，restic 会扫描源目录中的所有文件、子目录和其他条目。 来自每个文件的数据被拆分为可变长度的 Blob，这些 Blob 以 64 字节的滑动窗口定义的偏移量进行切割。 该实现使用 Rabin 指纹来实现内容定义分块 (Content Defined Chunking, CDC)。 初始化存储库时，随机选择一个不可约多项式(不可约多项式，顾名思义即不能写成两个次数较低的多项式之乘积的多项式)并保存在文件 &lt;code&gt;config&lt;/code&gt; 中，增加安全性，让水印攻击更加困难。&lt;/p&gt;
&lt;p&gt;小于 512 KiB 的文件不会被拆分，Blob 的大小为 512 KiB 到 8 MiB。 实现的目标是Blob平均 1 MiB 大小。&lt;/p&gt;
&lt;p&gt;对于修改过的文件，只有修改过的 Blob 必须保存在后续备份中。 即使在文件中的任意位置插入或删除字节，仍然可以继续工作。&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;威胁模型&lt;/strong&gt;&lt;/h1&gt;&lt;p&gt;restic 的设计目标是能够将备份安全地存储在不完全受信任的位置，例如共享系统，其他人可以在其中访问文件（在系统管理员的情况下）甚至修改或删除它们。&lt;/p&gt;
&lt;p&gt;一般假设：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;创建备份的主机系统是受信任的。这是最基本的要求，对于创建可靠的备份至关重要。&lt;/li&gt;
&lt;li&gt;用户使用的是正版restic&lt;/li&gt;
&lt;li&gt;用户不与攻击者共享存储库密码。&lt;/li&gt;
&lt;li&gt;restic 备份程序并非是设计防止攻击者删除存储位置的文件。对此无能为力。如果需要保证这一点，一定要选择没有第三方可以访问的安全位置&lt;/li&gt;
&lt;li&gt;如果密钥泄露，整个存储库将重新加密。使用当前的密钥管理设计，如果不重新加密整个存储库，就不可能安全地撤销泄露的密钥。&lt;/li&gt;
&lt;li&gt;针对 restic 使用的加密原语（即 AES-256-CTR-Poly1305-AES 和 SHA-256），尚无法实现攻击。如果能够实现，会使 restic 提供的机密性或完整性保护变得无用。&lt;/li&gt;
&lt;li&gt;算力方面进步还无法实现对 restic 加密保护的暴力攻击&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;restic 备份程序可以保证以下内容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果没有存储库的密码，就无法访问存储文件和元数据的未加密内容。密钥文件中除了用于信息描述目的的元数据之外的所有内容都经过加密和鉴权的。缓存中的内容也进行了加密，防止metadata泄露&lt;/li&gt;
&lt;li&gt;对于存储在存储库中的所有数据的修复（坏 RAM、损坏的硬盘）可以被检测到&lt;/li&gt;
&lt;li&gt;被篡改的数据将无法解密&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;考虑到上述假设和保证，以下是各种的攻击手段：&lt;/p&gt;
&lt;p&gt;对备份存储位置具有读取权限的对手可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;尝试对存储库副本进行暴力密码猜测攻击（推荐使用 30 个以上字符的长密码）。&lt;/li&gt;
&lt;li&gt;通过文件访问模式推断哪些包可能包含树。&lt;/li&gt;
&lt;li&gt;通过使用存储库对象的创建时间戳推断备份的大小。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;具有网络访问权限的对手可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;尝试 DoS 存储备份存储库的服务器或客户端和服务器之间的网络连接。&lt;/li&gt;
&lt;li&gt;确定您创建备份的位置（即请求的来源位置）。&lt;/li&gt;
&lt;li&gt;确定您存储备份的位置（即，哪个提供程序/目标系统）。&lt;/li&gt;
&lt;li&gt;通过使用存储库对象的创建时间戳推断备份的大小。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下是与违反上述某些假设后产生影响的示例。&lt;/p&gt;
&lt;p&gt;破坏主机系统进行备份（通过恶意软件、物理访问等）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使整个备份过程变得不可信（例如，拦截密码、复制文件、操纵数据）。&lt;/li&gt;
&lt;li&gt;创建覆盖所有修改文件的快照（包含垃圾数据），并等到受信任的主机遗失所有正确的快照。&lt;/li&gt;
&lt;li&gt;为每个时间戳稍有不同的快照创建一个垃圾快照，等到忘记运行后，一次性删除所有正确快照&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在存储位置对您的文件具有写访问权限可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;删除或操作您的备份，从而削弱您从受损存储位置恢复文件的能力。&lt;/li&gt;
&lt;li&gt;确定哪些文件属于哪个快照（例如，基于存储文件的时间戳）。 当仅删除这些文件时，特定快照会消失，并且依赖于快照中的数据将无法完全恢复。Restic 并非设计来检测这种攻击。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;破坏具有对备份存储库附加访问权限的主机系统可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主机收到攻击后，使新的备份不可信（由于对新备份具有完全控制权）。 攻击者无法删除或操作旧备份。 因此，恢复在主机入侵之前*创建的旧快照仍然是可能的。 &lt;em&gt;注意：&lt;strong&gt;不&lt;/strong&gt;建议对仅追加快照运行自动忘记，当这些主机可能受到威胁时，因为使用虚假快照的攻击者可能会导致忘记删除正确的快照。&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;拥有未重新加密的存储库的泄露密钥可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;解密现有和未来的备份数据。 如果多台主机备份到同一个存储库，攻击者将可以访问每台主机的备份数据。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>[Digitalcloud.Training]AWS CERTIFIED SOLUTIONS ARCHITECT ASSOCIATE</title><link>https://sunqi.site/blog/2020-01-14-digitalcloud-training-aws-certified-solutions-architect-associate/</link><pubDate>Mon, 14 Mar 2022 16:49:16 +0000</pubDate><guid>https://sunqi.site/blog/2020-01-14-digitalcloud-training-aws-certified-solutions-architect-associate/</guid><description>
&lt;p&gt;该模拟题出自DigitalCloud Training的模拟题，一共20道题，相对来说答案比较准确，第一次答正确率只有60%，看起来还有不太扎实的知识点，并且英文多了不太爱仔细阅读也是准确率低的原因。&lt;/p&gt;
&lt;p&gt;另外，今天在AWS培训官网上看到ACA考试在3月份会推出全新的试题，所以还需要抓紧时间考过。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;答题情况统计&lt;span class="hx:absolute hx:-mt-20" id="答题情况统计"&gt;&lt;/span&gt;
&lt;a href="#%e7%ad%94%e9%a2%98%e6%83%85%e5%86%b5%e7%bb%9f%e8%ae%a1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Categories
AWS Analytics 100%
AWS Application Integration 100%
AWS Compute 33.33%
AWS Database 66.67%
AWS Management &amp;amp; Governance 100%
AWS Networking &amp;amp; Content Delivery 33.33%
AWS Security, Identity, &amp;amp; Compliance 50%
AWS Storage 33.33%&lt;/p&gt;
&lt;h2&gt;1. Question&lt;span class="hx:absolute hx:-mt-20" id="1-question"&gt;&lt;/span&gt;
&lt;a href="#1-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A Solutions Architect has been asked to suggest a solution for analyzing data in S3 using standard SQL queries. The solution should use a serverless technology.
Which AWS service can the Architect use?&lt;/p&gt;
&lt;p&gt;A. Amazon RedShift
B. AWS Data Pipeline
C. AWS Glue
D. Amazon Athena&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
Amazon Athena is an interactive query service that makes it easy to analyze data in Amazon S3 using standard SQL. Athena is serverless, so there is no infrastructure to manage, and you pay only for the queries that you run
Amazon RedShift is used for analytics but cannot analyze data in S3
AWS Glue is a fully managed extract, transform, and load (ETL) service that makes it easy for customers to prepare and load their data for analytics. It is not used for analyzing data in S3
AWS Data Pipeline is a web service that helps you reliably process and move data between different AWS compute and storage services, as well as on-premises data sources, at specified intervals&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://aws.amazon.com/athena/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/athena/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;2. Question&lt;span class="hx:absolute hx:-mt-20" id="2-question"&gt;&lt;/span&gt;
&lt;a href="#2-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A systems integration company that helps customers migrate into AWS repeatedly build large, standardized architectures using several AWS services. The Solutions Architects have documented the architectural blueprints for these solutions and are looking for a method of automating the provisioning of the resources.
Which AWS service would satisfy this requirement?&lt;/p&gt;
&lt;p&gt;A. AWS OpsWorks
B. AWS CloudFormation
C. AWS CodeDeploy
D. Elastic Beanstalk&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
CloudFormation allows you to use a simple text file to model and provision, in an automated and secure manner, all the resources needed for your applications across all regions and accounts
Elastic Beanstalk is a PaaS service that helps you to build and manage web applications
AWS OpsWorks is a configuration management service that helps you build and operate highly dynamic applications, and propagate changes instantly
AWS CodeDeploy is a deployment service that automates application deployments to Amazon EC2 instances, on-premises instances, or serverless Lambda functions&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/management-tools/aws-cloudformation/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/management-tools/aws-cloudformation/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;3. Question&lt;span class="hx:absolute hx:-mt-20" id="3-question"&gt;&lt;/span&gt;
&lt;a href="#3-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A data-processing application runs on an i3.large EC2 instance with a single 100 GB EBS gp2 volume. The application stores temporary data in a small database (less than 30 GB) located on the EBS root volume. The application is struggling to process the data fast enough, and a Solutions Architect has determined that the I/O speed of the temporary database is the bottleneck.
What is the MOST cost-efficient way to improve the database response times?&lt;/p&gt;
&lt;p&gt;A. Enable EBS optimization on the instance and keep the temporary files on the existing volume
B. Put the temporary database on a new 50-GB EBS gp2 volume
C. Move the temporary database onto instance storage
D. Put the temporary database on a new 50-GB EBS io1 volume with a 3000 IOPS allocation&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;p&gt;Incorrect
Explanation:
EC2 Instance Stores are high-speed ephemeral storage that is physically attached to the EC2 instance. The i3.large instance type comes with a single 475GB NVMe SSD instance store so it would be a good way to lower cost and improve performance by using the attached instance store. As the files are temporary, it can be assumed that ephemeral storage (which means the data is lost when the instance is stopped) is sufficient.
Enabling EBS optimization will not lower cost. Also, EBS Optimization is a network traffic optimization, it does not change the I/O speed of the volume.
Moving the DB to a new 50-GB EBS gp2 volume will not result in a performance improvement as you get IOPS allocated per GB so a smaller volume will have lower performance.
Moving the DB to a new 50-GB EBS io1 volume with a 3000 IOPS allocation will improve performance but is more expensive so will not be the most cost-efficient solution.&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/InstanceStorage.html&lt;/a&gt;
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/compute/amazon-ebs/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/compute/amazon-ebs/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;4. Question&lt;span class="hx:absolute hx:-mt-20" id="4-question"&gt;&lt;/span&gt;
&lt;a href="#4-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;An application you are designing receives and processes files. The files are typically around 4GB in size and the application extracts metadata from the files which typically takes a few seconds for each file. The pattern of updates is highly dynamic with times of little activity and then multiple uploads within a short period of time.
What architecture will address this workload the most cost efficiently?&lt;/p&gt;
&lt;p&gt;A. Upload files into an S3 bucket, and use the Amazon S3 event notification to invoke a Lambda function to extract the metadata
B. Place the files in an SQS queue, and use a fleet of EC2 instances to extract the metadata
C. Store the file in an EBS volume which can then be accessed by another EC2 instance for processing
D. Use a Kinesis data stream to store the file, and use Lambda for processing&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
Storing the file in an S3 bucket is the most cost-efficient solution, and using S3 event notifications to invoke a Lambda function works well for this unpredictable workload
Kinesis data streams runs on EC2 instances and you must therefore provision some capacity even when the application is not receiving files. This is not as cost-efficient as storing them in an S3 bucket prior to using Lambda for the processing
SQS queues have a maximum message size of 256KB. You can use the extended client library for Java to use pointers to a payload on S3 but the maximum payload size is 2GB
Storing the file in an EBS volume and using EC2 instances for processing is not cost efficient&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/storage/amazon-s3/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/storage/amazon-s3/&lt;/a&gt;
&lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;5. Question&lt;span class="hx:absolute hx:-mt-20" id="5-question"&gt;&lt;/span&gt;
&lt;a href="#5-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A Solutions Architect needs to deploy an HTTP/HTTPS service on Amazon EC2 instances that will be placed behind an Elastic Load Balancer. The ELB must support WebSockets.
How can the Architect meet these requirements?&lt;/p&gt;
&lt;p&gt;A. Launch an Application Load Balancer (ALB)
B. Launch a Network Load Balancer (NLB)
C. Launch a Classic Load Balancer (CLB)
D. Launch a Layer-4 Load Balancer&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
Both the ALB and NLB support WebSockets. However, only the ALB supports HTTP/HTTPS listeners. The NLB only supports TCP, TLS, UDP, TCP_UDP.
The CLB does not support WebSockets.
A “Layer-4 Load Balancer” is not suitable, we need a layer 7 load balancer for HTTP/HTTPS.&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/compute/elastic-load-balancing/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/compute/elastic-load-balancing/&lt;/a&gt;
&lt;a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html&lt;/a&gt;
&lt;a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-listeners.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-listeners.html&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;6. Question&lt;span class="hx:absolute hx:-mt-20" id="6-question"&gt;&lt;/span&gt;
&lt;a href="#6-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You are building an application that will collect information about user behavior. The application will rapidly ingest large amounts of dynamic data and requires very low latency. The database must be scalable without incurring downtime. Which database would you recommend for this scenario?&lt;/p&gt;
&lt;p&gt;A. RDS with Microsoft SQL
B. RedShift
C. DynamoDB
D. RDS with MySQL&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
Amazon Dynamo DB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability
Push button scaling means that you can scale the DB at any time without incurring downtime
DynamoDB provides low read and write latency
RDS uses EC2 instances so you have to change your instance type/size in order to scale compute vertically
RedShift uses EC2 instances as well, so you need to choose your instance type/size for scaling compute vertically, but you can also scale horizontally by adding more nodes to the cluster
Rapid ingestion of dynamic data is not an ideal use case for RDS or RedShift&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/database/amazon-dynamodb/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/database/amazon-dynamodb/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;7. Question&lt;span class="hx:absolute hx:-mt-20" id="7-question"&gt;&lt;/span&gt;
&lt;a href="#7-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You are running an Auto Scaling Group (ASG) with an Elastic Load Balancer (ELB) and a fleet of EC2 instances. Health checks are configured on the ASG to use EC2 status checks. The ELB has determined that an EC2 instance is unhealthy and has removed it from service. However, you noticed that the instance is still running and has not been terminated by the ASG.
What would be an explanation for this behavior?&lt;/p&gt;
&lt;p&gt;A. The health check grace period has not yet expired
B. The ELB health check type has not been selected for the ASG and so it is unaware that the instance has been determined to be unhealthy by the ELB and has been removed from service
C. Connection draining is enabled and the ASG is waiting for in-flight requests to complete
D. The ASG is waiting for the cooldown timer to expire before terminating the instance&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;p&gt;Incorrect
Explanation:
If using an ELB it is best to enable ELB health checks as otherwise EC2 status checks may show an instance as being healthy that the ELB has determined is unhealthy. In this case the instance will be removed from service by the ELB but will not be terminated by Auto Scaling
Connection draining is not the correct answer as the ELB has taken the instance out of service so there are no active connections
The health check grace period allows a period of time for a new instance to warm up before performing a health check
More information on ASG health checks:
By default uses EC2 status checks
Can also use ELB health checks and custom health checks
ELB health checks are in addition to the EC2 status checks
If any health check returns an unhealthy status the instance will be terminated
With ELB an instance is marked as unhealthy if ELB reports it as OutOfService
A healthy instance enters the InService state
If an instance is marked as unhealthy it will be scheduled for replacement
If connection draining is enabled, Auto Scaling waits for in-flight requests to complete or timeout before terminating instances
The health check grace period allows a period of time for a new instance to warm up before performing a health check (300 seconds by default)&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/compute/aws-auto-scaling/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/compute/aws-auto-scaling/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;8. Question&lt;span class="hx:absolute hx:-mt-20" id="8-question"&gt;&lt;/span&gt;
&lt;a href="#8-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A solutions Architect is designing a new workload where an AWS Lambda function will access an Amazon DynamoDB table.
What is the MOST secure means of granting the Lambda function access to the DynamoDB table?&lt;/p&gt;
&lt;p&gt;A. Create an identity and access management (IAM) role allowing access from AWS Lambda and assign the role to the DynamoDB table
B. Create an identity and access management (IAM) role with the necessary permissions to access the DynamoDB table, and assign the role to the Lambda function
C. Create a DynamoDB username and password and give them to the Developer to use in the Lambda function
D. Create an identity and access management (IAM) user and create access and secret keys for the user. Give the user the necessary permissions to access the DynamoDB table. Have the Developer use these keys to access the resources&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
The most secure method is to use an IAM role so you don’t need to embed any credentials in code and can tightly control the services that your Lambda function can access. You need to assign the role to the Lambda function, NOT to the DynamoDB table
You should not provide a username and password to the Developer to use with the function. This is insecure – always avoid using credentials in code!
You should not use an access key and secret ID to access DynamoDB. Again, this means embedding credentials in code which should be avoided.&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://aws.amazon.com/blogs/security/how-to-create-an-aws-iam-policy-to-grant-aws-lambda-access-to-an-amazon-dynamodb-table/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/blogs/security/how-to-create-an-aws-iam-policy-to-grant-aws-lambda-access-to-an-amazon-dynamodb-table/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;9. Question&lt;span class="hx:absolute hx:-mt-20" id="9-question"&gt;&lt;/span&gt;
&lt;a href="#9-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Your company has offices in several locations around the world. Each office utilizes resources deployed in the geographically closest AWS region. You would like to implement connectivity between all of the VPCs so that you can provide full access to each other’s resources. As you are security conscious you would like to ensure the traffic is encrypted and does not traverse the public Internet. The topology should be many-to-many to enable all VPCs to access the resources in all other VPCs.
How can you successfully implement this connectivity using only AWS services? (choose 2)&lt;/p&gt;
&lt;p&gt;A. Use inter-region VPC peering
B. Use software VPN appliances running on EC2 instances
C. Use VPC endpoints between VPCs
D. Implement a fully meshed architecture
E. Implement a hub and spoke architecture&lt;/p&gt;
&lt;p&gt;Answer: AD&lt;/p&gt;
&lt;p&gt;Incorrect
Explanation:
Peering connections can be created with VPCs in different regions (available in most regions now)
Data sent between VPCs in different regions is encrypted (traffic charges apply)
You cannot do transitive peering so a hub and spoke architecture would not allow all VPCs to communicate directly with each other. For this you need to establish a mesh topology
A VPC endpoint enables you to privately connect your VPC to supported AWS services and VPC endpoint services, it does not provide full VPC to VPC connectivity
Using software VPN appliances to connect VPCs together is not the best solution as it is cumbersome, expensive and would introduce bandwidth and latency constraints (amongst other problems)&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/networking-and-content-delivery/amazon-vpc/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/networking-and-content-delivery/amazon-vpc/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;10. Question&lt;span class="hx:absolute hx:-mt-20" id="10-question"&gt;&lt;/span&gt;
&lt;a href="#10-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A research company is developing a data lake solution in Amazon S3 to analyze huge datasets. The solution makes infrequent SQL queries only. In addition, the company wants to minimize infrastructure costs.
Which AWS service should be used to meet these requirements?&lt;/p&gt;
&lt;p&gt;A. Amazon Athena
B. Amazon Redshift Spectrum
C. Amazon Aurora
D. Amazon RDS for MySQL&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
Amazon Athena is an interactive query service that makes it easy to analyze data in Amazon S3 using standard SQL. Athena is serverless, so there is no infrastructure to manage, and you pay only for the queries that you run – this satisfies the requirement to minimize infrastructure costs for infrequent queries.
Amazon RedShift Spectrum is a feature of Amazon Redshift that enables you to run queries against exabytes of unstructured data in Amazon S3, with no loading or ETL required. However, RedShift nodes run on EC2 instances, so for infrequent queries this will not minimize infrastructure costs.
Amazon RDS and Aurora are not suitable solutions for analyzing datasets on S3 – these are both relational databases typically used for transactional (not analytical) workloads.&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/analytics/amazon-athena/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/analytics/amazon-athena/&lt;/a&gt;
&lt;a href="https://docs.aws.amazon.com/athena/latest/ug/what-is.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/athena/latest/ug/what-is.html&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;11. Question&lt;span class="hx:absolute hx:-mt-20" id="11-question"&gt;&lt;/span&gt;
&lt;a href="#11-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;An Architect is designing a serverless application that will accept images uploaded by users from around the world. The application will make API calls to back-end services and save the session state data of the user to a database.
Which combination of services would provide a solution that is cost-effective while delivering the least latency?&lt;/p&gt;
&lt;p&gt;A. Amazon CloudFront, API Gateway, Amazon S3, AWS Lambda, DynamoDB
B. Amazon S3, API Gateway, AWS Lambda, Amazon RDS
C. API Gateway, Amazon S3, AWS Lambda, DynamoDB
D. Amazon CloudFront, API Gateway, Amazon S3, AWS Lambda, Amazon RDS&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;p&gt;Incorrect
Explanation:
Amazon CloudFront caches content closer to users at Edge locations around the world. This is the lowest latency option for uploading content. API Gateway and AWS Lambda are present in all options. DynamoDB can be used for storing session state data
The option that presents API Gateway first does not offer a front-end for users to upload content to
Amazon RDS is not a serverless service so this option can be ruled out
Amazon S3 alone will not provide the least latency for users around the world unless you have many buckets in different regions and a way of directing users to the closest bucket (such as Route 3 latency based routing). However, you would then need to manage replicating the data&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/networking-and-content-delivery/amazon-cloudfront/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/networking-and-content-delivery/amazon-cloudfront/&lt;/a&gt;
&lt;a href="https://aws.amazon.com/blogs/aws/amazon-cloudfront-content-uploads-post-put-other-methods/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/blogs/aws/amazon-cloudfront-content-uploads-post-put-other-methods/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;12. Question&lt;span class="hx:absolute hx:-mt-20" id="12-question"&gt;&lt;/span&gt;
&lt;a href="#12-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A training provider hosts a website using Amazon API Gateway on the front end. Recently, there has been heavy traffic on the website and the company wants to control access by allowing authenticated traffic from paying students only.
How should the company limit access to authenticated users only? (choose 2)&lt;/p&gt;
&lt;p&gt;A. Deploy AWS KMS to identify users
B. Allow X.509 certificates to authenticate traffic
C. Assign permissions in AWS IAM to allow users
D. Limit traffic through API Gateway
E. Allow users that are authenticated through Amazon Cognito&lt;/p&gt;
&lt;p&gt;Answer: CE
Incorrect
Explanation:&lt;/p&gt;
&lt;p&gt;API Gateway supports multiple mechanisms for controlling and managing access to your API. These include resource policies, standard IAM roles and policies, Lambda authorizers, and Amazon Cognito user pools.
Amazon Cognito user pools let you create customizable authentication and authorization solutions for your REST APIs. Amazon Cognito user pools are used to control who can invoke REST API methods.
IAM roles and policies offer flexible and robust access controls that can be applied to an entire API or individual methods. IAM roles and policies can be used for controlling who can create and manage your APIs as well as who can invoke them.
Limiting traffic through the API Gateway will not filter authenticated traffic, it will just limit overall invocations. This may prevent users from connecting who have a legitimate need.
X.509 certificates are not a method of authentication you can use with API Gateway.
AWS KMS is used for key management not user identification.&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-control-access-to-api.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-control-access-to-api.html&lt;/a&gt;
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/networking-and-content-delivery/amazon-api-gateway/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/networking-and-content-delivery/amazon-api-gateway/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;13. Question&lt;span class="hx:absolute hx:-mt-20" id="13-question"&gt;&lt;/span&gt;
&lt;a href="#13-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;An Auto Scaling Group is unable to respond quickly enough to load changes resulting in lost messages from another application tier. The messages are typically around 128KB in size.
What is the best design option to prevent the messages from being lost?&lt;/p&gt;
&lt;p&gt;A. Launch an Elastic Load Balancer
B. Store the messages on Amazon S3
C. Use larger EC2 instance sizes
D. Store the messages on an SQS queue&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
In this circumstance the ASG cannot launch EC2 instances fast enough. You need to be able to store the messages somewhere so they don’t get lost whilst the EC2 instances are launched. This is a classic use case for decoupling and SQS is designed for exactly this purpose
Amazon Simple Queue Service (Amazon SQS) is a web service that gives you access to message queues that store messages waiting to be processed. SQS offers a reliable, highly-scalable, hosted queue for storing messages in transit between computers. An SQS queue can be used to create distributed/decoupled applications
Storing the messages on S3 is potentially feasible but SQS is the preferred solution as it is designed for decoupling. If the messages are over 256KB and therefore cannot be stored in SQS, you may want to consider using S3 and it can be used in combination with SQS by using the Amazon SQS Extended Client Library for Java
An ELB can help to distribute incoming connections to the back-end EC2 instances however if the ASG is not scaling fast enough then there aren’t enough resources for the ELB to distributed traffic to&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/application-integration/amazon-sqs/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/application-integration/amazon-sqs/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;14. Question&lt;span class="hx:absolute hx:-mt-20" id="14-question"&gt;&lt;/span&gt;
&lt;a href="#14-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Your company would like to restrict the ability of most users to change their own passwords whilst continuing to allow a select group of users within specific user groups.
What is the best way to achieve this? (choose 2)&lt;/p&gt;
&lt;p&gt;A. Under the IAM Password Policy deselect the option to allow users to change their own passwords
B. Create an IAM Policy that grants users the ability to change their own password and attach it to the individual user accounts
C. Create an IAM Policy that grants users the ability to change their own password and attach it to the groups that contain the users
D. Create an IAM Role that grants users the ability to change their own password and attach it to the groups that contain the users
E. Disable the ability for all users to change their own passwords using the AWS Security Token Service&lt;/p&gt;
&lt;p&gt;Answer:AC&lt;/p&gt;
&lt;p&gt;Incorrect
Explanation:
A password policy can be defined for enforcing password length, complexity etc. (applies to all users)
You can allow or disallow the ability to change passwords using an IAM policy and you should attach this to the group that contains the users, not to the individual users themselves
You cannot use an IAM role to perform this function
The AWS STS is not used for controlling password policies&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/security-identity-compliance/aws-iam/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/security-identity-compliance/aws-iam/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;15. Question&lt;span class="hx:absolute hx:-mt-20" id="15-question"&gt;&lt;/span&gt;
&lt;a href="#15-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A Solutions Architect has created a VPC design that meets the security requirements of their organization. Any new applications that are deployed must use this VPC design.
How can project teams deploy, manage, and delete VPCs that meet this design with the LEAST administrative effort?&lt;/p&gt;
&lt;p&gt;A. Deploy an AWS CloudFormation template that defines components of the VPC
B. Use AWS Elastic Beanstalk to deploy both the VPC and the application
C. Clone the existing authorized VPC for each new project
D. Run a script that uses the AWS Command Line interface to deploy the VPC&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
CloudFormation allows you to define your infrastructure through code and securely and repeatably deploy the infrastructure with minimal administrative effort. This is a perfect use case for CloudFormation.
You can use a script to create the VPCs using the AWS CLI however this would be a lot more work to create and manage the scripts.
You cannot clone VPCs.
You cannot deploy the VPC through Elastic Beanstalk – you need to deploy the VPC first and then deploy your application using Beanstalk.&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/management-tools/aws-cloudformation/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/management-tools/aws-cloudformation/&lt;/a&gt;
&lt;a href="https://aws.amazon.com/cloudformation/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/cloudformation/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;16. Question&lt;span class="hx:absolute hx:-mt-20" id="16-question"&gt;&lt;/span&gt;
&lt;a href="#16-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Your organization has a data lake on S3 and you need to find a solution for performing in-place queries of the data assets in the data lake. The requirement is to perform both data discovery and SQL querying, and complex queries from a large number of concurrent users using BI tools.
What is the BEST combination of AWS services to use in this situation? (choose 2)&lt;/p&gt;
&lt;p&gt;A. AWS Glue for the ad hoc SQL querying
B. AWS Lambda for the complex queries
C. RedShift Spectrum for the complex queries
D. Amazon Athena for the ad hoc SQL querying&lt;/p&gt;
&lt;p&gt;Answer: CD&lt;/p&gt;
&lt;p&gt;Incorrect
Explanation:
Performing in-place queries on a data lake allows you to run sophisticated analytics queries directly on the data in S3 without having to load it into a data warehouse
You can use both Athena and Redshift Spectrum against the same data assets. You would typically use Athena for ad hoc data discovery and SQL querying, and then use Redshift Spectrum for more complex queries and scenarios where a large number of data lake users want to run concurrent BI and reporting workloads
AWS Lambda is a serverless technology for running functions, it is not the best solution for running analytics queries
AWS Glue is an ETL service&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://docs.aws.amazon.com/aws-technical-content/latest/building-data-lakes/in-place-querying.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/aws-technical-content/latest/building-data-lakes/in-place-querying.html&lt;/a&gt;
&lt;a href="https://aws.amazon.com/redshift/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/redshift/&lt;/a&gt;
&lt;a href="https://aws.amazon.com/athena/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/athena/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;17. Question&lt;span class="hx:absolute hx:-mt-20" id="17-question"&gt;&lt;/span&gt;
&lt;a href="#17-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;You have recently enabled Access Logs on your Application Load Balancer (ALB). One of your colleagues would like to process the log files using a hosted Hadoop service. What configuration changes and services can be leveraged to deliver this requirement?&lt;/p&gt;
&lt;p&gt;A. Configure Access Logs to be delivered to DynamoDB and use EMR for processing the log files
B. Configure Access Logs to be delivered to S3 and use Kinesis for processing the log files
C. Configure Access Logs to be delivered to S3 and use EMR for processing the log files
D. Configure Access Logs to be delivered to EC2 and install Hadoop for processing the log files&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
Access Logs can be enabled on ALB and configured to store data in an S3 bucket. Amazon EMR is a web service that enables businesses, researchers, data analysts, and developers to easily and cost-effectively process vast amounts of data. EMR utilizes a hosted Hadoop framework running on Amazon EC2 and Amazon S3
Neither Kinesis or EC2 provide a hosted Hadoop service
You cannot configure access logs to be delivered to DynamoDB&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/analytics/amazon-emr/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/analytics/amazon-emr/&lt;/a&gt;
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/compute/elastic-load-balancing/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/compute/elastic-load-balancing/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;18. Question&lt;span class="hx:absolute hx:-mt-20" id="18-question"&gt;&lt;/span&gt;
&lt;a href="#18-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A company is deploying a big data and analytics workload. The analytics will be run from a fleet of thousands of EC2 instances across multiple AZs. Data needs to be stored on a shared storage layer that can be mounted and accessed concurrently by all EC2 instances. Latency is not a concern however extremely high throughput is required.
What storage layer would be most suitable for this requirement?&lt;/p&gt;
&lt;p&gt;A. Amazon EFS in General Purpose mode
B. Amazon EFS in Max I/O mode
C. Amazon S3
D. Amazon EBS PIOPS&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
Amazon EFS file systems in the Max I/O mode can scale to higher levels of aggregate throughput and operations per second with a tradeoff of slightly higher latencies for file operations
Amazon S3 is not a storage layer that can be mounted and accessed concurrently
Amazon EBS volumes cannot be shared between instances&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/storage/amazon-efs/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/storage/amazon-efs/&lt;/a&gt;
&lt;a href="https://docs.aws.amazon.com/efs/latest/ug/performance.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/efs/latest/ug/performance.html&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;19. Question&lt;span class="hx:absolute hx:-mt-20" id="19-question"&gt;&lt;/span&gt;
&lt;a href="#19-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;An application launched on Amazon EC2 instances needs to publish personally identifiable information (PII) about customers using Amazon SNS. The application is launched in private subnets within an Amazon VPC.
Which is the MOST secure way to allow the application to access service endpoints in the same region?&lt;/p&gt;
&lt;p&gt;A. Use a proxy instance
B. Use a NAT gateway
C. Use AWS PrivateLink
D. Use an Internet Gateway&lt;/p&gt;
&lt;p&gt;Answer: C&lt;/p&gt;
&lt;p&gt;Correct
Explanation:
To publish messages to Amazon SNS topics from an Amazon VPC, create an interface VPC endpoint. Then, you can publish messages to SNS topics while keeping the traffic within the network that you manage with the VPC. This is the most secure option as traffic does not need to traverse the Internet.
Internet Gateways are used by instances in public subnets to access the Internet and this is less secure than an VPC endpoint.
A NAT Gateway is used by instances in private subnets to access the Internet and this is less secure than an VPC endpoint.
A proxy instance will also use the public Internet and so is less secure than a VPC endpoint.&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://docs.aws.amazon.com/sns/latest/dg/sns-vpc-endpoint.html"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/sns/latest/dg/sns-vpc-endpoint.html&lt;/a&gt;
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/networking-and-content-delivery/amazon-vpc/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/networking-and-content-delivery/amazon-vpc/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;20. Question&lt;span class="hx:absolute hx:-mt-20" id="20-question"&gt;&lt;/span&gt;
&lt;a href="#20-question" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A retail organization is deploying a new application that will read and write data to a database. The company wants to deploy the application in three different AWS Regions in an active-active configuration. The databases need to replicate to keep information in sync.
Which solution best meets these requirements?&lt;/p&gt;
&lt;p&gt;A. Amazon Aurora Global Database
B. Amazon DynamoDB with global tables
C. Amazon Athena with Amazon S3 cross-region replication
D. AWS Database Migration Service with change data capture&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;p&gt;Incorrect
Explanation:
Amazon DynamoDB global tables provide a fully managed solution for deploying a multi-region, multi-master database. This is the only solution presented that provides an active-active configuration where reads and writes can take place in multiple regions with full bi-directional synchronization.
Amazon Athena with S3 cross-region replication is not suitable. This is not a solution that provides a transactional database solution (Athena is used for analytics), or active-active synchronization.
Amazon Aurora Global Database provides read access to a database in multiple regions – it does not provide active-active configuration with bi-directional synchronization (though you can failover to your read-only DBs and promote them to writable).&lt;/p&gt;
&lt;p&gt;References:
&lt;a href="https://digitalcloud.training/certification-training/aws-solutions-architect-associate/database/amazon-dynamodb/"target="_blank" rel="noopener"&gt;https://digitalcloud.training/certification-training/aws-solutions-architect-associate/database/amazon-dynamodb/&lt;/a&gt;
&lt;a href="https://aws.amazon.com/blogs/database/how-to-use-amazon-dynamodb-global-tables-to-power-multiregion-architectures/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/blogs/database/how-to-use-amazon-dynamodb-global-tables-to-power-multiregion-architectures/&lt;/a&gt;&lt;/p&gt;</description></item><item><title>使用Chrome浏览器打开vCenter Web客户端</title><link>https://sunqi.site/blog/use-chrome-open-vcenter-web-client/</link><pubDate>Mon, 14 Mar 2022 08:08:56 +0800</pubDate><guid>https://sunqi.site/blog/use-chrome-open-vcenter-web-client/</guid><description>
&lt;p&gt;在vCenter 5.x时代，vCenter Web Client都是基于Flash实现的，随着Flash逐步被淘汰，在Web端使用vCenter就非常不方便。最近由于需要对最新的ESXi 7.0版本进行测试，原有的vCenter 5.5版本无法直接对7.0版本进行管理，所以决定对vCenter进行升级。升级后的vCenter使用了全新的HTML5进行了重构，很方便的就可以在浏览器端使用vCenter，而无需再使用Windows环境下载客户端。&lt;/p&gt;
&lt;p&gt;但是在我的Mac环境中，由于Chrome升级了浏览器安全性，虽然使用了https协议，但是仍然无法通过Chrome打开vCenter环境，通过查询VMware相关帮助文档，最终在安装证书后，顺利的使用Chrome浏览器打开了vCenter页面。&lt;/p&gt;
&lt;h2&gt;现象&lt;span class="hx:absolute hx:-mt-20" id="现象"&gt;&lt;/span&gt;
&lt;a href="#%e7%8e%b0%e8%b1%a1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;先来看一下现象，按照通常情况，如果证书不被信任，Chrome会在高级选项中显示是否要继续的选项，但是打开vCenter后，并没有相关选项。通过对证书项检查，发现Chrome认为证书无效，在高级中并没有出现继续访问的提示，所以解决该问题的关键就是让Chrome能够正确识别vCenter的证书。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-03-14-08-24-19.png" alt="2022-03-14-08-24-19" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;下载证书&lt;span class="hx:absolute hx:-mt-20" id="下载证书"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%8b%e8%bd%bd%e8%af%81%e4%b9%a6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;那么该从哪里下载证书呢？通过查询VMWare Knowledge Base(&lt;a href="https://kb.vmware.com/s/article/2108294?lang=zh_CN#certificate_download_in_small_deployments"target="_blank" rel="noopener"&gt;https://kb.vmware.com/s/article/2108294?lang=zh_CN#certificate_download_in_small_deployments&lt;/a&gt;)，得知可以直接从vCenter中获取证书，安装后即可恢复正常。&lt;/p&gt;
&lt;p&gt;简单来说，vCenter的证书被存放在了https://vcenter_ip/certs/download.zip，下载导入到系统后就可以正常访问了。但是仍然受限与Chrome浏览器安全性要求，你仍然无法直接进行下载，此时有两个选项：通过Safari浏览器或者在Terminal中执行wget命令。&lt;/p&gt;
&lt;h3&gt;Safari浏览器&lt;span class="hx:absolute hx:-mt-20" id="safari浏览器"&gt;&lt;/span&gt;
&lt;a href="#safari%e6%b5%8f%e8%a7%88%e5%99%a8" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;虽然Safari浏览器也认为证书有问题，但是还是可以下载该文件。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-03-14-08-36-10.png" alt="2022-03-14-08-36-10" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;wget方式&lt;span class="hx:absolute hx:-mt-20" id="wget方式"&gt;&lt;/span&gt;
&lt;a href="#wget%e6%96%b9%e5%bc%8f" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在Terminal中，执行wget指令&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;wget https://192.168.10.2/certs/download.zip --no-check-certificate&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;在Mac中导入证书&lt;span class="hx:absolute hx:-mt-20" id="在mac中导入证书"&gt;&lt;/span&gt;
&lt;a href="#%e5%9c%a8mac%e4%b8%ad%e5%af%bc%e5%85%a5%e8%af%81%e4%b9%a6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;下载完成解压缩后，你会得到这样的一个目录结构：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;certs
├── lin
│   ├── a5f3f954.0
│   ├── a5f3f954.r0
│   └── fadc1192.0
├── mac
│   ├── a5f3f954.0
│   ├── a5f3f954.r0
│   └── fadc1192.0
└── win
├── a5f3f954.0.crt
├── a5f3f954.r0.crl
└── fadc1192.0.crt
3 directories, 9 files&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;其中mac路径下的a5f3f954.0和fadc1192.0是我们需要导入的证书，在Mac中打开[钥匙串访问]。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-03-14-08-41-19.png" alt="2022-03-14-08-41-19" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;左侧选择[证书]，并将两个文件直接拖入其中即可，如图所示。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-03-14-08-43-33.png" alt="2022-03-14-08-43-33" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;此时先双击其中的一个证书，在打开的页面中，展开[信任]，在[使用此证书时]后选择[始终允许]，关闭对话框时，需要输入系统密码。另外一个，也执行同样的操作。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-03-14-08-45-05.png" alt="2022-03-14-08-45-05" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;此时，刷新Chrome页面，已经可以正常打开vCenter页面了(因为我之前信任过，可能你的需要在高级中点击继续即可)。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-03-14-08-48-29.png" alt="2022-03-14-08-48-29" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;总结&lt;span class="hx:absolute hx:-mt-20" id="总结"&gt;&lt;/span&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;作为虚拟化时代最重要的生产力工具，VMware ESXi依旧保持着巨大的活力，即使在云计算时代的冲击下，其强大的稳定性和轻运维、易运维的特性，仍然在企业级客户中占据一席之地。&lt;/p&gt;</description></item><item><title>AWS Certified Solutions Architect - Associate Exam(Q101-Q200)</title><link>https://sunqi.site/blog/2020-01-08-aws-certified-solutions-architect-associate-exam-q101-q200/</link><pubDate>Tue, 08 Mar 2022 15:36:23 +0000</pubDate><guid>https://sunqi.site/blog/2020-01-08-aws-certified-solutions-architect-associate-exam-q101-q200/</guid><description>
&lt;p&gt;通过之前100道题的梳理，发现这个网站竟然有这么多争议的题目，我觉得有可能是有些题目已经跟不上AWS自身发展速度了，有了更多的方法。总之，通过这些题目的梳理，对AWS服务细节层面有了更多的了解，希望能够一次性通过ACA考试。这篇继续这个网站101到200题的学习工作，希望能提高点速度。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;(争议)A Solutions Architect needs to use AWS to implement pilot light disaster recovery for a three-tier web application hosted in an on-premises datacenter. Which solution allows rapid provision of working, fully-scaled production environment?&lt;span class="hx:absolute hx:-mt-20" id="争议a-solutions-architect-needs-to-use-aws-to-implement-pilot-light-disaster-recovery-for-a-three-tier-web-application-hosted-in-an-on-premises-datacenter-which-solution-allows-rapid-provision-of-working-fully-scaled-production-environment"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-solutions-architect-needs-to-use-aws-to-implement-pilot-light-disaster-recovery-for-a-three-tier-web-application-hosted-in-an-on-premises-datacenter-which-solution-allows-rapid-provision-of-working-fully-scaled-production-environment" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Continuously replicate the production database server to Amazon RDS. Use AWS CloudFormation to deploy the application and any additional servers if necessary.
B. Continuously replicate the production database server to Amazon RDS. Create one application load balancer and register on-premises servers. Configure ELB Application Load Balancer to automatically deploy Amazon EC2 instances for application and additional servers if the on-premises application is down.
C. Use a scheduled Lambda function to replicate the production database to AWS. Use Amazon Route 53 health checks to deploy the application automatically to Amazon S3 if production is unhealthy.
D. Use a scheduled Lambda function to replicate the production database to AWS. Register on-premises servers to an Auto Scaling group and deploy the application and additional servers if production is unavailable.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：有人说答案是A，因为题目中的这个词pilot light(A pilot light is a small gas flame)，准确的翻译没查到，从字面理解应该就是简单轻量级的意思。A选项的方式是当出现灾难时，使用CloudFormation进行除数据库外的重建。所以很多人认为这种方式更符合题目的要求。但是从B选项看，更符合一个容灾的场景，当发生灾难时，通过B中的配置，可以做到马上接管的效果，比A选项更像是一个容灾的解决方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect notices slower response times from an application. The CloudWatch metrics on the MySQL RDS indicate Read IOPS are high and fluctuate significantly when the database is under load. How should the database environment be re-designed to resolve the IOPS fluctuation?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-notices-slower-response-times-from-an-application-the-cloudwatch-metrics-on-the-mysql-rds-indicate-read-iops-are-high-and-fluctuate-significantly-when-the-database-is-under-load-how-should-the-database-environment-be-re-designed-to-resolve-the-iops-fluctuation"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-notices-slower-response-times-from-an-application-the-cloudwatch-metrics-on-the-mysql-rds-indicate-read-iops-are-high-and-fluctuate-significantly-when-the-database-is-under-load-how-should-the-database-environment-be-re-designed-to-resolve-the-iops-fluctuation" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Change the RDS instance type to get more RAM.
B. Change the storage type to Provisioned IOPS.
C. Scale the web server tier horizontally.
D. Split the DB layer into separate RDS instances.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;h2&gt;A Solutions Architect is designing a solution that can monitor memory and disk space utilization of all Amazon EC2 instances running Amazon Linux and&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-designing-a-solution-that-can-monitor-memory-and-disk-space-utilization-of-all-amazon-ec2-instances-running-amazon-linux-and"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-designing-a-solution-that-can-monitor-memory-and-disk-space-utilization-of-all-amazon-ec2-instances-running-amazon-linux-and" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Windows. Which solution meets this requirement?&lt;/p&gt;
&lt;p&gt;A. Default Amazon CloudWatch metrics.
B. Custom Amazon CloudWatch metrics.
C. Amazon Inspector resource monitoring.
D. Default monitoring of Amazon EC2 instances.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题又是原网站给出的错题，原来给出的答案是A。我曾经对AWS两个行为比较纳闷：一个是为什么没有VNC，另外一个是为什么不提供内存监控，直到又一次和AWS的架构师聊才理解了AWS的良苦用心。AWS始终把用户安全放在第一位，但凡用户的东西我是坚决不能碰的，而无论是VNC还是内存监控无疑与这一原则相违背的。所以内存不可能是默认监控的范畴，必须通过custom脚本完成，同样磁盘利用率也是类似的方式。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is creating a new relational database. The Compliance team will use the database, and mandates that data content must be stored across three different Availability Zones. Which of the following options should the Architect Use?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-creating-a-new-relational-database-the-compliance-team-will-use-the-database-and-mandates-that-data-content-must-be-stored-across-three-different-availability-zones-which-of-the-following-options-should-the-architect-use"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-creating-a-new-relational-database-the-compliance-team-will-use-the-database-and-mandates-that-data-content-must-be-stored-across-three-different-availability-zones-which-of-the-following-options-should-the-architect-use" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon Aurora
B. Amazon RDS MySQL with Multi-AZ enabled
C. Amazon DynamoDB
D. Amazon ElastiCache&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;问：Amazon Aurora 如何提高我的数据库对磁盘故障的容错能力？&lt;/p&gt;
&lt;p&gt;Amazon Aurora 会将您的数据库卷分成分散在很多个磁盘上的 10GB 的区段。每 10GB 的数据库卷组块都能在三个可用区间用六种方法进行复制。Amazon Aurora 的设计可透明应对多达两个数据副本的损失，而不会影响数据库写入可用性，还能在不影响读取可用性的情况下应对多达三个副本。Amazon Aurora 存储还具有自我修复能力。可连续扫描数据块和磁盘有无出错并自动修复之。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A company needs to quickly ensure that all files created in an Amazon S3 bucket in us-east-1 are also available in another bucket in ap-southeast-2. Which option represents the SIMPLIEST way to implement this design?&lt;span class="hx:absolute hx:-mt-20" id="a-company-needs-to-quickly-ensure-that-all-files-created-in-an-amazon-s3-bucket-in-us-east-1-are-also-available-in-another-bucket-in-ap-southeast-2-which-option-represents-the-simpliest-way-to-implement-this-design"&gt;&lt;/span&gt;
&lt;a href="#a-company-needs-to-quickly-ensure-that-all-files-created-in-an-amazon-s3-bucket-in-us-east-1-are-also-available-in-another-bucket-in-ap-southeast-2-which-option-represents-the-simpliest-way-to-implement-this-design" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Add an S3 lifecycle rule to move any files from the bucket in us-east-1 to the bucket in ap-southeast-2.
B. Create a Lambda function to be triggered for every new file in us-east-1 that copies the file to the bucket in ap-southeast-2.
C. Use SNS to notify the bucket in ap-southeast-2 to create a file whenever the file is created in the bucket in us-east-1.
D. Enable versioning and configure cross-region replication from the bucket in us-east-1 to the bucket in ap-southeast-2.&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题要求的是最简单的方法，B理论上是可以的，但是与D相比过于复杂。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;An organization has a long-running image processing application that runs on Spot Instances that will be terminated when interrupted. A highly available workload must be designed to respond to Spot Instance interruption notices. The solution must include a two-minute warning when there is not enough capacity. How can these requirements be met?&lt;span class="hx:absolute hx:-mt-20" id="an-organization-has-a-long-running-image-processing-application-that-runs-on-spot-instances-that-will-be-terminated-when-interrupted-a-highly-available-workload-must-be-designed-to-respond-to-spot-instance-interruption-notices-the-solution-must-include-a-two-minute-warning-when-there-is-not-enough-capacity-how-can-these-requirements-be-met"&gt;&lt;/span&gt;
&lt;a href="#an-organization-has-a-long-running-image-processing-application-that-runs-on-spot-instances-that-will-be-terminated-when-interrupted-a-highly-available-workload-must-be-designed-to-respond-to-spot-instance-interruption-notices-the-solution-must-include-a-two-minute-warning-when-there-is-not-enough-capacity-how-can-these-requirements-be-met" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Use Amazon CloudWatch Events to invoke an AWS Lambda function that can launch On-Demand Instances.
B. Regularly store data from the application on Amazon DynamoDB. Increase the maximum number of instances in the AWS Auto Scaling group.
C. Manually place a bid for additional Spot Instances at a higher price in the same AWS Region and Availability Zone.
D. Ensure that the Amazon Machine Image associated with the application has the latest configurations for the launch configuration.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Taking Advantage of Amazon EC2 Spot Instance Interruption Notices(&lt;a href="https://aws.amazon.com/cn/blogs/compute/taking-advantage-of-amazon-ec2-spot-instance-interruption-notices/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/cn/blogs/compute/taking-advantage-of-amazon-ec2-spot-instance-interruption-notices/&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;In January 2018, the Spot Instance interruption notice also became available as an event in Amazon CloudWatch Events. This allows targets such as AWS Lambda functions or Amazon SNS topics to process Spot Instance interruption notices by creating a CloudWatch Events rule to monitor for the notice.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;分析：网站给出的答案是B，但是这道题目考察的应该是合理利用Spot Instance的通知是这道题目的关键，&amp;ldquo;must include a two-minute warning&amp;rdquo; =&amp;gt; Need CloudWatch&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company has an Amazon RDS-managed online transaction processing system that has very heavy read and write. The Solutions Architect notices throughput issues with the system. How can the responsiveness of the primary database be improved?&lt;span class="hx:absolute hx:-mt-20" id="a-company-has-an-amazon-rds-managed-online-transaction-processing-system-that-has-very-heavy-read-and-write-the-solutions-architect-notices-throughput-issues-with-the-system-how-can-the-responsiveness-of-the-primary-database-be-improved"&gt;&lt;/span&gt;
&lt;a href="#a-company-has-an-amazon-rds-managed-online-transaction-processing-system-that-has-very-heavy-read-and-write-the-solutions-architect-notices-throughput-issues-with-the-system-how-can-the-responsiveness-of-the-primary-database-be-improved" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. (争议)Use asynchronous replication for standby to maximize throughput during peak demand.
B. Offload SELECT queries that can tolerate stale data to READ replica.
C. Offload SELECT and UPDATE queries to READ replica.
D. Offload SELECT query that needs the most current data to READ replica.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：原网站给出的答案是A，大部分反对的理由是RDS之间的复制是同步的并不是异步的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company is designing a failover strategy in Amazon Route 53 for its resources between two AWS Regions. The company must have the ability to route a user&amp;rsquo;s traffic to the region with least latency, and if both regions are healthy, Route 53 should route traffic to resources in both regions. Which strategy should the Solutions Architect recommend?&lt;span class="hx:absolute hx:-mt-20" id="a-company-is-designing-a-failover-strategy-in-amazon-route-53-for-its-resources-between-two-aws-regions-the-company-must-have-the-ability-to-route-a-users-traffic-to-the-region-with-least-latency-and-if-both-regions-are-healthy-route-53-should-route-traffic-to-resources-in-both-regions-which-strategy-should-the-solutions-architect-recommend"&gt;&lt;/span&gt;
&lt;a href="#a-company-is-designing-a-failover-strategy-in-amazon-route-53-for-its-resources-between-two-aws-regions-the-company-must-have-the-ability-to-route-a-users-traffic-to-the-region-with-least-latency-and-if-both-regions-are-healthy-route-53-should-route-traffic-to-resources-in-both-regions-which-strategy-should-the-solutions-architect-recommend" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Configure active-active failover using Route 53 latency DNS records.
B. Configure active-passive failover using Route 53 latency DNS records.
C. Configure active-active failover using Route 53 failover DNS records.
D. Configure active-passive failover using Route 53 failover DNS records.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题很明显是需要AA模式的，with least latency，所以需要latency。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Active-Active Failover
Use this failover configuration when you want all of your resources to be available the majority of the time. When a resource becomes unavailable, Route 53 can detect that it&amp;rsquo;s unhealthy and stop including it when responding to queries.&lt;/p&gt;
&lt;p&gt;In active-active failover, all the records that have the same name, the same type (such as A or AAAA), and the same routing policy (such as weighted or latency) are active unless Route 53 considers them unhealthy. Route 53 can respond to a DNS query using any healthy record.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A company is developing several critical long-running applications hosted on Docker. How should a Solutions Architect design a solution to meet the scalability and orchestration requirements on AWS?&lt;span class="hx:absolute hx:-mt-20" id="a-company-is-developing-several-critical-long-running-applications-hosted-on-docker-how-should-a-solutions-architect-design-a-solution-to-meet-the-scalability-and-orchestration-requirements-on-aws"&gt;&lt;/span&gt;
&lt;a href="#a-company-is-developing-several-critical-long-running-applications-hosted-on-docker-how-should-a-solutions-architect-design-a-solution-to-meet-the-scalability-and-orchestration-requirements-on-aws" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Use Amazon ECS and Service Auto Scaling.
B. Use Spot Instances for orchestration and for scaling containers on existing Amazon EC2 instances.
C. Use AWS OpsWorks to launch containers in new Amazon EC2 instances.
D. Use Auto Scaling groups to launch containers on existing Amazon EC2 instances.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Amazon Elastic Container Service (Amazon ECS) 是用于在可扩展群集上运行 Docker 应用程序的 Amazon Web Service。在本教程中，您将了解如何在负载均衡器后面的 Amazon ECS 集群上运行支持 Docker 的示例应用程序，对该示例应用程序进行测试，然后删除您的资源以免产生费用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;(争议)A Solutions Architect is developing a new web application on AWS. The Architect expects the application to become very popular, so the application must scale to support the load. The Architect wants to focus on software development and deploying new features without provisioning or managing instances. What solution is appropriate?&lt;span class="hx:absolute hx:-mt-20" id="争议a-solutions-architect-is-developing-a-new-web-application-on-aws-the-architect-expects-the-application-to-become-very-popular-so-the-application-must-scale-to-support-the-load-the-architect-wants-to-focus-on-software-development-and-deploying-new-features-without-provisioning-or-managing-instances-what-solution-is-appropriate"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-solutions-architect-is-developing-a-new-web-application-on-aws-the-architect-expects-the-application-to-become-very-popular-so-the-application-must-scale-to-support-the-load-the-architect-wants-to-focus-on-software-development-and-deploying-new-features-without-provisioning-or-managing-instances-what-solution-is-appropriate" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon API Gateway and AWS Lambda
B. Elastic Load Balancing with Auto Scaling groups and Amazon EC2
C. Amazon API Gateway and Amazon EC2
D. Amazon CloudFront and AWS Lambda&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：题目的需求是：1、不想运维；2、集中精力去做开发。这是非常典型的Serverless的需求，将底层交给云原生服务，专注于业务开发。首先应该选择AWS Lambda服务，则AD作为选项。原答案给出的是D，但是CloudFront作为CDN服务，好像并没有向外提供接口的能力，AWS Lambda服务并不像阿里的函数计算提供了Http trigger，所以无法对外提供API接口的能力，从这个角度看A更合理一些。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A Solutions Architect is deploying a new production MySQL database on AWS. It is critical that the database is highly available. What should the Architect do to achieve this goal with Amazon RDS?&lt;span class="hx:absolute hx:-mt-20" id="a-solutions-architect-is-deploying-a-new-production-mysql-database-on-aws-it-is-critical-that-the-database-is-highly-available-what-should-the-architect-do-to-achieve-this-goal-with-amazon-rds"&gt;&lt;/span&gt;
&lt;a href="#a-solutions-architect-is-deploying-a-new-production-mysql-database-on-aws-it-is-critical-that-the-database-is-highly-available-what-should-the-architect-do-to-achieve-this-goal-with-amazon-rds" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Create a read replica of the primary database and deploy it in a different AWS Region.
B. Enable multi-AZ to create a standby database in a different Availability Zone.
C. Enable multi-AZ to create a standby database in a different AWS Region.
D. Create a read replica of the primary database and deploy it in a different Availability Zone.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：原题目给出的是A，但是B明显是正确答案。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://aws.amazon.com/cn/rds/ha/?nc1=h_ls"target="_blank" rel="noopener"&gt;https://aws.amazon.com/cn/rds/ha/?nc1=h_ls&lt;/a&gt;
Amazon Relational Database Service (Amazon RDS) supports two easy-to-use options for ensuring High Availability of your relational database.
For your MySQL, MariaDB, PostgreSQL, Oracle, and SQL Server database (DB) instances, you can use Amazon RDS Multi-AZ deployments. When you provision a Multi-AZ DB instance, Amazon RDS automatically creates a primary DB instance and synchronously replicates the data to a standby instance in a different Availability Zone (AZ). In case of an infrastructure failure, Amazon RDS performs an automatic failover to the standby DB instance. Since the endpoint for your DB instance remains the same after a failover, your application can resume database operation without the need for manual administrative intervention. Learn more &amp;raquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;An organization designs a mobile application for their customers to upload photos to a site. The application needs a secure login with MFA. The organization wants to limit the initial build time and maintenance of the solution. Which solution should a Solutions Architect recommend to meet the requirements?&lt;span class="hx:absolute hx:-mt-20" id="an-organization-designs-a-mobile-application-for-their-customers-to-upload-photos-to-a-site-the-application-needs-a-secure-login-with-mfa-the-organization-wants-to-limit-the-initial-build-time-and-maintenance-of-the-solution-which-solution-should-a-solutions-architect-recommend-to-meet-the-requirements"&gt;&lt;/span&gt;
&lt;a href="#an-organization-designs-a-mobile-application-for-their-customers-to-upload-photos-to-a-site-the-application-needs-a-secure-login-with-mfa-the-organization-wants-to-limit-the-initial-build-time-and-maintenance-of-the-solution-which-solution-should-a-solutions-architect-recommend-to-meet-the-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Use Amazon Cognito Identity with SMS-based MFA.
B. Edit AWS IAM policies to require MFA for all users.
C. Federate IAM against corporate AD that requires MFA.
D. Use Amazon API Gateway and require SSE for photos.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;h2&gt;(争议)A Solutions Architect is designing a solution to monitor weather changes by the minute. The frontend application is hosted on Amazon EC2 instances. The backend must be scalable to a virtually unlimited size, and data retrieval must occur with minimal latency. Which AWS service should the Architect use to store the data and achieve these requirements?&lt;span class="hx:absolute hx:-mt-20" id="争议a-solutions-architect-is-designing-a-solution-to-monitor-weather-changes-by-the-minute-the-frontend-application-is-hosted-on-amazon-ec2-instances-the-backend-must-be-scalable-to-a-virtually-unlimited-size-and-data-retrieval-must-occur-with-minimal-latency-which-aws-service-should-the-architect-use-to-store-the-data-and-achieve-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-solutions-architect-is-designing-a-solution-to-monitor-weather-changes-by-the-minute-the-frontend-application-is-hosted-on-amazon-ec2-instances-the-backend-must-be-scalable-to-a-virtually-unlimited-size-and-data-retrieval-must-occur-with-minimal-latency-which-aws-service-should-the-architect-use-to-store-the-data-and-achieve-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon S3
B. Amazon DynamoDB
C. Amazon RDS
D. Amazon EBS&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：这道题很多人都认为B是正确的，但是从篇气象公司最佳实践看，确实采用的是S3方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;AWS Case Study: The Weather Company(&lt;a href="https://aws.amazon.com/cn/solutions/case-studies/the-weather-company/"target="_blank" rel="noopener"&gt;https://aws.amazon.com/cn/solutions/case-studies/the-weather-company/&lt;/a&gt;)
The platform ingests information from more than 100 different sources and generates close to one-half terabyte (TB) of data each time it updates. The information is mapped and processed into forecast points that can be retrieved in real time, based on queries coming into the system. All data is stored in Amazon Simple Storage Service (Amazon S3), leveraging the efficiency of cloud storage as opposed to an on-premises storage solution and eliminating the hassle of managing a storage platform.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A company hosts a website on premises. The website has a mix of static and dynamic content, but users experience latency when loading static files. Which AWS service can help reduce latency?&lt;span class="hx:absolute hx:-mt-20" id="a-company-hosts-a-website-on-premises-the-website-has-a-mix-of-static-and-dynamic-content-but-users-experience-latency-when-loading-static-files-which-aws-service-can-help-reduce-latency"&gt;&lt;/span&gt;
&lt;a href="#a-company-hosts-a-website-on-premises-the-website-has-a-mix-of-static-and-dynamic-content-but-users-experience-latency-when-loading-static-files-which-aws-service-can-help-reduce-latency" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon CloudFront with on-premises servers as the origin
B. ELB Application Load Balancer
C. Amazon Route 53 latency-based routing
D. Amazon EFS to store and server static files&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;h2&gt;A company wants to analyze all of its sales information aggregated over the last 12 months. The company expects there to be over 10TB of data from multiple sources. What service should be used?&lt;span class="hx:absolute hx:-mt-20" id="a-company-wants-to-analyze-all-of-its-sales-information-aggregated-over-the-last-12-months-the-company-expects-there-to-be-over-10tb-of-data-from-multiple-sources-what-service-should-be-used"&gt;&lt;/span&gt;
&lt;a href="#a-company-wants-to-analyze-all-of-its-sales-information-aggregated-over-the-last-12-months-the-company-expects-there-to-be-over-10tb-of-data-from-multiple-sources-what-service-should-be-used" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon DynamoDB
B. Amazon Aurora MySQL
C. Amazon RDS MySQL
D. Amazon Redshift&lt;/p&gt;
&lt;p&gt;Answer: D&lt;/p&gt;
&lt;h2&gt;A media company has deployed a multi-tier architecture on AWS. Web servers are deployed in two Availability Zones using an Auto Scaling group with a default Auto Scaling termination policy. The web servers&amp;rsquo; Auto Scaling group currently has 15 instances running. Which instance will be terminated first during a scale-in operation?&lt;span class="hx:absolute hx:-mt-20" id="a-media-company-has-deployed-a-multi-tier-architecture-on-aws-web-servers-are-deployed-in-two-availability-zones-using-an-auto-scaling-group-with-a-default-auto-scaling-termination-policy-the-web-servers-auto-scaling-group-currently-has-15-instances-running-which-instance-will-be-terminated-first-during-a-scale-in-operation"&gt;&lt;/span&gt;
&lt;a href="#a-media-company-has-deployed-a-multi-tier-architecture-on-aws-web-servers-are-deployed-in-two-availability-zones-using-an-auto-scaling-group-with-a-default-auto-scaling-termination-policy-the-web-servers-auto-scaling-group-currently-has-15-instances-running-which-instance-will-be-terminated-first-during-a-scale-in-operation" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. The instance with the oldest launch configuration.
B. The instance in the Availability Zone that has most instances.
C. The instance closest to the next billing hour.
D. The oldest instance in the group.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;控制在缩小过程中终止哪些 Auto Scaling 实例(&lt;a href="https://docs.aws.amazon.com/zh_cn/autoscaling/ec2/userguide/as-instance-termination.html#default-termination-policy"target="_blank" rel="noopener"&gt;https://docs.aws.amazon.com/zh_cn/autoscaling/ec2/userguide/as-instance-termination.html#default-termination-policy&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;当达到缩减策略的阈值时，策略生效，Auto Scaling 组终止其中一个实例。如果您没有为该组分配特定的终止策略，则使用默认终止策略。它选择有两个实例的可用区，并终止从最旧启动配置启动的实例。如果这些实例是从同一启动配置启动的，则 Auto Scaling 组选择最接近下一个计费小时的实例并终止该实例。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;A retail company has sensors placed in its physical retail stores. The sensors send messages over HTTP when customers interact with in-store product displays. A Solutions Architect needs to implement a system for processing those sensor messages; the results must be available for the Data Analysis team. Which architecture should be used to meet these requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-retail-company-has-sensors-placed-in-its-physical-retail-stores-the-sensors-send-messages-over-http-when-customers-interact-with-in-store-product-displays-a-solutions-architect-needs-to-implement-a-system-for-processing-those-sensor-messages-the-results-must-be-available-for-the-data-analysis-team-which-architecture-should-be-used-to-meet-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-retail-company-has-sensors-placed-in-its-physical-retail-stores-the-sensors-send-messages-over-http-when-customers-interact-with-in-store-product-displays-a-solutions-architect-needs-to-implement-a-system-for-processing-those-sensor-messages-the-results-must-be-available-for-the-data-analysis-team-which-architecture-should-be-used-to-meet-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Implement an Amazon API Gateway to server as the HTTP endpoint. Have the API Gateway trigger an AWS Lambda function to process the messages, and save the results to an Amazon DynamoDB table.
B. Create an Amazon EC2 instance to server as the HTTP endpoint and to process the messages. Save the results to Amazon S3 for the Data Analysis team to download.
C. Use Amazon Route 53 to direct incoming sensor messages to a Lambda function to process the message and save the results to a Amazon DynamoDB table.
D. Use AWS Direct Connect to connect sensors to DynamoDB so that data can be written directly to a DynamoDB table where it can be accessed by the Data Analysis team.&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：原来AWS Lambda的HTTP trigger是这么实现的&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A client is migrating a legacy web application to the AWS Cloud. The current system uses an Oracle database as a relational database management system solution. Backups occur every night, and the data is stored on-premises. The Solutions Architect must automate the backups and identity a storage solution while keeping costs low. Which AWS service will meet these requirements?&lt;span class="hx:absolute hx:-mt-20" id="a-client-is-migrating-a-legacy-web-application-to-the-aws-cloud-the-current-system-uses-an-oracle-database-as-a-relational-database-management-system-solution-backups-occur-every-night-and-the-data-is-stored-on-premises-the-solutions-architect-must-automate-the-backups-and-identity-a-storage-solution-while-keeping-costs-low-which-aws-service-will-meet-these-requirements"&gt;&lt;/span&gt;
&lt;a href="#a-client-is-migrating-a-legacy-web-application-to-the-aws-cloud-the-current-system-uses-an-oracle-database-as-a-relational-database-management-system-solution-backups-occur-every-night-and-the-data-is-stored-on-premises-the-solutions-architect-must-automate-the-backups-and-identity-a-storage-solution-while-keeping-costs-low-which-aws-service-will-meet-these-requirements" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon RDS
B. Amazon RedShift
C. Amazon DynamoDB Accelerator
D. Amazon ElastiCache&lt;/p&gt;
&lt;p&gt;Answer: A&lt;/p&gt;
&lt;h2&gt;(争议)A company has an Amazon RDS database backing its production website. The Sales team needs to run queries against the database to track training program effectiveness. Queries against the production database cannot impact performance, and the solution must be easy to maintain. How can these requirements be met?&lt;span class="hx:absolute hx:-mt-20" id="争议a-company-has-an-amazon-rds-database-backing-its-production-website-the-sales-team-needs-to-run-queries-against-the-database-to-track-training-program-effectiveness-queries-against-the-production-database-cannot-impact-performance-and-the-solution-must-be-easy-to-maintain-how-can-these-requirements-be-met"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%89%e8%ae%aea-company-has-an-amazon-rds-database-backing-its-production-website-the-sales-team-needs-to-run-queries-against-the-database-to-track-training-program-effectiveness-queries-against-the-production-database-cannot-impact-performance-and-the-solution-must-be-easy-to-maintain-how-can-these-requirements-be-met" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Use an Amazon Redshift database. Copy the product database into Redshift and allow the team to query it.
B. Use an Amazon RDS read replica of the production database and allow the team to query against it.
C. Use multiple Amazon EC2 instances running replicas of the production database, placed behind a load balancer.
D. Use an Amazon DynamoDB table to store a copy of the data.&lt;/p&gt;
&lt;p&gt;Answer: B&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;争议：原有答案给出的是A，根据题目描述看起来是一个数据仓库的需求。从easy to maintain的角度说B，更简单&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;A company must collect temperature data from thousands of remote weather devices. The company must also store this data in a data warehouse to run aggregations and visualizations. Which services will meet these requirements? (Choose two.)&lt;span class="hx:absolute hx:-mt-20" id="a-company-must-collect-temperature-data-from-thousands-of-remote-weather-devices-the-company-must-also-store-this-data-in-a-data-warehouse-to-run-aggregations-and-visualizations-which-services-will-meet-these-requirements-choose-two"&gt;&lt;/span&gt;
&lt;a href="#a-company-must-collect-temperature-data-from-thousands-of-remote-weather-devices-the-company-must-also-store-this-data-in-a-data-warehouse-to-run-aggregations-and-visualizations-which-services-will-meet-these-requirements-choose-two" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A. Amazon Kinesis Data Firehouse
B. Amazon SQS
C. Amazon Redshift
D. Amazon SNS
E. Amazon DynamoDB&lt;/p&gt;
&lt;p&gt;Answer: AC&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;分析：A负责接收数据并处理，C作为数据仓库存储下来&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Gitlab之间进行同步备份</title><link>https://sunqi.site/blog/schedule-sync-gitlab/</link><pubDate>Mon, 14 Feb 2022 07:23:44 +0800</pubDate><guid>https://sunqi.site/blog/schedule-sync-gitlab/</guid><description>
&lt;p&gt;目前，我们公司有两个研发团队，分别在北京和武汉，考虑到访问速度的问题，原有武汉的研发环境在近端部署。也就是北京和武汉分别有两套独立的研发管理环境，虽然这解决了近端访问速度的问题，但是管理上较为分散，比如研发环境备份和恢复就是最重要的问题之一。最近，处于对安全性和合规性的考虑，希望将北京和武汉的源代码，统一的集中备份，防止公司资产流失。&lt;/p&gt;
&lt;h2&gt;Gitlab同步备份需求分析&lt;span class="hx:absolute hx:-mt-20" id="gitlab同步备份需求分析"&gt;&lt;/span&gt;
&lt;a href="#gitlab%e5%90%8c%e6%ad%a5%e5%a4%87%e4%bb%bd%e9%9c%80%e6%b1%82%e5%88%86%e6%9e%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;由于历史原因，北京团队使用Gerrit进行代码审核和管理的工具，但是对于很多开发人员来说，入门比较陡峭，需要记忆很多git命令，所以考虑团队扩展性的需要，将Gerrit环境逐步切换至Gitlab中，而武汉团队则是直接选择了Gitlab进行代码管理。&lt;/p&gt;
&lt;p&gt;在选择目标侧环境时，原本想使用阿里云效和腾讯的Coding环境进行备份，以我们目前体量来看，是完全免费的。但是考虑到随着公司增长，后期可能会产生成本，所以决定利用现有的K8S生产环境部署一套Gitlab，用于代码备份。&lt;/p&gt;
&lt;p&gt;所以本次要解决的问题就是将两个团队Gitlab环境下的所有项目定期备份至远程的Gitlab中。在最初期的方案设计中，想使用最简单的Sehll脚本进行同步，但是会出现以下几个问题要解决：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在前期配置过程中，如果待同步项目较多，则在目标端进行预配置的工作较多，增加了管理成本，所以希望将整组的项目进行完整的增量同步&lt;/li&gt;
&lt;li&gt;如果在源端有新的代码库增加，则需要至少维护同步脚本和备份端的Gitlab环境进行修改&lt;/li&gt;
&lt;li&gt;如果还想同步Gitlab上诸如Wiki等文档类页面，则需要额外的手段进行&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;解决过程及思考&lt;span class="hx:absolute hx:-mt-20" id="解决过程及思考"&gt;&lt;/span&gt;
&lt;a href="#%e8%a7%a3%e5%86%b3%e8%bf%87%e7%a8%8b%e5%8f%8a%e6%80%9d%e8%80%83" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;基于以上几点考虑，期望寻求一种自动化手段解决该问题，争取实现零运维的效果。&lt;/p&gt;
&lt;h3&gt;方案一：利用Gitlab原生机制&lt;span class="hx:absolute hx:-mt-20" id="方案一利用gitlab原生机制"&gt;&lt;/span&gt;
&lt;a href="#%e6%96%b9%e6%a1%88%e4%b8%80%e5%88%a9%e7%94%a8gitlab%e5%8e%9f%e7%94%9f%e6%9c%ba%e5%88%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在Gitlab中提供了一种仓库(projects)级别的同步方式，具体配置如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;进入仓库的的Settings，点击Repository&lt;/li&gt;
&lt;li&gt;打开Mirroring repositories&lt;/li&gt;
&lt;li&gt;配置目标仓库地址及同步方式&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2022-02-14-14-10-21.png" alt="2022-02-14-14-10-21" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;在开源版本中，只支持Push方式，而商业版本则支持Push和Pull两种方式。这个功能的优势是实时性，每当有代码提交后，则自动触发同步，避免了不必要的负载。&lt;/p&gt;
&lt;p&gt;但是遗憾的是，在本地进行了测试时，只显示正在同步，但是一直没有同步成功，也没有给出具体的任务状态或失败原因。同时，并没有在组级别上提供同步能力，每次新增项目时，仍然需要手动在源端和目标端进行频繁操作，维护成本较高，所以最终放弃了该方案。&lt;/p&gt;
&lt;h3&gt;方案二：开源项目&lt;span class="hx:absolute hx:-mt-20" id="方案二开源项目"&gt;&lt;/span&gt;
&lt;a href="#%e6%96%b9%e6%a1%88%e4%ba%8c%e5%bc%80%e6%ba%90%e9%a1%b9%e7%9b%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在放弃第一个解决方案后，开始在Github上寻找开源项目。有一个基于Shell开发的gitlab-mirrors的项目引起了我的关注，这个项目由多个shell脚本组成。目标端支持除gitlab之外的多种Git仓库，看起来可以满足我们的需要。但是经过调研，发现gitlab-mirrors是以project为单位，无法按照组级别进行同步，所以也无法满足我们的需要。经过多番搜索，并没有一个项目能够百分之百满足我们组级别同步备份需求的项目。&lt;/p&gt;
&lt;h3&gt;方案三：自主实现自动化流程&lt;span class="hx:absolute hx:-mt-20" id="方案三自主实现自动化流程"&gt;&lt;/span&gt;
&lt;a href="#%e6%96%b9%e6%a1%88%e4%b8%89%e8%87%aa%e4%b8%bb%e5%ae%9e%e7%8e%b0%e8%87%aa%e5%8a%a8%e5%8c%96%e6%b5%81%e7%a8%8b" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;由于以上两种方式均无法满足需求，所以决定基于Gitlab开放的Python库进行二次开发，满足需求。基本的思路为：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在源端获取待同步组内的所有项目、子组&lt;/li&gt;
&lt;li&gt;克隆代码、所有分支、tags&lt;/li&gt;
&lt;li&gt;判断目标端Gitlab是否存在该组或者项目，如果没有则创建&lt;/li&gt;
&lt;li&gt;Push代码、分支、tags&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在满足了以上需求后，需要定期执行脚本实现周期性增量同步，那么如何利用Docker实现最简单的部署呢？所以需求进一步更新为：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;构建一个容器，该容器能够支持定期执行同步任务&lt;/li&gt;
&lt;li&gt;容器要利用系统的crontab，支持灵活配置&lt;/li&gt;
&lt;li&gt;任务在执行时要避免重复执行&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;基于以上需求，我开发了gitlab-sync脚本及容器(&lt;a href="https://github.com/xiaoquqi/gitlab-sync"target="_blank" rel="noopener"&gt;https://github.com/xiaoquqi/gitlab-sync&lt;/a&gt;)，改代码已经上传到github中，以下就为大家介绍详细的使用方法。&lt;/p&gt;
&lt;h2&gt;使用方法&lt;span class="hx:absolute hx:-mt-20" id="使用方法"&gt;&lt;/span&gt;
&lt;a href="#%e4%bd%bf%e7%94%a8%e6%96%b9%e6%b3%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;通过以下配置，你可以轻松完成从Gitlab A中的Group A周期同步至Gitlab B中的Group B中。&lt;/p&gt;
&lt;h3&gt;前提条件&lt;span class="hx:absolute hx:-mt-20" id="前提条件"&gt;&lt;/span&gt;
&lt;a href="#%e5%89%8d%e6%8f%90%e6%9d%a1%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在开始配置gitlab-sync前，以下信息是必须提前获取的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LOCAL_GTILAB_URL: 源端的Gitlab的WEB地址及端口&lt;/li&gt;
&lt;li&gt;LOCAL_GITLAB_TOKEN: 源端Gitlab的Token，需要读取的权限&lt;/li&gt;
&lt;li&gt;LOCAL_GITLAB_GROUP: 源端Gitlab待同步的组，该组下所有项目及后续新增项目都会自动同步到目标端&lt;/li&gt;
&lt;li&gt;REMOTE_GTILAB_URL: 目标端Gitlab的WEB地址及端口&lt;/li&gt;
&lt;li&gt;REMOTE_GTILAB_TOKEN: 目标端Gitlab的Token，需要读取和写入权限&lt;/li&gt;
&lt;li&gt;REMOTE_GTILAB_GROUP: 目标端的组，可以与源端不一样&lt;/li&gt;
&lt;li&gt;REMOTE_GTILAB_PUSH_URL: 目标端Push地址，用于作为git push的目标端&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;除了这些信息外，Docker启动会默认将$HOME/.ssh路径挂载至容器内，所以需要你的key已经加入到源端和目标端的Gitlab中，以保证正确的Clone和Push的操作。&lt;/p&gt;
&lt;h3&gt;获取代码及配置&lt;span class="hx:absolute hx:-mt-20" id="获取代码及配置"&gt;&lt;/span&gt;
&lt;a href="#%e8%8e%b7%e5%8f%96%e4%bb%a3%e7%a0%81%e5%8f%8a%e9%85%8d%e7%bd%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在代码中，提供了docker-compose.yml文件，可以直接使用。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;git clone https://github.com/xiaoquqi/gitlab-sync
cd gitlab-sync
cp env.sample .env
cp crontab/cron.exmaple crontab/cron&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;在.env文件中，根据提前准备好的变量进行配置&lt;/li&gt;
&lt;li&gt;cron是crontab的配置文件，根据需求设定周期同步策略，后面的命令行不建议修改，其中flock是为了避免任务被重复运行&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;启动同步&lt;span class="hx:absolute hx:-mt-20" id="启动同步"&gt;&lt;/span&gt;
&lt;a href="#%e5%90%af%e5%8a%a8%e5%90%8c%e6%ad%a5" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;完成配置后，启动容器开始同步。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;docker-compose up -d&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;可以在Host主机的/var/log/gitlab-sync/gitlab-sync.log获取执行过程中的日志。&lt;/p&gt;
&lt;h2&gt;总结&lt;span class="hx:absolute hx:-mt-20" id="总结"&gt;&lt;/span&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在整个过程中，原本是想以脚本方式做最简单的处理，但是考虑到了后期运维成本等问题，最终决定考虑一种全自动化方式进行运维。&lt;/p&gt;
&lt;p&gt;在处理容器运行crontab时，遇到用户环境变量无法获取的问题，目前采用的一种方式是一种Work Around，在容器启动后，将当前用户环境变量Dump到根分区下固定文件，在执行period_task.sh脚本中去加载这个脚本，从而获取环境变量。如果有更好的方法进行优化，欢迎提交Pull Request。&lt;/p&gt;
&lt;p&gt;如果大家在使用过程中有任何问题，欢迎反馈，我会持续优化代码。&lt;/p&gt;</description></item><item><title>Chrome插件Automa应用(一)——自动化测试</title><link>https://sunqi.site/blog/%E5%88%A9%E7%94%A8chrome%E6%8F%92%E4%BB%B6automa%E8%BF%9B%E8%A1%8C%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95/</link><pubDate>Wed, 01 Dec 2021 22:53:06 +0800</pubDate><guid>https://sunqi.site/blog/%E5%88%A9%E7%94%A8chrome%E6%8F%92%E4%BB%B6automa%E8%BF%9B%E8%A1%8C%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95/</guid><description>
&lt;p&gt;上周的时候，郑伟突然给我过来一个有意思的开源项目（https://github.com/Kholid060/automa）。这是一个Chrome插件项目，起初并没有看懂这个插件的作用，但是随着深入了解，发现这个插件的功能太强大了，简直就是一个可视化版本的Selenium，在很多场景下都可以应用。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;应用场景&lt;span class="hx:absolute hx:-mt-20" id="应用场景"&gt;&lt;/span&gt;
&lt;a href="#%e5%ba%94%e7%94%a8%e5%9c%ba%e6%99%af" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;自动化测试：这是我首先想到的场景，通过自动化手段，构建多个自动化测试用例，运行后可以通过截图或者值判断，来判断测试用例的执行情况&lt;/li&gt;
&lt;li&gt;爬虫：现在各大网站对爬虫严防死守，通过浏览器插件的方式最大程度模拟人为操作行为，通过网页方式来爬取数据&lt;/li&gt;
&lt;li&gt;薅羊毛：这也是这个插件特别有用的场景，比如：某些网站的每天签到任务可以通过插件定时执行方式完成，再比如刷票的场景，都能通过这个插件轻松定制完成&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;插件使用方法介绍&lt;span class="hx:absolute hx:-mt-20" id="插件使用方法介绍"&gt;&lt;/span&gt;
&lt;a href="#%e6%8f%92%e4%bb%b6%e4%bd%bf%e7%94%a8%e6%96%b9%e6%b3%95%e4%bb%8b%e7%bb%8d" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;至于如何在Chrome安装这个插件，这里就不多介绍了，反正我是从Chrome的应用市场安装的，具体原因你懂得。&lt;/p&gt;</description></item><item><title>将博客从Hexo迁移至Hugo</title><link>https://sunqi.site/blog/migrate-from-hexo-to-hugo/</link><pubDate>Mon, 29 Nov 2021 20:23:54 +0800</pubDate><guid>https://sunqi.site/blog/migrate-from-hexo-to-hugo/</guid><description>
&lt;p&gt;自从了解了Github Pages这种静态博客后，开始喜欢上这种技术人员才能鼓捣明白的协作方式。自己的博客系统也从最初的Octopress，切换到Hexo，直到最近看到Hugo这种号称全球最快的静态博客系统，被适合技术人员的风格样式所吸引。于是在经历了三天的折腾后，顺利的将Hexo迁移至Hugo中。同时，利用github workflows在提交后，将博客自动发布到腾讯的云开发中。其实这三种不同的博客系统也恰好了代表了每一个时代流行的语言，Octopress(Ruby)，Hexo(Node.js)，Hugo(Go)。时代在发展社会在进步，唯一不变的是开发人员追去完美的心，记录下这一过程，也作为切换至Hugo后的第一篇博文。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;安装Hugo&lt;span class="hx:absolute hx:-mt-20" id="安装hugo"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85hugo" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;因为Hugo是Go语言开发的，所以安装起来比较简单，不过在我的Mac上，我最终还是选择brew方式进行安装。由于之前运行的brew是x86版本的，为了安装Hugo也对brew重新进行了安装。brew配置好了之后，直接安装命令即可。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;brew install hugo&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;后续的流程相对简单，根据Hugo官网的Quick Start按照步骤即可。&lt;/p&gt;
&lt;h3&gt;创建站点&lt;span class="hx:absolute hx:-mt-20" id="创建站点"&gt;&lt;/span&gt;
&lt;a href="#%e5%88%9b%e5%bb%ba%e7%ab%99%e7%82%b9" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;hugo new site quickstart&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;添加一个主题&lt;span class="hx:absolute hx:-mt-20" id="添加一个主题"&gt;&lt;/span&gt;
&lt;a href="#%e6%b7%bb%e5%8a%a0%e4%b8%80%e4%b8%aa%e4%b8%bb%e9%a2%98" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;经过对比，我选择了相对低调、灵活的LoveIt作为博客主题。这个主题非常灵活，基本把要预留的内容都留出来了，所以不需要将themes中的文件存放于博客版本库中，只需要以submodule形式存在即可。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;cd quickstart
git init
git submodule add https://github.com/dillonzq/LoveIt themes/LoveIt&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;配置Hugo&lt;span class="hx:absolute hx:-mt-20" id="配置hugo"&gt;&lt;/span&gt;
&lt;a href="#%e9%85%8d%e7%bd%aehugo" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Hugo每个主题都会有一个exampleSite的目录，比如LoveIt，就是在themes/LoveIt/exampleSite。这里面存放了主题配置的基本样例，我们至少需要将config.toml拷贝至你的Blog根目录，之后就可以进行配置了。其他资源文件可以视实际需要拷贝至相应的目录中。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;.
├── assets
│   ├── css
│   ├── images
│   └── music
├── config.toml
├── content
│   ├── about
│   ├── categories
│   ├── posts
│   └── tags
└── static
├── _redirects
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── apple-touch-icon.png
├── browserconfig.xml
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon.ico
├── mstile-150x150.png
├── safari-pinned-tab.svg
└── site.webmanifest&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;在配置文件中，有比较详细的中文注释，根据实际内容进行调整就可以了，我删除掉了英语和法语部分的配置，其他配置按照我的实际需要进行了配置。由于配置内容过多，这里就不一一列举了，这里面只把一些特殊的选项和大家分享一下。&lt;/p&gt;
&lt;h3&gt;如何配置百度统计？&lt;span class="hx:absolute hx:-mt-20" id="如何配置百度统计"&gt;&lt;/span&gt;
&lt;a href="#%e5%a6%82%e4%bd%95%e9%85%8d%e7%bd%ae%e7%99%be%e5%ba%a6%e7%bb%9f%e8%ae%a1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在params.footer中保留了一个custom的参数，只需要将百度统计写入其中就可以，例如：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;[params.footer]
......
custom = &amp;#39;&amp;lt;script&amp;gt; var _hmt = _hmt || []; (function() { var hm = document.createElement(&amp;#34;script&amp;#34;); hm.src = &amp;#34;https://hm.baidu.com/hm.js?08e49a207e75eef254a959d4b9dede90&amp;#34;; var s = document.getElementsByTagName(&amp;#34;script&amp;#34;)[0]; s.parentNode.insertBefore(hm, s); })(); &amp;lt;/script&amp;gt;&amp;lt;script async src=&amp;#34;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3492265208608388&amp;#34; crossorigin=&amp;#34;anonymous&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;&amp;#39;
......&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;如何配置ICP及备案信息？&lt;span class="hx:absolute hx:-mt-20" id="如何配置icp及备案信息"&gt;&lt;/span&gt;
&lt;a href="#%e5%a6%82%e4%bd%95%e9%85%8d%e7%bd%aeicp%e5%8f%8a%e5%a4%87%e6%a1%88%e4%bf%a1%e6%81%af" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;仍然在params.footer中保留了一个icp参数，只需要将备案信息写入其中即可，例如：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;[params.footer]
......
icp = &amp;#39;&amp;lt;br /&amp;gt;&amp;lt;a target=&amp;#34;_blank&amp;#34; href=&amp;#34;http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=11010502042680&amp;#34; style=&amp;#34;display:inline-block;text-decoration:none;height:20px;line-height:20px;&amp;#34;&amp;gt;&amp;lt;img src=&amp;#34;/images/beian.png&amp;#34; style=&amp;#34;float:left;&amp;#34;/&amp;gt;京公网安备 11010502042680号&amp;lt;/a&amp;gt; | &amp;lt;a target=&amp;#34;_blank&amp;#34; href=&amp;#34;https://beian.miit.gov.cn/&amp;#34;&amp;gt;京ICP备2020039231号-1&amp;lt;/a&amp;gt;&amp;#39;
......&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;从Hexo迁移至Hugo&lt;span class="hx:absolute hx:-mt-20" id="从hexo迁移至hugo"&gt;&lt;/span&gt;
&lt;a href="#%e4%bb%8ehexo%e8%bf%81%e7%a7%bb%e8%87%b3hugo" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;因为Hexo本质上也是使用Markdown方式进行管理，所以迁移上也比较方便，但是由于每个人遇到的问题并不相同，所以这里分享一下我自己遇到的实际问题。&lt;/p&gt;
&lt;h3&gt;如何迁移？&lt;span class="hx:absolute hx:-mt-20" id="如何迁移"&gt;&lt;/span&gt;
&lt;a href="#%e5%a6%82%e4%bd%95%e8%bf%81%e7%a7%bb" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是我在Hexo中的文档目录&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;|-- source
| |-- _drafts -&amp;gt; 草稿目录，在Hugo中是通过模板中的draft参数控制，可以先拷贝至Hugo /content/posts目录中
| |-- _posts -&amp;gt; 文章目录，拷贝至/content/posts目录中
| |-- about -&amp;gt; 关于目录，拷贝至/content/about目录中
| |-- favicon.ico -&amp;gt; 浏览器favorite icon图标
| `-- images -&amp;gt; 静态文件，拷贝至/static/images目录中&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;文章结构&lt;span class="hx:absolute hx:-mt-20" id="文章结构"&gt;&lt;/span&gt;
&lt;a href="#%e6%96%87%e7%ab%a0%e7%bb%93%e6%9e%84" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;之前在编写Hexo时候，使用了Hexo Admin插件，不知道为什么生成的文章是这个样子的：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;title: &amp;#34;将博客从Hexo迁移至Hexo&amp;#34;
date: 2021-11-29T20:23:54&amp;#43;08:00
---&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;由于缺少了顶部的&amp;mdash;，导致Hugo无法正确识别标题和创建时间。于是用Python写了一个简单的脚本进行替换。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;import glob
import re
files = glob.glob(&amp;#34;../content/posts/*&amp;#34;)
for f in files:
with open(f, &amp;#34;r&amp;#34;) as rfhd:
lines = rfhd.readlines()
first_line = lines[0].strip()
if not first_line == &amp;#34;---&amp;#34;:
print(f)
lines.insert(0, &amp;#34;---\n&amp;#34;)
with open(f, &amp;#34;w&amp;#43;&amp;#34;) as wfhd:
wfhd.writelines(lines)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;部分图片无法显示&lt;span class="hx:absolute hx:-mt-20" id="部分图片无法显示"&gt;&lt;/span&gt;
&lt;a href="#%e9%83%a8%e5%88%86%e5%9b%be%e7%89%87%e6%97%a0%e6%b3%95%e6%98%be%e7%a4%ba" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在我早期写的博客中，我使用了{% img &amp;hellip;}来引用图片，但是这种方式在Hugo中是无法正确显示的。于是仍然使用Python脚本进行了全局性替换。由于只是作为临时替换，所以在代码规范性上差了一点，但是能解决我的问题了。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;for f in files:
with open(f, &amp;#34;r&amp;#34;) as rfhd:
lines = rfhd.readlines()
for index, line in enumerate(lines):
line = line.strip()
if re.match(r&amp;#34;{\s*%\s*img&amp;#34;, line):
print(&amp;#34;Found line:&amp;#34;, line)
image_path = None
m1 = re.match(r&amp;#34;{\s*%\s*img\s*(\/images\/[-A-Za-z0-9&amp;#43;&amp;amp;@#/%?=~_|!:,.;]&amp;#43;)\s&amp;#43;&amp;#34;, line)
if m1:
image_path = m1.group(1)
print(m1.group(1))
m2 = re.match(r&amp;#34;{\s*%\s*img\s&amp;#43;\w&amp;#43;\s&amp;#43;(\/images\/[-A-Za-z0-9&amp;#43;&amp;amp;@#/%?=~_|!:,.;]&amp;#43;)\s&amp;#43;&amp;#34;, line)
if m2:
image_path = m2.group(1)
print(m2.group(1))
new_image_path = &amp;#34;![](%s)\n&amp;#34; % image_path
print(new_image_path)
lines[index] = new_image_path
print(lines)
with open(f, &amp;#34;w&amp;#43;&amp;#34;) as wfhd:
wfhd.writelines(lines)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;目录结构问题&lt;span class="hx:absolute hx:-mt-20" id="目录结构问题"&gt;&lt;/span&gt;
&lt;a href="#%e7%9b%ae%e5%bd%95%e7%bb%93%e6%9e%84%e9%97%ae%e9%a2%98" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在我完成了以上两步后，发现我的部分文章中的右侧目录显示不够完整，正常的显示逻辑应该是这样的效果。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2021-11-30-10-00-24.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;我发现我的文章中一级标题都没有显示，经过调查，发现之前存在一个误区，在一篇文档中，其实title部分才是一级标题，正常文章中的标题要从二级写起，这样目录才能正常生成出来。这意味着，我需要将原有文档中不规范的标题都加一个#才可以，所以仍然采用Python批量替换方式完成。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;for f in files:
with open(f, &amp;#34;r&amp;#34;) as rfhd:
lines = rfhd.readlines()
print(&amp;#34;Reading file:&amp;#34;, f)
# If we need to do replace in the file
if_replace = False
# In code area, ignore start #
if_code_start = False
for index, line in enumerate(lines):
if re.match(r&amp;#34;^\s*```&amp;#34;, line):
if_code_start = not if_code_start
print(&amp;#34;if code start: [%s]%s&amp;#34; % (index, if_code_start))
if re.match(r&amp;#34;^\s*#\s&amp;#43;\S&amp;#43;&amp;#34;, line):
if not if_code_start:
if_replace = True
print(&amp;#34;if file need to replace: %s&amp;#34; % if_replace)
if re.match(r&amp;#34;^\s*#&amp;#34;, line) and if_replace:
print(&amp;#34;Orig replace line is: %s&amp;#34; % line)
print(&amp;#34;Will replace line to: #%s&amp;#34; % line)
lines[index] = &amp;#34;#%s&amp;#34; % line
with open(f, &amp;#34;w&amp;#43;&amp;#34;) as wfhd:
wfhd.writelines(lines)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;至此，所有的文章已经能够在Hugo中按照顺序显示了。&lt;/p&gt;
&lt;h3&gt;保持链接格式&lt;span class="hx:absolute hx:-mt-20" id="保持链接格式"&gt;&lt;/span&gt;
&lt;a href="#%e4%bf%9d%e6%8c%81%e9%93%be%e6%8e%a5%e6%a0%bc%e5%bc%8f" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在原有Hexo中，文章基本是按照时间格式进行命名，例如/year/month/day/title方式，但是在Hugo默认的方式中则是采用了直接命名的方式，这就需要我们在配置中进行修改，以达到上线后和原有链接保持一致的效果。在config.toml中修改如下内容：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;[permalinks]
# posts = &amp;#34;:year/:month/:filename&amp;#34;
posts = &amp;#34;/:year/:month/:day/:slug/&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;利用Github Action自动上线&lt;span class="hx:absolute hx:-mt-20" id="利用github-action自动上线"&gt;&lt;/span&gt;
&lt;a href="#%e5%88%a9%e7%94%a8github-action%e8%87%aa%e5%8a%a8%e4%b8%8a%e7%ba%bf" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;配置到了这里，基本具备了上线条件，之前我在Github上使用了Travis CI方式进行编译上线，但是随着Github Workflow越来越成熟，所以这次决定采用Github方式进行部署。由于Github Pages在国内访问越来越慢，大概在前年将博客迁移至腾讯的云开发中。腾讯默认提供的云开发Action不太好用，于是我还是用执行命令方式完成，以下是我的github workflow yaml，供大家参考。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;name: Deploy to Tecent Cloudbase # 名字自取
on:
push:
branches:
- master # 这里的意思是当 main分支发生push的时候，运行下面的jobs，这里先改为github-actions
jobs:
deploy: # 任务名自取
runs-on: ubuntu-18.04 # 在什么环境运行任务
steps:
- uses: actions/checkout@v2 # 引用actions/checkout这个action，与所在的github仓库同名
with:
submodules: true # Fetch Hugo themes (true OR recursive) 获取submodule主题
fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod
- name: Setup Hugo # 步骤名自取
uses: peaceiris/actions-hugo@v2 # hugo官方提供的action，用于在任务环境中获取hugo
with:
hugo-version: &amp;#39;latest&amp;#39; # 获取最新版本的hugo
# extended: true
- name: Build
run: hugo --minify # 使用hugo构建静态网页
- uses: actions/setup-node@v2
with:
node-version: &amp;#39;14&amp;#39;
- run: npm i -g @cloudbase/cli
- run: tcb login --apiKeyId ${{secrets.secretId}} --apiKey ${{secrets.secretKey}}
- run: cd public &amp;amp;&amp;amp; tcb hosting deploy -e ${{secrets.envId}} --verbose&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;需要替换的secrets变量，需要在Github中进行创建。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2021-11-30-10-13-55.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;添加评论系统&lt;span class="hx:absolute hx:-mt-20" id="添加评论系统"&gt;&lt;/span&gt;
&lt;a href="#%e6%b7%bb%e5%8a%a0%e8%af%84%e8%ae%ba%e7%b3%bb%e7%bb%9f" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;LoveIt主题中支持多种评论系统，最终我使用的是valine，不过需要注册一个LeanCloud账号，建立一个开发板的应用程序后，再更新配置文件才行。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2021-11-30-13-21-40.png" alt="Lean Cloud" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;建立好应用后，在应用详情中找到”应用凭证“，获取相关鉴权信息。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2021-11-30-13-24-01.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;最后在Hugo config.toml中进行更新&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;[params.page.comment.valine]
enable = true
appId = &amp;#34;your_appId&amp;#34;
appKey = &amp;#34;your_appKey&amp;#34;
......
serverURLs = &amp;#34;https://your_leancloud_url&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;配置好的效果如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2021-11-30-13-28-35.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;总结&lt;span class="hx:absolute hx:-mt-20" id="总结"&gt;&lt;/span&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;其实Hugo LoveIt中还提供了很多功能，暂未深入研究，也欢迎大家共同交流。&lt;/p&gt;
&lt;p&gt;到这里，我的全新Hugo样式的Blog已经发布上线，这是整体的效果，也欢迎大家经常访问我的博客——老孙正经胡说（https://sunqi.site）。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/2021-11-30-10-15-29.png" alt="" loading="lazy" /&gt;&lt;/p&gt;</description></item><item><title>如何在苹果日历订阅钉钉日历？</title><link>https://sunqi.site/blog/%E5%A6%82%E4%BD%95%E5%9C%A8%E8%8B%B9%E6%9E%9C%E6%97%A5%E5%8E%86%E8%AE%A2%E9%98%85%E9%92%89%E9%92%89%E6%97%A5%E5%8E%86/</link><pubDate>Thu, 11 Nov 2021 10:03:10 +0000</pubDate><guid>https://sunqi.site/blog/%E5%A6%82%E4%BD%95%E5%9C%A8%E8%8B%B9%E6%9E%9C%E6%97%A5%E5%8E%86%E8%AE%A2%E9%98%85%E9%92%89%E9%92%89%E6%97%A5%E5%8E%86/</guid><description>
&lt;p&gt;通常我会使用苹果日历来管理我的所有行程，这样在不同苹果设备上就能实现互联互通，大多数的软件通过日历订阅或者CalDAV方式提供了对苹果日历的支持。很多公司开始使用钉钉作为自己的企业级IM工具，但是钉钉自带的日历却无法显示在苹果日历中，只能反向的由钉钉显示苹果日历的内容，非常不方便。今天无意间发现，钉钉的日历可以支持CalDAV方式了，所以赶紧在苹果的设备上进行了测试，终于可以实现苹果同步钉钉的日程了，以下就为大家分享一下。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;从钉钉获取CalDAV的配置&lt;span class="hx:absolute hx:-mt-20" id="从钉钉获取caldav的配置"&gt;&lt;/span&gt;
&lt;a href="#%e4%bb%8e%e9%92%89%e9%92%89%e8%8e%b7%e5%8f%96caldav%e7%9a%84%e9%85%8d%e7%bd%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;进入钉钉后，打开日历，进入设置。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-272.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;这里的用户名、密码和地址等信息需要复制到后面的苹果日历中。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-273.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;在手机日历中添加CalDAV&lt;span class="hx:absolute hx:-mt-20" id="在手机日历中添加caldav"&gt;&lt;/span&gt;
&lt;a href="#%e5%9c%a8%e6%89%8b%e6%9c%ba%e6%97%a5%e5%8e%86%e4%b8%ad%e6%b7%bb%e5%8a%a0caldav" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;进入手机设置，进入日历，添加账户。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-274.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;选择其他中，添加日历CalDAV账户。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-275.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;配置完成后，就应该能够从系统日历中看到钉钉的日历了。&lt;/p&gt;
&lt;h2&gt;在Mac上添加CalDAV&lt;span class="hx:absolute hx:-mt-20" id="在mac上添加caldav"&gt;&lt;/span&gt;
&lt;a href="#%e5%9c%a8mac%e4%b8%8a%e6%b7%bb%e5%8a%a0caldav" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;通过这种方式添加CalDAV无法在苹果设备之间进行同步，如果需要Mac侧也受到相关信息，还需要单独进行配置。&lt;/p&gt;
&lt;p&gt;在Mac上打开日历，在日历菜单中，点击“账户”，进入后右侧划到最下面，点击“添加其他账户&amp;hellip;”&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-278.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;类似在手机上的流程，选择添加CalDAV，添加钉钉的鉴权信息，就完成了添加。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-279.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;这是在日历显示的样子，如果你在钉钉还订阅了其他日历，也会自动通过这种方式同步过来显示，非常方便。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-277.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;</description></item><item><title>如何清理/boot分区下的内容?</title><link>https://sunqi.site/blog/%E5%A6%82%E4%BD%95%E6%B8%85%E7%90%86-boot%E5%88%86%E5%8C%BA%E4%B8%8B%E7%9A%84%E5%86%85%E5%AE%B9/</link><pubDate>Sat, 06 Nov 2021 16:26:51 +0000</pubDate><guid>https://sunqi.site/blog/%E5%A6%82%E4%BD%95%E6%B8%85%E7%90%86-boot%E5%88%86%E5%8C%BA%E4%B8%8B%E7%9A%84%E5%86%85%E5%AE%B9/</guid><description>
&lt;p&gt;CentOS运行时间长了，随着系统更新，/boot分区空间会越来越小，因为存留低版本内核相关文件没有得到及时清理，所以需要手动进行清理，但是由于内核文件重要性，如果清理方法不当就会导致系统无法启动。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;查询已经安装内核&lt;span class="hx:absolute hx:-mt-20" id="查询已经安装内核"&gt;&lt;/span&gt;
&lt;a href="#%e6%9f%a5%e8%af%a2%e5%b7%b2%e7%bb%8f%e5%ae%89%e8%a3%85%e5%86%85%e6%a0%b8" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;首先查询一下已经安装的内核信息。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;rpm -q kernel&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;例如得到如下列表：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;kernel-3.10.0-862.el7.x86_64
kernel-3.10.0-1062.4.3.el7.x86_64
kernel-3.10.0-1062.9.1.el7.x86_64&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;查询正在使用的内核&lt;span class="hx:absolute hx:-mt-20" id="查询正在使用的内核"&gt;&lt;/span&gt;
&lt;a href="#%e6%9f%a5%e8%af%a2%e6%ad%a3%e5%9c%a8%e4%bd%bf%e7%94%a8%e7%9a%84%e5%86%85%e6%a0%b8" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;uname -a&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;例如得到如下信息：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;Linux compute201 3.10.0-1062.4.3.el7.x86_64 #1 SMP Wed Nov 13 23:58:53 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;删除无用的内核&lt;span class="hx:absolute hx:-mt-20" id="删除无用的内核"&gt;&lt;/span&gt;
&lt;a href="#%e5%88%a0%e9%99%a4%e6%97%a0%e7%94%a8%e7%9a%84%e5%86%85%e6%a0%b8" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;rpm -e kernel-3.10.0-862.el7.x86_64
rpm -e kernel-3.10.0-1062.9.1.el7.x86_64&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>利用Tushare对一夜持股法进行回归验证</title><link>https://sunqi.site/blog/%E5%88%A9%E7%94%A8tushare%E5%AF%B9%E6%8A%96%E9%9F%B3%E8%82%A1%E7%A5%A8%E6%8A%95%E8%B5%84%E6%96%B9%E6%B3%95%E8%BF%9B%E8%A1%8C%E5%9B%9E%E5%BD%92%E9%AA%8C%E8%AF%81/</link><pubDate>Thu, 01 Jul 2021 18:23:09 +0000</pubDate><guid>https://sunqi.site/blog/%E5%88%A9%E7%94%A8tushare%E5%AF%B9%E6%8A%96%E9%9F%B3%E8%82%A1%E7%A5%A8%E6%8A%95%E8%B5%84%E6%96%B9%E6%B3%95%E8%BF%9B%E8%A1%8C%E5%9B%9E%E5%BD%92%E9%AA%8C%E8%AF%81/</guid><description>
&lt;p&gt;最近在抖音看到很多金融博主在推荐一些投资股票的心得，可以说是五花八门，再看评论区，更是千奇百怪，大部分人都在说没用，但又拿不出什么证据来。事实是检验真理的唯一标准，我觉得对于此类投资观点，最好的方式进行用历史数据去验证，因为历史总是重复的，如果是对的，那么对于未来的投资也算是找到了一条生财之道。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;关于一夜持股法&lt;span class="hx:absolute hx:-mt-20" id="关于一夜持股法"&gt;&lt;/span&gt;
&lt;a href="#%e5%85%b3%e4%ba%8e%e4%b8%80%e5%a4%9c%e6%8c%81%e8%82%a1%e6%b3%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;简单来说，一夜持股法是利用两天之间的追涨来获取收益，即第一天尾盘买入股票，第二天趁着涨势再卖掉，降低盘中震荡对于价格的冲击，如此反复操作，获取收益。&lt;/p&gt;
&lt;p&gt;在原文视频中，作者给出了这种操作的八个条件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在收盘前，即下午2点半左右看盘&lt;/li&gt;
&lt;li&gt;在当天的股票中，利用软件筛选出涨幅在3%-5%的股票&lt;/li&gt;
&lt;li&gt;再根据量比排名，找出大于1的股票&lt;/li&gt;
&lt;li&gt;再根据换手率排名，选出换手率在5%-10%的股票，换手率太高可能有庄家出货嫌疑，换手率太低第二天缺乏上攻的动力&lt;/li&gt;
&lt;li&gt;再根据流通盘排名，筛选出50亿-200亿之间的股票，股票流通盘太大，拉动需要大量资金&lt;/li&gt;
&lt;li&gt;查看K线图，删除成交量忽高忽低的，只留下成交量持续放大的股票&lt;/li&gt;
&lt;li&gt;观察K线形态，如果在重要均线下方，或者近期冲高回落有套牢盘的全部删掉，只留下K线上方没有任何压力的，第二天冲高概率才大&lt;/li&gt;
&lt;li&gt;观察当天分时图，股价全天必须在分时图均线价格上方，那么意味着所有人都吃到了涨幅，第二天冲高有动力；股票价格必须要强于当天的大盘分时图，选择逆势而上的强势股&lt;/li&gt;
&lt;li&gt;均线在下午2点半左右，创出新高，股价回落均线&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;分析&lt;span class="hx:absolute hx:-mt-20" id="分析"&gt;&lt;/span&gt;
&lt;a href="#%e5%88%86%e6%9e%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;看到以上八个苛刻的条件，可能大部分还没找到股票，当天交易估计就结束了，别说交易了。说实话我刚看到这个视频时候，也是将信将疑，所以决定用程序对过去一年的历史数据进行校验。如果有效，再通过程序实现一个自动化交易的算法，完成自动化交易。&lt;/p&gt;
&lt;h3&gt;数据源&lt;span class="hx:absolute hx:-mt-20" id="数据源"&gt;&lt;/span&gt;
&lt;a href="#%e6%95%b0%e6%8d%ae%e6%ba%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;首先我们来分析一下我们需要哪些数据源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;股票列表，包括涨幅、量比、换手率、流通盘&lt;/li&gt;
&lt;li&gt;股票K线数据，包括重要的均线&lt;/li&gt;
&lt;li&gt;股票分时图&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;回归验证&lt;span class="hx:absolute hx:-mt-20" id="回归验证"&gt;&lt;/span&gt;
&lt;a href="#%e5%9b%9e%e5%bd%92%e9%aa%8c%e8%af%81" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;我们主要针对2020年1月到2020年12月的数据，以及2021年上半年的数据进行回归交易，回归验证的流程为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我们假设有10万本金进行上述交易&lt;/li&gt;
&lt;li&gt;我们先根据上述条件进行股票过滤，如果当天能够筛选出股票，将资金平均分为3份，购买股票&lt;/li&gt;
&lt;li&gt;卖出策略有很多种，我们先采取最简单的策略进行回归，我们假定在第二天上午10点30分将股票全部卖出&lt;/li&gt;
&lt;li&gt;运行程序进行模拟，并计算总收益&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;实现方法&lt;span class="hx:absolute hx:-mt-20" id="实现方法"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%9e%e7%8e%b0%e6%96%b9%e6%b3%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;我们需要大量的历史交易数据，通过对网上资料的搜索，我发现tushare是目前提供最全的金融SDK，不仅仅是股票，还包括其他很多金融产品。tushare分为两个版本，一个为普通版本，一个为专业版本。普通版本虽然功能还能使用，但是逐步在废弃。专业版本是依靠积分机制来获取不同接口权限的，可以通过对社区贡献或者直接捐钱获取积分，不过这也不难理解，毕竟一个社区的良性发展需要资金支持。&lt;/p&gt;
&lt;p&gt;Tushare旧版本的文档在这里：http://tushare.org/fundamental.html
全新版本的文档在：https://waditu.com/document/1&lt;/p&gt;
&lt;p&gt;旧版本有很多接口已经废弃了，使用的时候会有提示。而新版本则需要先申请token，再进行使用，根据你的积分不同，你调用的接口和频度是不同的。同时tushare返回的格式直接就是pandas的DateFrame类型，可以直接进行排序或者过滤等数据操作，非常方便。目前对于一夜持股法的验证还在继续中，也欢迎有兴趣的同学参与。&lt;/p&gt;</description></item><item><title>利用阿里云Serverless Kubernetes构建任务运行环境</title><link>https://sunqi.site/blog/%E5%A6%82%E4%BD%95%E5%88%A9%E7%94%A8%E9%98%BF%E9%87%8C%E4%BA%91serverless-kubernetes%E6%9E%84%E5%BB%BA%E7%8E%AF%E5%A2%83/</link><pubDate>Thu, 27 May 2021 06:18:51 +0000</pubDate><guid>https://sunqi.site/blog/%E5%A6%82%E4%BD%95%E5%88%A9%E7%94%A8%E9%98%BF%E9%87%8C%E4%BA%91serverless-kubernetes%E6%9E%84%E5%BB%BA%E7%8E%AF%E5%A2%83/</guid><description>
&lt;p&gt;Kubernetes是容器编排首选平台，现在各大云商也都推出了自己的Kubernetes服务。但是搭建Kubernetes环境往往在初始节点上需要很多云主机支持，三个Master节点实现HA，三个Node作为计算节点，成本开销比较大。后来阿里云推出了部分托管版本的Kubernetes，即Master节点托管给阿里云，用户只需要根据需求创建Node节点，大大节省了开销。但是如果用户连Node节点都不想创建，希望做到真正的按需分配怎么办呢？那么，你可以使用阿里云基于容器平台ECI构建的全托管版本的Kubernetes，即Kubernetes Serverless版本。这种环境下，用户可以完全忽略Master和Node节点，你的所有服务都会自动运行在ECI容器实例中，而费用则根据你的容器实际运行的时间和存储占用收取。这种方式适合有限时间内的任务运行方式，大大节约计算资源费用支出。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;服务创建&lt;span class="hx:absolute hx:-mt-20" id="服务创建"&gt;&lt;/span&gt;
&lt;a href="#%e6%9c%8d%e5%8a%a1%e5%88%9b%e5%bb%ba" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在服务目录找到Serverless容器服务ASK，进入后创建集群。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-245.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;顶部选择创建ASK集群，这种才是不需要创建master和node节点的模式。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-246.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;根据提示选择地域、版本和网络等信息。目前Kubernetes版本支持1.20.4和1.18.8两个版本，可以根据实际情况选择。另外如果你的集群有访问外网的需求，需要在选择网络的时候，确保你的VPC绑定了NAT网关，并正确配置了路由规则。&lt;/p&gt;
&lt;p&gt;Serverless Kubernetes本身并不收取任何费用，都是通过调用的资源进行收费，在无使用的情况下，仅仅API Server使用的SLB会收取少量的费用，根据业务需求，适当选择SLB规格。如果需求不大，可以选择一个最小的。默认一天的价格大概在1.2元左右。另外，日志服务可以关闭掉，否则后期增长过快，也是一笔不小的开支。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-247.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;配置完成后，点击创建，等待完成后，和正常的Kubernetes环境一样使用。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-248.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;云商提供的Kubernetes所有操作都可以通过页面点击完成，即使你不会写yaml也可以使用这个集群。&lt;/p&gt;
&lt;h2&gt;存储创建&lt;span class="hx:absolute hx:-mt-20" id="存储创建"&gt;&lt;/span&gt;
&lt;a href="#%e5%ad%98%e5%82%a8%e5%88%9b%e5%bb%ba" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;使用Kubernetes时需要对存储管理需要有一个认知，这里我只按照需求场景来分析一下，我们在实际使用中往往涉及到两种类型的数据：静态数据（例如配置文件）和动态数据（应用使用过程中产生的数据）。&lt;/p&gt;
&lt;h3&gt;静态数据&lt;span class="hx:absolute hx:-mt-20" id="静态数据"&gt;&lt;/span&gt;
&lt;a href="#%e9%9d%99%e6%80%81%e6%95%b0%e6%8d%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;通常我使用“配置项”来对我的配置文件进行管理，配置项是一个键值对，最终在启动容器时，会以目录方式映射到容器内某个目录中。如果你对安全性有要求，还可以使用保密字典存放相关信息。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-249.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;动态数据&lt;span class="hx:absolute hx:-mt-20" id="动态数据"&gt;&lt;/span&gt;
&lt;a href="#%e5%8a%a8%e6%80%81%e6%95%b0%e6%8d%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;动态数据的管理通过“存储”目录进行配置，最终映射到容器内的存储叫存储声明，而存储声明的背后是存储卷(Persistent Volume)或者存储类(Storage Class)。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-250.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;这是Kubernetes官网对相关概念的诠释：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;StorageClass 为管理员提供了描述存储 &amp;ldquo;类&amp;rdquo; 的方法。 不同的类型可能会映射到不同的服务质量等级或备份策略，或是由集群管理员制定的任意策略。 Kubernetes 本身并不清楚各种类代表的什么。这个类的概念在其他存储系统中有时被称为 &amp;ldquo;配置文件&amp;rdquo;。&lt;/p&gt;
&lt;p&gt;持久卷（PersistentVolume，PV）是集群中的一块存储，可以由管理员事先供应，或者 使用存储类（Storage Class）来动态供应。 持久卷是集群资源，就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样，也是使用 卷插件来实现的，只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。 此 API 对象中记述了存储的实现细节，无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;后端存储可以支持多种类型，例如：云盘、NAS或者对象存储，如果使用存储类还可以支持Ceph RBD、GlusterFS。可以根据应用的特点选择后端存储类型。存储类的配置稍微复杂，所以这里直接使用NAS作为后端存储。&lt;/p&gt;
&lt;h4&gt;NAS服务配置&lt;span class="hx:absolute hx:-mt-20" id="nas服务配置"&gt;&lt;/span&gt;
&lt;a href="#nas%e6%9c%8d%e5%8a%a1%e9%85%8d%e7%bd%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;NAS按量付费的模式，非常适合存储空间动态变化较大的场景，如果能选择合适的资源包，能做到成本最优。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-251.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;NAS分为通用型和极速型，这里我们分别选择容量型和性能型。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-252.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h4&gt;存储卷配置&lt;span class="hx:absolute hx:-mt-20" id="存储卷配置"&gt;&lt;/span&gt;
&lt;a href="#%e5%ad%98%e5%82%a8%e5%8d%b7%e9%85%8d%e7%bd%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;回到Kubernetes存储管理中，创建存储卷，选择NAS，总量方面是指这个存储的可用量，默认通用型性能型NAS配额是1PB，而容量型是10PB，这里根据实际情况填写就可以了。另外需要选择挂载点信息。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-253.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;任务创建&lt;span class="hx:absolute hx:-mt-20" id="任务创建"&gt;&lt;/span&gt;
&lt;a href="#%e4%bb%bb%e5%8a%a1%e5%88%9b%e5%bb%ba" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;下面就可以正式启动容器了，这里之所以选择任务方式创建，是要有效的控制执行次数。当然这和你的业务类型有很大的关系。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-254.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;第一步是基本信息填写，没有太特殊的。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-255.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;第二步是主要配置，如果你的镜像仓库就是托管在阿里云容器服务内，建议使用vpc地址，这样避免产生不必要的流量。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-256.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;下面就是对于存储的配置，在我的conf中包含两个文件，一个是oss的连接信息，另外一个secret words文件。这样每次执行完成后，会自动的将文件上传至OSS中。&lt;/p&gt;
&lt;p&gt;另外选择我们刚刚配置的NAS存储。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-257.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;第三步可以控制并发运行的数量。比如，我们希望并行的执行10个任务，则成功运行Pod数和并行运行的Pod数都设置成10，超时时间根据实际应用情况可以设置长一些，重启策略设置为不重启。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-258.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;最后点击创建，任务就可以执行了。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-259.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;最后，通过点击任务详情，查看日志，查看任务详情。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-260.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;总结&lt;span class="hx:absolute hx:-mt-20" id="总结"&gt;&lt;/span&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;使用Kubernetes Serverless特别适合按需使用的任务场景，配合各种资源包，能够大幅度降低成本，同时做到高并发。相关代码已经托管到github上，有兴趣的朋友可以一起共同完善，我的github账号为xiaoquqi。&lt;/p&gt;</description></item><item><title>阿里云盘与网盘终于合并</title><link>https://sunqi.site/blog/%E9%98%BF%E9%87%8C%E4%BA%91%E7%9B%98%E4%B8%8E%E7%BD%91%E7%9B%98%E7%BB%88%E4%BA%8E%E5%90%88%E5%B9%B6/</link><pubDate>Sat, 13 Mar 2021 19:41:48 +0000</pubDate><guid>https://sunqi.site/blog/%E9%98%BF%E9%87%8C%E4%BA%91%E7%9B%98%E4%B8%8E%E7%BD%91%E7%9B%98%E7%BB%88%E4%BA%8E%E5%90%88%E5%B9%B6/</guid><description>
&lt;p&gt;之前曾经写过一篇《我需要什么样的网盘？》来介绍内测版本的阿里云盘和Teambition网盘，其中重点讲述了阿里云内测的网盘和云盘项目，今天得到了一个确切的消息，阿里云盘和Teambition网盘终将合并。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;目前阿里云盘开始公测，到3月17日之前都可以申请。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-214.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;目前登陆Teambiton后，会收到网盘合并的通知。登陆后，会弹出合并通知。同时，如果你同时是云盘和Teambition网盘测试用户，你将获得双倍容量即6TB。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-215.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;如果你在Teambition上存放数据，有几件事情需要关注一下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文件数量少：自行手动迁移&lt;/li&gt;
&lt;li&gt;文件数量多：如果目前已存储较多数据，也可申请使用我们提供的技术迁移服务。点击填写报名表，我们将在 10 个工作日内完成技术迁移，届时将以短信通知你。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;另外一个值得关注就是Teambition和阿里云盘未来之间的关系，从官方给出的解释来看，一些Teambition的特色功能例如圈点评论并不会同步到阿里云盘，而阿里云盘的相册备份等特色功能也不会同步到Teambition端，但是两个应用之间功能对齐已经在计划中。&lt;/p&gt;
&lt;p&gt;我早在上一篇软文实际上已经分析过这个问题，两个“同一公司的竞品”终于殊途同归，也算是大势所趋了。另外我还注意到阿里新的云盘图标并非阿里的传统颜色，而是近似蓝色的背景，白色的线条。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-216.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;另外，阿里云盘目前仍然不支持PC客户端，入口只有APP和网页部分，不过目前已经预留了客户端下载位置，应该很快就会发布了。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-217.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;APP方面，目前界面比较干净清爽，但是功能也偏少，目前并不支持百度云盘的分享功能。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-218.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;已经提供了基本的相册和视频备份功能（百度视频备份功能，如果是高清要收费，普通免费）和人脸识别分类功能。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-219.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-220.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;虽然功能尚不完善，相信随着用户使用量激增，作为企业存储最常用的功能，这款产品的快速迭代是很快的事情，同时未来也期待与钉钉之间的深度整合，让企业办公变得更完整。&lt;/p&gt;</description></item><item><title>关闭Mac系统开机启动音</title><link>https://sunqi.site/blog/%E5%85%B3%E9%97%ADmac%E7%B3%BB%E7%BB%9F%E5%BC%80%E6%9C%BA%E5%90%AF%E5%8A%A8%E9%9F%B3/</link><pubDate>Fri, 05 Mar 2021 07:31:00 +0000</pubDate><guid>https://sunqi.site/blog/%E5%85%B3%E9%97%ADmac%E7%B3%BB%E7%BB%9F%E5%BC%80%E6%9C%BA%E5%90%AF%E5%8A%A8%E9%9F%B3/</guid><description>
&lt;p&gt;不知道你是否和我有一样的困惑，宁静的早晨打开iMac，一声浑然天成的开机声响彻屋内。虽然以Mac系统稳定性来说不必关机，但是对于iMac这种没有电池的主机，我还是有定期关机的习惯，只不过开机声这个问题让我很困扰。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;Big Sur关闭开机音&lt;span class="hx:absolute hx:-mt-20" id="big-sur关闭开机音"&gt;&lt;/span&gt;
&lt;a href="#big-sur%e5%85%b3%e9%97%ad%e5%bc%80%e6%9c%ba%e9%9f%b3" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在macOS Big Sur 11或者以上版本中，可以直接通过系统菜单就将开机启动声音进行关闭，具体的设置路径如下：&lt;/p&gt;
&lt;p&gt;系统左上角 &amp;gt;【系统偏好设置】&amp;gt;【声音】&amp;gt;【声音效果】，取消【启动时播放声音】即可。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-206.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;低版本关闭开机音&lt;span class="hx:absolute hx:-mt-20" id="低版本关闭开机音"&gt;&lt;/span&gt;
&lt;a href="#%e4%bd%8e%e7%89%88%e6%9c%ac%e5%85%b3%e9%97%ad%e5%bc%80%e6%9c%ba%e9%9f%b3" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;那么对于低版本的Mac系统如何关闭声音呢，答案只能通过命令行的方式了。在【终端】中输入：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;sudo nvram StartupMute=%01&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;恢复开机音：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;sudo nvram StartupMute=%00&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>如何在Mac上控制独立应用的音量</title><link>https://sunqi.site/blog/%E5%A6%82%E4%BD%95%E5%9C%A8mac%E4%B8%8A%E6%8E%A7%E5%88%B6%E7%8B%AC%E7%AB%8B%E5%BA%94%E7%94%A8%E7%9A%84%E9%9F%B3%E9%87%8F/</link><pubDate>Thu, 04 Mar 2021 09:12:00 +0000</pubDate><guid>https://sunqi.site/blog/%E5%A6%82%E4%BD%95%E5%9C%A8mac%E4%B8%8A%E6%8E%A7%E5%88%B6%E7%8B%AC%E7%AB%8B%E5%BA%94%E7%94%A8%E7%9A%84%E9%9F%B3%E9%87%8F/</guid><description>
&lt;p&gt;我平时用Mac开会时，需要将音量调大的情况，但是有时候忘记打开了勿扰模式，导致其他应用在通知的时候声音也巨大，比如钉钉。那么如何在Mac是否有方法独立的控制每一个应用的音量呢？答案就是Background Music。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-202.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;关于Background Music&lt;span class="hx:absolute hx:-mt-20" id="关于background-music"&gt;&lt;/span&gt;
&lt;a href="#%e5%85%b3%e4%ba%8ebackground-music" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Background Music是一款纯开源软件，代码托管在Github上(&lt;a href="https://github.com/kyleneideck/BackgroundMusic"target="_blank" rel="noopener"&gt;https://github.com/kyleneideck/BackgroundMusic&lt;/a&gt;)。&lt;/p&gt;
&lt;p&gt;如下图所示，你可以针对每一个服务进行独立选择音量提示的范围，比如我就把钉钉静音了。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-203.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;安装&lt;span class="hx:absolute hx:-mt-20" id="安装"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;你可以尝试使用代码编译，当然最简单的就是下载打好包的pkg文件，直接安装即可，现在安装时候需要注意，如果你是Big Sur版本，需要下载的是预览版本。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bug Sur版本：https://github.com/kyleneideck/BackgroundMusic/releases/tag/0.4.0-SNAPSHOT-c0ab98b&lt;/li&gt;
&lt;li&gt;早期版本：https://github.com/kyleneideck/BackgroundMusic/releases/download/v0.3.2/BackgroundMusic-0.3.2.pkg&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;开机启动&lt;span class="hx:absolute hx:-mt-20" id="开机启动"&gt;&lt;/span&gt;
&lt;a href="#%e5%bc%80%e6%9c%ba%e5%90%af%e5%8a%a8" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;【系统偏好配置】-&amp;gt;【用于与群组】-&amp;gt;【登陆项】-&amp;gt;【添加】，从应用程序中选择Backgroud Music即可。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-204.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-205.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;</description></item><item><title>PostgreSQL无法启动“global/pg_control”：Permission denied</title><link>https://sunqi.site/blog/postgresql%E6%97%A0%E6%B3%95%E5%90%AF%E5%8A%A8global-pg-controlpermission-denied/</link><pubDate>Thu, 11 Feb 2021 08:44:00 +0000</pubDate><guid>https://sunqi.site/blog/postgresql%E6%97%A0%E6%B3%95%E5%90%AF%E5%8A%A8global-pg-controlpermission-denied/</guid><description>
&lt;p&gt;昨天在为用户进行迁移后，用户Windows 2012系统上PostgreSQL服务无法启动，日志中提示“global/pg_control”：Permission denied，于是上网一顿搜索终于解决了这个问题。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;检查&lt;span class="hx:absolute hx:-mt-20" id="检查"&gt;&lt;/span&gt;
&lt;a href="#%e6%a3%80%e6%9f%a5" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;如果端口没有被占用，那么你可以用PostgreSQL原生的命令启动它。进入postgresql安装路径下的 bin 文件夹，在这里打开命令行，执行下面的命令：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;.\pg_ctl start -D ..\data&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;如果程序报出如下错误：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;ERROR: could not open control file “global/pg_control”: Permission denied&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-159.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;则说明当前操作系统用户丢失了data文件夹及其内容的权限。&lt;/p&gt;
&lt;h2&gt;解决方案&lt;span class="hx:absolute hx:-mt-20" id="解决方案"&gt;&lt;/span&gt;
&lt;a href="#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;首先，进入postgresql 的安装路径，右键data文件夹，依次点击属性——安全——编辑，你能看到所有用户或用户组的权限。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-160.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;确保System 和 Administrator 拥有“完全控制”权限。Users 用户组默认只拥有“读取和执行”，“列出文件夹内容”和“读取”3种权限。当启动数据库提示“权限不足”时，应再添加“修改”和 “写入”。我这次出现问题就在这里，User没有修改和写入权限，添加后即可启动成功。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-161.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;ol start="3"&gt;
&lt;li&gt;保存并尝试再次在bin 文件夹下执行：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;.\pg_ctl start -D ..\data&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;观察PostgreSQL数据库能否启动。&lt;/p&gt;
&lt;h2&gt;参考链接&lt;span class="hx:absolute hx:-mt-20" id="参考链接"&gt;&lt;/span&gt;
&lt;a href="#%e5%8f%82%e8%80%83%e9%93%be%e6%8e%a5" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.csdn.net/international24/article/details/89710703"target="_blank" rel="noopener"&gt;https://blog.csdn.net/international24/article/details/89710703&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>利用腾讯云开发免费搭建个人博客</title><link>https://sunqi.site/blog/%E5%88%A9%E7%94%A8%E8%85%BE%E8%AE%AF%E4%BA%91%E5%BC%80%E5%8F%91%E5%85%8D%E8%B4%B9%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/</link><pubDate>Wed, 03 Feb 2021 07:03:00 +0000</pubDate><guid>https://sunqi.site/blog/%E5%88%A9%E7%94%A8%E8%85%BE%E8%AE%AF%E4%BA%91%E5%BC%80%E5%8F%91%E5%85%8D%E8%B4%B9%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/</guid><description>
&lt;p&gt;之前一直使用Github Pages搭建个人博客，随着Github访问越来越困难，个人博客国内访问速度越来越慢。之前也试过用cloudflare进行加速，但是收效甚微，所以才考虑将项目迁回到国内。一个偶然的机会，腾讯云开发进入我的视野，起因是他们的9.9元计划，不过后来由于我配置错误，这部分资源无法使用。但是经过研究，原来腾讯云开发提供了最基础的免费资源，恰好可以让我们搭建个人的Blog，经过将近一年多的使用过程中，非常好用，所以就记录下来，供大家参考。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;什么是腾讯云开发&lt;span class="hx:absolute hx:-mt-20" id="什么是腾讯云开发"&gt;&lt;/span&gt;
&lt;a href="#%e4%bb%80%e4%b9%88%e6%98%af%e8%85%be%e8%ae%af%e4%ba%91%e5%bc%80%e5%8f%91" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;腾讯云开发是我一种非常推崇的开发理念，简单来说就是将Serverless进行了进一步封装，为开发者提供了更便捷的开发体验。目前云开发将轻量级业务中常见的数据库、存储（包括文件存储、对象存储）、云函数（计算资源）、基础运维（告警、监控、日志）进行了整合，同时云开发与微信小程序之间有个非常紧密的整合，能够快速帮助微信小程序构建服务端程序，基本可以承载很多基于微信场景的业务开发，比如电商等应用的开发，并且基于这样的基础架构，支撑千万级并发的需要。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-126.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;目前腾讯云开发，主要在广州和上海区域提供服务。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-125.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;腾讯云开发目前提供用户可以创建一个免费的环境，其中包含了存储、数据库等免费资源，但是相对于博客场景，主要还是静态资源的托管，每个月有1GB的存储空间，和5GB/月的流量，如果资源不够还可以购买额外的资源包。&lt;/p&gt;
&lt;p&gt;更多的免费额度请参考https://cloud.tencent.com/document/product/876/47816&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-127.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;构建过程&lt;span class="hx:absolute hx:-mt-20" id="构建过程"&gt;&lt;/span&gt;
&lt;a href="#%e6%9e%84%e5%bb%ba%e8%bf%87%e7%a8%8b" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;先说一下整体的构建思路：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我们的博客源代码仍然托管在github上，这样不需要破坏现有逻辑&lt;/li&gt;
&lt;li&gt;如果你有自己的域名，最好申请备案，因为云开发在绑定域名的时候必须要求已备案的域名，但是如果你就不想备案，也有一个Work Around方法，就是通过cloudflare进行跳转的方式实现了，后面会简单介绍&lt;/li&gt;
&lt;li&gt;通过Travis CI自动构建，并上传至云开发中，这样就实现我们在提交代码后，自动进行博客发布的效果了&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;云开发购买&lt;span class="hx:absolute hx:-mt-20" id="云开发购买"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%91%e5%bc%80%e5%8f%91%e8%b4%ad%e4%b9%b0" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;云开发购买的过程，这里不再赘述了，只需要在新建时选择免费资源即可。因为我已经购买过资源了，所以提示我再次购买。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-128.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;成功构建后，你会得到这样的环境id，这个id作为你后续使用cli命令行更新环境的参数使用。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-129.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;Travis CI配置文件&lt;span class="hx:absolute hx:-mt-20" id="travis-ci配置文件"&gt;&lt;/span&gt;
&lt;a href="#travis-ci%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;相信很多人都使用Travis CI构建自己的Github Pages，确实非常方便，虽然Github也提供了自己的CI工具，但是我依然保留着使用Travis CI的习惯。我们无须调整之前的Github Pages的配置或者策略，只需要在你的master分支下，增加或者修改你的.travis.yml即可。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;sudo: false
language: node_js
node_js:
- 10 # use nodejs v10 LTS
cache: npm
branches:
only:
- master # build master branch only
before_install:
- npm i -g @cloudbase/cli
- git clone --depth=1 https://github.com/JoeyBling/hexo-theme-yilia-plus.git themes/yilia-plus
after_success:
- cloudbase login --apiKeyId $TECENT_AK --apiKey $TECENT_KS
- cd public &amp;amp;&amp;amp; echo &amp;#39;y&amp;#39; | tcb hosting deploy -e your-env-id
script:
- hexo generate # generate static files
deploy:
repo: xiaoquqi/xiaoquqi.github.io
target_branch: master
provider: pages
skip-cleanup: true
github-token: $GH_TOKEN
keep-history: true
on:
branch: master
local-dir: public&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;在新的配置文件中，我保留了之前deploy到Github Pages的逻辑，主要增加的逻辑是在before_install开始前，安装cloudbase的cli。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;before_install:
- npm i -g @cloudbase/cli&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;在hexo generate成功后，增加部署的命令，这里需要在Travis CI中配置腾讯云的鉴权环境变量。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;after_success:
- cloudbase login --apiKeyId $TECENT_AK --apiKey $TECENT_KS
- cd public &amp;amp;&amp;amp; echo &amp;#39;y&amp;#39; | tcb hosting deploy -e your-env-id&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;目前cloudbase cli(简写：tcb)，有一个问题，如果超过1000个文件上传会有个提示，导致Travis CI认为没有返回任务失败，但是实际上已经提交上去了，这里已经给腾讯团队提交了一个需求，在cloudbase cli中增加一个force-yes的选项。&lt;/p&gt;
&lt;p&gt;这样我们在提交代码后，就可以实现在腾讯云开发中自动发布我们博客的效果了。&lt;/p&gt;</description></item><item><title>CentOS7 zshrc快速配置</title><link>https://sunqi.site/blog/centos7-zshrc%E5%BF%AB%E9%80%9F%E9%85%8D%E7%BD%AE/</link><pubDate>Tue, 02 Feb 2021 17:15:00 +0000</pubDate><guid>https://sunqi.site/blog/centos7-zshrc%E5%BF%AB%E9%80%9F%E9%85%8D%E7%BD%AE/</guid><description>
&lt;p&gt;大部分时间里，我还是习惯于ssh到远程的CentOS7服务器上工作，因为Mac配置了漂亮zsh的缘故，所以也想把我的CentOS7切换到zsh模式。这是最终配置好的效果：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-124.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;原理部分不再赘述，有兴趣可以参照MacOS的zsh配置篇。&lt;/p&gt;
&lt;p&gt;CentOS7配置zsh与Mac上还是有一定区别的，因为版本要求，zsh需要自己安装编译，字体也需要自己安装，接下来是详细的步骤。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;安装zsh&lt;span class="hx:absolute hx:-mt-20" id="安装zsh"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85zsh" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;虽然通过yum方式可以安装zsh，但是无法满足powerlevel10k的要求，所以先使用zsh源码进行编译后安装。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;WORKSPACE=$HOME/workspace/zsh
mkdir -p $WORKSPACE
cd $WORKSPACE
curl -o zsh.tar.xz https://jaist.dl.sourceforge.net/project/zsh/zsh/5.8/zsh-5.8.tar.xz
tar -xvf zsh-5.8.tar.xz
cd zsh
make
make install&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;zsh会安装在用户目录中/usr/local/bin/zsh中，将zsh设置为默认的系统shell，配置成功后，需要关闭Terminal重新登陆。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;chsh -s /usr/local/bin/zsh&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;安装流程&lt;span class="hx:absolute hx:-mt-20" id="安装流程"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85%e6%b5%81%e7%a8%8b" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;接下来的流程与MacOS上安装类似，由于以上各个项目帮我们做了大量的优化，所以让zsh的安装过程变得简单了很多，大体的流程为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;安装oh-my-zsh，其实就是clone回来&lt;/li&gt;
&lt;li&gt;安装powerlevel10k，其实也是clone回来&lt;/li&gt;
&lt;li&gt;powerlevel10k的基本配置，根据我们喜欢进行定制&lt;/li&gt;
&lt;li&gt;最后是zsh的配置，也就是修改.zshrc文件&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;oh-my-zsh安装&lt;span class="hx:absolute hx:-mt-20" id="oh-my-zsh安装"&gt;&lt;/span&gt;
&lt;a href="#oh-my-zsh%e5%ae%89%e8%a3%85" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;官方的方法是通过curl或wget，执行github上的install.sh文件，但是由于raw.githubusercontent.com已经属于常年被墙的状态，所以并不推荐这种方式，这里采用的方式是将oh-my-zsh下载回来后，再执行install.sh。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;export WORKSPACE=$HOME/workspace/zsh
mkdir -p $WORKSPACE
cd $WORKSPACE
git clone https://e.coding.net/xiaoquqi/github/ohmyzsh.git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;安装脚本在ohmyzsh/tools/install.sh中，这里我们通过环境变量设置本地源&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;export REMOTE=https://e.coding.net/xiaoquqi/github/ohmyzsh.git
$WORKSPACE/ohmyzsh/tools/install.sh&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;powerlevel10k安装&lt;span class="hx:absolute hx:-mt-20" id="powerlevel10k安装"&gt;&lt;/span&gt;
&lt;a href="#powerlevel10k%e5%ae%89%e8%a3%85" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;powerlevel10k已经被gitee缓存了，所以我就没再做单独的缓存源，直接利用官方提供的命令获取。powerlevel10k会被clone到ohmyzsh的custom路径中。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;git clone --depth=1 https://gitee.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;替换默认的zsh主题&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;sed -i &amp;#34;s/^ZSH_THEME=.*/ZSH_THEME=\&amp;#34;powerlevel10k\/powerlevel10k\&amp;#34;/g&amp;#34; $HOME/.zshrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;在正式启用主题前，还需要对powerlevel下载字体的文件进行优化。由于是从github下载字体，所以powerlevel10k配置一定会失败，必须要进行替换后，才能安装正常。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;sed -i &amp;#34;s#^local -r font_base_url=.*#local -r font_base_url=&amp;#39;https://xiaoquqi.coding.net/p/github/d/powerlevel10k-media/git/raw/master&amp;#39;#g&amp;#34; $HOME/.oh-my-zsh/custom/themes/powerlevel10k/internal/wizard.zsh&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;source zshrc会自动触发配置，按照向导和喜欢的样式来就好，这里就不再赘述了&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;source ~/.zshrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;如果想重新配置，也可以使用命令：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;p10k configure&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;加载插件&lt;span class="hx:absolute hx:-mt-20" id="加载插件"&gt;&lt;/span&gt;
&lt;a href="#%e5%8a%a0%e8%bd%bd%e6%8f%92%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;通过修改.zshrc中的plugins变量可以实现插件加载的效果，比如使用virtualenv插件。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;plugins=(git virtualenv)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Mac iTerm2 zshrc快速配置</title><link>https://sunqi.site/blog/mac-zshrc%E5%BF%AB%E9%80%9F%E9%85%8D%E7%BD%AE/</link><pubDate>Tue, 02 Feb 2021 11:26:00 +0000</pubDate><guid>https://sunqi.site/blog/mac-zshrc%E5%BF%AB%E9%80%9F%E9%85%8D%E7%BD%AE/</guid><description>
&lt;p&gt;zsh基本上已经成为Mac上的标配了，界面美观还有点缀的小图标，非常漂亮。但是网上配置zsh文章很多，配置方法也是五花八门，并且由于github被墙的原因，经过由于网络问题安装失败。经过反复测试，在国内的代码托管网站进行了Github部分关键项目定时缓存后，提高配置效率。这里写一篇自用的配置方法，留给有需要的人。&lt;/p&gt;
&lt;p&gt;我的环境：iTerm2 + oh-my-zsh + powerlevel10k，这是我的配置效果：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-123.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;原理解析&lt;span class="hx:absolute hx:-mt-20" id="原理解析"&gt;&lt;/span&gt;
&lt;a href="#%e5%8e%9f%e7%90%86%e8%a7%a3%e6%9e%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我们开始配置前，还是有必要讲一下这几个项目的关系，以便了解其工作原理。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;iTerm2不用说了，MacOS上必备的Terminal工具，替代原有系统自带的工具。&lt;/li&gt;
&lt;li&gt;ohmyzsh(&lt;a href="https://github.com/ohmyzsh/ohmyzsh/"target="_blank" rel="noopener"&gt;https://github.com/ohmyzsh/ohmyzsh/&lt;/a&gt;) 是一套基于zsh深度定制的插件及主题管理的框架，方便定制适合你的zsh环境。&lt;/li&gt;
&lt;li&gt;Nerd Fonts(&lt;a href="https://www.nerdfonts.com/"target="_blank" rel="noopener"&gt;https://www.nerdfonts.com/&lt;/a&gt;) 我们在截图中看到的那些可爱的小图标就是来自这个项目，让我们原本枯燥的Terminal增添了几分乐趣。&lt;/li&gt;
&lt;li&gt;powerlevel10k(&lt;a href="https://github.com/romkatv/powerlevel10k"target="_blank" rel="noopener"&gt;https://github.com/romkatv/powerlevel10k&lt;/a&gt;) 是一套zsh皮肤，也是目前我个人比较喜欢的一套皮肤，同时提供了较强的配置能力，包括字体下载，iTerm2的配置都自动完成了，所以也是目前使用最顺手的一套皮肤。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;安装流程&lt;span class="hx:absolute hx:-mt-20" id="安装流程"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85%e6%b5%81%e7%a8%8b" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;由于以上各个项目帮我们做了大量的优化，所以让zsh的安装过程变得简单了很多，大体的流程为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;安装oh-my-zsh，其实就是clone回来&lt;/li&gt;
&lt;li&gt;安装powerlevel10k，其实也是clone回来&lt;/li&gt;
&lt;li&gt;powerlevel10k的基本配置，根据我们喜欢进行定制&lt;/li&gt;
&lt;li&gt;最后是zsh的配置，也就是修改.zshrc文件&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;oh-my-zsh安装&lt;span class="hx:absolute hx:-mt-20" id="oh-my-zsh安装"&gt;&lt;/span&gt;
&lt;a href="#oh-my-zsh%e5%ae%89%e8%a3%85" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;官方的方法是通过curl或wget，执行github上的install.sh文件，但是由于raw.githubusercontent.com已经属于常年被墙的状态，所以并不推荐这种方式，这里采用的方式是将oh-my-zsh下载回来后，再执行install.sh。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;export WORKSPACE=$HOME/workspace/zsh
mkdir -p $WORKSPACE
cd $WORKSPACE
git clone https://e.coding.net/xiaoquqi/github/ohmyzsh.git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;安装脚本在ohmyzsh/tools/install.sh中，这里我们通过环境变量设置本地源&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;export REMOTE=https://e.coding.net/xiaoquqi/github/ohmyzsh.git
$WORKSPACE/ohmyzsh/tools/install.sh&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;powerlevel10k安装&lt;span class="hx:absolute hx:-mt-20" id="powerlevel10k安装"&gt;&lt;/span&gt;
&lt;a href="#powerlevel10k%e5%ae%89%e8%a3%85" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;powerlevel10k已经被gitee缓存了，所以我就没再做单独的缓存源，直接利用官方提供的命令获取。powerlevel10k会被clone到ohmyzsh的custom路径中。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;git clone --depth=1 https://gitee.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;替换默认的zsh主题&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;sed -i &amp;#39;&amp;#39; &amp;#34;s/^ZSH_THEME=.*/ZSH_THEME=\&amp;#34;powerlevel10k\/powerlevel10k\&amp;#34;/g&amp;#34; $HOME/.zshrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;在正式启用主题前，还需要对powerlevel下载字体的文件进行优化。由于是从github下载字体，所以powerlevel10k配置一定会失败，必须要进行替换后，才能安装正常。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;sed -i &amp;#39;&amp;#39; &amp;#34;s#^local -r font_base_url=.*#local -r font_base_url=&amp;#39;https://xiaoquqi.coding.net/p/github/d/powerlevel10k-media/git/raw/master&amp;#39;#g&amp;#34; $HOME/.oh-my-zsh/custom/themes/powerlevel10k/internal/wizard.zsh&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;source zshrc会自动触发配置，按照向导和喜欢的样式来就好，这里就不再赘述了&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;source ~/.zshrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;如果想重新配置，也可以使用命令：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;p10k configure&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;加载插件&lt;span class="hx:absolute hx:-mt-20" id="加载插件"&gt;&lt;/span&gt;
&lt;a href="#%e5%8a%a0%e8%bd%bd%e6%8f%92%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;通过修改.zshrc中的plugins变量可以实现插件加载的效果，比如使用virtualenv插件。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;plugins=(git virtualenv)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>如何在微信开发者工具中使用vim编辑模式</title><link>https://sunqi.site/blog/%E5%A6%82%E4%BD%95%E5%9C%A8%E5%BE%AE%E4%BF%A1%E5%BC%80%E5%8F%91%E8%80%85%E5%B7%A5%E5%85%B7%E4%B8%AD%E4%BD%BF%E7%94%A8vim%E7%BC%96%E8%BE%91%E6%A8%A1%E5%BC%8F/</link><pubDate>Wed, 27 Jan 2021 07:52:10 +0000</pubDate><guid>https://sunqi.site/blog/%E5%A6%82%E4%BD%95%E5%9C%A8%E5%BE%AE%E4%BF%A1%E5%BC%80%E5%8F%91%E8%80%85%E5%B7%A5%E5%85%B7%E4%B8%AD%E4%BD%BF%E7%94%A8vim%E7%BC%96%E8%BE%91%E6%A8%A1%E5%BC%8F/</guid><description>
&lt;p&gt;随着云计算技术的发展特别是无服务化的发展，在业务系统的研发上，前端和后端的边界逐步被打破。微信小程序便是这一方面的典型代表，特别是结合了腾讯Serverless云开发的套件后，小程序融会贯通成为业务开发非常重要的载体。今年疫情期间，基于小程序开发的健康码充分发挥了小程序这一方面的特点。小程序上手开发难度不高，基本都是基于Javascript生态构建，对于前端开发或者后端开发来说，无疑都是福音，让大家真正的做一次全栈开发。&lt;/p&gt;
&lt;p&gt;作为一名10多年的开发人员，vim是我最常使用的编辑器，但是在微信开发者工具中并没有直接提供vim的开发模式。经过不断的探索，终于发现微信开发者工具对VS Code插件的兼容模式，于是按照文档将VS Code vim插件安装在微信开发者工具中。果然，我熟悉的vim模式又回来了，这篇文章就为大家简单分享一下。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;在VS Code安装vim插件&lt;span class="hx:absolute hx:-mt-20" id="在vs-code安装vim插件"&gt;&lt;/span&gt;
&lt;a href="#%e5%9c%a8vs-code%e5%ae%89%e8%a3%85vim%e6%8f%92%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;首先在VS Code中安装vim模拟器，如图所示，我安装的是1.18.5版本。我使用的是mac系统，安装完成后，插件会存放在用户HOME目录下的$HOME/.vscode/extensions/vscodevim.vim-1.18.5中。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-116.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;在微信开发者工具安装VS Code插件&lt;span class="hx:absolute hx:-mt-20" id="在微信开发者工具安装vs-code插件"&gt;&lt;/span&gt;
&lt;a href="#%e5%9c%a8%e5%be%ae%e4%bf%a1%e5%bc%80%e5%8f%91%e8%80%85%e5%b7%a5%e5%85%b7%e5%ae%89%e8%a3%85vs-code%e6%8f%92%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;1、在微信开发者工具中点击“设置”-&amp;gt;&amp;ldquo;扩展设置&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-117.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;2、在打开的窗口中选择“编辑器自定义扩展”，因为我已经安装过了，所以截图中已经包含了vscode.vim插件&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-118.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;3、点击上方的“打开扩展文件夹”，此时会打开微信开发者插件目录，而你要做的就是将vscode插件拷贝过去。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-119.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;但是由于从Finder中无法直接访问隐藏目录，先在左侧选择HOME目录。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-121.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;使用“前往文件夹”选项，填入.vscode/extensions。将.vscode/extensions/vscodevim.vim-1.18.5拷贝之刚才打开的微信开发者工具的扩展目录中。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-120.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;4、重启微信开发者工具后，就能在“编辑器自定义扩展”中看到vim插件，启动插件后，再次退出重启，此时编辑器里已经可以使用vim模式了。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-122.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;</description></item><item><title>使用镜像源加速Github Clone速度</title><link>https://sunqi.site/blog/%E4%BD%BF%E7%94%A8%E9%95%9C%E5%83%8F%E6%BA%90%E5%8A%A0%E9%80%9Fgithub-clone%E9%80%9F%E5%BA%A6/</link><pubDate>Mon, 25 Jan 2021 09:11:00 +0000</pubDate><guid>https://sunqi.site/blog/%E4%BD%BF%E7%94%A8%E9%95%9C%E5%83%8F%E6%BA%90%E5%8A%A0%E9%80%9Fgithub-clone%E9%80%9F%E5%BA%A6/</guid><description>
&lt;p&gt;Github被屏蔽已经不是什么太新鲜的事情了，但是对开发人员下载速度确实造成很大的困扰，所以需要使用镜像源来加速下载速度。但是，我在clone的时候又不想每次破坏原有的链接，那有没有什么自动的方法来帮助我们来修改呢？&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;设定gitconfig自动实现替换&lt;span class="hx:absolute hx:-mt-20" id="设定gitconfig自动实现替换"&gt;&lt;/span&gt;
&lt;a href="#%e8%ae%be%e5%ae%9agitconfig%e8%87%aa%e5%8a%a8%e5%ae%9e%e7%8e%b0%e6%9b%bf%e6%8d%a2" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;通过在HOME目录下的.gitconfig文件可以实现自动的对github.com进行替换的目的，具体的方式如下：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;git config --global url.&amp;#34;https://gitclone.com/&amp;#34;.insteadOf https://github.com&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;在$HOME/.gitconfig会发现增加了如下行：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;[url &amp;#34;https://gitclone.com/&amp;#34;]
insteadOf = https://github.com&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;其他镜像源&lt;span class="hx:absolute hx:-mt-20" id="其他镜像源"&gt;&lt;/span&gt;
&lt;a href="#%e5%85%b6%e4%bb%96%e9%95%9c%e5%83%8f%e6%ba%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;目前国内提供github镜像源还包括以下地址，但是通过网站测速（https://tool.chinaz.com/sitespeed）来看，目前相对于北京最稳定和快速的是gitclone.com，所以可以根据不同地域灵活进行选择以下地址：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fastgit.org: &lt;a href="https://doc.fastgit.org/"target="_blank" rel="noopener"&gt;https://doc.fastgit.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;gitclone.com: &lt;a href="https://gitclone.com/"target="_blank" rel="noopener"&gt;https://gitclone.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;gitee: &lt;a href="https://gitee.com/mirrors"target="_blank" rel="noopener"&gt;https://gitee.com/mirrors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;cnpmjs.org: &lt;a href="https://github.com.cnpmjs.org/"target="_blank" rel="noopener"&gt;https://github.com.cnpmjs.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;文件下载&lt;span class="hx:absolute hx:-mt-20" id="文件下载"&gt;&lt;/span&gt;
&lt;a href="#%e6%96%87%e4%bb%b6%e4%b8%8b%e8%bd%bd" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;还有一种情况是要从github下载某个文件，由于raw.githubusercontent.com属于长期被屏蔽状态，所以基本通过wget进行下载，比如要下载的文件为：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;curl -O https://raw.githubusercontent.com/xiaoquqi/dockprom/master/docker-compose.vmware.exporters.yml&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;可以替换为：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;https://raw.staticdn.net/xiaoquqi/dockprom/master/docker-compose.vmware.exporters.yml&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>利用Docker快速搭建Prometheus监控及告警平台</title><link>https://sunqi.site/blog/%E5%88%A9%E7%94%A8docker%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BAprometheus%E7%9B%91%E6%8E%A7%E5%8F%8A%E5%91%8A%E8%AD%A6%E5%B9%B3%E5%8F%B0/</link><pubDate>Fri, 25 Dec 2020 21:32:48 +0000</pubDate><guid>https://sunqi.site/blog/%E5%88%A9%E7%94%A8docker%E5%BF%AB%E9%80%9F%E6%90%AD%E5%BB%BAprometheus%E7%9B%91%E6%8E%A7%E5%8F%8A%E5%91%8A%E8%AD%A6%E5%B9%B3%E5%8F%B0/</guid><description>
&lt;p&gt;开源项目出现让IT产业得到了蓬勃发展的机会，大批的社区贡献者通过向开源社区贡献代码实现自我价值。企业通过使用开源项目，增加了对核心技术的掌控能力。虽然开源项目从功能性上是基本可用的，但是需要从用户体验、运维层面投入人力，本文目的就是帮助读者利用Docker快速构建一套基于Prometheus的监控及告警平台，能够实现对用户环境基本监控，本文将持续更新，收集好用的exporter及Grafana Dashboard。&lt;/p&gt;
&lt;p&gt;目前本文涉及的监控内容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;主机监控&lt;/li&gt;
&lt;li&gt;容器监控&lt;/li&gt;
&lt;li&gt;Ceph监控&lt;/li&gt;
&lt;li&gt;VMware监控&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- more --&gt;
&lt;h2&gt;项目说明&lt;span class="hx:absolute hx:-mt-20" id="项目说明"&gt;&lt;/span&gt;
&lt;a href="#%e9%a1%b9%e7%9b%ae%e8%af%b4%e6%98%8e" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我们假设读者已经使用CentOS搭建了容器环境，并配置了国内源的前提下。如果没有设置请参考&lt;a href="http://sunqi.site/2020/07/31/CentOS-7%E5%88%9D%E5%A7%8B%E5%8C%96%E8%84%9A%E6%9C%AC/"target="_blank" rel="noopener"&gt;《CentOS 7和Docker初始化安装》&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;Prometheus快速构建的docker compose原始项目来自&lt;a href="https://github.com/stefanprodan/dockprom"target="_blank" rel="noopener"&gt;stefanprodan/dockprom&lt;/a&gt;，但是由于原项目中的cAdvisor使用了Google源，所以Fork的项目修改为国内源&lt;a href="https://github.com/xiaoquqi/dockprom"target="_blank" rel="noopener"&gt;xiaoquqi/dockprom&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;原项目中包含的组件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prometheus (metrics database) http://&lt;host-ip&gt;:9090&lt;/li&gt;
&lt;li&gt;Prometheus-Pushgateway (push acceptor for ephemeral and batch jobs) http://&lt;host-ip&gt;:9091&lt;/li&gt;
&lt;li&gt;AlertManager (alerts management) http://&lt;host-ip&gt;:9093&lt;/li&gt;
&lt;li&gt;Grafana (visualize metrics) http://&lt;host-ip&gt;:3000&lt;/li&gt;
&lt;li&gt;Caddy (reverse proxy and basic auth provider for prometheus and alertmanager)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;默认包含的采集器：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NodeExporter (host metrics collector)&lt;/li&gt;
&lt;li&gt;cAdvisor (containers metrics collector)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在此基础上增加的内容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ceph exporter&lt;/li&gt;
&lt;li&gt;VMware exporter&lt;/li&gt;
&lt;li&gt;钉钉告警webhook&lt;/li&gt;
&lt;li&gt;轻量级http服务，用于内网分发docker-compse.exporter.yml&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;环境快速构建&lt;span class="hx:absolute hx:-mt-20" id="环境快速构建"&gt;&lt;/span&gt;
&lt;a href="#%e7%8e%af%e5%a2%83%e5%bf%ab%e9%80%9f%e6%9e%84%e5%bb%ba" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;git clone https://github.com/xiaoquqi/dockprom
cd dockprom
docker-compose up -d&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;启动完成后，用浏览器访问：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prometheus: http://yourip:9090&lt;/li&gt;
&lt;li&gt;Grafana: http://yourip:3000&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;默认的用户名/密码为: admin/admin，如果需要修改可以在启动之前修改docker-compose.yml文件。&lt;/p&gt;
&lt;p&gt;访问Prometheus，查看metrics是否被正确采集。如果有采集器有红色字样，根据提示查看具体的错误原因，大部分的错误都是因为配置问题，或者网络不通造成的。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-109.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;Grafana配置&lt;span class="hx:absolute hx:-mt-20" id="grafana配置"&gt;&lt;/span&gt;
&lt;a href="#grafana%e9%85%8d%e7%bd%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;访问Grafana的控制面板，其中已经内置了一些模板，也可以选择Import导入Grafana模板库的模板，数据源选择已经配置好的Prometheus即可。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-110.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;主机监控&lt;span class="hx:absolute hx:-mt-20" id="主机监控"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%bb%e6%9c%ba%e7%9b%91%e6%8e%a7" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;默认安装情况下，主机层面仅监控了本机，如果需要增加新的监控主机，需要进行以下两步：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;为主机安装node exporter&lt;/li&gt;
&lt;li&gt;修改Prometheus配置文件，并重启服务&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1、安装node exporter&lt;span class="hx:absolute hx:-mt-20" id="1安装node-exporter"&gt;&lt;/span&gt;
&lt;a href="#1%e5%ae%89%e8%a3%85node-exporter" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在项目中，内置了一个单独的docker-compose.exporters.yml，如果目标主机安装了容器，可以直接将该yaml文件拷贝至目标节点后，启动监控服务即可。当然也可以通过软件包安装方式，本文不再赘述。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;docker-compose -f docker-compose.exporters.yml up -d&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;安装完成后，访问metrics接口，即代表安装成功&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;curl http://localhost:9100/metrics&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;node_softnet_processed_total{cpu=&amp;#34;14&amp;#34;} 2.8795339e&amp;#43;07
node_softnet_processed_total{cpu=&amp;#34;15&amp;#34;} 2.3535384e&amp;#43;07
node_softnet_processed_total{cpu=&amp;#34;16&amp;#34;} 3.4674675e&amp;#43;07
node_softnet_processed_total{cpu=&amp;#34;17&amp;#34;} 2.5727501e&amp;#43;07
node_softnet_processed_total{cpu=&amp;#34;18&amp;#34;} 2.5931391e&amp;#43;07
node_softnet_processed_total{cpu=&amp;#34;19&amp;#34;} 2.67231846e&amp;#43;08
node_softnet_processed_total{cpu=&amp;#34;2&amp;#34;} 4.3448998e&amp;#43;07
node_softnet_processed_total{cpu=&amp;#34;20&amp;#34;} 3.0684276e&amp;#43;07
node_softnet_processed_total{cpu=&amp;#34;21&amp;#34;} 3.0587632e&amp;#43;07&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;2、修改Prometheus配置文件&lt;span class="hx:absolute hx:-mt-20" id="2修改prometheus配置文件"&gt;&lt;/span&gt;
&lt;a href="#2%e4%bf%ae%e6%94%b9prometheus%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;回到Prometheus节点，找到dockerprom/prometheus/prometheus.yml进行如下修改，在nodeexporter段的targets增加新的监控节点后重启服务。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;## A scrape configuration containing exactly one endpoint to scrape.
scrape_configs:
- job_name: &amp;#39;nodeexporter&amp;#39;
scrape_interval: 5s
static_configs:
- targets: [&amp;#39;nodeexporter:9100&amp;#39;, &amp;#39;newip:9100&amp;#39;]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;docker restart prometheus&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;告警配置&lt;span class="hx:absolute hx:-mt-20" id="告警配置"&gt;&lt;/span&gt;
&lt;a href="#%e5%91%8a%e8%ad%a6%e9%85%8d%e7%bd%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;其实监控并不是最终的目的，往往告警才是监控系统成功与否的关键，在实际运维中对于根因分析和告警收敛是有非常强烈的需求的，本文中暂时还没对此做深入的分析，仅仅提供了常规的告警手段。告警的配置方法有两种方式，一种是通过Prometheus AlertManager，另外一种也可以通过在Grafana上直接进行配置。&lt;/p&gt;
&lt;p&gt;对于告警方式支持多种方式，例如我们常用的邮件或者钉钉等，当然你也可以实现你自己的方式，这里我们使用钉钉的WEBHOOK作为告警方式。&lt;/p&gt;
&lt;h3&gt;1. 钉钉webhook配置&lt;span class="hx:absolute hx:-mt-20" id="1-钉钉webhook配置"&gt;&lt;/span&gt;
&lt;a href="#1-%e9%92%89%e9%92%89webhook%e9%85%8d%e7%bd%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;默认已经启动了钉钉容器，只需要修改dingtalk/config.yaml即可。Targets下面有各种示例，比如配置一个最简单的钉钉告警：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;targets:
devops:
url: https://oapi.dingtalk.com/robot/send?access_token=xxxxx&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这里的devops是自定义的，但是和后面要填入alertmanager的链接地址有关，比如本例中alertmanager回调地址就是http://&lt;yourip&gt;:8060/dingtalk/devops/send&lt;/p&gt;
&lt;h1&gt;## 2. 修改AlertManager配置&lt;/h1&gt;&lt;p&gt;修改alertmanager/config.yml&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;route:
receiver: &amp;#39;dingtalk&amp;#39;
receivers:
- name: &amp;#39;dingtalk&amp;#39;
webhook_configs:
- send_resolved: true
url: http://&amp;lt;yourip&amp;gt;:8060/dingtalk/devops/send&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这里不要用localhost，因为部署在容器内。&lt;/p&gt;
&lt;h1&gt;## 3. 修改Prometheus配置文件&lt;/h1&gt;&lt;p&gt;修改alert.rules，尝试修改一些规则测试告警，例如：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;- name: host
rules:
- alert: high_cpu_load
expr: node_load1 &amp;gt; 0.2
for: 1s
labels:
severity: warning
annotations:
summary: &amp;#34;Server under high load&amp;#34;
description: &amp;#34;Docker host is under high load, the avg load 1m is at {{ $value}}. Reported by instance {{ $labels.instance }} of job {{ $labels.job }}.&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;此时可以通过AlertManager查看http://&lt;yourip&gt;:9093/#/alerts，检查是否有告警产生。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-111.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;如果告警产生了，但是无法触发钉钉，可以通过检查alertmanager容器进行debug，例如上述提到的localhost问题。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;level=warn ts=2020-12-29T07:21:56.345Z caller=notify.go:674 component=dispatcher receiver=dingtalk integration=webhook[0] msg=&amp;#34;Notify attempt failed, will retry later&amp;#34; attempts=1 err=&amp;#34;Post \&amp;#34;http://localhost:8060/dingtalk/devops/send\&amp;#34;: dial tcp 127.0.0.1:8060: connect: connection refused&amp;#34;
level=error ts=2020-12-29T07:26:56.344Z caller=dispatch.go:309 component=dispatcher msg=&amp;#34;Notify for alerts failed&amp;#34; num_alerts=1 err=&amp;#34;dingtalk/webhook[0]: notify retry canceled after 16 attempts: Post \&amp;#34;http://localhost:8060/dingtalk/devops/send\&amp;#34;: dial tcp 127.0.0.1:8060: connect: connection refused&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Ceph监控&lt;span class="hx:absolute hx:-mt-20" id="ceph监控"&gt;&lt;/span&gt;
&lt;a href="#ceph%e7%9b%91%e6%8e%a7" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;确保Ceph配置文件已经在/etc/ceph目录下，并且能够正常访问Ceph集群。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;docker-compose -f docker-compose.ceph.exporters.yml up -d&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;通过访问http://&lt;yourip&gt;:9128/metrics验证是否能够正常获取数据。&lt;/p&gt;
&lt;p&gt;在prometheus/prometheus.yml文件中增加一个新的Job&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;scrape_configs:
......
- job_name: &amp;#39;ceph-exporter&amp;#39;
scrape_interval: 5s
honor_labels: true
static_configs:
- targets: [&amp;#39;192.168.10.201:9128&amp;#39;]
labels:
instance: Ceph Cluster&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;最后重启prometheus容器&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;docker restart prometheus&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;在Grafana中导入三个模板：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ceph Cluster Overview: &lt;a href="https://grafana.com/dashboards/917"target="_blank" rel="noopener"&gt;https://grafana.com/dashboards/917&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ceph Pools Overview: &lt;a href="https://grafana.com/dashboards/926"target="_blank" rel="noopener"&gt;https://grafana.com/dashboards/926&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ceph OSD Overview: &lt;a href="https://grafana.com/dashboards/923"target="_blank" rel="noopener"&gt;https://grafana.com/dashboards/923&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ceph Cluster效果：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-113.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;Ceph Pool效果：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-114.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;Ceph OSD效果：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-115.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;VMware监控&lt;span class="hx:absolute hx:-mt-20" id="vmware监控"&gt;&lt;/span&gt;
&lt;a href="#vmware%e7%9b%91%e6%8e%a7" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;首先修改docker-compose.vmware.exporters.yml中vcenter的连接信息：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;services:
vmware-exporter:
image: pryorda/vmware_exporter:v0.11.1
container_name: vmware-exporter
restart: unless-stopped
ports:
- &amp;#39;9272:9272&amp;#39;
expose:
- 9272
environment:
VSPHERE_HOST: &amp;#34;VC_HOST&amp;#34;
VSPHERE_IGNORE_SSL: &amp;#34;True&amp;#34;
VSPHERE_USER: &amp;#34;VC_USERNAME&amp;#34;
VSPHERE_PASSWORD: &amp;#34;VC_PASSWORD&amp;#34;
labels:
org.label-schema.group: &amp;#34;monitoring&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;启动VMware exporter：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;docker-compose -f docker-compose.vmware.exporters.yml up -d&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;通过访问http://&lt;yourip&gt;:9272/metrics验证是否能够正常获取数据。&lt;/p&gt;
&lt;p&gt;在prometheus/prometheus.yml文件中增加一个新的Job&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;scrape_configs:
......
- job_name: &amp;#39;vmware_vcenter&amp;#39;
metrics_path: &amp;#39;/metrics&amp;#39;
scrape_timeout: 15s
static_configs:
- targets: [&amp;#39;192.168.10.13:9272&amp;#39;]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;最后重启prometheus容器&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;docker restart prometheus&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;在Grafana中导入模板：https://grafana.com/grafana/dashboards/11243&lt;/p&gt;
&lt;p&gt;效果如下：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-112.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;</description></item><item><title>我需要一款什么样的网盘？</title><link>https://sunqi.site/blog/%E6%88%91%E9%9C%80%E8%A6%81%E4%B8%80%E6%AC%BE%E4%BB%80%E4%B9%88%E6%A0%B7%E7%9A%84%E7%BD%91%E7%9B%98/</link><pubDate>Mon, 14 Dec 2020 21:56:00 +0000</pubDate><guid>https://sunqi.site/blog/%E6%88%91%E9%9C%80%E8%A6%81%E4%B8%80%E6%AC%BE%E4%BB%80%E4%B9%88%E6%A0%B7%E7%9A%84%E7%BD%91%E7%9B%98/</guid><description>
&lt;p&gt;大概是在8月份的时候，收到阿里要做网盘的消息，那篇文章以“免费”、“不限速”这样的噱头来吸引读者的眼球，直击目前网盘的痛点，当时确实赚足了流量。不过两个月过后，阿里的网盘仍然是犹抱琵琶半遮面的感觉，始终让人看不清楚阿里网盘的端倪。十月底的时候，依靠阿里MVP这一“天时”，搞到了阿里云盘的内测码，并进行了深度体验，所以这篇文章主要是两个目的：第一，是交个作业，毕竟“拿人内测码，与人评测”；第二，网盘我用了不少，也从我的需求角度来讲一下，我对网盘的需求到底是什么，希望能引起读者的一些共鸣。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;阿里云盘or网盘——傻傻分不清楚&lt;span class="hx:absolute hx:-mt-20" id="阿里云盘or网盘傻傻分不清楚"&gt;&lt;/span&gt;
&lt;a href="#%e9%98%bf%e9%87%8c%e4%ba%91%e7%9b%98or%e7%bd%91%e7%9b%98%e5%82%bb%e5%82%bb%e5%88%86%e4%b8%8d%e6%b8%85%e6%a5%9a" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我相信很多关注了阿里网盘的朋友都会有一个问题，到底哪个是阿里真的网盘？我们通过公开渠道，至少能找到阿里云有至少三款“云盘”或者“网盘”。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-97.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-98.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-99.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;幸运的一点，我除了通过阿里MVP渠道获取到Teambition开发的网盘，同时还获取了阿里云盘的内测码，所以有机会对这两款都进行了充分体验。&lt;/p&gt;
&lt;h3&gt;Teambiton网盘&lt;span class="hx:absolute hx:-mt-20" id="teambiton网盘"&gt;&lt;/span&gt;
&lt;a href="#teambiton%e7%bd%91%e7%9b%98" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;2019年初阿里耗资1亿美金收购了团队协作平台Teambition，通过收购及整合兼并，阿里不断扩大自身在To B领域的影响力。在推出网盘前，Teambition已经推出了代码托管平台codeUp和Flow，为企业构建完整的DevOps流程垫定了基础。网盘也是顺应这一趋势，阿里也继续丰富着自己的To B版图。&lt;/p&gt;
&lt;p&gt;不过与我们理解的传统网盘有所区别，目前网盘是紧耦合在原有的Teambition体系内，更像是Teambition的一个扩展功能，而不能独立使用，这一点从网页版和手机侧的设计就能看出来。所以，也许Teambition网盘的目标客户也许并不是传统的网盘用户，更像是解决企业成员间文件存储和分享的问题。&lt;/p&gt;
&lt;p&gt;目前Teambition暂不支持企业网盘，还需要切换至个人账户。但是在我测试过程中，有个小Bug，我明明在登陆后是个人账户，但是仍然看到的是企业网盘暂未开放的提示信息。需要先切换到企业，再切换回个人后才能看到。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-100.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;先来看一下整体的界面风格，从内测版本的截图看，Teambition的网盘目前还处于非常简单的状态，界面上展现的功能并不多，我认为类似最早期对象存储的基本功能。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-101.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;由于目前还处于内测阶段，所以基本不会对上传和下载速度做任何限制，不知道在商用化之后免费权益到底如何？我家的宽带是联通300Mbps，上传之前对网速进行了基本测试，上传的时候我使用的是浏览器直接上传的方式，我的iMac使用网线和路由器直接进行连接。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-103.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;我是晚上做的测试，上传了一个4.66GB的MP4文件，上传速度基本稳定在了400KB/s。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-104.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;这个和我最早期的一次测试结果是有出入的，感觉速度没有这么慢，并且中途失败了好几次，于是第二天早晨的时候，在失败后进行了重传。这时候速度基本上能把网络的上行速度跑满。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-107.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;另外，对于网盘很重要的分享功能也并未开放，只能作为用户自有的网络存储空间。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-105.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;手机侧的功能也基本与网页版本相似，并且必须要借助Teambition APP使用，暂时没有提供任何自动备份的功能。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-106.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;阿里云盘&lt;span class="hx:absolute hx:-mt-20" id="阿里云盘"&gt;&lt;/span&gt;
&lt;a href="#%e9%98%bf%e9%87%8c%e4%ba%91%e7%9b%98" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;经过与阿里内部确认，阿里的云盘和Teambition是完全独立的两个团队，也就是这是两端独立的产品，所以这也让我怀疑我当初看到的文章到底是在讲网盘还是云盘的？&lt;/p&gt;
&lt;p&gt;阿里的云盘更接近传统对网盘的认知，这一点从用户体验上就能感觉到。与网盘不同的是，阿里云盘相对来说比较独立，之前只开放了手机版本，目前已经可以从网页上进行登陆了。目前只能通过网页版进行内测资格的申请，而所有操作也只能在手机侧完成。阿里云盘的域名是aliyundrive.com。&lt;/p&gt;
&lt;p&gt;目前的客户端方面只提供了手机侧的，对我来说比较重要的客户端的还没有看到。从上传的感受来说，云盘的稳定性要好于网盘，网速基本上稳定在5MB/s，中间没有出现任何断线情况。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-108.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;我需要什么样的网盘产品？&lt;span class="hx:absolute hx:-mt-20" id="我需要什么样的网盘产品"&gt;&lt;/span&gt;
&lt;a href="#%e6%88%91%e9%9c%80%e8%a6%81%e4%bb%80%e4%b9%88%e6%a0%b7%e7%9a%84%e7%bd%91%e7%9b%98%e4%ba%a7%e5%93%81" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;回答这个问题，先要从我用了哪两款付费网盘产品说起。目前我使用的两款付费网盘的产品，一款是苹果的iCloud，一款是百度的网盘。iCloud的费用一个月是21元/月200GB家庭共享空间，而百度网盘超级会员一个月是18元/月空间，空间达到了5TB，但是无法家庭共享。&lt;/p&gt;
&lt;p&gt;可能有人会问为什么每个月要花将近40元在付费网盘呢？为什么不使用同一种网盘呢？这主要源自我最主要的几个需求：&lt;/p&gt;
&lt;p&gt;一、解决不同设备之间的文件同步问题。我目前使用的手机是iPhone、办公电脑是Mac Pro，而家里使用的是iMac。因为经常要在家里工作，而又懒着背笔记本回家，所以重要文件在不同电脑的传输对我来说就非常重要了。另外，因为有时候需要出去交流，所以会从手机侧查看文件，那么手机与PC之间的文件互通也变得非常重要了。百度网盘之前在Mac侧会有个同步盘的应用，但是后来不再维护了，并且同步盘之前在同步过程中经常发生同步冲突，而莫名其妙产生了多个文件的问题。后来还试过类似OneDrive等网盘，都有类似的问题。最终发现只有苹果自身的方案才能最完美的符合我的要求。
二、费用成本问题。虽然苹果的方案很完美，但是也是最贵的，苹果的付费储存空间方案跨度太大，200GB之后就是2TB，价格直接从21元/月涨到了68元/月。因为会拍摄一些视频资料，所以对空间消耗比加大，无奈之下，只得选择了百度网盘作为补充，一方面是之前有很多文件都存在了百度网盘上，另外一方面付费后也不受下载限速的影响了，算是作为一种二级存储的方案使用。近期，准备购置百度的智能音箱，还能直接播放网盘内宝宝的音频。
三、照片、视频自动备份功能。虽然iCloud也能对照片、视频进行自动备份，但是有了孩子之后发现照片和视频成倍增加，真是不禁用，这时百度网盘的照片、视频自动备份就派上了用场。&lt;/p&gt;
&lt;p&gt;其实，百度网盘还有一些类似照片整理、搜索等功能也非常强大，但是相比前两点并非刚需，所以只是偶尔会用到。&lt;/p&gt;
&lt;p&gt;虽然这种组合使用方式在一定程度基本满足了我的日常需求，只是要定期的将部分数据导入百度网盘略显繁琐。但是另外一个网盘的需求依然困扰着我，就是对于微信的备份功能。虽然钉钉在这一点上要明显好于微信，但是谁让微信是第一社交软件呢？平时的沟通还是在微信，经常遇到一些文件不随手存下来就被微信清理掉的情况。虽然腾讯也有自己的微盘，但是就是不支持微信的自动备份功能，如果支持我估计我会立马付费购买。&lt;/p&gt;
&lt;p&gt;总结一下我对网盘的几个需求：第一，空间足够大，上传下载不限速；第二、设备之间能够互相同步；第三、微信聊天记录和附件的自动备份功能。&lt;/p&gt;</description></item><item><title>Docker构建服务器空间占满问题</title><link>https://sunqi.site/blog/docker%E6%9E%84%E5%BB%BA%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%A9%BA%E9%97%B4%E5%8D%A0%E6%BB%A1%E9%97%AE%E9%A2%98/</link><pubDate>Fri, 13 Nov 2020 14:19:41 +0000</pubDate><guid>https://sunqi.site/blog/docker%E6%9E%84%E5%BB%BA%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%A9%BA%E9%97%B4%E5%8D%A0%E6%BB%A1%E9%97%AE%E9%A2%98/</guid><description>
&lt;h2&gt;现象描述&lt;span class="hx:absolute hx:-mt-20" id="现象描述"&gt;&lt;/span&gt;
&lt;a href="#%e7%8e%b0%e8%b1%a1%e6%8f%8f%e8%bf%b0" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;今天Jenkins构建突然出现问题，检查Jenkins Job日志发现no space left，于是登录到Jenkins Build服务器上，发现容器所在的/var/lib空间被完全满了。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-94.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;排查过程&lt;span class="hx:absolute hx:-mt-20" id="排查过程"&gt;&lt;/span&gt;
&lt;a href="#%e6%8e%92%e6%9f%a5%e8%bf%87%e7%a8%8b" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;检查容器空间&lt;span class="hx:absolute hx:-mt-20" id="检查容器空间"&gt;&lt;/span&gt;
&lt;a href="#%e6%a3%80%e6%9f%a5%e5%ae%b9%e5%99%a8%e7%a9%ba%e9%97%b4" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;首先从容器层面检查一下空间占用情况：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;docker system df&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;发现有容器的占用空间达到了1个多TB的空间。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-95.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;清理无用的容器和镜像&lt;span class="hx:absolute hx:-mt-20" id="清理无用的容器和镜像"&gt;&lt;/span&gt;
&lt;a href="#%e6%b8%85%e7%90%86%e6%97%a0%e7%94%a8%e7%9a%84%e5%ae%b9%e5%99%a8%e5%92%8c%e9%95%9c%e5%83%8f" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;先用prune进行一下清理，为了保险起见，过滤一下时间&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;docker system prune -a -f --filter &amp;#34;until = 1h&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;清理完成后，空间仍然没有释放，于是继续排查。&lt;/p&gt;
&lt;h3&gt;检查/var/lib下的空间占用&lt;span class="hx:absolute hx:-mt-20" id="检查varlib下的空间占用"&gt;&lt;/span&gt;
&lt;a href="#%e6%a3%80%e6%9f%a5varlib%e4%b8%8b%e7%9a%84%e7%a9%ba%e9%97%b4%e5%8d%a0%e7%94%a8" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;通过检查发现/var/lib/docker/overlay2中的66d44a19ee93a191cc0585efac45e10696edfd0381d0dc96d9646080337f629e目录空间占用巨大，进入后发现其中有tmp目录没有及时清理。由于没有Jenkins任务在执行，所以手动清理了/tmp/tmp*的目录，空间被立即释放了。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-96.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;那么此时问题清晰了，这一层属于Jenkins，进入容器后发现Jenkins的/tmp目录没有被及时清理，属于Build逻辑有缺陷造成了，及时修复Pipeline的Jenkinsfile后，该问题不再出现。&lt;/p&gt;</description></item><item><title>MacOS VPN拨号后自动设置路由</title><link>https://sunqi.site/blog/macos-vpn%E6%8B%A8%E5%8F%B7%E5%90%8E%E8%87%AA%E5%8A%A8%E8%AE%BE%E7%BD%AE%E8%B7%AF%E7%94%B1/</link><pubDate>Wed, 11 Nov 2020 20:04:07 +0000</pubDate><guid>https://sunqi.site/blog/macos-vpn%E6%8B%A8%E5%8F%B7%E5%90%8E%E8%87%AA%E5%8A%A8%E8%AE%BE%E7%BD%AE%E8%B7%AF%E7%94%B1/</guid><description>
&lt;h2&gt;目的&lt;span class="hx:absolute hx:-mt-20" id="目的"&gt;&lt;/span&gt;
&lt;a href="#%e7%9b%ae%e7%9a%84" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;公司使用的VPN是L2TP协议的，平时在家远程工作时需要VPN拨入，但是又不想所有的流量都经过VPN，需要使用路由表来路由指定的网段。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;允许L2TP共享密钥为空&lt;span class="hx:absolute hx:-mt-20" id="允许l2tp共享密钥为空"&gt;&lt;/span&gt;
&lt;a href="#%e5%85%81%e8%ae%b8l2tp%e5%85%b1%e4%ba%ab%e5%af%86%e9%92%a5%e4%b8%ba%e7%a9%ba" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;公司L2TP共享密钥为空，默认MacOS是不支持的，所以需要在配置文件中特殊设定，在/etc/ppp下生成options文件。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;sudo tee /etc/ppp/options &amp;lt;&amp;lt; EOF
plugin L2TP.ppp
l2tpnoipsec
EOF&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;自动路由设置&lt;span class="hx:absolute hx:-mt-20" id="自动路由设置"&gt;&lt;/span&gt;
&lt;a href="#%e8%87%aa%e5%8a%a8%e8%b7%af%e7%94%b1%e8%ae%be%e7%bd%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;原理很简单，在连接VPN后将指定网段的IP经过VPN虚拟接口即可，具体的实现如下：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;sudo touch /etc/ppp/ip-up
sudo chmod 0755 /etc/ppp/ip-up&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ip-up的内容如下，只需要修改SUBNET网段即可，例如：192.168.10.0/24&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;##!/bin/sh
/sbin/route add &amp;lt;SUBNET&amp;gt; -interface $1 &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;其余可利用参数如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$1: VPN接口(例如：ppp0)&lt;/li&gt;
&lt;li&gt;$2: 未知&lt;/li&gt;
&lt;li&gt;$3: VPN服务器地址&lt;/li&gt;
&lt;li&gt;$4: VPN网关地址&lt;/li&gt;
&lt;li&gt;$5: 非VPN网关，本地使用&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>利用钉钉通讯录同步构建本地LDAP服务</title><link>https://sunqi.site/blog/%E5%88%A9%E7%94%A8%E9%92%89%E9%92%89%E9%80%9A%E8%AE%AF%E5%BD%95%E5%90%8C%E6%AD%A5%E6%9E%84%E5%BB%BA%E6%9C%AC%E5%9C%B0ldap%E6%9C%8D%E5%8A%A1/</link><pubDate>Sat, 31 Oct 2020 18:24:00 +0000</pubDate><guid>https://sunqi.site/blog/%E5%88%A9%E7%94%A8%E9%92%89%E9%92%89%E9%80%9A%E8%AE%AF%E5%BD%95%E5%90%8C%E6%AD%A5%E6%9E%84%E5%BB%BA%E6%9C%AC%E5%9C%B0ldap%E6%9C%8D%E5%8A%A1/</guid><description>
&lt;p&gt;目前钉钉已经成为很多企业日常处理流程的必备工具，但是由于钉钉并没有开放鉴权接口，无法让钉钉作为本地系统的统一鉴权系统使用，每次有同事加入或者离开时，都需要人为的对本地系统进行维护，非常繁琐。那么有没有一种方法可以让钉钉作为本地的统一鉴权系统使用呢？&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;目前，在我们公司使用OpenLDAP服务作为各个服务统一鉴权的入口，使用的应用系统包括：Gerrit/Jenkins/Yapi/Wiki/进度跟踪等，目前所有的系统都支持LDAP鉴权，所以如果能将钉钉的通讯录定期同步至LDAP中就可以实现统一鉴权的需求。但是由于钉钉的密码无法同步回本地，所以密码层面仍然是独立的。&lt;/p&gt;
&lt;p&gt;本文章的实现思路参考了&lt;a href="https://xujiwei.com/blog/2020/02/internal-authorize-based-on-dingtalk-virtual-ldap-keyclaok/"target="_blank" rel="noopener"&gt;《基于钉钉 + Virtual-LDAP + KeyCloak 的内网统一认证系统
》&lt;/a&gt;，感谢原作者的思路及贡献的virtual-ldap模块，本文所有的优化都是基于此文章基础上进行的优化。&lt;/p&gt;
&lt;h2&gt;实现思路&lt;span class="hx:absolute hx:-mt-20" id="实现思路"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%9e%e7%8e%b0%e6%80%9d%e8%b7%af" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;简单来说，我们希望能通过钉钉提供的LDAP作为统一鉴权方式，但是由于钉钉没有开放这个能力，那么我们需要将钉钉模拟一个LDAP服务。模拟出的LDAP环境，在内网环境中，我们对于LDAP信息的使用基本上围绕着用户名和密码，其他的信息以钉钉为准。所以，除了开放LDAP接口外，我们还需要提供用户界面，允许用户在内网修改密码。&lt;/p&gt;
&lt;p&gt;整体的实现思路如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;钉钉开发者平台：需要在钉钉开发者平台新建一个程序，获取鉴权信息后，赋予通讯录同步权限，提供给VirtualLDAP进行数据同步&lt;/li&gt;
&lt;li&gt;VirtualLDAP：该组件是上面提到的作者开发的虚拟LDAP组件，主要功能为同步钉钉通讯录，并以LDAP协议对外提供服务&lt;/li&gt;
&lt;li&gt;KeyCloak：对于这个场景过重，但是暂时没有发现更好的方案，可以触发自动同步并且可以让内网用户进行密码修改&lt;/li&gt;
&lt;li&gt;本地的全部系统按照LDAP配置方式即可实现鉴权&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-90.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;钉钉开发者平台&lt;span class="hx:absolute hx:-mt-20" id="钉钉开发者平台"&gt;&lt;/span&gt;
&lt;a href="#%e9%92%89%e9%92%89%e5%bc%80%e5%8f%91%e8%80%85%e5%b9%b3%e5%8f%b0" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这里我创建的是H5微应用，配置时有几点需要注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IP地址白名单：需要为你未来运行VirtualLDAP配置访问IP白名单，目前钉钉开发者平台对于同一个IP只能给一个应用使用，但是可以通过通配符进行配置，例如：192.168.10.*的方式，那么192.168.10网段所有地址均可以访问&lt;/li&gt;
&lt;li&gt;权限：需要为该应用开放所有通讯录只读权限即可&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-92.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;VirtualLDAP&lt;span class="hx:absolute hx:-mt-20" id="virtualldap"&gt;&lt;/span&gt;
&lt;a href="#virtualldap" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是基于Node.js开发的一款组件，主要用于同步钉钉通讯录和模拟LDAP协议。基于原作者版本，为了满足自身应用场景，进行了如下修改：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;由于作者没有提供Docker运行方式，所以在github的pull request中有人进行了改造&lt;/li&gt;
&lt;li&gt;仍然是在同一个pull request中，增加了pinyin组件，在LDAP中增加了一个pinyin属性，方便业务系统使用&lt;/li&gt;
&lt;li&gt;登录名和密码：为了防止公司人员重复，所以特别采用了全拼名称+电话号码后四位方式，作为唯一的用户名，而初始密码为全名名称+电话号码前四位，例如：张三的电话号码为13812345678，则登录名称为zhangsan5678，密码为zhangsan1381,&lt;/li&gt;
&lt;li&gt;在使用VirtualLDAP时，需要使用MySQL存储持久化数据，例如用户修改后的密码，所以对鉴权规则进行了修改，先检查数据库密码是否匹配，再检查LDAP&lt;/li&gt;
&lt;li&gt;实现了整体组件的编排，增加了docker-compose.yaml，方便用户使用，该编排文件中包含了KeyCloak、VirtualLDAP和MySQL&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;KeyCloak&lt;span class="hx:absolute hx:-mt-20" id="keycloak"&gt;&lt;/span&gt;
&lt;a href="#keycloak" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;KeyCloak两部分需要进行配置：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;管理员在第一次使用时配置VirtualLDAP的信息，用于用户同步，方便新用户修改密码&lt;/li&gt;
&lt;li&gt;新用户自行修改密码&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;正如之前所说，KeyCloak功能过于强大，这里用到的功能非常有限，如果有新的应用场景，欢迎留言。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-93.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;搭建方式&lt;span class="hx:absolute hx:-mt-20" id="搭建方式"&gt;&lt;/span&gt;
&lt;a href="#%e6%90%ad%e5%bb%ba%e6%96%b9%e5%bc%8f" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这里提供了完整的编排文件，直接使用即可完成整套环境的快速建立。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;git clone https://github.com/xiaoquqi/virtual-ldap
cd virtual-ldap/docker-compose
docker-compose up -d0&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;配置文件&lt;span class="hx:absolute hx:-mt-20" id="配置文件"&gt;&lt;/span&gt;
&lt;a href="#%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;VirtualLDAP配置文件修改。所有配置在virtual-ldap/docker-compose/config.js中进行修改，需要修改钉钉的appKey和appSecret，以及root DN的信息，配置文件有比较详细的介绍，所以这里不再赘述。&lt;/li&gt;
&lt;li&gt;KeyCloak的默认密码修改在docker-compose.yaml中&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;登录相关信息&lt;span class="hx:absolute hx:-mt-20" id="登录相关信息"&gt;&lt;/span&gt;
&lt;a href="#%e7%99%bb%e5%bd%95%e7%9b%b8%e5%85%b3%e4%bf%a1%e6%81%af" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;URL: ldap://ip:1389&lt;/li&gt;
&lt;li&gt;ManageDN: cn=admin,dc=oneprocloud,dc=com&lt;/li&gt;
&lt;li&gt;ManagePassword: password&lt;/li&gt;
&lt;li&gt;User Search Base: ou=People,o=department,dc=oneprocloud,dc=com&lt;/li&gt;
&lt;li&gt;User Search Filter: uid={0}&lt;/li&gt;
&lt;li&gt;Display Name LDAP attribute: cn&lt;/li&gt;
&lt;li&gt;Email Address LDAP attribute: mail&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;待优化&lt;span class="hx:absolute hx:-mt-20" id="待优化"&gt;&lt;/span&gt;
&lt;a href="#%e5%be%85%e4%bc%98%e5%8c%96" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;目前对于LDAP的组没有充分利用，配置文件中允许创建特定组，并且通过用户email进行匹配，如果需要可以进行配置&lt;/li&gt;
&lt;li&gt;如果有外部用户，暂时无方法进行创建，例如：如果需要在LDAP中增加一个非钉钉用户暂时无法实现，需要进行开发实现&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Kubernetes All-in-One环境安装</title><link>https://sunqi.site/blog/kubernetes%E5%9F%BA%E6%9C%AC%E5%AE%89%E8%A3%85/</link><pubDate>Fri, 31 Jul 2020 09:38:00 +0000</pubDate><guid>https://sunqi.site/blog/kubernetes%E5%9F%BA%E6%9C%AC%E5%AE%89%E8%A3%85/</guid><description>
&lt;h2&gt;Kubernetes安装及初始化&lt;span class="hx:absolute hx:-mt-20" id="kubernetes安装及初始化"&gt;&lt;/span&gt;
&lt;a href="#kubernetes%e5%ae%89%e8%a3%85%e5%8f%8a%e5%88%9d%e5%a7%8b%e5%8c%96" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;研发环境搭建Kubernetes All-in-One环境搭建。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h3&gt;CentOS 7初始化&lt;span class="hx:absolute hx:-mt-20" id="centos-7初始化"&gt;&lt;/span&gt;
&lt;a href="#centos-7%e5%88%9d%e5%a7%8b%e5%8c%96" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;## Set SELinux in permissive mode (effectively disabling it)
setenforce 0
##sed -i &amp;#39;s/^SELINUX=enforcing$/SELINUX=permissive/&amp;#39; /etc/selinux/config
sed -i &amp;#39;s/^SELINUX=enforcing$/SELINUX=disabled/&amp;#39; /etc/selinux/config
systemctl stop NetworkManager
systemctl disable NetworkManager
systemctl status firewalld
systemctl stop firewalld
systemctl disable firewalld
systemctl status firewalld
firewall-cmd --state
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum clean all &amp;amp;&amp;amp; yum makecache
yum update -y&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Docker国内源安装&lt;span class="hx:absolute hx:-mt-20" id="docker国内源安装"&gt;&lt;/span&gt;
&lt;a href="#docker%e5%9b%bd%e5%86%85%e6%ba%90%e5%ae%89%e8%a3%85" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;## Install Docker
curl -sSL https://get.daocloud.io/docker | sh -s -- &amp;#34;--mirror&amp;#34; &amp;#34;Aliyun&amp;#34;
## Replace docker repo
mkdir -p /etc/docker
cat &amp;gt; /etc/docker/daemon.json &amp;lt;&amp;lt;EOF
{
&amp;#34;registry-mirrors&amp;#34;: [&amp;#34;https://6m7d428u.mirror.aliyuncs.com&amp;#34;],
&amp;#34;dns&amp;#34;: [&amp;#34;114.114.114.114&amp;#34;],
&amp;#34;exec-opts&amp;#34;: [&amp;#34;native.cgroupdriver=systemd&amp;#34;],
&amp;#34;log-driver&amp;#34;: &amp;#34;json-file&amp;#34;,
&amp;#34;log-opts&amp;#34;: {
&amp;#34;max-size&amp;#34;: &amp;#34;100m&amp;#34;
},
&amp;#34;storage-driver&amp;#34;: &amp;#34;overlay2&amp;#34;,
&amp;#34;storage-opts&amp;#34;: [
&amp;#34;overlay2.override_kernel_check=true&amp;#34;
]
}
EOF
systemctl enable docker &amp;amp;&amp;amp; systemctl daemon-reload &amp;amp;&amp;amp; systemctl restart docker
curl -L https://get.daocloud.io/docker/compose/releases/download/1.28.4/docker-compose-`uname -s`-`uname -m` &amp;gt; /usr/local/bin/docker-compose
chmod &amp;#43;x /usr/local/bin/docker-compose&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;安装Kubernetes软件&lt;span class="hx:absolute hx:-mt-20" id="安装kubernetes软件"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85kubernetes%e8%bd%af%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;## step1 Installation Process
cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
exclude=kube*
EOF
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0 --disableexcludes=kubernetes
systemctl enable kubelet
## for CentOS 7
cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
vm.swappiness=0
EOF
sysctl --system
## from k8s 1.8, swap need to be cloased, otherwise k8s could not be started
## swapoff -a
## Modify /etc/fstab, comment swap mount&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;初始化Kubernetes集群&lt;span class="hx:absolute hx:-mt-20" id="初始化kubernetes集群"&gt;&lt;/span&gt;
&lt;a href="#%e5%88%9d%e5%a7%8b%e5%8c%96kubernetes%e9%9b%86%e7%be%a4" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;## Step2 initialization
## Specify kubernetes-version if mirror do not contain latest kubernetes container. ex: if kubeadm is version 1.18.5, you can only
## install kubernetes = 1.18.x
kubeadm init --pod-network-cidr=10.244.0.0/16 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version=1.18.0
## Response from output
## You should now deploy a pod network to the cluster.
## Run &amp;#34;kubectl apply -f [podnetwork].yaml&amp;#34; with one of the options listed at:
## https://kubernetes.io/docs/concepts/cluster-administration/addons/
## Then you can join any number of worker nodes by running the following on each as root:
## kubeadm join 192.168.10.111:6443 --token 1odaru.0by05advhbu7edgt \
## --discovery-token-ca-cert-hash sha256:3efb71c40cce36c5ed90fc8b5831233aba06eec26576088e8e7a7a892d272776
## Step3 To use cluster
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
## Step4 flannel Network
sysctl net.bridge.bridge-nf-call-iptables=1
kubectl apply -f https://gitee.com/xiaoquqi/flannel/raw/master/Documentation/kube-flannel.yml&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;允许Master节点运行Pods&lt;span class="hx:absolute hx:-mt-20" id="允许master节点运行pods"&gt;&lt;/span&gt;
&lt;a href="#%e5%85%81%e8%ae%b8master%e8%8a%82%e7%82%b9%e8%bf%90%e8%a1%8cpods" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;kubectl taint nodes --all node-role.kubernetes.io/master-&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;测试&lt;span class="hx:absolute hx:-mt-20" id="测试"&gt;&lt;/span&gt;
&lt;a href="#%e6%b5%8b%e8%af%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;安装Wordpress和MySQL&lt;span class="hx:absolute hx:-mt-20" id="安装wordpress和mysql"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85wordpress%e5%92%8cmysql" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;curl -LO https://raw.githubusercontent.com/xiaoquqi/k8s_demo/master/wordpress/mysql-deployment.yaml
curl -LO https://raw.githubusercontent.com/xiaoquqi/k8s_demo/master/wordpress/wordpress-deployment.yaml
curl -LO https://raw.githubusercontent.com/xiaoquqi/k8s_demo/master/wordpress/kustomization.yaml&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;执行安装&lt;span class="hx:absolute hx:-mt-20" id="执行安装"&gt;&lt;/span&gt;
&lt;a href="#%e6%89%a7%e8%a1%8c%e5%ae%89%e8%a3%85" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;kubectl apply -k ./&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;验证&lt;span class="hx:absolute hx:-mt-20" id="验证"&gt;&lt;/span&gt;
&lt;a href="#%e9%aa%8c%e8%af%81" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;kubectl get secrets
kubectl get pvc
kubectl get pods
kubectl get services wordpress&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;资源清理&lt;span class="hx:absolute hx:-mt-20" id="资源清理"&gt;&lt;/span&gt;
&lt;a href="#%e8%b5%84%e6%ba%90%e6%b8%85%e7%90%86" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;kubectl delete -k ./&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>CentOS 7和Docker初始化安装</title><link>https://sunqi.site/blog/centos-7%E5%88%9D%E5%A7%8B%E5%8C%96%E8%84%9A%E6%9C%AC/</link><pubDate>Fri, 31 Jul 2020 09:34:00 +0000</pubDate><guid>https://sunqi.site/blog/centos-7%E5%88%9D%E5%A7%8B%E5%8C%96%E8%84%9A%E6%9C%AC/</guid><description>
&lt;h2&gt;CentOS 7初始化&lt;span class="hx:absolute hx:-mt-20" id="centos-7初始化"&gt;&lt;/span&gt;
&lt;a href="#centos-7%e5%88%9d%e5%a7%8b%e5%8c%96" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;该安装脚本为搭建研发环境常用的脚本，记录在Blog中便于查阅。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;## Set SELinux in permissive mode (effectively disabling it)
setenforce 0
##sed -i &amp;#39;s/^SELINUX=enforcing$/SELINUX=permissive/&amp;#39; /etc/selinux/config
sed -i &amp;#39;s/^SELINUX=enforcing$/SELINUX=disabled/&amp;#39; /etc/selinux/config
systemctl stop NetworkManager
systemctl disable NetworkManager
systemctl status firewalld
systemctl stop firewalld
systemctl disable firewalld
systemctl status firewalld
firewall-cmd --state
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum clean all &amp;amp;&amp;amp; yum makecache
yum update -y&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Docker国内源安装&lt;span class="hx:absolute hx:-mt-20" id="docker国内源安装"&gt;&lt;/span&gt;
&lt;a href="#docker%e5%9b%bd%e5%86%85%e6%ba%90%e5%ae%89%e8%a3%85" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;## Install Docker
curl -sSL https://get.daocloud.io/docker | sh -s -- &amp;#34;--mirror&amp;#34; &amp;#34;Aliyun&amp;#34;
## Replace docker repo
mkdir -p /etc/docker
cat &amp;gt; /etc/docker/daemon.json &amp;lt;&amp;lt;EOF
{
&amp;#34;registry-mirrors&amp;#34;: [&amp;#34;https://6m7d428u.mirror.aliyuncs.com&amp;#34;],
&amp;#34;dns&amp;#34;: [&amp;#34;114.114.114.114&amp;#34;],
&amp;#34;exec-opts&amp;#34;: [&amp;#34;native.cgroupdriver=systemd&amp;#34;],
&amp;#34;log-driver&amp;#34;: &amp;#34;json-file&amp;#34;,
&amp;#34;log-opts&amp;#34;: {
&amp;#34;max-size&amp;#34;: &amp;#34;100m&amp;#34;
},
&amp;#34;storage-driver&amp;#34;: &amp;#34;overlay2&amp;#34;,
&amp;#34;storage-opts&amp;#34;: [
&amp;#34;overlay2.override_kernel_check=true&amp;#34;
]
}
EOF
systemctl enable docker &amp;amp;&amp;amp; systemctl daemon-reload &amp;amp;&amp;amp; systemctl restart docker
curl -L https://get.daocloud.io/docker/compose/releases/download/1.28.4/docker-compose-`uname -s`-`uname -m` &amp;gt; /usr/local/bin/docker-compose
chmod &amp;#43;x /usr/local/bin/docker-compose&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>[阿里云]使用DataQuotient 画像分析筛选优质基金</title><link>https://sunqi.site/blog/%E9%98%BF%E9%87%8C%E4%BA%91-%E4%BD%BF%E7%94%A8dataquotient-%E7%94%BB%E5%83%8F%E5%88%86%E6%9E%90%E7%AD%9B%E9%80%89%E4%BC%98%E8%B4%A8%E5%9F%BA%E9%87%91/</link><pubDate>Tue, 14 Apr 2020 11:10:17 +0000</pubDate><guid>https://sunqi.site/blog/%E9%98%BF%E9%87%8C%E4%BA%91-%E4%BD%BF%E7%94%A8dataquotient-%E7%94%BB%E5%83%8F%E5%88%86%E6%9E%90%E7%AD%9B%E9%80%89%E4%BC%98%E8%B4%A8%E5%9F%BA%E9%87%91/</guid><description>
&lt;p&gt;该教程是阿里云帮助文档一部分，这里做了进一步完善：https://help.aliyun.com/document_detail/160711.html?spm=a2c4g.11174283.6.603.682fa00bJ7AHYK&lt;/p&gt;
&lt;h2&gt;需求描述&lt;span class="hx:absolute hx:-mt-20" id="需求描述"&gt;&lt;/span&gt;
&lt;a href="#%e9%9c%80%e6%b1%82%e6%8f%8f%e8%bf%b0" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;4433法则通过对同类基金（例如股票类基金）长期和短期的表现进行分析，为您在众多基金中筛选少数优质基金。&lt;/p&gt;
&lt;pre&gt;
4433法则如下：
4：代表近一年收益率排名前1/4的基金。
4：代表近两年、三年、五年以来，收益率排名前1/4的基金。
3：指近六个月收益率排名前1/3的基金。
3：指近三个月以来收益率排名前1/3的基金。
&lt;/pre&gt;
&lt;p&gt;本教程为您演示如何从当日的1126个股票类的基金产品中，筛选出符合4433法则的69条优质基金。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;实现流程&lt;span class="hx:absolute hx:-mt-20" id="实现流程"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%9e%e7%8e%b0%e6%b5%81%e7%a8%8b" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-0.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;准备数据&lt;span class="hx:absolute hx:-mt-20" id="准备数据"&gt;&lt;/span&gt;
&lt;a href="#%e5%87%86%e5%a4%87%e6%95%b0%e6%8d%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;获取基金数据，从天天基金网接口获取股票型基金的不同时间区间的收益率数据&lt;/li&gt;
&lt;li&gt;数据输入MaxCompute&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;创建基金信息标签系统&lt;span class="hx:absolute hx:-mt-20" id="创建基金信息标签系统"&gt;&lt;/span&gt;
&lt;a href="#%e5%88%9b%e5%bb%ba%e5%9f%ba%e9%87%91%e4%bf%a1%e6%81%af%e6%a0%87%e7%ad%be%e7%b3%bb%e7%bb%9f" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;新建实体，用于将数源和待分析的对象绑定在一起&lt;/li&gt;
&lt;li&gt;绑定标签，将数据源与标签进行绑定&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;筛选并导出优质基金群体&lt;span class="hx:absolute hx:-mt-20" id="筛选并导出优质基金群体"&gt;&lt;/span&gt;
&lt;a href="#%e7%ad%9b%e9%80%89%e5%b9%b6%e5%af%bc%e5%87%ba%e4%bc%98%e8%b4%a8%e5%9f%ba%e9%87%91%e7%be%a4%e4%bd%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;同步标签至RDS，这个例子中因为只是从MaxCompute到RDS，真实环境中有可能从多个数据源同步至目标RDS中，该服务支持数据的合并等&lt;/li&gt;
&lt;li&gt;根据上述预先建立好的模型，新建长期和短期表现较好群体&lt;/li&gt;
&lt;li&gt;计算群体&lt;/li&gt;
&lt;li&gt;导出优质基金列表&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;实现过程&lt;span class="hx:absolute hx:-mt-20" id="实现过程"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%9e%e7%8e%b0%e8%bf%87%e7%a8%8b" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;前提条件&lt;span class="hx:absolute hx:-mt-20" id="前提条件"&gt;&lt;/span&gt;
&lt;a href="#%e5%89%8d%e6%8f%90%e6%9d%a1%e4%bb%b6" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;本教程基于DataQuotient 画像分析、MaxCompute和RDS产品，请确保您已购买该产品。&lt;/p&gt;
&lt;h3&gt;获取基础数据&lt;span class="hx:absolute hx:-mt-20" id="获取基础数据"&gt;&lt;/span&gt;
&lt;a href="#%e8%8e%b7%e5%8f%96%e5%9f%ba%e7%a1%80%e6%95%b0%e6%8d%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;根据教程提供的线索，从天天基金网获取了全部股票型基金的数据，脚本已经提交到Github上，有需要的可以直接拿过去用。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;git clone https://github.com/xiaoquqi/fund
cd fund
python fund-cli.py -d -v&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;在MaxCompute导入数据&lt;span class="hx:absolute hx:-mt-20" id="在maxcompute导入数据"&gt;&lt;/span&gt;
&lt;a href="#%e5%9c%a8maxcompute%e5%af%bc%e5%85%a5%e6%95%b0%e6%8d%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;h4&gt;开通MaxCompute服务&lt;span class="hx:absolute hx:-mt-20" id="开通maxcompute服务"&gt;&lt;/span&gt;
&lt;a href="#%e5%bc%80%e9%80%9amaxcompute%e6%9c%8d%e5%8a%a1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;之前我并没有开通过MaxCompute服务，所以需要开通一下DataWorks，才能使用MaxCompute服务。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-1.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;这个就是DataWorks控制台，从操作上看局限性很高（比如不支持删除表
&lt;img src="https://sunqi.site/images/pasted-2.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;），所以建议采用IntelliJ IDEA中的MaxCompute Studio插件，安装方式见：https://www.alibabacloud.com/help/zh/doc-detail/50889.htm?spm=a2c63.p38356.b99.275.5e652ea3SZgau1
&lt;img src="https://sunqi.site/images/pasted-41.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h4&gt;创建MaxCompute表&lt;span class="hx:absolute hx:-mt-20" id="创建maxcompute表"&gt;&lt;/span&gt;
&lt;a href="#%e5%88%9b%e5%bb%bamaxcompute%e8%a1%a8" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;由于做的时候才发现数据源并没有近五年的数据，所以修改了一下创建语句，先把表名建立起来，之后进入DDL模式进行表创建：&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;create table if not exists fund_profit_stocktype
( `fundid` bigint comment &amp;#39;基金编号&amp;#39;,
`fundname` string comment &amp;#39;基金名称&amp;#39;,
`latest3months` double comment &amp;#39;近三月&amp;#39;,
`latest6months` double comment &amp;#39;近六月&amp;#39;,
`latest1year` double comment &amp;#39;近一年&amp;#39;,
`latest2years` double comment &amp;#39;近两年&amp;#39;,
`latest3years` double comment &amp;#39;近三年&amp;#39;,
`currentyear` double comment &amp;#39;今年来&amp;#39;,
`fromcreated` double comment &amp;#39;成立来&amp;#39;,
) comment &amp;#39;基金信息&amp;#39; ;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-3.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h4&gt;导入数据&lt;span class="hx:absolute hx:-mt-20" id="导入数据"&gt;&lt;/span&gt;
&lt;a href="#%e5%af%bc%e5%85%a5%e6%95%b0%e6%8d%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;原有文档是通过DDL去创建的数据，由于我们已经将数据保存在CSV文件中，所以我们选择导入方式试一下。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-4.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-5.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-7.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;不知道什么原因，下拉菜单选择并不生效，于是我决定将原有CSV无用字段全部删除，便于后续测试。删除字段的时候，发现我获取的数据并不包含近五年的项，但是包含成立以来的数据，所以对字段进行一下修改。上面的SQL是我修改过的。页面好像并没有删除表的功能，所以为了不影响测试，我重新建了一张表来导入数据。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-8.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;关联云计算资源&lt;span class="hx:absolute hx:-mt-20" id="关联云计算资源"&gt;&lt;/span&gt;
&lt;a href="#%e5%85%b3%e8%81%94%e4%ba%91%e8%ae%a1%e7%ae%97%e8%b5%84%e6%ba%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;回到画像服务，继续进行配置&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-13.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-14.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;我用的主账号的AK/KS竟然提示我权限不足，于是我去查了半天RAM文档，以为MaxCompute需要更精确的授权，结果发现是提示信息误导了我，只是我的project写错了，最后project信息还是回到DataWorks控制台才找到，如下图所示。&lt;/p&gt;
&lt;p&gt;需要添加这么多信息感觉不是特别方便，都是阿里云的资源感觉没有必要使用AK/KS去通讯吧？&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-15.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-16.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;配置好后的云计算资源&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-17.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;标签管理&lt;span class="hx:absolute hx:-mt-20" id="标签管理"&gt;&lt;/span&gt;
&lt;a href="#%e6%a0%87%e7%ad%be%e7%ae%a1%e7%90%86" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;配置好后，可以继续进行标签配置。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-9.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-10.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h4&gt;关联MaxCompute表&lt;span class="hx:absolute hx:-mt-20" id="关联maxcompute表"&gt;&lt;/span&gt;
&lt;a href="#%e5%85%b3%e8%81%94maxcompute%e8%a1%a8" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-11.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;如果你没有正确配置云计算资源，是无法看到MaxCompute下的表。
&lt;img src="https://sunqi.site/images/pasted-12.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;绑定表和字段
&lt;img src="https://sunqi.site/images/pasted-18.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-19.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-20.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;字段绑定后无法删除，需要到详情中删除
&lt;img src="https://sunqi.site/images/pasted-21.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-22.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;最开始显示为0，后来又显示出数据总量，但是根据上方提示，MaxCompute是不支持显示的。
&lt;img src="https://sunqi.site/images/pasted-23.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;过了一会又出现了1185的数据总量，不知道为什么
&lt;img src="https://sunqi.site/images/pasted-33.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-25.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;筛选出优质基金群体&lt;span class="hx:absolute hx:-mt-20" id="筛选出优质基金群体"&gt;&lt;/span&gt;
&lt;a href="#%e7%ad%9b%e9%80%89%e5%87%ba%e4%bc%98%e8%b4%a8%e5%9f%ba%e9%87%91%e7%be%a4%e4%bd%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;h4&gt;同步标签至RDS&lt;span class="hx:absolute hx:-mt-20" id="同步标签至rds"&gt;&lt;/span&gt;
&lt;a href="#%e5%90%8c%e6%ad%a5%e6%a0%87%e7%ad%be%e8%87%b3rds" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-24.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-26.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-27.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-28.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-29.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;显示同步成功，但是发现输出的信息里有红色的信息，以为是错误，但是仔细一看又是INFO级别的日志，而且显示的太长了。
&lt;img src="https://sunqi.site/images/pasted-31.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-32.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h4&gt;群体画像&lt;span class="hx:absolute hx:-mt-20" id="群体画像"&gt;&lt;/span&gt;
&lt;a href="#%e7%be%a4%e4%bd%93%e7%94%bb%e5%83%8f" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;需要切换至群体画像的工作空间。
&lt;img src="https://sunqi.site/images/pasted-30.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;新建短期表现优质的基金。
&lt;img src="https://sunqi.site/images/pasted-34.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;如果配置正确，可以从结果中看出筛选出的结果。
&lt;img src="https://sunqi.site/images/pasted-35.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-36.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;新建长期表现优质的基金。
&lt;img src="https://sunqi.site/images/pasted-37.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;使用群体计算，找出二者的交集。这个就是我们希望得到的结果。
&lt;img src="https://sunqi.site/images/pasted-38.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/pasted-39.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;利用下载功能，可以下载我们筛选出来的基金。
&lt;img src="https://sunqi.site/images/pasted-40.png" alt="upload successful" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;总结&lt;span class="hx:absolute hx:-mt-20" id="总结"&gt;&lt;/span&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;使用阿里云DataQuotient服务可以快速帮助用户构建用户画像，能够满足多种应用场景，利用函数计算进行数据爬取定期导入到MaxCompute，可以很容易定制出优质基金筛选功能的API接口，供上层业务场景使用。&lt;/p&gt;</description></item><item><title>[Python]利用ZooKeeper构建分布式定时任务</title><link>https://sunqi.site/blog/2020-03-24-python-how-to-use-zookeeper-to-build-distribution-system/</link><pubDate>Tue, 24 Mar 2020 20:39:06 +0000</pubDate><guid>https://sunqi.site/blog/2020-03-24-python-how-to-use-zookeeper-to-build-distribution-system/</guid><description>
&lt;p&gt;本文涉及的源代码路径：&lt;a href="https://github.com/xiaoquqi/openstackclient-demo/tree/master/tooz"target="_blank" rel="noopener"&gt;https://github.com/xiaoquqi/openstackclient-demo/tree/master/tooz&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;一、目前现状及存在的问题&lt;span class="hx:absolute hx:-mt-20" id="一目前现状及存在的问题"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%80%e7%9b%ae%e5%89%8d%e7%8e%b0%e7%8a%b6%e5%8f%8a%e5%ad%98%e5%9c%a8%e7%9a%84%e9%97%ae%e9%a2%98" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在实际业务系统中，经常有需要定时执行的任务，例如任务状态的定时更新、定时发送状态信息等。在我们的云迁移产品中，允许用户可以设定周期同步规则，定期执行数据同步并调用云平台接口执行快照操作。在单机版本中，通常在同一时间点并发任务量较少的情况下，问题并不是很突出，但是随着我们将云迁移服务从单机版本改造为平台版本后，当多个用户的多台主机同时触发快照任务时，一方面传统的设计方式就成为了瓶颈，无法保证用户的同步任务在同一时间点被触发（需要排队）；另外一方面，目前Active-Passive（简称AP方式）的高可靠部署方式无法利用集群横向扩展能力，无法满足高并发的要求。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/1.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h3&gt;软件架构设计&lt;span class="hx:absolute hx:-mt-20" id="软件架构设计"&gt;&lt;/span&gt;
&lt;a href="#%e8%bd%af%e4%bb%b6%e6%9e%b6%e6%9e%84%e8%ae%be%e8%ae%a1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;目前云迁移平台的各个服务模块在设计上使用了OpenStack方式，即大部分模块复用了类似Nova的实现框架。即API层直接集成oslo.service中定义好的WSGI Service基类，Worker采用了olso.service中定义好的Service基类，即Eventlet协程方式，API与Worker通讯使用RabbitMQ，API南向接口除少量直接更新数据库操作采用同步接口外，其余所有接口全部使用异步方式。API发送请求后，得到202 Accepted回复，后续通过GET接口不断轮询任务接口等到任务完成。&lt;/p&gt;
&lt;h3&gt;高可靠部署&lt;span class="hx:absolute hx:-mt-20" id="高可靠部署"&gt;&lt;/span&gt;
&lt;a href="#%e9%ab%98%e5%8f%af%e9%9d%a0%e9%83%a8%e7%bd%b2" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;根据OpenStack官方的HA部署文档（&lt;a href="https://docs.openstack.org/ha-guide/"target="_blank" rel="noopener"&gt;https://docs.openstack.org/ha-guide/&lt;/a&gt;），将服务分为无状态和有状态两种。无服务状态只需要直接部署多份即可，有状态服务往往需要通过Pacemaker控制副本数量，来保证高可靠。在云迁移平台部署中，我们将全部服务部署于K8S集群中，所以并不需要Pacemaker+Corosync这样的组件（Pacemaker节点上线为16）。但是，由于需要保持定时任务在单一节点被触发（避免任务被重复执行），所以承载定时快照的模块只能同时存在一个容器在运行，无法构成Active-Active（简称AA方式）模式。这样的部署方式，也造成了上述提到的AP模式对扩展性的瓶颈。&lt;/p&gt;
&lt;h2&gt;二、问题思路及解决方案&lt;span class="hx:absolute hx:-mt-20" id="二问题思路及解决方案"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%8c%e9%97%ae%e9%a2%98%e6%80%9d%e8%b7%af%e5%8f%8a%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;思路一、利用消息队列解耦任务分配与任务执行&lt;span class="hx:absolute hx:-mt-20" id="思路一利用消息队列解耦任务分配与任务执行"&gt;&lt;/span&gt;
&lt;a href="#%e6%80%9d%e8%b7%af%e4%b8%80%e5%88%a9%e7%94%a8%e6%b6%88%e6%81%af%e9%98%9f%e5%88%97%e8%a7%a3%e8%80%a6%e4%bb%bb%e5%8a%a1%e5%88%86%e9%85%8d%e4%b8%8e%e4%bb%bb%e5%8a%a1%e6%89%a7%e8%a1%8c" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;从上述对现状的描述，我们不难看出，现有任务分配与任务执行是在同一个任务中执行的，当存在大量任务时，任务执行会对任务产生产生很大的影响。同时，由于任务执行唯一性的需要，在部署上只能采用上述的AP模式，导致任务无法由多个任务同时执行。&lt;br /&gt;所以，我们可以将任务分解为分配和执行两个阶段。任务分配上，单纯的进行任务生成，由于任务生成相对较快，生成后的任务发送至消息队列，由无状态性的Worker接收后执行。这样就解决了单点执行的效率低下问题。&lt;br /&gt;但是这样的解决方案仍然存在缺陷，我们在任务生成的模块仍然必须需要采用AP模式部署，来保证任务的唯一性。如果在任务数量非常庞大时，该部分仍然是一个瓶颈；另外一方面这样的实现方式，我们需要将任务生成部分单独拆分出一个模块，同时增加了开发和部署上的复杂度，所以我们来看一下第二种解决思路。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/2.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;思路二、利用Zookeeper构建可扩展的分布式定时任务&lt;span class="hx:absolute hx:-mt-20" id="思路二利用zookeeper构建可扩展的分布式定时任务"&gt;&lt;/span&gt;
&lt;a href="#%e6%80%9d%e8%b7%af%e4%ba%8c%e5%88%a9%e7%94%a8zookeeper%e6%9e%84%e5%bb%ba%e5%8f%af%e6%89%a9%e5%b1%95%e7%9a%84%e5%88%86%e5%b8%83%e5%bc%8f%e5%ae%9a%e6%97%b6%e4%bb%bb%e5%8a%a1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;为了解决思路一的局限性，我们本质上要解决的是任务执行的分布式问题，即如何让Worker不重复的判定任务的归属后再执行，由被动改为主动。&lt;/p&gt;
&lt;p&gt;我们来看以下几种场景：&lt;br /&gt;1、假定我们现在有3个Worker可以用于任务生成，在某一个时间点，将同时产生100个任务。如何由这3个Worker主动产生属于自身负责的任务？&lt;br /&gt;2、我们知道大部分云平台目前都有云原生的弹性扩展服务，如果我们结合云平台的弹性扩展服务自动将我们用于任务生成的Worker动态进行调整时，例如变为6个时，还能保证这100个任务能够被自动的由6个节点不重复的产生呢？&lt;br /&gt;3、当负载降低后，节点数量由6个变为3个后，如何恢复场景1的状态呢？保证任务不漏生成呢？&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/3.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;如果想达到以上场景需求，需要以下几个条件：&lt;br /&gt;1、节点之间能够准确知道其他节点的存在——利用Zookeeper进行服务发现&lt;br /&gt;2、尽量合理的进行任务（对象）分布，同时兼顾节点增加和减少时，降低对象分配时的位移——利用一致性哈希环&lt;/p&gt;
&lt;h2&gt;三、技术要点&lt;span class="hx:absolute hx:-mt-20" id="三技术要点"&gt;&lt;/span&gt;
&lt;a href="#%e4%b8%89%e6%8a%80%e6%9c%af%e8%a6%81%e7%82%b9" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1、Zookeeper&lt;span class="hx:absolute hx:-mt-20" id="1zookeeper"&gt;&lt;/span&gt;
&lt;a href="#1zookeeper" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;对于Zookeeper的解释网络上有各种各样的详细集成，这里就不再赘述了，这里我直接引用了这篇文章（https://www.jianshu.com/p/50becf121c66）中开头的内容：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;官方文档上这么解释zookeeper，它是一个分布式服务框架，是Apache Hadoop 的一个子项目，它主要是用来解决分布式应用中经常遇到的一些数据管理问题，如：统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。
上面的解释有点抽象，简单来说zookeeper=文件系统+监听通知机制。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/4.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;从我们应用场景的角度看，Zookeeper帮我们解决了Worker之间相互认识的过程，及时、准确的告诉我们：到底现在有多少个和我相同的活跃节点存在。至于底层是如何实现的，感兴趣的同学可以查看具体的Zookeeper实现原理文档，这里只介绍与我们实现相关的内容。&lt;/p&gt;
&lt;h3&gt;2、一致性Hash&lt;span class="hx:absolute hx:-mt-20" id="2一致性hash"&gt;&lt;/span&gt;
&lt;a href="#2%e4%b8%80%e8%87%b4%e6%80%a7hash" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;又是一个经典的算法，相关的文章也很多，这里推荐大家几篇，这里摘抄出对理解我们实现有价值的内容。 参考文档：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;《面试必备：什么是一致性Hash算法？》&lt;a href="https://zhuanlan.zhihu.com/p/34985026"target="_blank" rel="noopener"&gt;https://zhuanlan.zhihu.com/p/34985026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;《五分钟看懂一致性哈希算法》&lt;a href="https://juejin.im/post/5ae1476ef265da0b8d419ef2"target="_blank" rel="noopener"&gt;https://juejin.im/post/5ae1476ef265da0b8d419ef2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;《一致性hash在分布式系统中的应用》&lt;a href="http://www.firefoxbug.com/index.php/archives/2791/"target="_blank" rel="noopener"&gt;http://www.firefoxbug.com/index.php/archives/2791/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2.1 关于一致性哈希算法&lt;span class="hx:absolute hx:-mt-20" id="21-关于一致性哈希算法"&gt;&lt;/span&gt;
&lt;a href="#21-%e5%85%b3%e4%ba%8e%e4%b8%80%e8%87%b4%e6%80%a7%e5%93%88%e5%b8%8c%e7%ae%97%e6%b3%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;blockquote&gt;
&lt;p&gt;一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的，设计目标是为了解决因特网中的热点(Hot spot)问题，初衷和CARP十分类似。一致性哈希修正了CARP使用的简单哈希算法带来的问题，使得DHT可以在P2P环境中真正得到应用。但现在一致性hash算法在分布式系统中也得到了广泛应用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;2.2 一致性哈希算法在缓存技术中的应用&lt;span class="hx:absolute hx:-mt-20" id="22-一致性哈希算法在缓存技术中的应用"&gt;&lt;/span&gt;
&lt;a href="#22-%e4%b8%80%e8%87%b4%e6%80%a7%e5%93%88%e5%b8%8c%e7%ae%97%e6%b3%95%e5%9c%a8%e7%bc%93%e5%ad%98%e6%8a%80%e6%9c%af%e4%b8%ad%e7%9a%84%e5%ba%94%e7%94%a8" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/5.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;上述的方式虽然提升了性能，我们不再需要对整个Redis服务器进行遍历！但是，使用上述Hash算法进行缓存时，会出现一些缺陷，主要体现在服务器数量变动的时候，所有缓存的位置都要发生改变！
试想一下，如果4台缓存服务器已经不能满足我们的缓存需求，那么我们应该怎么做呢？很简单，多增加几台缓存服务器不就行了！假设：我们增加了一台缓存服务器，那么缓存服务器的数量就由4台变成了5台。那么原本hash(a.png) % 4 = 2 的公式就变成了hash(a.png) % 5 = ？ ， 可想而知这个结果肯定不是2的，这种情况带来的结果就是当服务器数量变动时，所有缓存的位置都要发生改变！换句话说，当服务器数量发生改变时，所有缓存在一定时间内是失效的，当应用无法从缓存中获取数据时，则会向后端数据库请求数据（还记得上一篇的《缓存雪崩》吗？）！
同样的，假设4台缓存中突然有一台缓存服务器出现了故障，无法进行缓存，那么我们则需要将故障机器移除，但是如果移除了一台缓存服务器，那么缓存服务器数量从4台变为3台，也是会出现上述的问题！
所以，我们应该想办法不让这种情况发生，但是由于上述Hash算法本身的缘故，使用取模法进行缓存时，这种情况是无法避免的，为了解决这些问题，Hash一致性算法（一致性Hash算法）诞生了！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;2.3 一致性哈希在缓存中的应用&lt;span class="hx:absolute hx:-mt-20" id="23-一致性哈希在缓存中的应用"&gt;&lt;/span&gt;
&lt;a href="#23-%e4%b8%80%e8%87%b4%e6%80%a7%e5%93%88%e5%b8%8c%e5%9c%a8%e7%bc%93%e5%ad%98%e4%b8%ad%e7%9a%84%e5%ba%94%e7%94%a8" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;初始状态，将节点映射到哈希环中&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/6.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;将对象映射到换后，找到负责处理的Node节点。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/7.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;容错性，Node C出现故障后，只需要将Object C迁移到Node D上。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/8.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;增加节点，此时增加了Node X，在Node C右侧，那么此时只有Object C需要移动到Node X节点。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/9.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;3、tooz和kazoo&lt;span class="hx:absolute hx:-mt-20" id="3tooz和kazoo"&gt;&lt;/span&gt;
&lt;a href="#3tooz%e5%92%8ckazoo" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Python中操作zookeeper的项目叫kazoo（&lt;a href="https://kazoo.readthedocs.io/en/latest/"target="_blank" rel="noopener"&gt;https://kazoo.readthedocs.io/en/latest/&lt;/a&gt;）。&lt;br /&gt;tooz是OpenStack中为简化开发人员操作分布式系统一致性所开发的组件，利用底层组件抽象出一致性组成员管理、分布式锁、选举、构建哈希环等。tooz除支持zookeeper作为后端，还可以支持Memcached、Redis、IPC、File、PostgreSQL、MySQL、Etcd、Consul等。&lt;br /&gt;有关于tooz的发展历史可以参考：&lt;a href="https://julien.danjou.info/python-distributed-membership-lock-with-tooz/"target="_blank" rel="noopener"&gt;https://julien.danjou.info/python-distributed-membership-lock-with-tooz/&lt;/a&gt;&lt;br /&gt;这里我们主要使用tooz操作zookeeper实现我们的一致性组及一致性哈希。&lt;/p&gt;
&lt;h3&gt;4、oslo相关项目&lt;span class="hx:absolute hx:-mt-20" id="4oslo相关项目"&gt;&lt;/span&gt;
&lt;a href="#4oslo%e7%9b%b8%e5%85%b3%e9%a1%b9%e7%9b%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这几年一直在做OpenStack项目，从OpenStack项目中学习到很多设计、架构、研发管理等各种新知识、新理念。oslo项目就是在OpenStack不断的迭代中产生的公共项目库，这些库可以让你非常轻松的构建基于Python的构建近似于OpenStack的分布式、可扩展的微服务系统。&lt;br /&gt;之前在从事OpenStack开发培训过程中，有专门的一节课去讲解OpenStack中用到的公共库，其中oslo相关项目就是非常重要的一部分内容。olso项目设计的库非常多，在这个内容中会涉及到oslo.config、oslo.log、oslo.service、oslo.utils和oslo.messaging项目。严格意义上来说，为了更精准控制任务，我们还应该引入oslo.db项目由数据库持久化的维护任务运行状态，包括任务回收等工作，但是本次内容主要讲解的是zookeeper，所以这部分的内容需要开发者在实际项目中去实现。&lt;br /&gt;关于olso开发的内容，我会以视频课程的形式为大家讲解，敬请期待。&lt;/p&gt;
&lt;h2&gt;四、实现过程&lt;span class="hx:absolute hx:-mt-20" id="四实现过程"&gt;&lt;/span&gt;
&lt;a href="#%e5%9b%9b%e5%ae%9e%e7%8e%b0%e8%bf%87%e7%a8%8b" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1、Zookeeper部署&lt;span class="hx:absolute hx:-mt-20" id="1zookeeper部署"&gt;&lt;/span&gt;
&lt;a href="#1zookeeper%e9%83%a8%e7%bd%b2" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker-compose -f zookeeper.yml -d up&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;启动完成后，将使用本地的三个容器作为zookeeper的三个节点和三个不同的端口（2181/2182/2183）便于zookeeper连接。如果在生产环境中部署时，可以使用云原生服务或部署在多个可用区的方式，保证高可靠。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/10.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h4&gt;Zookeeper常用命令行&lt;span class="hx:absolute hx:-mt-20" id="zookeeper常用命令行"&gt;&lt;/span&gt;
&lt;a href="#zookeeper%e5%b8%b8%e7%94%a8%e5%91%bd%e4%bb%a4%e8%a1%8c" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;进入容器，就可以使用zkCli.sh进入zookeeper的CLI模式。如果是初次接触zookeeper，可以把zookeeper理解成一个文件系统，这里我们常用的命令就是ls。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; -it zookeeper_zoo1_1 bash
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; bin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zkCli.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;看到这样的提示，就表示连接成功了。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/11.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;如上面提到的zookeeper的存储结构所示，我们先从根节点（/）进行获取。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls /&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;此时返回&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/12.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;这里zookeeper目录属于保留的目录，我们来看一下tooz的内容。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls /tooz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;此时返回&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/13.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;如果我们想继续查看distribution_tasks的内容，可以继续使用ls命令获取。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls /tooz/distribution_tasks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;通常我们会为每一个加入的节点取一个唯一的标识，当节点加入后我们使用ls命令就可以看到，如果离开了，则返回为空。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/14.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;zookeeper常用的命令还包括get，stat等获取value和更详细的信息，还包含更新节点操作set和删除节点rm。这里面就不做一一介绍了，我们直接操作zookeeper主要是为了帮助大家更好的理解程序逻辑。&lt;br /&gt;具体的命令行信息可以参考：&lt;a href="https://www.tutorialspoint.com/zookeeper/zookeeper_cli.htm"target="_blank" rel="noopener"&gt;https://www.tutorialspoint.com/zookeeper/zookeeper_cli.htm&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;2、tooz基本使用方法&lt;span class="hx:absolute hx:-mt-20" id="2tooz基本使用方法"&gt;&lt;/span&gt;
&lt;a href="#2tooz%e5%9f%ba%e6%9c%ac%e4%bd%bf%e7%94%a8%e6%96%b9%e6%b3%95" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;关于tooz的两个示例主要来自于这篇博客：&lt;a href="https://dzone.com/articles/scaling-a-polling-python-application-with-tooz"target="_blank" rel="noopener"&gt;https://dzone.com/articles/scaling-a-polling-python-application-with-tooz&lt;/a&gt;&lt;br /&gt;原文中的例子是有些Bug的，这里面进行重新进行了优化和整理，并且使用zookeeper替代etcd3驱动。&lt;/p&gt;
&lt;h4&gt;2.1 组成员（tooz/test_tooz/test_group_members.py）&lt;span class="hx:absolute hx:-mt-20" id="21-组成员tooztest_tooztest_group_memberspy"&gt;&lt;/span&gt;
&lt;a href="#21-%e7%bb%84%e6%88%90%e5%91%98tooztest_tooztest_group_memberspy" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;在这个例子中，我们主要为大家演示tooz如何进行组成员的管理。结合我们自身的需求，这里的成员就是每一个Worker。通过这个列子我们将观察三种不同场景的变化：&lt;br /&gt;1、初始状态下，我们只能看到一个成员；&lt;br /&gt;2、当启动了一个新的进程时，第一个成员马上会发现有第二个成员的加入；&lt;br /&gt;3、同时，当我们用CTRL + C结束某一个进程时，另外一个活着的进程会立即发现组成员的变化。&lt;/p&gt;
&lt;h5&gt;时序图&lt;span class="hx:absolute hx:-mt-20" id="时序图"&gt;&lt;/span&gt;
&lt;a href="#%e6%97%b6%e5%ba%8f%e5%9b%be" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h5&gt;&lt;p&gt;这里为了更直观表达，用时序图来说明程序的运行逻辑。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/15.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h5&gt;完整的代码&lt;span class="hx:absolute hx:-mt-20" id="完整的代码"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%8c%e6%95%b4%e7%9a%84%e4%bb%a3%e7%a0%81" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h5&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;##!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;tooz&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;coordination&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;%Y-%m-&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s2"&gt; %H:%M:%S&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ZOOKEEPER_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;zookeeper://localhost:2181&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Check that a client and group ids are passed as arguments&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Usage: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;client id&amp;gt; &amp;lt;group id&amp;gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Get the Coordinator object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coordination&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_coordinator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ZOOKEEPER_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Start it (initiate connection).&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start_heart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Create the group&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;coordination&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GroupAlreadyExist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Join the group&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# # Print the members list&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# #c.run_watchers()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;members&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_members&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;[&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;]Current nodes in cluster: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;members&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CTRL C is pressed!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# # Leave the group&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;leave_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;[&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;]After leave cluster nodes: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_members&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# # Stop when we&amp;#39;re done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h5&gt;执行效果&lt;span class="hx:absolute hx:-mt-20" id="执行效果"&gt;&lt;/span&gt;
&lt;a href="#%e6%89%a7%e8%a1%8c%e6%95%88%e6%9e%9c" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h5&gt;&lt;p&gt;第一个成员&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python test_group_members.py client1 group1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/16.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;第二个成员加入，观察第一个成员的标准输出，为了观察加入集群的时间，我们加入了date&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;date &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; python test_group_members.py client2 group1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/17.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;第一个脚本的标准输出，在16:07:27秒的时候加入了集群:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/18.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;将第二个成员关闭，直接在第二个成员脚本按CTRL + C，首先观察第二个成员的输出：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/19.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;第一个成员的输出，在16:08:51分时，集群中已经没有了第二个成员了：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/20.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h4&gt;2.2 一致性哈希（tooz/test_tooz/test_ping.py）&lt;span class="hx:absolute hx:-mt-20" id="22-一致性哈希tooztest_tooztest_pingpy"&gt;&lt;/span&gt;
&lt;a href="#22-%e4%b8%80%e8%87%b4%e6%80%a7%e5%93%88%e5%b8%8ctooztest_tooztest_pingpy" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;这个模拟测试中，使用分布式任务去ping某一个C类网段(255个IP地址)中的全部IP地址，如果由一个任务去完成，那么只能顺序执行，无法满足并发需求，这里采用一致性哈希算法，让任务分布在各个Worker上。为了节省时间，我们将原有程序中的实际ping换成了time.sleep等待方式。&lt;br /&gt;另外在程序启动后，我们默认等待10秒等待其他成员(member)加入，在实际开发过程中，还需要对任务的状态进行严格控制，防止同一任务重复被执行，在演示代码中主要偏重演示分布式，所以并没有在任务状态上增加过多处理。&lt;/p&gt;
&lt;h5&gt;时序图&lt;span class="hx:absolute hx:-mt-20" id="时序图-1"&gt;&lt;/span&gt;
&lt;a href="#%e6%97%b6%e5%ba%8f%e5%9b%be-1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h5&gt;&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/21.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;代码需要说明的几点：&lt;br /&gt;0、在程序开始时，我们默认等待了10秒，等待其他节点加入，如果在循环开始后，再有新加入的节点时，由于并不知道第一个节点已经处理过的任务，所以在第二个Worker加入后根据当时哈希环对之前的任务重新分配并执行，造成了重复执行，这个问题需要通过额外的手段（例如数据库记录先前执行的任务状态）监控任务状态来防止任务重新执行。&lt;br /&gt;1、代码中使用了tooz内置的Hash环，但是也可以在外部自己构建哈希环，我们在后续最终的例子中还是采用了外部构建哈希环的方法。&lt;br /&gt;2、Tooz partitioner依赖于watchers，所以在每次循环的时候必须要调用run_watchers即使获取成员的加入和离开。&lt;br /&gt;3、无论是group还是member在变量传递时都要变成bytes类型，这样可以确保对象的唯一性，所以在代码处理上都用到了encode()方法。&lt;br /&gt;4、__tooz_hash__方法需要在使用Partition时自己实现，能够唯一标识出对象的方法，例如ID、名称等信息。&lt;/p&gt;
&lt;h5&gt;完整的代码&lt;span class="hx:absolute hx:-mt-20" id="完整的代码-1"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%8c%e6%95%b4%e7%9a%84%e4%bb%a3%e7%a0%81-1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h5&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;##!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## -*- coding: utf-8 -*-&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;subprocess&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;tooz&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;coordination&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;%Y-%m-&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s2"&gt; %H:%M:%S&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ZOOKEEPER_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;zookeeper://localhost:2181&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Check that a client and group ids are passed as arguments&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Usage: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;client id&amp;gt; &amp;lt;group id&amp;gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Get the Coordinator object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coordination&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_coordinator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ZOOKEEPER_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Start it (initiate connection).&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start_heart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Join the partitioned group&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join_partitioned_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hostname&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__tooz_hash__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Returns a unique byte identifier so Tooz
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; can distribute this object.&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;lt;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__class__&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;hosts_to_ping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;192.168.10.&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;[&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;]Waiting 10 seconds for other members...&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;[&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;]Current members: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_members&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hosts_to_ping&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run_watchers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;belongs_to_self&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;[&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;]&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt; belongs to &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;members_for_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;=&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Waiting for next loop...&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;KeyboardInterrupt&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CTRL C is pressed!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# # Leave the group&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;leave_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# # Stop when we&amp;#39;re done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h5&gt;执行效果&lt;span class="hx:absolute hx:-mt-20" id="执行效果-1"&gt;&lt;/span&gt;
&lt;a href="#%e6%89%a7%e8%a1%8c%e6%95%88%e6%9e%9c-1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h5&gt;&lt;p&gt;我们分别使用两个不同的窗口，同时启动两个Worker，我们可以很明显的看到主机被分配到两个不同的Worker中。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python test_ping.py client1 group1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python test_pring.py client2 group1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/22.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;加入第三个Worker，可以看到一部分任务又被分配给了第三个Worker上&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python test_ping.py client3 group2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/23.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span class="hx:absolute hx:-mt-20" id=""&gt;&lt;/span&gt;
&lt;a href="#" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;暂停第二个Worker，我们看到第二个Worker被停止后，任务重新被平衡到Worker1和Worker2上。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/24.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;3、构建分布式定时任务&lt;span class="hx:absolute hx:-mt-20" id="3构建分布式定时任务"&gt;&lt;/span&gt;
&lt;a href="#3%e6%9e%84%e5%bb%ba%e5%88%86%e5%b8%83%e5%bc%8f%e5%ae%9a%e6%97%b6%e4%bb%bb%e5%8a%a1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;为了保持代码的兼容性，所以这里的实现是基于目前OpenStack体系的实现。另外，将任务发送给消息的部分在这个例子中并没有体现。示例代码仍然重复实现上述ping的例子，部分代码参考于Sahara项目的实现。&lt;/p&gt;
&lt;p&gt;由于代码量较大，这里不贴出全部代码，仅仅对核心实现进行分析，完整代码请参考：&lt;a href="https://github.com/xiaoquqi/openstackclient-demo/tree/master/tooz/distribute_periodic_tasks"target="_blank" rel="noopener"&gt;https://github.com/xiaoquqi/openstackclient-demo/tree/master/tooz/distribute_periodic_tasks&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;代码结构&lt;span class="hx:absolute hx:-mt-20" id="代码结构"&gt;&lt;/span&gt;
&lt;a href="#%e4%bb%a3%e7%a0%81%e7%bb%93%e6%9e%84" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;.
├── coordinator.py -&amp;gt; 一致性哈希的实现，该类中并没有直接使用上述tooz的partition，而是自己重新实现了HashRing
├── periodic.py -&amp;gt; 定时任务，基于oslo_service的PeriodicTasks基类
├── service.py -&amp;gt; Service类，继承于oslo.service的Service基类
└── test_periodic_task.py -&amp;gt; 程序入口&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4&gt;coordinator.py&lt;span class="hx:absolute hx:-mt-20" id="coordinatorpy"&gt;&lt;/span&gt;
&lt;a href="#coordinatorpy" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Coordinator是关键实现，所以这里重点对该类进行解释，在period task中需要调用coordinator即可实现分布式触发定时任务。&lt;/p&gt;
&lt;p&gt;在coordinator.py中共实现了两个类，Coordinator和HashRing。&lt;br /&gt;1、Coordinator类主要是针对tooz中对group members相关操作的封装，类似我们在tooz中的第一个例子；&lt;br /&gt;2、HashRing是继承于Coordinator类，在功能上接近于tooz中Hash和Partition的实现，但是更简洁，tooz构建HashRing的用的PartitionNumber是32(2^5)，而我们用的是40，更大的数字会带来更均匀的分布但是会导致构建成本增加&lt;br /&gt;3、HashRing中最重要的方法就是get_subset，通过映射到HashRing上的ID来判断Object的归属Worker&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/25.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HashRing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Coordinator&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;backend_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;group_id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replicas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CONF&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hash_ring_replicas_count&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HashRing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backend_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# nosec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_build_ring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ring&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;members&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_members&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Coordinator members: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;members&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;members&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replicas&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;hashed_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;:&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ring&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hashed_key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ring&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ring&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_check_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ring&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sorted_keys&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Checks if this object belongs to this member or not&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;hashed_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bisect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bisect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sorted_keys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashed_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sorted_keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ring&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;sorted_keys&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;member_id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_subset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Returns subset that belongs to this member&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coordinator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ring&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_build_ring&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_check_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ring&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;objects&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4&gt;运行效果&lt;span class="hx:absolute hx:-mt-20" id="运行效果"&gt;&lt;/span&gt;
&lt;a href="#%e8%bf%90%e8%a1%8c%e6%95%88%e6%9e%9c" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;分别在两个Terminal中运行脚本，可以看到Host被均匀的分布在两个Worker中执行。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;test_periodic_task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/2020-03-24/26.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;五、总结&lt;span class="hx:absolute hx:-mt-20" id="五总结"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%94%e6%80%bb%e7%bb%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;通过以上实例，我们了解了如何通过zookeeper构建分布式系统并进行任务调度，当然zookeeper在分布式系统还有更多的应用场景值得我们去学习。另外，OpenStack中很多抽象出来的模块对快速构建Python分布式系统是非常有帮助的，值得我们学习。&lt;/p&gt;</description></item><item><title>深度解读OpenStack Mitaka国内代码贡献</title><link>https://sunqi.site/blog/2016-04-07-contribution-in-mitaka/</link><pubDate>Thu, 07 Apr 2016 23:19:39 +0800</pubDate><guid>https://sunqi.site/blog/2016-04-07-contribution-in-mitaka/</guid><description>
&lt;p&gt;转眼间，OpenStack又迎来了新版本发布的日子，这是OpenStack第13个版本，也是Big Tent后的第二个版本，秉承“公开公正”的原则，OpenStack Release的项目达到了29个，比Liberty多出了8个。&lt;/p&gt;
&lt;p&gt;去年的时候，对国内的OpenStack Liberty贡献进行了深度解读后引起了广泛的关注，在今年Mitaka版本发布之后，类似的解读已经遍布朋友圈，但是在看过后，发现并非国内贡献的全部统计，所以决定还是自己写一篇完整的深度解读系列文章，来帮助国内用户对国内OpenStack的现状有一个全面的了解和认识。&lt;/p&gt;
&lt;p&gt;这几天一直在思考写这篇文章的目的和意义，我们搞分析也好，搞排名也罢，到底是为了什么？Mitaka版本更新后，各个公司也以排名作为企业宣传的最好的武器，我觉得这些都无可厚非。但是我觉得更重要的一点是在当前去IOEV的大形势下，我们应该告诉国内的企业用户，有一批热衷于追求Geek精神的年轻人在为中国未来的IT产业变革做着不懈的努力，他们用数字证明了国外公司能做到的我们国内公司也能做到，这个世界上不仅有IOEV，还有中国制造的OpenStack。&lt;/p&gt;
&lt;p&gt;对于友商们已经分析的数据，这里不再赘述，本文主要通过stackalytics.com提供的API对国内社区贡献进行一次深度挖掘和整理。&lt;/p&gt;
&lt;p&gt;OpenStack Liberty深度解读请见：http://xiaoquqi.github.io/blog/2015/10/29/contribution-in-liberty/&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;Release项目简介&lt;span class="hx:absolute hx:-mt-20" id="release项目简介"&gt;&lt;/span&gt;
&lt;a href="#release%e9%a1%b9%e7%9b%ae%e7%ae%80%e4%bb%8b" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Openstack官方的Release的网站已经更新为：http://releases.openstack.org/&lt;/p&gt;
&lt;p&gt;在Big Tent公布之后，OpenStack的项目被分为Core Projects和Big Tent Projects。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/contribution-in-mitaka-big-tent.jpg" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;让我们来看一下在Mitaka版本中，多了哪些新项目。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;几个与Docker相关的项目被发布出来，magnum, senlin, solum&lt;/li&gt;
&lt;li&gt;数据备份容灾的项目：freezer&lt;/li&gt;
&lt;li&gt;计费的项目：cloudkitty&lt;/li&gt;
&lt;li&gt;NFV相关的项目：tracker&lt;/li&gt;
&lt;li&gt;监控相关的项目：monasca&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;关于这些新项目的一些介绍，我将放在另外一篇博客里，敬请关注。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/contribution-in-mitaka-projects.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;社区贡献总体分析&lt;span class="hx:absolute hx:-mt-20" id="社区贡献总体分析"&gt;&lt;/span&gt;
&lt;a href="#%e7%a4%be%e5%8c%ba%e8%b4%a1%e7%8c%ae%e6%80%bb%e4%bd%93%e5%88%86%e6%9e%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;本次统计的方法仍然为commits的方式，统计范围为stackalystatics默认统计的全部项目。&lt;/p&gt;
&lt;p&gt;从总体参与的公司数量来看，Mitaka版本略有下降，但是参与的人数多了100多人。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/contribution-in-mitaka-companies-contributors.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;p&gt;整个社区的公司贡献排名上没有明显的变化，传统的几大豪强仍然霸占公司排名的前十位，华为表现依然强劲，是中国区唯一能进入前十名的公司。&lt;/p&gt;
&lt;p&gt;在模块方面，整体统计的绝大部分比例已经被others所占据，说明在Big Tent计划下，OpenStack正在朝更多元化的方向演进。在Mitaka排名前十位的项目中，fuel相关的两个项目都进入了前十，说明fuel在OpenStack部署的地位已经越来越重要了。同时，核心项目中的nova，neutron，cinder项目仍然在前十名的范围内，贡献量基本保持不变。值得一提的是，在Mitaka统计的项目数量已经从Liberty的708个增长到了829个，可见在短短的6个月内，OpenStack社区的蓬勃发展。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/contribution-in-mitaka-companies-modules.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h2&gt;OpenStack国内社区分析&lt;span class="hx:absolute hx:-mt-20" id="openstack国内社区分析"&gt;&lt;/span&gt;
&lt;a href="#openstack%e5%9b%bd%e5%86%85%e7%a4%be%e5%8c%ba%e5%88%86%e6%9e%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;看完了整体统计，我们再回到国内，因为已经有文章做了我在Liberty时候的分析，所以这里我换个角度来看国内的社区贡献，首先是统计排名的变化。&lt;/p&gt;
&lt;h3&gt;贡献企业&lt;span class="hx:absolute hx:-mt-20" id="贡献企业"&gt;&lt;/span&gt;
&lt;a href="#%e8%b4%a1%e7%8c%ae%e4%bc%81%e4%b8%9a" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在Liberty中，有13家国内企业为社区做了贡献，在Mitaka中这个数量增加到了15家企业，这里简单的将这些企业做了一下分类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;互联网用户：乐视、新浪、网易&lt;/li&gt;
&lt;li&gt;电信用户：中国移动&lt;/li&gt;
&lt;li&gt;传统IT服务商：华为、中兴、华三&lt;/li&gt;
&lt;li&gt;私有云服务商：Easystack、九州云、海云捷迅、北京有云、麒麟云、UMCloud、象云、Huron(休伦科技)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/contribution-in-mitaka-china-companies.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;行业分析&lt;span class="hx:absolute hx:-mt-20" id="行业分析"&gt;&lt;/span&gt;
&lt;a href="#%e8%a1%8c%e4%b8%9a%e5%88%86%e6%9e%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;通过行业的分析我们可以看出，国内的主要贡献仍然来自私有云服务商和传统IT服务商，换言之来自于以OpenStack提供产品或者服务的公司。厂商们贡献的目的很明确，主要为了展示自身在开源项目中的积累和专家形象。而用户的贡献主要来自平时在使用OpenStack时候遇到Bug，就是在实际应用过程中出现的问题。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/contribution-in-mitaka-china-by-industry.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;人员投入分析&lt;span class="hx:absolute hx:-mt-20" id="人员投入分析"&gt;&lt;/span&gt;
&lt;a href="#%e4%ba%ba%e5%91%98%e6%8a%95%e5%85%a5%e5%88%86%e6%9e%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;单纯的社区贡献排名的比较仅仅是一个维度，下面我们来看一下各个公司的人员投入情况：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;排名前几位的公司对社区投入的人力基本都是两位数，相对于Liberty版本，人员均有所增加&lt;/li&gt;
&lt;li&gt;在人均贡献投入上，99cloud是国内最高的，平均达到了59天，甚至超过了华为，这个统计不仅仅包含了代码贡献，还包含了邮件、Review、Blueprint的时间，基本可以衡量每个公司在OpenStack社区贡献方面的投入力量&lt;/li&gt;
&lt;li&gt;人员投入来看，Easystack和中国移动无疑是最下本的两家，Easystack从Liberty的3人，增长到了23人，一下子增加了20人；中国移动也从最初的4个人，增加到了13个人，可见中国移动未来对OpenStack的野心&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/contribution-in-mitaka-companies-effort.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;贡献模块分析&lt;span class="hx:absolute hx:-mt-20" id="贡献模块分析"&gt;&lt;/span&gt;
&lt;a href="#%e8%b4%a1%e7%8c%ae%e6%a8%a1%e5%9d%97%e5%88%86%e6%9e%90" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;从模块的角度进行统计，国内企业的贡献情况并未出现一个统一的趋势，总体的贡献项目为193个，项目几乎涉及OpenStack所有最活跃的项目，从排名前十的项目来看：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;得益于华为的主导，dargonflow项目的贡献量超高&lt;/li&gt;
&lt;li&gt;紧随其后的，也是当下的热点，容器相关的两个项目&lt;/li&gt;
&lt;li&gt;几大OpenStack老模块贡献量也高居前十位，说明这些模块是在解决方案中使用频率较高的&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/contribution-in-mitaka-modules.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;h3&gt;投入产出比&lt;span class="hx:absolute hx:-mt-20" id="投入产出比"&gt;&lt;/span&gt;
&lt;a href="#%e6%8a%95%e5%85%a5%e4%ba%a7%e5%87%ba%e6%af%94" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是一个很敏感的话题，每个公司对社区的投入到底换来多少项目上的回报呢？可能这只有每个公司的CEO能够回答的问题了。我在这里就不多做过多的分析，留给大家充分讨论的空间吧。&lt;/p&gt;
&lt;h2&gt;总结&lt;span class="hx:absolute hx:-mt-20" id="总结"&gt;&lt;/span&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;刚刚结束在南京的OpenStack开发培训，也了解到5G的通信网络上已经确定引入了OpenStack，虽然我说不清楚他的具体用途，但是我相信这对OpenStack这个项目、社区是一个重大的利好消息。我也相信，通过国内企业的集体努力，一定能让OpenStack在中国遍地开花结果。&lt;/p&gt;</description></item><item><title>Consul主要使用场景</title><link>https://sunqi.site/blog/2015-12-24-use-consul/</link><pubDate>Thu, 24 Dec 2015 18:07:24 +0800</pubDate><guid>https://sunqi.site/blog/2015-12-24-use-consul/</guid><description>
&lt;p&gt;假设你已经按照之前的Consul安装方法部署了一套具备环境，具体方法可以参考：http://xiaoquqi.github.io/blog/2015/12/07/consul-installation/&lt;/p&gt;
&lt;p&gt;这篇文章里主要介绍Consul的使用场景，服务和健康检查。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;Service&lt;span class="hx:absolute hx:-mt-20" id="service"&gt;&lt;/span&gt;
&lt;a href="#service" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;服务注册有点像OpenStack Keystone的Endpoints，可以通过API方式查询到所有服务的端点信息。&lt;/p&gt;
&lt;p&gt;在Agent的节点上添加一个service，之后重启服务。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;添加一个服务&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ echo &amp;#39;{&amp;#34;service&amp;#34;: {&amp;#34;name&amp;#34;: &amp;#34;web&amp;#34;, &amp;#34;tags&amp;#34;: [&amp;#34;rails&amp;#34;], &amp;#34;port&amp;#34;: 80}}&amp;#39; \
&amp;gt;/etc/consul.d/web.json&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;重启agent&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;重新加载新的服务并不需要杀死进程重启服务，只需要给进程直接发送一个SIGHUP。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ kill -HUP $(ps -ef | grep agent | grep -v grep | awk &amp;#39;{print $2}&amp;#39;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;日志输出&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;从输出的日志上都可以看到加载了新的服务web。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;==&amp;gt; Caught signal: hangup
==&amp;gt; Reloading configuration...
==&amp;gt; WARNING: Expect Mode enabled, expecting 3 servers
2015/12/24 12:01:11 [INFO] agent: Synced service &amp;#39;web&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;利用API查询&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们在任意节点上利用REST API查看服务。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ curl http://localhost:8500/v1/catalog/service/web&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;[{&amp;#34;Node&amp;#34;:&amp;#34;server1.consul.com&amp;#34;,&amp;#34;Address&amp;#34;:&amp;#34;200.21.1.101&amp;#34;,&amp;#34;ServiceID&amp;#34;:&amp;#34;web&amp;#34;,&amp;#34;ServiceName&amp;#34;:&amp;#34;web&amp;#34;,&amp;#34;ServiceTags&amp;#34;:[&amp;#34;rails&amp;#34;],&amp;#34;ServiceAddress&amp;#34;:&amp;#34;&amp;#34;,&amp;#34;ServicePort&amp;#34;:80}]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Health Check&lt;span class="hx:absolute hx:-mt-20" id="health-check"&gt;&lt;/span&gt;
&lt;a href="#health-check" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;健康检查的方法主要是通过运行一小段脚本的方式，根据运行的结果判断检查对象的健康状况。所以可以通过任意语言定义这个脚本，脚本运行将通过和consul执行的相同用户执行。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;添加一个健康检查&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;每30秒ping google.com&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ echo &amp;#39;{&amp;#34;check&amp;#34;: {&amp;#34;name&amp;#34;: &amp;#34;ping&amp;#34;,
&amp;#34;script&amp;#34;: &amp;#34;ping -c1 google.com &amp;gt;/dev/null&amp;#34;, &amp;#34;interval&amp;#34;: &amp;#34;30s&amp;#34;}}&amp;#39; \
&amp;gt; /etc/consul.d/ping.json&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;为刚才的服务添加健康检查&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ echo &amp;#39;{&amp;#34;service&amp;#34;: {&amp;#34;name&amp;#34;: &amp;#34;web&amp;#34;, &amp;#34;tags&amp;#34;: [&amp;#34;rails&amp;#34;], &amp;#34;port&amp;#34;: 80,
&amp;#34;check&amp;#34;: {&amp;#34;script&amp;#34;: &amp;#34;curl localhost &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&amp;#34;, &amp;#34;interval&amp;#34;: &amp;#34;10s&amp;#34;}}}&amp;#39; \
&amp;gt; /etc/consul.d/web.json&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;重启agent&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ kill -HUP $(ps -ef | grep agent | grep -v grep | awk &amp;#39;{print $2}&amp;#39;)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;日志输出&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;从输出的日志上都可以看到加载了新的服务web。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;==&amp;gt; Caught signal: hangup
==&amp;gt; Reloading configuration...
==&amp;gt; WARNING: Expect Mode enabled, expecting 3 servers
2015/12/24 12:43:56 [INFO] agent: Synced service &amp;#39;web&amp;#39;
2015/12/24 12:43:56 [INFO] agent: Synced check &amp;#39;ping&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;经过一段时间后出现了critical和warning日志&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt; 2015/12/24 12:43:58 [WARN] agent: Check &amp;#39;service:web&amp;#39; is now critical
2015/12/24 12:44:08 [WARN] agent: Check &amp;#39;ping&amp;#39; is now warning&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;利用API查询&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Health check的状态包含了很多种，有any, unkown, passing, warning, critical。any包含了所有状态。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ curl http://localhost:8500/v1/health/state/critical&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;[{&amp;#34;Node&amp;#34;:&amp;#34;server1.consul.com&amp;#34;,&amp;#34;CheckID&amp;#34;:&amp;#34;service:web&amp;#34;,&amp;#34;Name&amp;#34;:&amp;#34;Service &amp;#39;web&amp;#39; check&amp;#34;,&amp;#34;Status&amp;#34;:&amp;#34;critical&amp;#34;,&amp;#34;Notes&amp;#34;:&amp;#34;&amp;#34;,&amp;#34;Output&amp;#34;:&amp;#34;&amp;#34;,&amp;#34;ServiceID&amp;#34;:&amp;#34;web&amp;#34;,&amp;#34;ServiceName&amp;#34;:&amp;#34;web&amp;#34;}]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;参考文档&lt;span class="hx:absolute hx:-mt-20" id="参考文档"&gt;&lt;/span&gt;
&lt;a href="#%e5%8f%82%e8%80%83%e6%96%87%e6%a1%a3" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.consul.io/docs/agent/http/catalog.html"target="_blank" rel="noopener"&gt;http://www.consul.io/docs/agent/http/catalog.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.consul.io/docs/agent/http/health.html"target="_blank" rel="noopener"&gt;http://www.consul.io/docs/agent/http/health.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Consul的安装方法</title><link>https://sunqi.site/blog/2015-12-07-consul-installation/</link><pubDate>Mon, 07 Dec 2015 10:00:13 +0800</pubDate><guid>https://sunqi.site/blog/2015-12-07-consul-installation/</guid><description>
&lt;h2&gt;什么是Consul?&lt;span class="hx:absolute hx:-mt-20" id="什么是consul"&gt;&lt;/span&gt;
&lt;a href="#%e4%bb%80%e4%b9%88%e6%98%afconsul" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Consul拥有众多的组件，简言之，就是一个用于在你的基础设施中，发现和配置服务的工具。包含以下关键功能：服务发现、健康检查、键值存储和多数据中心支持。再说的通俗一点，就是用于管理分布式系统的利器。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;安装Consul&lt;span class="hx:absolute hx:-mt-20" id="安装consul"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85consul" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Consul的安装比较简单，下载之后直接解压缩就可以了，下载地址：https://www.consul.io/downloads.html&lt;/p&gt;
&lt;p&gt;我们把consul直接放在/usr/local/bin目录中。&lt;/p&gt;
&lt;h2&gt;Consul Server&lt;span class="hx:absolute hx:-mt-20" id="consul-server"&gt;&lt;/span&gt;
&lt;a href="#consul-server" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ /usr/local/bin/consul agent -server -bootstrap-expect 3 -data-dir /tmp/consul -node=server1 -bind=10.10.10.10&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;参数说明&lt;span class="hx:absolute hx:-mt-20" id="参数说明"&gt;&lt;/span&gt;
&lt;a href="#%e5%8f%82%e6%95%b0%e8%af%b4%e6%98%8e" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;-server - Serve模式&lt;/li&gt;
&lt;li&gt;-bootstrap-expect - Server数量&lt;/li&gt;
&lt;li&gt;-data-dir - 数据目录&lt;/li&gt;
&lt;li&gt;-node - Node名称&lt;/li&gt;
&lt;li&gt;-bind - 集群通讯地址&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;输出&lt;span class="hx:absolute hx:-mt-20" id="输出"&gt;&lt;/span&gt;
&lt;a href="#%e8%be%93%e5%87%ba" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;==&amp;gt; WARNING: Expect Mode enabled, expecting 3 servers
==&amp;gt; WARNING: It is highly recommended to set GOMAXPROCS higher than 1
==&amp;gt; Starting Consul agent...
==&amp;gt; Starting Consul agent RPC...
==&amp;gt; Consul agent running!
Node name: &amp;#39;server1.consul.com&amp;#39;
Datacenter: &amp;#39;dc1&amp;#39;
Server: true (bootstrap: false)
Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400)
Cluster Addr: 200.21.1.101 (LAN: 8301, WAN: 8302)
Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
Atlas: &amp;lt;disabled&amp;gt;
==&amp;gt; Log data will now stream in as it occurs:
2015/12/23 03:13:36 [WARN] memberlist: Binding to public address without encryption!
2015/12/23 03:13:36 [INFO] serf: EventMemberJoin: server1.consul.com 200.21.1.101
2015/12/23 03:13:36 [WARN] memberlist: Binding to public address without encryption!
2015/12/23 03:13:36 [INFO] serf: EventMemberJoin: server1.consul.com.dc1 200.21.1.101
2015/12/23 03:13:36 [INFO] raft: Node at 200.21.1.101:8300 [Follower] entering Follower state
2015/12/23 03:13:36 [INFO] consul: adding server server1.consul.com (Addr: 200.21.1.101:8300) (DC: dc1)
2015/12/23 03:13:36 [INFO] consul: adding server server1.consul.com.dc1 (Addr: 200.21.1.101:8300) (DC: dc1)
2015/12/23 03:13:36 [ERR] agent: failed to sync remote state: No cluster leader
2015/12/23 03:13:37 [WARN] raft: EnableSingleNode disabled, and no known peers. Aborting election.
2015/12/23 03:13:51 [ERR] agent: failed to sync remote state: No cluster leader
==&amp;gt; Newer Consul version available: 0.6.0
2015/12/23 03:14:17 [ERR] agent: failed to sync remote state: No cluster leader&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;查看成员&lt;span class="hx:absolute hx:-mt-20" id="查看成员"&gt;&lt;/span&gt;
&lt;a href="#%e6%9f%a5%e7%9c%8b%e6%88%90%e5%91%98" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ consul members&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;Node Address Status Type Build Protocol DC
server1.consul.com 200.21.1.101:8301 alive server 0.5.2 2 dc1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Consul Agent&lt;span class="hx:absolute hx:-mt-20" id="consul-agent"&gt;&lt;/span&gt;
&lt;a href="#consul-agent" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ /usr/local/bin/consul agent -data-dir /tmp/consul -node=agent1 -bind=10.10.10.100 -config-dir /etc/consul.d&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;输出&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;==&amp;gt; WARNING: It is highly recommended to set GOMAXPROCS higher than 1
==&amp;gt; Starting Consul agent...
==&amp;gt; Starting Consul agent RPC...
==&amp;gt; Consul agent running!
Node name: &amp;#39;agent1.consul.com&amp;#39;
Datacenter: &amp;#39;dc1&amp;#39;
Server: false (bootstrap: false)
Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400)
Cluster Addr: 200.21.1.201 (LAN: 8301, WAN: 8302)
Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
Atlas: &amp;lt;disabled&amp;gt;
==&amp;gt; Log data will now stream in as it occurs:
2015/12/24 08:09:51 [WARN] memberlist: Binding to public address without encryption!
2015/12/24 08:09:51 [INFO] serf: EventMemberJoin: agent1.consul.com 200.21.1.201
2015/12/24 08:09:51 [ERR] agent: failed to sync remote state: No known Consul servers
2015/12/24 08:09:56 [INFO] agent.rpc: Accepted client: 127.0.0.1:42794
2015/12/24 08:09:56 [INFO] agent: (LAN) joining: [200.21.1.101 200.21.1.102 200.21.1.103]
2015/12/24 08:09:56 [INFO] serf: EventMemberJoin: server1.consul.com 200.21.1.101
2015/12/24 08:09:56 [INFO] consul: adding server server1.consul.com (Addr: 200.21.1.101:8300) (DC: dc1)
2015/12/24 08:09:58 [ERR] agent: failed to sync remote state: rpc error: No cluster leader
2015/12/24 08:10:02 [INFO] agent: (LAN) joined: 1 Err: &amp;lt;nil&amp;gt;
2015/12/24 08:10:02 [INFO] agent.rpc: Accepted client: 127.0.0.1:42800
==&amp;gt; Newer Consul version available: 0.6.0
2015/12/24 08:10:21 [WARN] agent: Check &amp;#39;ping&amp;#39; is now warning
2015/12/24 08:10:22 [ERR] agent: failed to sync remote state: rpc error: No cluster leader
2015/12/24 08:10:43 [ERR] agent: failed to sync remote state: rpc error: No cluster leader
2015/12/24 08:11:01 [WARN] agent: Check &amp;#39;ping&amp;#39; is now warning
2015/12/24 08:11:02 [ERR] agent: failed to sync remote state: rpc error: No cluster leader
2015/12/24 08:11:23 [ERR] agent: failed to sync remote state: rpc error: No cluster leader
2015/12/24 08:11:41 [WARN] agent: Check &amp;#39;ping&amp;#39; is now warning
2015/12/24 08:11:43 [ERR] agent: failed to sync remote state: rpc error: No cluster leader
2015/12/24 08:12:12 [ERR] agent: failed to sync remote state: rpc error: No cluster leader
2015/12/24 08:12:21 [WARN] agent: Check &amp;#39;ping&amp;#39; is now warning
2015/12/24 08:12:36 [ERR] agent: failed to sync remote state: rpc error: No cluster leader
2015/12/24 08:13:01 [WARN] agent: Check &amp;#39;ping&amp;#39; is now warning
2015/12/24 08:13:03 [ERR] agent: failed to sync remote state: rpc error: No cluster leader&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;server日志输出&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt; 2015/12/24 08:09:58 [INFO] serf: EventMemberJoin: agent1.consul.com 200.21.1.201&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;查看成员&lt;span class="hx:absolute hx:-mt-20" id="查看成员-1"&gt;&lt;/span&gt;
&lt;a href="#%e6%9f%a5%e7%9c%8b%e6%88%90%e5%91%98-1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ consul members&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;Node Address Status Type Build Protocol DC
server1.consul.com 200.21.1.101:8301 alive server 0.5.2 2 dc1
agent1.consul.com 200.21.1.201:8301 alive client 0.5.2 2 dc1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;最终结果&lt;span class="hx:absolute hx:-mt-20" id="最终结果"&gt;&lt;/span&gt;
&lt;a href="#%e6%9c%80%e7%bb%88%e7%bb%93%e6%9e%9c" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;$ consul members&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;Node Address Status Type Build Protocol DC
server1.consul.com 200.21.1.101:8301 alive server 0.5.2 2 dc1
agent1.consul.com 200.21.1.201:8301 alive client 0.5.2 2 dc1
agent2.consul.com 200.21.1.202:8301 alive client 0.5.2 2 dc1
server2.consul.com 200.21.1.102:8301 alive server 0.5.2 2 dc1
server3.consul.com 200.21.1.103:8301 alive server 0.5.2 2 dc1
agent3.consul.com 200.21.1.203:8301 alive client 0.5.2 2 dc1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;参考文档&lt;span class="hx:absolute hx:-mt-20" id="参考文档"&gt;&lt;/span&gt;
&lt;a href="#%e5%8f%82%e8%80%83%e6%96%87%e6%a1%a3" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.consul.io/intro/getting-started/install.html"target="_blank" rel="noopener"&gt;https://www.consul.io/intro/getting-started/install.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>使用Grafana+Diamond+Graphite构造完美监控面板</title><link>https://sunqi.site/blog/2015-12-01-use-grafana-to-monitor-your-cluster/</link><pubDate>Tue, 01 Dec 2015 07:59:46 +0800</pubDate><guid>https://sunqi.site/blog/2015-12-01-use-grafana-to-monitor-your-cluster/</guid><description>
&lt;p&gt;服务器监控软件五花八门，没有一个是对的，但是总有一款是适合你的，本文中将使用Grafana+Dimaond+Graphite构造一款漂亮的监控面板，你可以独自欣赏，也可以让他们和你的应用勾勾搭搭。&lt;/p&gt;
&lt;p&gt;本文中的安装测试，主要在CentOS 6.5下完成。先来张Grafna效果图，左边是我们的数据源Graphite，右边是我们的Grafna的效果图：&lt;/p&gt;
&lt;p&gt;&lt;img src="https://sunqi.site/images/blogs/grafana-screenshot.png" alt="" loading="lazy" /&gt;&lt;/p&gt;
&lt;!-- more --&gt;
&lt;h2&gt;安装及配置Dimaond&lt;span class="hx:absolute hx:-mt-20" id="安装及配置dimaond"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85%e5%8f%8a%e9%85%8d%e7%bd%aedimaond" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;安装Diamond最直接和简单的方法就是自己编译RPM或者DEB的安装包, Diamond在这方面提供了比较好的支持。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cd /root&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# yum install -y git rpm-build python-configobj python-setuptools&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# git clone https://github.com/python-diamond/Diamond&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cd Diamond&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# make rpm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cd dist&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# rpm -ivh diamond-*.noarch.rpm&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;默认情况下，Diamond开启了基本的监控信息，包括CPU、内存、磁盘的性能数据。当然，我们可以通过配置启动相应的监控项，也能通过自定义的方式进行相应的扩展。这里，我们在/etc/diamond/collectors加载额外的插件，下面的例子中开启了网络的监控。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cp -f /etc/diamond/diamond.conf.example /etc/diamond/diamond.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cat &amp;lt;&amp;lt; EOF | tee -a /etc/diamond/diamond.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;configs&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/etc/diamond/collectors/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;.conf&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cat &amp;lt;&amp;lt; EOF | tee /etc/diamond/collectors/net.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;collectors&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;NetworkCollector&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;EOF&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;那么到目前为止，Diamond的基本安装和配置已经完成，但是现在只是简单的采集数据，并没有指明数据要发送给谁，所以下一步我们来开始配置Graphite。&lt;/p&gt;
&lt;h2&gt;安装及配置Graphite&lt;span class="hx:absolute hx:-mt-20" id="安装及配置graphite"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85%e5%8f%8a%e9%85%8d%e7%bd%aegraphite" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Graphite主要做两件事情：按照时间存储数据、生成图表，在我们的场景里面，实质上就是把Graphite作为数据源给Grafana提供数据。另外还需要安装的是carbon，负责通过网络接受数据并保存到后端存储中；另外还需要whisper，负责生成Graphite样式的基于文件的时间序列的数据库。&lt;/p&gt;
&lt;h3&gt;安装软件包&lt;span class="hx:absolute hx:-mt-20" id="安装软件包"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85%e8%bd%af%e4%bb%b6%e5%8c%85" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# yum install -y graphite-web graphite-web-selinux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# yum install -y mysql mysql-server MySQL-python&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# yum install -y python-carbon python-whisper&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;配置MySQL&lt;span class="hx:absolute hx:-mt-20" id="配置mysql"&gt;&lt;/span&gt;
&lt;a href="#%e9%85%8d%e7%bd%aemysql" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# /etc/init.d/mysqld start&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# mysql -e &amp;#34;CREATE DATABASE graphite;&amp;#34; -u root&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# mysql -e &amp;#34;GRANT ALL PRIVILEGES ON graphite.* TO &amp;#39;graphite&amp;#39;@&amp;#39;localhost&amp;#39; IDENTIFIED BY &amp;#39;sysadmin&amp;#39;;&amp;#34; -u root&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# mysql -e &amp;#39;FLUSH PRIVILEGES;&amp;#39; -u root&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;配置Graphite&lt;span class="hx:absolute hx:-mt-20" id="配置graphite"&gt;&lt;/span&gt;
&lt;a href="#%e9%85%8d%e7%bd%aegraphite" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;local setting&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# SECRET_KEY=$(md5sum /etc/passwd | awk {&amp;#39;print $1&amp;#39;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# echo &amp;#34;SECRET_KEY = &amp;#39;$SECRET_KEY&amp;#39;&amp;#34; | tee -a /etc/graphite-web/local_settings.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# echo &amp;#34;TIME_ZONE = &amp;#39;Asia/Shanghai&amp;#39;&amp;#34; | tee -a /etc/graphite-web/local_settings.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cat &amp;lt;&amp;lt; EOF | tee -a /etc/graphite-web/local_settings.py&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DATABASES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;default&amp;#39;&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;NAME&amp;#39;&lt;/span&gt;: &lt;span class="s1"&gt;&amp;#39;graphite&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;ENGINE&amp;#39;&lt;/span&gt;: &lt;span class="s1"&gt;&amp;#39;django.db.backends.mysql&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;USER&amp;#39;&lt;/span&gt;: &lt;span class="s1"&gt;&amp;#39;graphite&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;PASSWORD&amp;#39;&lt;/span&gt;: &lt;span class="s1"&gt;&amp;#39;sysadmin&amp;#39;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;EOF
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cd /usr/lib/python2.6/site-packages/graphite&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ./manage.py syncdb --noinput&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# echo &amp;#34;from django.contrib.auth.models import User; User.objects.create_superuser(&amp;#39;admin&amp;#39;, &amp;#39;admin@hihuron.com&amp;#39;, &amp;#39;sysadmin&amp;#39;)&amp;#34; | ./manage.py shell&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Apache配置&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Listen 0.0.0.0:10000
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;VirtualHost *:10000&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ServerName graphite-web
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; DocumentRoot &lt;span class="s2"&gt;&amp;#34;/usr/share/graphite/webapp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ErrorLog /var/log/httpd/graphite-web-error.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; CustomLog /var/log/httpd/graphite-web-access.log common
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Alias /media/ &lt;span class="s2"&gt;&amp;#34;/usr/lib/python2.6/site-packages/django/contrib/admin/media/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; WSGIScriptAlias / /usr/share/graphite/graphite-web.wsgi
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; WSGIImportScript /usr/share/graphite/graphite-web.wsgi process-group&lt;span class="o"&gt;=&lt;/span&gt;%&lt;span class="o"&gt;{&lt;/span&gt;GLOBAL&lt;span class="o"&gt;}&lt;/span&gt; application-group&lt;span class="o"&gt;=&lt;/span&gt;%&lt;span class="o"&gt;{&lt;/span&gt;GLOBAL&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;Location &lt;span class="s2"&gt;&amp;#34;/content/&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SetHandler None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;/Location&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;Location &lt;span class="s2"&gt;&amp;#34;/media/&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; SetHandler None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;lt;/Location&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Diamond配置&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# HOST_IP=$(ifconfig | sed -En &amp;#39;s/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p&amp;#39; | head -1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sed -i &amp;#34;/^\[\[GraphiteHandler\]\]$/,/^\[.*\]/s/^host = 127.0.0.1$/host = $HOST_IP/&amp;#34; /etc/diamond/diamond.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sed -i &amp;#34;/^\[\[GraphitePickleHandler\]\]$/,/^\[.*\]/s/^host = 127.0.0.1$/host = $HOST_IP/&amp;#34; /etc/diamond/diamond.conf&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;启动服务&lt;span class="hx:absolute hx:-mt-20" id="启动服务"&gt;&lt;/span&gt;
&lt;a href="#%e5%90%af%e5%8a%a8%e6%9c%8d%e5%8a%a1" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# service carbon-cache restart&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# service httpd restart&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# service diamond restart&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;安装和配置Grafana&lt;span class="hx:absolute hx:-mt-20" id="安装和配置grafana"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85%e5%92%8c%e9%85%8d%e7%bd%aegrafana" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Grafana最主要的功能就是对数据的呈现，基于一切可提供time series的后台服务。这里面我们使用Graphite为Grafana提供数据。&lt;/p&gt;
&lt;h3&gt;安装及配置&lt;span class="hx:absolute hx:-mt-20" id="安装及配置"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85%e5%8f%8a%e9%85%8d%e7%bd%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# yum install -y nodejs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# rpm -ivh https://grafanarel.s3.amazonaws.com/builds/grafana-2.5.0-1.x86_64.rpm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sudo /sbin/chkconfig --add grafana-server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sed -i &amp;#39;s/^;http_port = 3000$/http_port = 10001/g&amp;#39; /etc/grafana/grafana.ini&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# sudo service grafana-server start&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;添加datasource&lt;span class="hx:absolute hx:-mt-20" id="添加datasource"&gt;&lt;/span&gt;
&lt;a href="#%e6%b7%bb%e5%8a%a0datasource" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Grafana提供了非常丰富的REST API，我们不仅可以直接利用Grafana作为数据呈现层，还可以利用REST API直接将Grafana的Graph集成在我们的应用中。下面我们利用REST API为Grafana添加datasource。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# curl -i &amp;#39;http://admin:admin@localhost:10001/api/datasources&amp;#39; -X POST -H &amp;#34;Accept: application/json&amp;#34; -H &amp;#34;Content-Type: application/json&amp;#34; -d &amp;#39;{&amp;#34;name&amp;#34;: &amp;#34;graphite&amp;#34;, &amp;#34;type&amp;#34;: &amp;#34;graphite&amp;#34;, &amp;#34;url&amp;#34;: &amp;#34;http://localhost:10000&amp;#34;, &amp;#34;access&amp;#34;: &amp;#34;proxy&amp;#34;, &amp;#34;basicAuth&amp;#34;: false}&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Ceph监控&lt;span class="hx:absolute hx:-mt-20" id="ceph监控"&gt;&lt;/span&gt;
&lt;a href="#ceph%e7%9b%91%e6%8e%a7" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;修改ceph脚本兼容性&lt;span class="hx:absolute hx:-mt-20" id="修改ceph脚本兼容性"&gt;&lt;/span&gt;
&lt;a href="#%e4%bf%ae%e6%94%b9ceph%e8%84%9a%e6%9c%ac%e5%85%bc%e5%ae%b9%e6%80%a7" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Diamond是基于Python开发的，但是由于CentOS 6.5的Python版本较低(2.6)，所以直接使用社区版本的Ceph监控时，会导致错误。可以通过简单的修改进行修复。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_stats_from_socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Return the parsed JSON data returned when ceph is told to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; dump the stats from the named socket.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; In the event of an error error, the exception is logged, and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; an empty result set is returned.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#json_blob = subprocess.check_output(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# [self.config[&amp;#39;ceph_binary&amp;#39;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# &amp;#39;--admin-daemon&amp;#39;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# name,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# &amp;#39;perf&amp;#39;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# &amp;#39;dump&amp;#39;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ceph_binary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;--admin-daemon&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;perf&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;dump&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Popen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;json_blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;communicate&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;增加对ceph osd perf监控&lt;span class="hx:absolute hx:-mt-20" id="增加对ceph-osd-perf监控"&gt;&lt;/span&gt;
&lt;a href="#%e5%a2%9e%e5%8a%a0%e5%af%b9ceph-osd-perf%e7%9b%91%e6%8e%a7" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在实际运维Ceph过程中，ceph osd perf是一个非常重要的指令，能够观察出集群中磁盘的latency的信息，通过观察变化，可以辅助判断磁盘出现性能问题。Diamond的设计中，每个Diamond Agent只会采集自己本机的指标，所以我们在添加的时候，只需要在一个节点上增加这个监控就可以了。在ceph.py中结尾处新增加一个类。&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CephOsdCollector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CephCollector&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_stats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Return the parsed JSON data returned when ceph is told to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; dump the stats from the named socket.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; In the event of an error error, the exception is logged, and
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; an empty result set is returned.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;#json_blob = subprocess.check_output(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# [self.config[&amp;#39;ceph_binary&amp;#39;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# &amp;#39;--admin-daemon&amp;#39;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# name,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# &amp;#39;perf&amp;#39;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# &amp;#39;dump&amp;#39;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ceph_binary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;osd&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;perf&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;--format=json&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Popen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PIPE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;json_blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;communicate&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CalledProcessError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Could not get stats from &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Could not get stats from &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;json_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_blob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Could not parse stats from &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Could not parse stats from &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json_data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_publish_stats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;Given a stats dictionary from _get_stats_from_socket,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; publish the individual values.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;perf&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;osd_perf_infos&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;counter_prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;osd.&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;perf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;stat_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stat_value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;flatten_dictionary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;perf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;perf_stats&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;counter_prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;stat_name is &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stat_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;stat_value is &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stat_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publish_gauge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stat_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stat_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;collect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; Collect stats
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;in ceph osd collector&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_get_stats&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_publish_stats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;修改Diamond监控配置&lt;span class="hx:absolute hx:-mt-20" id="修改diamond监控配置"&gt;&lt;/span&gt;
&lt;a href="#%e4%bf%ae%e6%94%b9diamond%e7%9b%91%e6%8e%a7%e9%85%8d%e7%bd%ae" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# cat &amp;lt;&amp;lt; EOF | tee /etc/diamond/collectors/ceph.conf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;collectors&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;CephCollector&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[[&lt;/span&gt;CephOsdCollector&lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; True
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;EOF&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# service diamond restart&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>使用MongoDB作为Salt Pillar后端存储数据</title><link>https://sunqi.site/blog/2015-02-23-use-mongodb-to-store-salt-pillar/</link><pubDate>Mon, 23 Feb 2015 15:19:21 +0800</pubDate><guid>https://sunqi.site/blog/2015-02-23-use-mongodb-to-store-salt-pillar/</guid><description>
&lt;p&gt;今天在查找salt中pillar嵌套pillar的方法时，无意之间发现了pillar除了可以直接使用文件(sls)外，也同时支持多种后端的数据存储方式。例如：MySQL, MongoDB, Ldap, json, cobbler甚至是puppet。这无疑为开发中的接口提供了极大的便利。&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;详细的支持列表可见：http://docs.saltstack.com/en/latest/ref/pillar/all/index.html#all-salt-pillars&lt;/p&gt;
&lt;p&gt;严格意义上来说，这篇博文并非完全原创，英文原文请参考：http://www.tmartin.io/articles/2014/salt-pillar-mongodb/&lt;/p&gt;
&lt;p&gt;下面就来说说详细的配置方式，假定你已经有了一个部署好的salt环境，并且正确配置了salt master和salt minion，并且完成认证，主机名为salt-master.salt.com，这里我们使用Ubuntu 12.04 64bit作为演示环境。&lt;/p&gt;
&lt;h2&gt;安装MongoDB和Python MongoDB&lt;span class="hx:absolute hx:-mt-20" id="安装mongodb和python-mongodb"&gt;&lt;/span&gt;
&lt;a href="#%e5%ae%89%e8%a3%85mongodb%e5%92%8cpython-mongodb" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;apt-get install mongodb python-pymongo python-pymongo-ext&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;确保你能连接到MongoDB&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;mongo&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;MongoDB shell version: 2.2.3
connecting to: test
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;创建MongoDB数据库和存放Pillar的Collection&lt;span class="hx:absolute hx:-mt-20" id="创建mongodb数据库和存放pillar的collection"&gt;&lt;/span&gt;
&lt;a href="#%e5%88%9b%e5%bb%bamongodb%e6%95%b0%e6%8d%ae%e5%ba%93%e5%92%8c%e5%ad%98%e6%94%bepillar%e7%9a%84collection" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;创建数据库pillar&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;use pillar&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;在数据库中插入pillar数据&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;db.pillar.insert({
_id: &amp;#39;salt-master.salt.com&amp;#39;,
mongo_pillar: {
key1: &amp;#34;value1&amp;#34;,
key2: &amp;#34;value2&amp;#34;,
}})&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;注意：这里的_id必须要和你的minion节点的主机名一致，并且无法使用通配符，也就是一个节点都有自己一套独立的pillar，这一点和文件中定义pillar有很大的不同。mongo_pillar部分中是定义的是pillar中的内容，也就是我们可以直接引用的部分。&lt;/p&gt;
&lt;h3&gt;配置Salt Master&lt;span class="hx:absolute hx:-mt-20" id="配置salt-master"&gt;&lt;/span&gt;
&lt;a href="#%e9%85%8d%e7%bd%aesalt-master" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;下一步就是告诉Salt Master，我们在MongoDB中存放了pillar数据，需要劳您大驾，移步MongoDB读取数据。修改：&lt;/p&gt;
&lt;p&gt;/etc/salt/master&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;添加&lt;/p&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;mongo.db: &amp;#34;pillar&amp;#34;
mongo.host: &amp;#34;localhost&amp;#34;
ext_pillar:
- mongo: {}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;注意：如果需要使用不同于标准安装接口，请使用mongo.port，如果需要配置用户名和密码，请使用mongo.user和mongo.password。其他参数定义，请详见：http://docs.saltstack.com/en/latest/ref/pillar/all/salt.pillar.mongo.html#module-documentation&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;测试&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;salt salt-master.salt.com pillar.item mongo_pillar&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;返回&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;salt-master.salt.com:
----------
mongo_pillar:
----------
key1:
value1
key2:
value2
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;如果想在sls中直接使用&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code"&gt;
&lt;div&gt;&lt;pre&gt;&lt;code&gt;{% raw %}{{ salt[&amp;#39;pillar.get&amp;#39;](&amp;#39;mongo_pillar:key1&amp;#39;) }}{% endraw %}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0"&gt;
&lt;button
class="hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50"
title="复制代码"
aria-label="复制代码"
data-copied-label="已复制！"
&gt;
&lt;div class="hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;div class="hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4"&gt;&lt;/div&gt;
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;总结&lt;span class="hx:absolute hx:-mt-20" id="总结"&gt;&lt;/span&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="subheading-anchor" aria-label="此章节的永久链接"&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;pillar应该是salt中一个比较灵活的配置选项，个人理解pillar的作用就像puppet中init定义的初始化的参数的默认值，每次部署时，只需要更改pillar的文件就可以啦。但是随着代码的增长(主要用于部署OpenStack)，发现pillar的管理越来越难，pillar本身对如何组织结构并没有严格的限制，而且嵌套(extend)功能暂时还不能很完美的支持(&lt;a href="https://github.com/saltstack/salt/issues/3991"target="_blank" rel="noopener"&gt;https://github.com/saltstack/salt/issues/3991&lt;/a&gt;)，这也给pillar的管理提高了复杂度。&lt;/p&gt;</description></item></channel></rss>