<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>NolanHo</title><description>Treading stars to exhaust the Truth.</description><link>https://axi.moe/</link><templateTheme>Firefly</templateTheme><templateThemeVersion>1.0.0</templateThemeVersion><templateThemeUrl>https://github.com/CuteLeaf/Firefly</templateThemeUrl><lastBuildDate>2026年5月9日 18:41:14</lastBuildDate><item><title>pi-context：一个让 AI 自己管记忆的小工具</title><link>https://axi.moe/posts/picontex/</link><guid isPermaLink="true">https://axi.moe/posts/picontex/</guid><description>我在翻 Pi Agent 扩展时偶然看到一个叫 pi-context 的小项目，代码不到 600 行。读完源码后，我发现它解决了一个我一直很在意但没人做好的问题：怎么让 Agent 主动管理自己的上下文，而不是被动等着框架替它&quot;失忆&quot;。</description><pubDate>Sat, 25 Apr 2026 12:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;pi-context：一个让 AI 自己管记忆的小工具&lt;a href=&quot;#pi-context一个让-ai-自己管记忆的小工具&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;我一直在想这件事&lt;a href=&quot;#我一直在想这件事&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;用 Claude Code 久了，你会发现一个规律：前三十分钟最顺，之后越来越钝，到了某个点它会突然”失忆”——早期反复强调的规则不见了，开始问一些明明之前已经答过的问题。&lt;/p&gt;&lt;p&gt;后来知道这叫 compaction。上下文快到 95% 的时候，Claude Code 会把整段历史丢给模型做摘要，然后用摘要替换原始对话。有人跟踪过这个过程：一个跑了 200 分钟的 Agent，压缩完后把最初的访问控制规则忘了——那些规则不在系统提示里，而在对话早期，被当成了可丢弃的细节。&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;compaction 优化的是”接下来该做什么”，不是”为什么这么做”。决策上下文是压缩的第一批牺牲品。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;这件事让我不舒服的地方在于：&lt;strong&gt;Agent 对这一切毫无感知&lt;/strong&gt;。它不知道自己正在膨胀，不知道哪些是噪音，更不知道压缩什么时候来。它就像一个只能 malloc 不能 free 的程序，等着操作系统替它做一次全身麻醉的脑叶切除。&lt;/p&gt;&lt;p&gt;我要的不是更大的窗口。我要的是 Agent &lt;strong&gt;知道自己什么时候该清内存，以及清哪一部分&lt;/strong&gt;。&lt;/p&gt;&lt;p&gt;后来我在 Kimi CLI 上看到了 &lt;code&gt;d-mail&lt;/code&gt;。名字来自《命运石之门》，功能也像时间旅行：Agent 读了一个大文件，发现只有三行有用，就调用 &lt;code&gt;SendDMail&lt;/code&gt; 回滚到”读文件之前”的 checkpoint，带一条消息告诉过去的自己：“我读了 error.log，根因是 DB 连接池耗尽。”&lt;/p&gt;&lt;p&gt;这是个精妙的机制。但用它的人很快会发现一个问题：Agent 能”回到过去”，但它&lt;strong&gt;不知道自己在哪里&lt;/strong&gt;。没有一个地图告诉它”我现在在时间线的哪个位置&quot;&quot;我可以跳回哪些 checkpoint”。d-mail 给了 Agent 一辆时间机器，但没给导航仪。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;然后我看到了 pi-context&lt;a href=&quot;#然后我看到了-pi-context&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;那阵子在翻 Pi Agent 的扩展生态。Pi 是 Mario Zechner 写的一个极简编码 Agent，session 设计很有意思——存储不是线性数组，是一棵树，每个消息是一个节点，通过 &lt;code&gt;id&lt;/code&gt;/&lt;code&gt;parentId&lt;/code&gt; 链接。Pi 提供了 &lt;code&gt;/tree&lt;/code&gt; 命令让人类跳转，但 Agent 看不到这棵树。&lt;/p&gt;&lt;p&gt;有一天在 GitHub 上翻到 &lt;a href=&quot;https://github.com/ttttmr/pi-context&quot; target=&quot;_blank&quot;&gt;pi-context&lt;/a&gt;，作者是 &lt;a href=&quot;https://github.com/ttttmr&quot; target=&quot;_blank&quot;&gt;ttttmr&lt;/a&gt;。README 说实现了”Agentic Context Management”——让 AI 主动管理自己的上下文。&lt;/p&gt;&lt;p&gt;打开源码。代码非常少，核心只有四个文件：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;src/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;index.ts      # 扩展入口&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;context.ts    # /context 命令的 Token 仪表盘&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;utils.ts      # 辅助函数&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;skills/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;context-management/SKILL.md   # Agent 使用指南&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;读完之后，我发现它解决了一个我一直很在意但没人做好的问题。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;发现一：Session Tree 被翻译成了 Git&lt;a href=&quot;#发现一session-tree-被翻译成了-git&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;看到 Pi 的 tree 结构，第一反应就是：这和 git 太像了。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;每条消息都是一个 commit&lt;/li&gt;
&lt;li&gt;跳转到任意节点就是 &lt;code&gt;git checkout&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;把一堆探索性的对话压缩成 summary，像 squash merge&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;pi-context 的作者把这个直觉变成了可执行的设计。给 Agent 三个工具：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;context_tag&lt;/code&gt;：&lt;code&gt;git tag&lt;/code&gt;，标记节点&lt;/li&gt;
&lt;li&gt;&lt;code&gt;context_log&lt;/code&gt;：&lt;code&gt;git log&lt;/code&gt;，查看上下文骨架&lt;/li&gt;
&lt;li&gt;&lt;code&gt;context_checkout&lt;/code&gt;：&lt;code&gt;git checkout&lt;/code&gt;，在骨架上跳转&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Agent 不需要懂 Pi 内部复杂的树结构。只需要三个操作：&lt;strong&gt;打标签、看地图、做跳转&lt;/strong&gt;。&lt;/p&gt;&lt;p&gt;但有个工程问题：对话多了之后 tree 会非常巨大。让 Agent 直接看完整 tree，它的上下文会先被 tree 本身撑爆。所以必须精简。&lt;/p&gt;&lt;p&gt;pi-context 的解法是&lt;strong&gt;只展示骨架&lt;/strong&gt;。通过一个 &lt;code&gt;isInteresting&lt;/code&gt; 函数过滤，只保留五类节点：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;ROOT / HEAD（起点和当前位置）&lt;/li&gt;
&lt;li&gt;Tags（Agent 主动标记的里程碑）&lt;/li&gt;
&lt;li&gt;Summaries（压缩归档点）&lt;/li&gt;
&lt;li&gt;Branch Points（发生分支决策的关键路口）&lt;/li&gt;
&lt;li&gt;User Messages（用户的原始输入，天然的任务边界）&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;中间所有的思考过程、工具调用、内部操作都被折叠。Agent 看到的不是流水账，是一份带书签的目录。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;35d4182f (ROOT)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ba87607d USER: 排查超时&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;a8e58e1d AI: 读取了日志&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;37ac65e1 TOOL: cat error.log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;36c8ea0b SUM: 根因是DB连接池耗尽...     &amp;lt;- 类似一个 squash commit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;236d45e1 USER: 准备修复&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;a8e58e1d (HEAD) AI: 方案如下...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Agent 决定跳转的时候，就是 &lt;code&gt;git checkout&lt;/code&gt;，带一个消息：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;context_checkout(&quot;36c8ea0b&quot;, &quot;已确认根因是连接池耗尽，推荐增加到50...&quot;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这个设计让我意识到，上下文管理的本质不是”压缩”，而是&lt;strong&gt;降维&lt;/strong&gt;——把高维的完整对话历史降维到低维的”里程碑空间”，让 Agent 能在不丢失方向感的情况下管理记忆。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;/assets/pi-context/session-tree.png&quot; alt=&quot;Session Tree 结构&quot; /&gt;&lt;figcaption&gt;Session Tree 结构&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;发现二：HUD 比地图更重要&lt;a href=&quot;#发现二hud-比地图更重要&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;context_log&lt;/code&gt; 输出时前置了一个 HUD：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[Context Dashboard]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;• Context Usage:    62.3% (124.6k/200.0k)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;• Segment Size:     12 steps since last tag &apos;auth-jwt-start&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;---------------------------------------------------&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Context Usage&lt;/code&gt; 告诉 Agent 内存压力。&lt;code&gt;Segment Size&lt;/code&gt; 告诉它距离上次标记走了多少步。&lt;/p&gt;&lt;p&gt;这个设计很聪明。Agent 不需要理解”信息密度”是什么，它只需要知道”12 步没标记”意味着该行动了。HUD 把抽象的”上下文健康度”变成了两个可以比较的具体数字。&lt;/p&gt;&lt;p&gt;但让我更感兴趣的是 HUD 背后的设计哲学。pi-context 在 &lt;code&gt;before_agent_start&lt;/code&gt; 钩子中向系统提示追加了一段指令：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;use context-management skill&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Proactively manage session history with context_tag, context_log, and context_checkout.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;When history becomes noisy, squash it into a precise carryover summary instead of dragging failed attempts forward.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这段指令不做 API 说明，而是&lt;strong&gt;把上下文管理的心智模型写进了 Agent 的行为准则&lt;/strong&gt;。Agent 被明确告知：你有责任主动管理历史，噪音出现时压缩它，别把失败的尝试拖向未来。&lt;/p&gt;&lt;p&gt;这是一种”认知脚手架”——不是给 Agent 工具，而是教 Agent 建立空间认知：在哪里→要去哪里→怎么去。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;/assets/pi-context/loop.png&quot; alt=&quot;Build-Perceive-Navigate 循环&quot; /&gt;&lt;figcaption&gt;Build-Perceive-Navigate 循环&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;发现三：时间旅行的三段式状态机&lt;a href=&quot;#发现三时间旅行的三段式状态机&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;context_checkout&lt;/code&gt; 是整个系统最复杂的部分。读源码时注意到，实现横跨了 Pi 的三个生命周期事件：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 1. 工具调用阶段：同步创建新分支&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;execute&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;_id&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nid&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sm&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;branchWithSummary&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;tid&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;enrichedMessage&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;CheckoutParams&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;&lt;span&gt;params&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;nid&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;tid&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;enrichedMessage&lt;/span&gt;&lt;span&gt; };&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; [{ &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;text&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;text&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;checkout start&quot;&lt;/span&gt;&lt;span&gt; }] };&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 2. turn_end 阶段：abort 当前回合&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;pi&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;on&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;turn_end&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;event&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;&lt;span&gt;CheckoutParams&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;abort&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 3. agent_end 阶段：执行真正的树导航&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;pi&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;on&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;agent_end&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;async&lt;/span&gt;&lt;span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;_event&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;&lt;span&gt;CheckoutParams&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;CommandCtx&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;await&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CommandCtx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;navigateTree&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;CheckoutParams&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;nid&lt;/span&gt;&lt;span&gt;, { &lt;/span&gt;&lt;span&gt;summarize&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt; });&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;CheckoutParams&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;});&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Pi 的会话管理不允许在工具执行过程中直接改变当前分支。所以必须把”创建分支”和”切换 HEAD”拆成两个不同生命周期的事件。&lt;code&gt;turn_end&lt;/code&gt; 的 &lt;code&gt;abort&lt;/code&gt; 确保旧上下文不会继续输出污染新状态。&lt;/p&gt;&lt;p&gt;这是一个&lt;strong&gt;跨生命周期的分布式状态机&lt;/strong&gt;。三个事件之间通过模块级变量 &lt;code&gt;CheckoutParams&lt;/code&gt; 传递状态——在正常的工程实践里，这种方式看起来有点粗糙。但考虑到 Pi Extension API 的限制，这可能是当时最简洁的方案。&lt;/p&gt;&lt;p&gt;另一个印象深刻的细节是 &lt;code&gt;backupTag&lt;/code&gt;：跳转前把当前状态钉上一个标签，原始历史被永久保存在侧枝。Agent 事后如果发现总结里漏掉了关键细节，随时可以 checkout 回去查看。&lt;/p&gt;&lt;p&gt;不是删除，是归档。时间旅行是无损的。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;/assets/pi-context/dmail.png&quot; alt=&quot;D-Mail 时间旅行&quot; /&gt;&lt;figcaption&gt;D-Mail 时间旅行&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;源码里还有一个容易被忽略的细节&lt;a href=&quot;#源码里还有一个容易被忽略的细节&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;context_tag&lt;/code&gt; 的自动去噪让我停下来想了一会儿。&lt;/p&gt;&lt;p&gt;如果 Agent 没有指定 target，pi-context 不会盲目标记当前叶子节点，而是&lt;strong&gt;回溯找到最后一个”有意义”的节点&lt;/strong&gt;。具体做法是：跳过内部工具（如 &lt;code&gt;context_log&lt;/code&gt; 自己）产生的 ToolResult，跳过只包含内部工具调用的 Assistant 消息。&lt;/p&gt;&lt;p&gt;这个逻辑背后是对 Agent 实际行为的深刻理解：Agent 在决定打标签之前，通常会先调用 &lt;code&gt;context_log&lt;/code&gt; 查看当前状态。如果没有这个去噪逻辑，标签会被钉在 &lt;code&gt;context_log&lt;/code&gt; 自己的输出上——一个对业务毫无意义的元操作节点。&lt;/p&gt;&lt;p&gt;这种”自动跳过噪音”的设计，说明作者不只是写了一个工具，而是&lt;strong&gt;观察了 Agent 的行为模式&lt;/strong&gt;之后做的优化。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;双向时间旅行&lt;a href=&quot;#双向时间旅行&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;d-mail 是”回到过去”。但 Session Tree 天然支持&lt;strong&gt;双向跳转&lt;/strong&gt;：每个 SUM 节点都标记了来源，可以从归档的总结再跳回原始分支，也可以从原始分支跳转到另一个未来。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;/assets/pi-context/backup.png&quot; alt=&quot;双向时间旅行&quot; /&gt;&lt;figcaption&gt;双向时间旅行&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;这张图模拟了一个修 bug 场景。Agent 在主线 fork 出 &lt;code&gt;fix bug-1&lt;/code&gt; 分支，修到一半发现新问题。把分支总结为 &lt;code&gt;SUM: 修复xx&lt;/code&gt; 合并回主线，继续走向 release。但 release 上没复现，Agent 又 checkout 回 fix 分支深入排查，最终发现 bug 和某个 feat 有关，生成新的总结。&lt;/p&gt;&lt;p&gt;绿线是”回到过去”——从侧枝合并回主线。紫线是”前往未来”——从侧枝直接生成新的主线节点。只要分支不被垃圾回收，Agent 随时可以在树的空间里自由移动。&lt;/p&gt;&lt;p&gt;session tree 还有个好处：只要不是太久远的分支，都在缓存里。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;读完源码后的一些想法&lt;a href=&quot;#读完源码后的一些想法&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;上下文管理会不会成为 Agent 的”内存管理单元”（MMU）？&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;现在的 Agent 就像一个没有 MMU 的程序——所有内存 flat 映射，没有分页，没有换入换出。pi-context 做的不是增加内存容量，而是给 Agent 提供了分页和换页的能力。这会不会是未来 Agent 架构的一个标准组件？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Session Tree 是不是一种可操作的长期记忆？&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果把一个 Agent 的所有会话都挂载在一棵巨大的 Session Tree 上，持续通过 summary 把重要内容保留在主线，不重要的内容稀释到久远分支——这本质上就是一种&lt;strong&gt;涌现式的长期记忆&lt;/strong&gt;。重要信息被自然筛选，不重要信息被遗忘，但并未真正删除，只是检索成本变高。&lt;/p&gt;&lt;p&gt;主线 = 工作记忆，侧枝 = 长期记忆。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;和 Git 的同步回溯&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果 &lt;code&gt;context_tag&lt;/code&gt; 和 &lt;code&gt;context_checkout&lt;/code&gt; 能搭配对应的 Git 操作，代码状态和上下文状态可以实现原子级同步回溯。Agent 驱动的重构和实验将拥有真正的 Undo——不是撤销最后一步，而是撤销整个思维过程。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;一些不足&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;context_log&lt;/code&gt; 的 HUD 只显示百分比和步数，如果能显示”最近 N 条消息的平均 token 长度”或”工具调用密度”，Agent 可以更精确地判断信息密度。&lt;/li&gt;
&lt;li&gt;checkout 后的 summary 是一次无缓存的全量历史调用。如果在每次 ReAct 循环都触发，成本会很高。也许可以在 session 内缓存，或者引入更智能的触发策略。&lt;/li&gt;
&lt;li&gt;目前没有”召回”工具——Agent 需要找回某个被归档的具体细节时，只能 checkout 回 backup tag。一个只读的消息召回工具可能会更有用。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;最后&lt;a href=&quot;#最后&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;pi-context 的代码不到 600 行，但它触及了一个根本问题：&lt;strong&gt;当 Agent 变得越来越长命、越来越复杂，谁来管理它的记忆？&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;传统的答案是”框架帮它压缩”或”人类帮它切换”。pi-context 的答案是：&lt;strong&gt;让 Agent 像管理代码一样管理自己的上下文&lt;/strong&gt;——打标签、看日志、做 Checkout、写提交信息。&lt;/p&gt;&lt;p&gt;我不知道这个方案在实际业务中能带来多大提升。但从源码设计的精巧程度来看，作者 ttttmr 不仅写了一个工具，而是提出了一种新的范式。这个范式值得被更多人注意到。&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/ttttmr/pi-context&quot; target=&quot;_blank&quot;&gt;https://github.com/ttttmr/pi-context&lt;/a&gt;&lt;/p&gt;&lt;p&gt;作者的设计思路原文 &lt;a href=&quot;https://blog.xlab.app/p/6a966aeb/&quot; target=&quot;_blank&quot;&gt;https://blog.xlab.app/p/6a966aeb/&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>终端的语义层叠：几种终端方案的底层原理</title><link>https://axi.moe/posts/tstack01/</link><guid isPermaLink="true">https://axi.moe/posts/tstack01/</guid><description>终端模拟器、PTY、tmux 与 WezTerm 的分层机制和交互语义差异。</description><pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Unix 终端不是统一的设备。1970 年代的 VT100 和 2020 年代的 Kitty 在颜色数、光标控制方式、鼠标支持、键盘编码格式上都不同。程序查询 terminfo 数据库，确认自己运行在哪种终端上，然后发送对应的控制序列。&lt;/p&gt;
&lt;p&gt;当我发现 Vim 在 tmux 里的颜色比在原生终端里少，鼠标滚轮在不同程序下行为不一致时，才开始理解终端、PTY、multiplexer 之间叠加了多少层语义。&lt;a href=&quot;../whywez01/&quot;&gt;选型经历见《我为什么选 WezTerm》&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;计算发生在本地时，terminfo 查询和控制序列传输都在同一台机器上完成。计算发生在远程机器上时，网络会断，显示设备在本地。传统工具链把会话管理和显示输入拆分到不同工具；远程开发中，SSH 连接同时承载会话管理和显示输入。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;TTY 与终端模拟器&lt;a href=&quot;#tty-与终端模拟器&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;物理终端&lt;a href=&quot;#物理终端&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;早期计算机没有图形界面。用户通过物理终端与机器交互——一台独立的硬件设备，有键盘和显示器，通过串口连接到主机。DEC VT100 于 1978 年推出，它定义了大量至今仍在使用的控制序列标准。物理终端内部有自己的处理器和内存，接收键盘输入，向主机发送字符，接收主机返回的控制序列并在屏幕上渲染。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;TTY&lt;a href=&quot;#tty&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;TTY 是 Teletypewriter（电传打字机）的缩写。最早的终端确实是电传打字机——一台电动打字机，通过纸带和电话线与计算机通信。Unix 把这类设备抽象为 TTY 设备，在文件系统中表现为 &lt;code&gt;/dev/tty1&lt;/code&gt;、&lt;code&gt;/dev/tty2&lt;/code&gt; 等。&lt;/p&gt;&lt;p&gt;TTY 的核心功能：接收键盘输入传给连接的进程；接收进程的输出显示在屏幕上；处理基础编辑（行缓冲、回显、中断信号如 Ctrl+C）。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;终端模拟器&lt;a href=&quot;#终端模拟器&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;个人电脑普及后，终端模拟器取代物理终端——一个软件程序，模拟物理终端的行为。iTerm2、Alacritty、Kitty、macOS 自带的 Terminal.app 都是终端模拟器。&lt;/p&gt;&lt;p&gt;终端模拟器不做计算，只做三件事：接收键盘输入，转换成字节流发给 shell；接收 shell 输出的字节流，解析控制序列，在窗口中绘制字符；维护 scrollback 缓冲区保存历史输出。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;shell、terminal emulator、multiplexer 的区别&lt;a href=&quot;#shellterminal-emulatormultiplexer-的区别&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;shell&lt;/strong&gt;（bash、zsh、fish）：命令解释器。输入的命令由它解析和执行。shell 不关心字符怎么画到屏幕上，只读写 TTY。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;terminal emulator&lt;/strong&gt;（iTerm2、Alacritty、Kitty）：负责画字符、处理字体颜色、滚动、复制。它创建 PTY master，shell 运行在 PTY slave 上。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;terminal multiplexer&lt;/strong&gt;（tmux、zellij）：在 shell 之上再套一层，管理多个会话、窗口、pane。它持有 PTY master，shell 运行在它创建的 PTY slave 上。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;打开 iTerm2 运行 zsh：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;iTerm2 (terminal emulator)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└── PTY master&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└── zsh (shell) 运行在 PTY slave 上&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;在 iTerm2 里运行 tmux，tmux 里再运行 zsh：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;iTerm2 (terminal emulator)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└── PTY master (iTerm2 持有)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└── tmux client&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└── UNIX socket&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;              &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└── tmux server&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└── PTY master (tmux server 持有)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;└── zsh (shell) 运行在 PTY slave 上&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;iTerm2 的 PTY master 连接的是 tmux client，不是 zsh；tmux server 持有另一个 PTY master，zsh 运行在它的 slave 端。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;为什么需要 PTY&lt;a href=&quot;#为什么需要-pty&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;物理终端时代，终端直接通过串口连接到主机。软件时代，终端模拟器和 shell 在同一台机器上运行，操作系统需要一种机制让它们通信，同时向 shell 呈现为一个真实的 TTY 设备。&lt;/p&gt;&lt;p&gt;PTY 就是为此设计的：一对虚拟设备（master 和 slave），slave 端对 shell 呈现为 &lt;code&gt;/dev/pts/N&lt;/code&gt; 这样的 TTY 设备，master 端由终端模拟器持有。操作系统在内核中转发两端的数据。&lt;/p&gt;&lt;p&gt;PTY 是操作系统提供的虚拟设备对；终端和 shell 通过它转发字节流。shell 不必分辨物理终端和软件终端，终端模拟器也不必关心 shell 内部运行什么程序。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;PTY 与网络断裂&lt;a href=&quot;#pty-与网络断裂&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;SSH 登录远程机器时，远程 &lt;code&gt;sshd&lt;/code&gt; 分配一个 PTY slave，shell 运行在这个 slave 上，master 端通过 SSH 加密通道与本地终端关联。&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart LR
    A[本地终端] --&amp;gt;|SSH| B[远程 sshd&amp;lt;br/&amp;gt;PTY master]
    B --&amp;gt;|PTY| C[shell&amp;lt;br/&amp;gt;PTY slave]
    D[网络断开] -.-&amp;gt;|sshd 退出| B
    B -.-&amp;gt;|master 关闭| C
    C -.-&amp;gt;|SIGHUP| E[进程终止]&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;网络断裂时，&lt;code&gt;sshd&lt;/code&gt; 进程退出，它持有的 PTY master 关闭。内核向 PTY slave 发送 SIGHUP。shell 及其子进程默认终止。未显式脱离控制终端的训练任务、agent 进程、长时间运行的编译会在网络抖动时终止。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;tmux 的解法：让 daemon 持有 PTY master&lt;a href=&quot;#tmux-的解法让-daemon-持有-pty-master&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;tmux 让独立的 daemon 进程持有 PTY master。SSH 断裂只切断 tmux client 与 daemon 之间的 UNIX domain socket 连接；daemon 继续运行，PTY slave 上的进程不会收到 SIGHUP，继续执行。&lt;/p&gt;&lt;p&gt;UNIX domain socket 是一种进程间通信机制，工作在同一台机器的文件系统命名空间内，不经过网络协议栈。tmux client 和 server 通过这个 socket 交换消息，速度比 TCP socket 快。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;terminfo：终端能力的注册表&lt;a href=&quot;#terminfo终端能力的注册表&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Unix 程序用 terminfo 确认终端型号——数据库存储在 &lt;code&gt;/usr/share/terminfo/&lt;/code&gt; 下，每个终端型号有一个条目，记录该终端支持哪些控制指令。&lt;/p&gt;&lt;p&gt;程序启动时读取 &lt;code&gt;$TERM&lt;/code&gt; 环境变量，在数据库中找到对应条目，然后决定发送哪种控制序列。比如 Vim 发送”清屏”字节序列之前，会先查 terminfo。&lt;/p&gt;&lt;p&gt;&lt;code&gt;$TERM&lt;/code&gt; 的值决定了应用程序认为自己运行在哪种终端上。控制这个变量，就控制了下游程序发送的控制序列。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;terminfo 的内部结构&lt;a href=&quot;#terminfo-的内部结构&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart LR
    A[程序启动] --&amp;gt; B[读取 $TERM]
    B --&amp;gt; C[查询 terminfo&amp;lt;br/&amp;gt;/usr/share/terminfo/]
    C --&amp;gt; D[获取控制序列模板]
    D --&amp;gt; E[发送 CSI / OSC&amp;lt;br/&amp;gt;到终端]
    
    style C fill:#fff2cc&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;一个 terminfo 条目可以用 &lt;code&gt;infocmp&lt;/code&gt; 命令查看：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;$ infocmp xterm-256color&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#   Reconstructed via infocmp from file: /usr/share/terminfo/78/xterm-256color&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;xterm-256color|xterm with 256 colors,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;am, bce, ccc, km, mc5i, mir, msgr, npc, xenl,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;colors#256, cols#80, it#8, lines#24, pairs#32767,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;bel=^G, blink=\E[5m, bold=\E[1m, clear=\E[H\E[2J,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cud=\E[%p1%dB,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dch=\E[%p1%dP, dl=\E[%p1%dM, ed=\E[J, el=\E[K,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;二进制文件包含五个部分：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Header&lt;/strong&gt;：包含 magic number（0x11A 或 0x21E，标识字节序）、name section 大小、boolean count、number count、string count、string table size&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Name section&lt;/strong&gt;：终端的主名称和别名，以 null 字节分隔&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Boolean section&lt;/strong&gt;：每个标志占 1 byte，值为 0 或 1。例如 &lt;code&gt;am&lt;/code&gt;（auto margin，自动换行）、&lt;code&gt;bce&lt;/code&gt;（background color erase，清屏时保留背景色）、&lt;code&gt;km&lt;/code&gt;（has meta key）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Number section&lt;/strong&gt;：每个数值占 2 bytes。例如 &lt;code&gt;colors#256&lt;/code&gt;（支持颜色数）、&lt;code&gt;cols#80&lt;/code&gt;（列数）、&lt;code&gt;lines#24&lt;/code&gt;（行数）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;String section&lt;/strong&gt;：每个能力对应 string table 中的一个偏移量，指向实际的控制序列模板。例如 &lt;code&gt;cup&lt;/code&gt;（cursor_address，移动光标）、&lt;code&gt;clear&lt;/code&gt;（清屏）、&lt;code&gt;smcup&lt;/code&gt;/&lt;code&gt;rmcup&lt;/code&gt;（进入/退出 alternate screen）、&lt;code&gt;kmous&lt;/code&gt;（鼠标支持）、&lt;code&gt;setaf&lt;/code&gt;/&lt;code&gt;setab&lt;/code&gt;（设置前景/背景颜色）&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;curses 库（Vim、htop、mutt 等工具的底层）在初始化时读取 &lt;code&gt;$TERM&lt;/code&gt;，解析 terminfo 条目；屏幕绘制操作——移动光标、改变颜色、清屏——都使用 terminfo 定义的序列。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;tmux 的叠加架构与代价&lt;a href=&quot;#tmux-的叠加架构与代价&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;tmux 在终端之上再建一个虚拟终端层，让会话在网络断开后继续运行。&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart LR
    subgraph 本地 [&quot;本地机器&quot;]
        T[终端模拟器]
    end
    
    subgraph 远程 [&quot;远程机器&quot;]
        C[tmux client] --&amp;gt;|UNIX socket| S[tmux server&amp;lt;br/&amp;gt;PTY master]
        S --&amp;gt;|PTY| App[应用程序&amp;lt;br/&amp;gt;PTY slave]
    end
    
    T &amp;lt;--&amp;gt;|SSH| C
    
    style T fill:#e1f5e1
    style S fill:#fff2cc&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;tmux server 从 tmux client 接收按键事件，处理后再向应用程序的 PTY slave 写入字节流；应用程序的输出从 PTY master 进入 tmux server，在 screen buffer 中渲染后整屏推送给 client。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;TERM 截获与能力降维&lt;a href=&quot;#term-截获与能力降维&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;tmux 默认设置 &lt;code&gt;TERM=screen*&lt;/code&gt; 或 &lt;code&gt;TERM=tmux-256color&lt;/code&gt;。下游程序查询 terminfo，读到的是 tmux 的能力集，而非 iTerm2、Alacritty 或 Kitty 的。&lt;/p&gt;&lt;p&gt;我第一次注意到这个问题，是在一台远程服务器上打开 Vim。本地 iTerm2 支持真彩色（&lt;code&gt;set termguicolors&lt;/code&gt; 正常工作），但同一台机器的 tmux session 里，Vim 只能显示 256 色。查了一下，tmux 把 &lt;code&gt;TERM&lt;/code&gt; 改成了 &lt;code&gt;screen-256color&lt;/code&gt;，Vim 查到的能力集里没有真彩色支持。这就是 TERM 截获的直接后果。&lt;/p&gt;&lt;p&gt;终端控制序列是以 ESC（&lt;code&gt;\x1b&lt;/code&gt;，ASCII 27）开头的字节流指令：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart TD
    A[ESC 0x1b] --&amp;gt; B{下一字节}
    B --&amp;gt;|&quot;0x5b [&quot;| C[CSI&amp;lt;br/&amp;gt;光标 / 颜色 / 清屏]
    B --&amp;gt;|&quot;0x5d ]&quot;| D[OSC&amp;lt;br/&amp;gt;剪贴板 / 标题]
    B --&amp;gt;|&quot;0x4d M&quot;| E[鼠标报告&amp;lt;br/&amp;gt;SGR 1006]
    B --&amp;gt;|&quot;0x49 I&quot;| F[聚焦事件&amp;lt;br/&amp;gt;获得焦点]
    B --&amp;gt;|&quot;0x4f O&quot;| G[聚焦事件&amp;lt;br/&amp;gt;失去焦点]&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CSI&lt;/strong&gt;（Control Sequence Introducer）：&lt;code&gt;ESC [&lt;/code&gt; 开头，用于光标移动、颜色设置、清屏。例如 &lt;code&gt;ESC [ 2 J&lt;/code&gt; 清屏，&lt;code&gt;ESC [ 31 m&lt;/code&gt; 设置红色前景&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OSC&lt;/strong&gt;（Operating System Command）：&lt;code&gt;ESC ]&lt;/code&gt; 开头，用于与操作系统交互。例如 &lt;code&gt;ESC ] 52 ; c ; &amp;lt;base64数据&amp;gt; ESC \&lt;/code&gt; 将数据写入系统剪贴板（OSC 52）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;鼠标报告&lt;/strong&gt;：应用程序启用鼠标模式后，终端将点击事件编码为 &lt;code&gt;ESC [ &amp;lt;按钮编码&amp;gt; ; &amp;lt;x&amp;gt; ; &amp;lt;y&amp;gt; M&lt;/code&gt; 发送给应用程序（SGR 1006 格式）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;聚焦事件&lt;/strong&gt;：终端获得或失去焦点时，向应用程序发送 &lt;code&gt;ESC [ I&lt;/code&gt; 和 &lt;code&gt;ESC [ O&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;tmux 截断、翻译或降级这些序列：&lt;/p&gt;


































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;能力&lt;/th&gt;&lt;th&gt;原生终端支持&lt;/th&gt;&lt;th&gt;经 tmux 后&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Kitty 键盘协议&lt;/td&gt;&lt;td&gt;完整修饰键&lt;/td&gt;&lt;td&gt;降级为传统编码&lt;/td&gt;&lt;td&gt;传统终端键盘编码无法区分 Ctrl+i 和 Tab，也无法报告多个修饰键同时按下。Kitty 扩展了编码格式，让程序收到完整的键值和修饰键掩码。tmux 作为中间层无法完整转发这些扩展编码&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sixel 图形&lt;/td&gt;&lt;td&gt;像素数据直传&lt;/td&gt;&lt;td&gt;通常被过滤&lt;/td&gt;&lt;td&gt;DEC 在 1980 年代定义的位图协议，通过 ANSI 序列传输像素数据。tmux 的内部数据结构是字符网格，每个格子存一个字符和颜色属性，无法承载像素矩阵&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;聚焦事件&lt;/td&gt;&lt;td&gt;原生支持&lt;/td&gt;&lt;td&gt;需额外配置转发&lt;/td&gt;&lt;td&gt;Vim 等编辑器用聚焦事件触发自动保存或状态刷新。tmux 默认不转发这些事件，因为焦点在 tmux client 和 server 之间多了一层传递&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Unicode width&lt;/td&gt;&lt;td&gt;终端特定处理&lt;/td&gt;&lt;td&gt;受 tmux 网格限制&lt;/td&gt;&lt;td&gt;East Asian Width 标准对某些字符的宽度定义存在歧义（如某些 emoji）。不同终端采用不同启发式规则。tmux 有自己的网格实现，可能与宿主终端规则不一致&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;双 buffer 结构&lt;a href=&quot;#双-buffer-结构&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;tmux 维护的 screen buffer 基于字符网格，与宿主终端的 scrollback 无关。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;scrollback&lt;/strong&gt;：终端模拟器（iTerm2、Alacritty）维护的历史输出缓冲区。当屏幕上的内容被新输出推上去后，旧内容进入 scrollback。用户可以用鼠标滚轮、触控板或 Shift+PageUp 回溯查看，用鼠标选中后 Command+C 直接复制到系统剪贴板。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;copy-mode&lt;/strong&gt;：tmux 自己的历史浏览机制。用户按前缀键加左方括号键进入，此时键盘事件被 tmux 消费，而不是发给 pane 内的应用程序。用 tmux 的键位导航：Space 开始选择，Enter 复制到 tmux 内部 buffer。这个 buffer 与系统剪贴板不直接互通；靠 OSC 52 或外部脚本才能把内容复制到系统剪贴板。&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart TD
    A[用户想回看历史输出] --&amp;gt; B{操作方式}
    B --&amp;gt;|鼠标滚轮&amp;lt;br/&amp;gt;Shift+PageUp| C[宿主终端 scrollback&amp;lt;br/&amp;gt;本地终端模拟器管理&amp;lt;br/&amp;gt;Command+C 原生复制]
    B --&amp;gt;|前缀键 + 左方括号键&amp;lt;br/&amp;gt;进入 copy-mode| D[tmux screen buffer&amp;lt;br/&amp;gt;tmux server 管理&amp;lt;br/&amp;gt;Space 选择 / Enter 复制]
    
    style C fill:#e1f5e1
    style D fill:#fff2cc&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;scrollback 由本地终端模拟器管理，copy-mode 由远程 tmux server 管理；数据不互通。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;alternate screen 的模拟&lt;a href=&quot;#alternate-screen-的模拟&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;许多全屏 TUI 程序（Vim、less、htop）在启动时请求进入 alternate screen——独立的屏幕缓冲区。退出时切回主屏幕，原来的终端内容仍然可见。&lt;code&gt;ESC [ ? 1049 h&lt;/code&gt; 和 &lt;code&gt;ESC [ ? 1049 l&lt;/code&gt; 两个控制序列实现这个切换。&lt;/p&gt;&lt;p&gt;tmux server 在自己的 screen buffer 中模拟 alternate screen，不直接转发给宿主终端；鼠标滚动和文本选择由 tmux server 处理。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;鼠标事件的多跳转发&lt;a href=&quot;#鼠标事件的多跳转发&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;tmux server 先收到 X10 或 SGR 1006 鼠标事件，再决定消费、转发或进入自己的滚动逻辑。应用程序不再直接处理这些事件。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;zellij 与 cmux&lt;a href=&quot;#zellij-与-cmux&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;zellij 的 modal 输入系统&lt;a href=&quot;#zellij-的-modal-输入系统&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;zellij 也是 client-server 架构，daemon 持有 PTY master，但在 Rust 中内嵌了一个 WASM 运行时，插件以 WebAssembly 模块形式加载，可以编程访问 pane、tab 和状态栏。&lt;/p&gt;&lt;p&gt;它的输入系统是一个显式的 modal 状态机。同一套输入设备在不同”模式”下执行不同功能。Vim 同样使用 modal 输入——normal mode 下 &lt;code&gt;j&lt;/code&gt; 向下移动光标，insert mode 下 &lt;code&gt;j&lt;/code&gt; 插入字母 j。用户切错 mode，输入就路由到错误目标。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Ctrl+p&lt;/code&gt; → pane mode&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+t&lt;/code&gt; → tab mode&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Ctrl+s&lt;/code&gt; → scroll mode&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PageDown&lt;/code&gt; / &lt;code&gt;PageUp&lt;/code&gt; 默认挂在 scroll mode 里&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart TD
    Agent[Agent&amp;lt;br/&amp;gt;node-pty] --&amp;gt;|ANSI 序列| Z[Zellij modal 状态机]
    Z --&amp;gt;|当前处于哪个 mode| Z
    Z --&amp;gt;|消费或转发| App[应用程序]
    
    style Z fill:#ffcccc&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;像 Codex 这样通过 &lt;code&gt;node-pty&lt;/code&gt; 注入 ANSI 序列的 agent 不跟踪 zellij 的 mode 状态。我在 zellij 里运行 Codex 时，它发送的 &lt;code&gt;PageUp&lt;/code&gt; 被 zellij 的 scroll mode 拦截，pane 内的程序根本没有收到这个序列。&lt;/p&gt;&lt;p&gt;&lt;code&gt;node-pty&lt;/code&gt; 是 Node.js 的一个库，它在操作系统中创建 PTY pair，JavaScript 程序通过它像真实终端一样与 shell 交互：写入字节流，读取输出。Codex 通过它向 shell 发送键盘输入和控制序列，期望目标程序直接消费这些字节。zellij 可能把序列收进自己的 mode 处理，不转发给 pane 内的应用程序。官方文档提到 Unlock-First preset：modal 系统在该 preset 下拦截流向应用程序的输入。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;cmux：本地终端与 JSON-RPC 控制&lt;a href=&quot;#cmux本地终端与-json-rpc-控制&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;cmux 用 Ghostty 的 Metal 渲染管线，是一个原生 macOS 终端，提供垂直标签页和 JSON-RPC socket API。&lt;/p&gt;&lt;p&gt;cmux 暴露了一个 socket 接口，外部程序向这个接口发送 JSON 对象来创建窗口、切换标签、查询状态。cmux 控制本地终端，不在远程机器上保持会话存活。&lt;/p&gt;&lt;p&gt;cmux 重启后只还原布局、工作目录和环境变量等元数据；pty 中运行的活跃进程状态不会恢复。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;WezTerm：把 multiplexing 做进终端本身&lt;a href=&quot;#wezterm把-multiplexing-做进终端本身&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart LR
    GUI[WezTerm GUI client&amp;lt;br/&amp;gt;本地渲染] &amp;lt;--&amp;gt;|RPC&amp;lt;br/&amp;gt;damage tracking| Mux[wezterm-mux-server&amp;lt;br/&amp;gt;远程或本地]
    Mux --&amp;gt;|PTY| App[应用程序]
    
    style GUI fill:#e1f5e1
    style Mux fill:#fff2cc&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;section&gt;&lt;h3&gt;Domain：本地与远程 pane 的来源标记&lt;a href=&quot;#domain本地与远程-pane-的来源标记&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;“domain”标记 pane 进程的来源：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;local&lt;/code&gt; domain：在本地机器启动进程&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ssh&lt;/code&gt; domain：通过 SSH 连接远程机器，启动 &lt;code&gt;wezterm-mux-server&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tls&lt;/code&gt; / &lt;code&gt;unix&lt;/code&gt; domain：连接已运行的 mux server&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;GUI 用同一套接口处理所有 domain 的 pane。远程 pane 和本地 pane 由同一个输入分发器处理，没有区别。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Damage tracking：从整屏推流到增量更新&lt;a href=&quot;#damage-tracking从整屏推流到增量更新&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart TB
    subgraph tmux [&quot;tmux 整屏推流&quot;]
        T1[screen buffer 变化] --&amp;gt; T2[序列化整屏字符网格]
        T2 --&amp;gt; T3[通过 UNIX socket 发送]
        T3 --&amp;gt; T4[client 重新渲染虚拟屏幕]
    end
    
    subgraph wez [&quot;WezTerm damage tracking&quot;]
        W1[screen buffer 变化] --&amp;gt; W2{哪些单元格变了?}
        W2 --&amp;gt; W3[只发送变化的单元格&amp;lt;br/&amp;gt;坐标 + 字符 + 颜色]
        W3 --&amp;gt; W4[client 更新对应区域]
    end
    
    style tmux fill:#fff2cc
    style wez fill:#e1f5e1&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;damage tracking 来自图形渲染：屏幕内容变化时，只重绘变化区域。WezTerm 把它用于终端远程传输。&lt;/p&gt;&lt;p&gt;mux server 维护每个 pane 的内部字符网格。当应用程序输出导致网格中的某些单元格发生变化时，server 只把这些变化的单元格——坐标、字符、颜色属性——打包发送给 GUI client。client 收到后，只更新对应的屏幕区域。&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;维度&lt;/th&gt;&lt;th&gt;tmux&lt;/th&gt;&lt;th&gt;WezTerm&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;传输内容&lt;/td&gt;&lt;td&gt;整屏字符流序列化&lt;/td&gt;&lt;td&gt;damage tracking 增量更新&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;带宽使用&lt;/td&gt;&lt;td&gt;高（每次全屏重绘）&lt;/td&gt;&lt;td&gt;低（只传变化的单元格）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;渲染分离&lt;/td&gt;&lt;td&gt;client 负责重新渲染虚拟屏幕&lt;/td&gt;&lt;td&gt;GUI client 只管本地渲染，mux server 管理 pty&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;交互语义&lt;/td&gt;&lt;td&gt;由 tmux server 二次定义&lt;/td&gt;&lt;td&gt;由 GUI client 直接定义&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;tmux 的 screen buffer 每次变化时，tmux server 把整个字符网格序列化为字符串，通过 UNIX socket 发送给 client。client 收到后，在自己的虚拟终端状态机中重新渲染。&lt;/p&gt;&lt;p&gt;mux server 管理 pty 和进程；GUI client 用 OpenGL、Metal 或 WebGPU 做本地渲染。两端通过 RPC 交换 damage tracking 更新和输入事件。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;TERM 端到端穿透&lt;a href=&quot;#term-端到端穿透&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在 WezTerm 的远程 domain 中，远程机器上的应用程序看到的 &lt;code&gt;TERM&lt;/code&gt; 仍然是 &lt;code&gt;wezterm&lt;/code&gt;（或配置的等效值），中间 multiplexer 不会替换它。Kitty 键盘协议、Sixel 图形、Unicode width 的特定行为——只要 WezTerm 原生支持——穿透时不经中间层翻译。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Lua 配置的统一命名空间&lt;a href=&quot;#lua-配置的统一命名空间&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ssh_domains&lt;/span&gt;&lt;span&gt; = {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;dev&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;remote_address&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;myserver&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;remote_wezterm_path&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;/home/user/.local/bin/wezterm&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;keys&lt;/span&gt;&lt;span&gt; = {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;d&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;mods&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;CMD&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;action&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;wezterm&lt;/span&gt;&lt;span&gt;.action.&lt;/span&gt;&lt;span&gt;ShowLauncherArgs&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;flags&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;DOMAINS&quot; &lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;ssh_domains&lt;/code&gt; 定义远程连接，&lt;code&gt;keys&lt;/code&gt; 定义本地键位，&lt;code&gt;flags = &quot;DOMAINS&quot;&lt;/code&gt; 弹出的 launcher 同时列出本地和远程 domain。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;部署代价&lt;a href=&quot;#部署代价&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;远程 domain/mux 通常在远程机器上也要部署 WezTerm 二进制文件，配置包含 &lt;code&gt;ssh_domains&lt;/code&gt;、&lt;code&gt;multiplexing&lt;/code&gt;、&lt;code&gt;remote_wezterm_path&lt;/code&gt; 等选项。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;AI Agent：输入与输出的精确对应&lt;a href=&quot;#ai-agent输入与输出的精确对应&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;AI agent 看不到屏幕，只能凭输出推断状态；输入与输出错位，推断就会出错。&lt;/p&gt;&lt;p&gt;Codex 通过 Node.js 的 &lt;code&gt;node-pty&lt;/code&gt; 模块操作伪终端。&lt;code&gt;node-pty&lt;/code&gt; 在操作系统中创建 PTY pair，JavaScript 程序像真实终端一样与 shell 交互：写入字节流，读取输出，解析 ANSI 转义序列来推断界面状态。&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart LR
    A[Agent] --&amp;gt;|写入字节流| P[node-pty]
    P --&amp;gt;|ANSI 序列| T[终端]
    T --&amp;gt;|输出| P
    P --&amp;gt;|读取| A
    T --&amp;gt;|消费或转发| App[目标应用程序]&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;agent 的输入直达目标程序，屏幕状态与它发送的序列一一对应，输出历史都在同一个 scrollback 里。中间层打断这种对应关系：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;鼠标事件被截获&lt;/strong&gt;：agent 发送的鼠标点击被 tmux copy-mode 消费，目标应用程序毫无感知&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;滚动语义断裂&lt;/strong&gt;：agent 期望 &lt;code&gt;PageUp&lt;/code&gt; 直接滚动历史输出，zellij 的 modal 系统将其映射为 mode 切换&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;历史输出歧义&lt;/strong&gt;：宿主终端的 scrollback 与 tmux pane history 是两个独立的数据结构，agent 读取历史时无法确定面对的是哪一个。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;WezTerm 用 damage-tracking RPC 和统一的本地渲染缓存在本地 GUI 中同步 pane 屏幕状态。我在 WezTerm 的远程 domain 里运行 Codex 时，它写入的字节流直达远程 pane，输出历史和本地终端共用一个 scrollback，没有 mode 系统拦截输入。控制序列由单一的 terminfo 定义。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;终端 emulator 与 multiplexer 为何分离&lt;a href=&quot;#终端-emulator-与-multiplexer-为何分离&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart TB
    subgraph 本地时代 [&quot;本地计算时代&quot;]
        A[终端模拟器] --&amp;gt;|PTY master| B[multiplexer]
        B --&amp;gt;|PTY master| C[shell]
    end
    
    subgraph 远程时代 [&quot;远程开发时代&quot;]
        D[本地终端模拟器] --&amp;gt;|SSH| E[远程 sshd]
        E --&amp;gt;|PTY master| F[multiplexer]
        F --&amp;gt;|PTY master| G[shell]
    end
    
    style 本地时代 fill:#e1f5e1
    style 远程时代 fill:#fff2cc&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;终端模拟器管显示和输入，multiplexer 管会话和窗格，PTY master 与二者在同一台机器上。&lt;/p&gt;&lt;p&gt;计算发生在另一台机器上时，PTY master 位于远程 &lt;code&gt;sshd&lt;/code&gt; 进程中，显示设备在本地。SSH 在两端转发数据。网络断开后，本地终端收不到远程输出，multiplexer 无法向本地发送输出。&lt;/p&gt;&lt;p&gt;terminfo 假设程序直接访问本地终端。控制序列跨越网络、穿越多层中间件时，tmux 的字符网格承载不了 Kitty graphics protocol 的像素数据；多层 TERM 翻译后的 Sixel 序列可能解析失败；attach/detach 切换时聚焦事件可能丢失。&lt;/p&gt;&lt;p&gt;WezTerm 从本地 GUI 到远程 pty 使用同一套 terminfo 和同一套 RPC 协议，远程终端是单一设备。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;什么时候选什么&lt;a href=&quot;#什么时候选什么&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;tmux 依赖少、安装广。如果只是需要 SSH 会话保活，不涉及 TERM 截获或 scrollback 分离，它是更轻量的选择。&lt;/p&gt;&lt;p&gt;当本地与计算分离、AI agent 直接操作终端时，部署 &lt;code&gt;wezterm-mux-server&lt;/code&gt; 得到统一的 terminfo、单一的 scrollback，控制序列不经中间层截获。这对应了我从 iTerm2 + tmux 切换到 WezTerm 远程 domain 时解决的那些具体问题。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>我为什么选 WezTerm</title><link>https://axi.moe/posts/whywez01/</link><guid isPermaLink="true">https://axi.moe/posts/whywez01/</guid><description>我在远程开发和 AI 编码场景下，从 tmux 切换到 WezTerm 的约束和取舍。</description><pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;我在 macOS 上操作，计算在远程开发机上完成。训练、实验、长时间运行的 agent 任务都在远程开发机上。网络会断，但任务不能跟着断。&lt;/p&gt;
&lt;p&gt;有一次，我在某地方改代码，WiFi 抖动了一下，或者我的位置移动了。SSH 断开，远程机上的训练任务收到 SIGHUP，直接终止。那批数据跑了六个小时。从那以后，远程开发机的会话保活成了硬需求。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart LR
    A[macOS 本地] --&amp;gt;|SSH| B[远程开发机]
    B --&amp;gt; C[训练任务]
    B --&amp;gt; D[agent 任务]
    B --&amp;gt; E[长时间运行的实验]
    
    style A fill:#e1f5e1
    style B fill:#fff2cc&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;过去这类需求默认指向 tmux。SSH 断开后，远程 shell 和进程仍然存活。tmux 保活会话，不管终端交互。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;我的工作流约束&lt;a href=&quot;#我的工作流约束&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;那次事件之后，我列出了四条必须同时满足的条件：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;远程任务在网络中断后继续活着&lt;/li&gt;
&lt;li&gt;本地交互保持原生终端体验&lt;/li&gt;
&lt;li&gt;可以按自己的工作流深度定制&lt;/li&gt;
&lt;li&gt;不和 Codex 这类 agent 驱动的终端工作流打架&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;tmux 保活了会话，但劫持了交互&lt;a href=&quot;#tmux-保活了会话但劫持了交互&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;tmux 把远程 shell 会话从 SSH 连接里解耦出来。本地断网，session 还在。&lt;/p&gt;&lt;p&gt;tmux 保活进程的同时，还接管了终端交互。&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart LR
    subgraph 本地 [&quot;本地机器&quot;]
        T[终端模拟器&amp;lt;br/&amp;gt;iTerm2 / Alacritty]
    end
    
    subgraph 远程 [&quot;远程机器&quot;]
        C[tmux client] --&amp;gt;|UNIX socket| S[tmux server]
        S --&amp;gt;|PTY| App[shell / 应用程序]
    end
    
    T &amp;lt;--&amp;gt;|SSH| C
    
    style T fill:#e1f5e1
    style S fill:#fff2cc&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在 tmux 里复制日志时，我要先按前缀键加左方括号键进入 copy-mode，用 Space 开始选择，Enter 复制到 tmux 内部 buffer，再想办法把它弄到系统剪贴板。而在 iTerm2 里，Command+C 直接复制选中的文本。这是两套完全不同的复制语义。&lt;/p&gt;&lt;p&gt;回看历史也一样。在 iTerm2 里，我用鼠标滚轮直接翻历史输出；在 tmux 里，滚轮可能进入 copy-mode，也可能被 pane 内的应用程序消费，取决于 mouse 开关和当前程序状态。宿主终端的 scrollback 和 tmux 的 pane history 是两个独立的数据结构，数据不互通。&lt;/p&gt;&lt;p&gt;Codex 高频刷新界面、持续输出长上下文时，这种双层语义干扰更明显。&lt;a href=&quot;../tstack01/&quot;&gt;底层原理见《终端的语义层叠》&lt;/a&gt;.&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;zellij 仍是 multiplexer&lt;a href=&quot;#zellij-仍是-multiplexer&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;zellij 站在 multiplexer 层，重做了界面和布局。它提供 pane 和 tab，同时把交互做成一套 modal 系统：Ctrl p 进 pane mode，Ctrl t 进 tab mode，Ctrl s 进 scroll mode，连 PageDown / PageUp 默认也挂在 scroll mode 里。&lt;/p&gt;&lt;p&gt;zellij 把终端输入收编进了自己的 mode 体系。Codex 读长输出时发送 PageUp，zellij 却把它映射为 scroll mode 切换，而不是直接滚动历史。agent 期望的输入语义和 zellij 的实际行为对不上。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;cmux 是本地终端，不解决远程持久化&lt;a href=&quot;#cmux-是本地终端不解决远程持久化&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;cmux 基于 Ghostty，是原生 macOS 终端，主打垂直标签页、通知提醒环、分屏面板、内置浏览器和 socket API，官网直接把 Claude Code、Codex 当成核心使用对象。&lt;/p&gt;&lt;p&gt;它把 agent 工作流包装成本地终端产品，不管远程会话保活。cmux 重启后只能恢复布局、工作目录、回滚缓冲区这些元数据，活跃的终端应用会话不会恢复。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;WezTerm 把远程会话做进终端&lt;a href=&quot;#wezterm-把远程会话做进终端&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart LR
    GUI[WezTerm GUI client&amp;lt;br/&amp;gt;本地渲染] &amp;lt;--&amp;gt;|RPC| Mux[wezterm-mux-server&amp;lt;br/&amp;gt;远程或本地]
    Mux --&amp;gt;|PTY| App[应用程序]
    
    style GUI fill:#e1f5e1
    style Mux fill:#fff2cc&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;WezTerm 是 terminal emulator。复制、滚动、文本选择、快捷键发生在终端自己的层，外部 multiplexer 不会先截获它们。它内置了 multiplexer/domain 模型，配置是 Lua。&lt;/p&gt;&lt;p&gt;我第一次注意到 &lt;code&gt;wezterm-mux-server&lt;/code&gt; 这个二进制文件时，才意识到 WezTerm 不是在终端外面套了一层 multiplexer，而是把远程会话能力直接做进了终端系统。&lt;code&gt;wezterm connect&lt;/code&gt; 连接的是 mux server，&lt;code&gt;wezterm cli&lt;/code&gt; 操作的是 mux server，远程 attach/detach 是终端自身的语义，不是额外再套一个 TUI。&lt;/p&gt;&lt;p&gt;它在命令层提供 wezterm connect、wezterm cli、wezterm start —domain … —attach，系统里还有单独的 wezterm-mux-server。wezterm connect 连接 multiplexer，wezterm cli 和 mux server 交互。&lt;/p&gt;&lt;p&gt;“本地 terminal emulator + SSH + 远程 tmux” 把远程会话管理套成额外一层 TUI。WezTerm 把它收进终端自己的 domain/mux 层。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;会话持续，网络断开后还能重新 attach&lt;/li&gt;
&lt;li&gt;本地接近原生终端，copy mode 和 pane buffer 不会重写交互&lt;/li&gt;
&lt;li&gt;配置都在同一个 Lua 脚本里&lt;/li&gt;
&lt;li&gt;远程 host 是常驻开发机，服务器上需要安装 WezTerm&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这套远程 mux 有成本。配置层里有 ssh_domains、multiplexing、remote_wezterm_path，用全远程 domain/mux 能力，远程机器上通常也要装一份 WezTerm。&lt;/p&gt;&lt;p&gt;WezTerm 不需要外部 multiplexer。terminal emulator 自己处理远程连接，复制、滚动和历史都在同一层。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;实际配置&lt;a href=&quot;#实际配置&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;远程连接、本地键位、domain 切换都在同一个 Lua 配置脚本里：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ssh_domains&lt;/span&gt;&lt;span&gt; = {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;dev&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;remote_address&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;myserver&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;remote_wezterm_path&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;/home/user/.local/bin/wezterm&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;keys&lt;/span&gt;&lt;span&gt; = {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;d&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;mods&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;CMD&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;action&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;wezterm&lt;/span&gt;&lt;span&gt;.action.&lt;/span&gt;&lt;span&gt;ShowLauncherArgs&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;flags&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;&quot;DOMAINS&quot; &lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;同一个 Lua 脚本里，&lt;code&gt;ssh_domains&lt;/code&gt; 定义远程连接，&lt;code&gt;keys&lt;/code&gt; 定义本地键位，&lt;code&gt;flags = &quot;DOMAINS&quot;&lt;/code&gt; 弹出的 launcher 同时列出本地和远程 domain。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;AI Agent 需要什么&lt;a href=&quot;#ai-agent-需要什么&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;AI agent 读字节流，不读像素。输出和输入对不上，它推断的状态就错。&lt;/p&gt;&lt;p&gt;Codex 通过 Node.js 的 &lt;code&gt;node-pty&lt;/code&gt; 模块操作伪终端：它写入字节流，读取输出，解析 ANSI 转义序列来推断界面状态。&lt;/p&gt;&lt;p&gt;agent 写入字节流，目标程序直接接收；屏幕内容与发送的序列一致；输出都在同一个 scrollback 里。这是 agent 推断界面状态的前提。&lt;/p&gt;&lt;p&gt;tmux 和 zellij 都在 agent 和终端之间加了一层，打破了这种对应关系：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;鼠标事件被截获：agent 发送的鼠标点击被 tmux copy-mode 消费，目标应用程序毫无感知&lt;/li&gt;
&lt;li&gt;滚动语义断裂：agent 发送 PageUp 想滚动历史输出，zellij 的 modal 系统却把它映射为 mode 切换&lt;/li&gt;
&lt;li&gt;历史输出歧义：宿主终端的 scrollback 与 tmux pane history 是两个独立的数据结构，agent 读取历史时无法确定面对的是哪一个&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;WezTerm 的 damage-tracking RPC 和本地渲染缓存在本地 GUI 上保存了 pane 屏幕的副本。agent 操作远程 pane 时，外部 mode 系统不会拦截输入，输出历史都在同一个 scrollback 里，terminfo 定义终端行为。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;什么时候选什么&lt;a href=&quot;#什么时候选什么&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;tmux 预装在大多数服务器上。纯 SSH、低安装成本的场景下，它不会增加部署负担。&lt;/p&gt;&lt;p&gt;WezTerm 更适合我的工作流：本地和计算分离，远程机常驻，任务常常长时间运行，日常交互密度高，同时用 Codex 这类 agent 工具工作。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>RL算法笔记 WIP</title><link>https://axi.moe/posts/kf6ea3bu/</link><guid isPermaLink="true">https://axi.moe/posts/kf6ea3bu/</guid><pubDate>Sun, 25 Jan 2026 23:02:40 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;RL算法笔记 WIP&lt;a href=&quot;#rl算法笔记-wip&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;最终目标!!!&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;776&quot; src=&quot;/_astro/image-20260125200746-d8skpej.CoJiwkrx_Z1oQ6rF.webp&quot; srcset=&quot;/_astro/image-20260125200746-d8skpej.CoJiwkrx_1XzKBO.webp 640w, /_astro/image-20260125200746-d8skpej.CoJiwkrx_9QdkK.webp 750w, /_astro/image-20260125200746-d8skpej.CoJiwkrx_Z1j4Vba.webp 828w, /_astro/image-20260125200746-d8skpej.CoJiwkrx_CI50b.webp 1080w, /_astro/image-20260125200746-d8skpej.CoJiwkrx_UvhXv.webp 1280w, /_astro/image-20260125200746-d8skpej.CoJiwkrx_Z1oQ6rF.webp 1440w&quot; /&gt;&lt;figcaption&gt;image&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;section&gt;&lt;h2&gt;贝尔曼公式 Bellman Equation&lt;a href=&quot;#贝尔曼公式-bellman-equation&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;定义&lt;a href=&quot;#定义&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;回报（Return）和价值（Value）&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;我们定义&lt;strong&gt;回报 (Return)&lt;/strong&gt;  。这是 Agent 从时刻  开始，一直持续到未来所能获得的折扣累计奖励：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;：执行动作后的即时奖励（reward）。&lt;/li&gt;
&lt;li&gt;：折扣因子（Discount Factor）。&lt;/li&gt;
&lt;li&gt;注：奖励（reward）是即时的，回报（return）是累计的。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这里面可以用递归的技巧写出：&lt;/p&gt;&lt;hr /&gt;&lt;ol&gt;
&lt;li&gt;状态价值函数（State Value）&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;状态价值函数  定义为：在状态  下，遵循策略  能获得期望回报（average return）。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;这里是回报（全局概念）而不是奖励（reward）&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;ol&gt;
&lt;li&gt;动作价值函数（Action Value）&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;在状态  下，遵循策略  采取动作 ，能获得期望回报（average return）。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;和 State Value 的差异就是它选择了一个 action&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;因此：&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;推导&lt;a href=&quot;#推导&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;基于上述定义，我们将  的递归形式代入价值函数的定义，进行展开。&lt;/p&gt;代入递归定义&lt;p&gt;这里分出来两个期望，分别是下一步的即时 reward 和未来的 return&lt;/p&gt;&lt;p&gt;1.&lt;/p&gt;选定动作后的期望奖励&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;第一步：由于  是个策略函数，输出多个动作，而每个动作都是一个可能性，因此  需要拆成对每个动作进行求和， 是在状态  下，选择动作  的概率&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;第二步： 是一个环境反馈项&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt; 是状态  和动作  下，环境给予的奖励（reward）&lt;/li&gt;
&lt;li&gt; 自不必说，是这个奖励  的概率&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;‍&lt;/p&gt;&lt;p&gt;2.&lt;/p&gt;&lt;p&gt;这里的遍历性（期望如何展开）在于，在  下还能去哪些状态 ，和 1 一样，我们自然而然的对下一状态  进行展开：&lt;/p&gt;&lt;p&gt;这里还存在期望项没有展开完，我们还需要继续进行，而由于 RL 算法一般假设马尔可夫过程，因此在求  期望时， 是不必要的，因此又可写成：&lt;/p&gt;&lt;p&gt;这里面有个容易注意到的事实（但我来说难以注意）， 恰好是我们刚刚定义的 ，其意义是站在  状态下的期望回报，只需换成 ，于是我们写成（又一递归形式）：&lt;/p&gt;&lt;p&gt;但这并非我们想要的项，因为  包含 ，而对于一个站在状态  的智能体来说，是只能通过某个动作  转换到 ，因而我们需要把  转成如此形式：&lt;/p&gt;&lt;p&gt;分别是状态  下，采取动作  能够到  的概率，以及状态  下，策略  能够生成动作  的概率，其实就是  到  的所有路径概率之和，最后代回得到：&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;贝尔曼方程&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;上面求的所有中间结果代回：&lt;/p&gt;&lt;p&gt;我们发现里面都有 ，直接提出（求和）：&lt;/p&gt;即时奖励折现后的未来价值&lt;p&gt;这就是贝尔曼方程&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;p&gt;注意这是个递推式，只描述了状态  下如何求价值函数，要求解需要对每个状态列出方程组成方程组求解。&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;p&gt;其次，把  提出写成这样的形式是有一定的妙处的，可以发现  是一个策略，而方括号里面都是价值，包括了即时和未来两项，我们回到动作价值的定义，后面就是 Action Value：&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;矩阵表示&lt;a href=&quot;#矩阵表示&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;由于我们上面求出的是个递推式，为了全局求解，我们实际上需要列出方程组，因此先推导矩阵表示，我们回到提出  之前，引入记号代表两项&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;即时奖励部分&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li&gt;未来回报部分&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;有了这两个记号原来的方程可以简化为：&lt;/p&gt;&lt;p&gt;再写成向量表示：&lt;/p&gt;&lt;p&gt;价值向量  ()：&lt;/p&gt;&lt;p&gt;奖励向量  ()：&lt;/p&gt;&lt;p&gt;转移矩阵  ()：第  行第  列的元素 &lt;/p&gt;&lt;p&gt;于是直接写成：&lt;/p&gt;&lt;p&gt;由于  和  都是已知的（假设我们知道环境），上面又是线性方程组，可以直接推导解析解：&lt;/p&gt;&lt;p&gt;但实际中解析解通常求不出来，原因如下：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;如果  很大，矩阵求逆会非常困难，复杂度 ，而实际问题中， 一般都很大&lt;/li&gt;
&lt;li&gt;有时我们不知道  和  是什么，或者难以模拟，被称为 Model-Free 场景&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;‍&lt;/p&gt;&lt;p&gt;于是我们需要一种迭代求解方法&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;贝尔曼最优方程 bellman optimal equation&lt;a href=&quot;#贝尔曼最优方程-bellman-optimal-equation&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;首先我们定义何为最优 &lt;strong&gt;，&lt;/strong&gt; 这和博弈论的优势策略是一样的：&lt;/p&gt;&lt;p&gt;我们就说策略  优于或等于 &lt;/p&gt;&lt;p&gt;基于此，我们要寻找的最优状态价值函数  定义为所有可能策略下的最大值：&lt;/p&gt;&lt;p&gt;这就引出几个问题：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;这样的策略是否存在？&lt;/li&gt;
&lt;li&gt;这样的策略是否唯一？&lt;/li&gt;
&lt;li&gt;这样的策略是随机策略还是确定性策略？&lt;/li&gt;
&lt;li&gt;如何达到这样的策略？&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;‍&lt;/p&gt;&lt;p&gt;我们继续用上面矩阵表示的记号，对于任意固定策略 ，价值函数满足线性方程：&lt;/p&gt;&lt;p&gt;观察上式，实际上的未知变量只有 ，我们可以看作是：&lt;/p&gt;&lt;p&gt;其中：&lt;/p&gt;&lt;p&gt;这个形式可以用不动点定理，需证明  是个收缩映射：&lt;/p&gt;&lt;p&gt;对于任意两个价值向量  和 ，满足：&lt;/p&gt;&lt;p&gt;详细证明略&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;p&gt;由此，我们可知解存在，并可以采用迭代方法求解：只需要随机初始化一个 ，不断应用函数 ，足够多步后我们能够得到最优的 &lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>在 RAG 和 Agentic 搜索下做结果融合的一些思路</title><link>https://axi.moe/posts/rn9lt25e/</link><guid isPermaLink="true">https://axi.moe/posts/rn9lt25e/</guid><pubDate>Sun, 28 Dec 2025 00:29:49 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;在 RAG 和 Agentic 搜索下做结果融合的一些思路&lt;a href=&quot;#在-rag-和-agentic-搜索下做结果融合的一些思路&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;前言：读 EverMemOS 项目源码时发现里面用了 Reciprocal Rank Fusion（RRF），详细了解后意识到它本质上是一类通用的排序融合方法，在 Hybrid 搜索场景下被广泛采用。本文不展开 EverMemOS 本身，而是借这个契机，单独从 RAG / Agentic 搜索的角度，把多通道结果在融合层如何合成一个统一排序这件事梳理清楚。&lt;/p&gt;&lt;section&gt;&lt;h2&gt;1. 为什么在 RAG / Agentic 搜索下需要 Hybrid？&lt;a href=&quot;#1-为什么在-rag--agentic-搜索下需要-hybrid&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在真实业务中，单一路径的检索往往难以覆盖所有信息需求，尤其是在 RAG 和 Agentic Search 这类对检索质量高度敏感的系统里更是如此。以用户画像、对话记忆、知识问答等场景为例，我们往往需要同时依赖几种通道：关键词检索负责捕捉原话里的特定词语，向量检索更擅长语义近邻，图检索能揭示实体和实体之间的关系，结构化检索则对表格、数据库中那些字段化的信息更有效。&lt;/p&gt;&lt;p&gt;这些通道各自擅长的是不同类型的相关性：有的更看重字面匹配，有的更看重语义相似，有的更强调上下文和结构。如果只选择其中一种，很容易出现两个极端：要么重要信息根本没有被召回，要么召回了一大堆噪声，排序结果非常不稳定。&lt;/p&gt;&lt;p&gt;在实际系统中，随着业务发展，查询的形态会不断演化：从短句关键词，到含有上下文的长问题，再到多轮对话中的追问和反问。对于 RAG 和 Agentic 搜索来说，这直接表现为：有些问题更依赖关键词的精确命中，有些问题更依赖语义近邻，还有一些问题只有在理解实体关系或结构化字段后才能被合理回答。Hybrid 搜索存在的意义，就是在召回阶段引入多视角，在融合阶段把这些视角下得到的结果汇总成一个相对稳定的排序，让上层的 LLM 或 Agent 不必在碎片化的多路结果上再做一次检索工作。&lt;/p&gt;&lt;p&gt;下面先给出一个简化的架构视图，用来说明召回与融合的分工，然后重点展开融合层可以采用的几种技术路径。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; width=&quot;3304&quot; height=&quot;1316&quot; src=&quot;/_astro/image-20251228002820-g43pbrd.DY8bvPP__Z1I8AEf.webp&quot; srcset=&quot;/_astro/image-20251228002820-g43pbrd.DY8bvPP__9viIV.webp 640w, /_astro/image-20251228002820-g43pbrd.DY8bvPP__2wLs2g.webp 750w, /_astro/image-20251228002820-g43pbrd.DY8bvPP__FUAT5.webp 828w, /_astro/image-20251228002820-g43pbrd.DY8bvPP__Z1dg0x.webp 1080w, /_astro/image-20251228002820-g43pbrd.DY8bvPP__Z2einJq.webp 1280w, /_astro/image-20251228002820-g43pbrd.DY8bvPP__Z13vKUB.webp 1668w, /_astro/image-20251228002820-g43pbrd.DY8bvPP__1I9Rmr.webp 2048w, /_astro/image-20251228002820-g43pbrd.DY8bvPP__1LEPqm.webp 2560w, /_astro/image-20251228002820-g43pbrd.DY8bvPP__Z1I8AEf.webp 3304w&quot; /&gt;&lt;figcaption&gt;image&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;2. 整体架构：召回与融合&lt;a href=&quot;#2-整体架构召回与融合&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在实践中，大家常用的描述是召回 → 融合 → 重排的三层结构。为了把注意力集中在融合层上，可以先把重排暂时放在一边，只保留前两层：召回层负责把各个通道的候选拉齐到桌面上，融合层负责给这一堆候选排出一个大家都能接受的顺序。&lt;/p&gt;&lt;p&gt;如果把整个过程压缩成几步，大致可以理解为：给定一个查询 ，我们并行地向 BM25、Embedding、图检索等通道发起检索，分别得到若干个形如  的列表；随后，在融合层把这些列表合并成一个候选集合，并按某种规则给出最终排序。召回阶段主要受索引结构、向量模型和吞吐约束的影响，而融合阶段则更多关注不同通道之间的博弈关系与整体鲁棒性。&lt;/p&gt;&lt;p&gt;下面先简要看一下召回层的设计要点，然后把主要篇幅留给融合层的方法与理论。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;3. 召回层：多通道设计与配额控制&lt;a href=&quot;#3-召回层多通道设计与配额控制&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;召回层的目标不是把顺序排好，而是尽量不漏掉潜在相关的文档。典型的设计要点包括：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;通道选择&lt;/strong&gt;：根据业务场景选择 BM25、Embedding、图搜索、结构化检索等通道；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配额控制（budgeting）&lt;/strong&gt; ：为每个通道分配 Top-K 配额，例如 BM25 取 100 条、Embedding 取 200 条、图搜索取 50 条；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;基础去重&lt;/strong&gt;：在单通道内部做简单去重（按文档 ID）；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;召回结果结构化&lt;/strong&gt;：统一整理为 &lt;code&gt;{doc_id, score, source}&lt;/code&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;结果集的规模在可控范围内，方便后续融合和重排。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;在实践中，召回层还有几个容易被忽视但很关键的问题：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;配额分配是策略问题而不是纯参数问题&lt;/strong&gt;：不同通道的 Top-K 配额不仅影响召回率，也直接影响后续融合的话语权。例如给 BM25 只 20 条、给向量 500 条，几乎等价于把主导权交给向量通道。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;静态配额 vs 动态配额&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;静态配额实现简单，但对不同 query 形态的适配性有限；&lt;/li&gt;
&lt;li&gt;动态配额可以基于 query 特征（长度、是否包含实体、是否是导航型等）调整不同通道的配额，更适合复杂业务，但需要更多监控与调参。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;候选池大小与下游成本&lt;/strong&gt;：召回过多会放大后续融合和重排的成本和延迟；召回过少则会直接限制上限。通常需要结合性能预算设定一个全局候选池上限，并按通道、按业务重要性进行切分。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;4. 融合层：几种混合技术&lt;a href=&quot;#4-融合层几种混合技术&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在融合层，我们的目标是把多通道召回得到的候选集合，转化为一个在全局上可比较的排序结果。常见的技术路径大致可以归为三类：&lt;/p&gt;&lt;section&gt;&lt;h3&gt;4.1 分数归一化与线性加权&lt;a href=&quot;#41-分数归一化与线性加权&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是一种最直观的方式。直接在分数空间里做融合，尝试将各通道的分数拉到同一量纲上，再做加权合成：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;对每个通道，先做一次归一化，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;min-max 归一化；&lt;/li&gt;
&lt;li&gt;z-score 归一化；&lt;/li&gt;
&lt;li&gt;基于排序的分位数映射（如将分数映射到  的分位区间）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;然后对同一文档来自不同通道的归一化分数求和或加权求和，例如：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&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;/ul&gt;&lt;p&gt;但在工程上会遇到一些明显问题：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;分数分布差异大&lt;/strong&gt;：不同通道分数的尺度和分布差异明显，归一化方式容易影响结果；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分布随时间漂移&lt;/strong&gt;：模型或索引配置变化后，分数分布可能随时间漂移，导致线下调好的权重在新场景失效；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;权重难以泛化&lt;/strong&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;以各通道的归一化分数  作为特征；&lt;/li&gt;
&lt;li&gt;用逻辑回归或线性回归学习最优的 。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这实质上是一种极简版的 Learning to Rank，但特征空间和模型形式都被限定在每通道一维分数这个极小的空间里，适合作为从启发式到学习式融合的过渡形态。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;4.2 基于名次的 RRF 及变体&lt;a href=&quot;#42-基于名次的-rrf-及变体&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;为了规避分数不可比的问题，另一类思路是&lt;strong&gt;只看名次，不看具体分数&lt;/strong&gt;。RRF（Reciprocal Rank Fusion）就是其中应用最广的一种，可以理解为一种带平滑项的倒数名次投票制。&lt;/p&gt;&lt;p&gt;我们只关心文档在每个通道中的名次 ，而不使用原始分数本身。RRF 的打分方式为：&lt;/p&gt;&lt;p&gt;其中：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;：第  个通道（BM25、Embedding、图搜索等）；&lt;/li&gt;
&lt;li&gt;：文档  在该通道返回结果中的名次（从 1 开始）；&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;靠后的名次贡献迅速衰减；&lt;/li&gt;
&lt;li&gt;如果某个文档在多个通道中都排在前列，那么它的  会显著高于只在单一路通道靠前的文档。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;与分数加权相比，RRF 的工程优势在于：&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;在 RRF 周边，还可以演化出一些变体：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;调整  的大小，以控制是只看前几名还是兼顾更多长尾结果；&lt;/li&gt;
&lt;li&gt;对不同通道使用不同的权重，例如在求和时乘以 ；&lt;/li&gt;
&lt;li&gt;将 RRF 得分与部分通道的分数归一化结果再做一次线性加权，形成「名次 + 分数」混合方案。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;如果从复杂度角度看，RRF 在工程上也比较友好：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;设通道数为 ，每个通道召回  条文档，则融合层只需处理  规模的候选集合；&lt;/li&gt;
&lt;li&gt;计算  的成本是线性的，排序成本是 ，对于多数在线检索场景是可以接受的；&lt;/li&gt;
&lt;li&gt;由于只依赖名次，RRF 对于分布漂移的敏感度明显低于分数加权，通常可以作为一个少调参也不容易炸的安全选项。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;4.3 规则与级联式 Hybrid&lt;a href=&quot;#43-规则与级联式-hybrid&quot;&gt;&lt;span&gt;#&lt;/span&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;辅通道：例如 BM25 或图搜索，用于弥补主通道在某些问题上的盲区。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;典型做法包括：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;先使用主通道得到 Top-N 结果；&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;figure&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; width=&quot;3878&quot; height=&quot;772&quot; src=&quot;/_astro/image-20251228002609-qq6pxqm.DJ23S4Xp_iLMAu.webp&quot; srcset=&quot;/_astro/image-20251228002609-qq6pxqm.DJ23S4Xp_1Si8Mu.webp 640w, /_astro/image-20251228002609-qq6pxqm.DJ23S4Xp_7CgP7.webp 750w, /_astro/image-20251228002609-qq6pxqm.DJ23S4Xp_Z28fGRP.webp 828w, /_astro/image-20251228002609-qq6pxqm.DJ23S4Xp_ZTHJtM.webp 1080w, /_astro/image-20251228002609-qq6pxqm.DJ23S4Xp_1DCVGd.webp 1280w, /_astro/image-20251228002609-qq6pxqm.DJ23S4Xp_Znt90T.webp 1668w, /_astro/image-20251228002609-qq6pxqm.DJ23S4Xp_ZcNYYO.webp 2048w, /_astro/image-20251228002609-qq6pxqm.DJ23S4Xp_22rXKI.webp 2560w, /_astro/image-20251228002609-qq6pxqm.DJ23S4Xp_iLMAu.webp 3878w&quot; /&gt;&lt;figcaption&gt;image&lt;/figcaption&gt;&lt;/figure&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;/ul&gt;&lt;p&gt;在工程上，规则与级联式 Hybrid 往往和 RRF / 分数加权组合使用：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;先按主-辅结构过滤、补充候选集合；&lt;/li&gt;
&lt;li&gt;再在合并后的候选上应用 RRF 或分数加权进行统一排序。&lt;/li&gt;
&lt;/ul&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;/section&gt;&lt;section&gt;&lt;h3&gt;4.4 排序聚合视角：RRF 与其它 Rank Fusion&lt;a href=&quot;#44-排序聚合视角rrf-与其它-rank-fusion&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;从更抽象的排序聚合（rank aggregation）或社会选择视角看，我们在做的事情是：给定多个排序器输出的序列，构造一个集体排序。这一问题在信息检索与投票理论中都被系统研究过。&lt;/p&gt;&lt;p&gt;经典的几类排序聚合方法包括：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Borda count&lt;/strong&gt;：每个排序位置赋予线性递减的分数，例如第 1 名  分、第 2 名  分等，对所有排序求和后得到最终顺序；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Condorcet 家族方法&lt;/strong&gt;：将排序问题转化为成对比较，寻找在多数意义下更优的一致排序；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kemeny optimal 排序&lt;/strong&gt;：在所有可能的全排序中，找到一个使得与各个输入排序距离之和最小的排序，这个定义在理论上很漂亮，但计算复杂度很高。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;RRF 可以看作是一种带有倒数权重核的 Borda 变体：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;它不是给第  名一个线性分数，而是给一个  形式的分数，使得前几名的权重更集中、后面的尾部衰减更快；&lt;/li&gt;
&lt;li&gt;平滑常数  决定了是只看非常靠前的少数结果，还是兼顾一个较长的前缀，实质上控制了方法的 top-heavy 程度；&lt;/li&gt;
&lt;li&gt;与 Kemeny 这类需要全局优化的排序不同，RRF 的计算是局部且可加的，只需遍历一次候选集合即可完成。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;与其它 rank fusion 方法相比，RRF 还具备两个在理论与实践上都很有用的性质：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;对单调变换不敏感&lt;/strong&gt;：由于只依赖名次，任何在单个通道内保持排序不变的分数变换（如对数、缩放）都不会影响最终结果；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对共识相关性的显式偏好&lt;/strong&gt;：只有在多个通道都给出较好名次的文档，才能获得显著更高的得分，这与我们在信息检索中追求的稳定相关结果高度契合。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;从更理论的角度看，许多排序聚合方法可以被视为在某种距离度量下逼近 Kemeny 最优排序，即在所有可能的全排序中，寻找一个与各个输入排序距离之和最小的排序。距离常用 Kendall tau，这一度量本质上统计了两个排序之间顺序相反的成对项个数。完全求解 Kemeny 排序是 NP 困难的，因此实际系统往往采用启发式近似。RRF 可以看作是一类强调前几名、一致性导向的启发式，它并不显式最小化某个全局目标，但通过对高名次赋予倒数权重，在直观上偏向那些在多数排序中都靠前的文档，从而在计算复杂度与近似质量之间取得一个工程上可接受的折中。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>mem0 源码阅读：一个工程化记忆系统</title><link>https://axi.moe/posts/9sof0224/</link><guid isPermaLink="true">https://axi.moe/posts/9sof0224/</guid><pubDate>Tue, 09 Dec 2025 01:26:35 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;mem0 源码阅读：一个工程化记忆系统&lt;a href=&quot;#mem0-源码阅读一个工程化记忆系统&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;blockquote&gt;&lt;p&gt;最近在系统性看各种 Agent Memory 的实现，学习了不少开源项目和论文，打算写一组文章，输出一些记忆文章。这篇文章准备当做系列里的第一篇（实际上 COLMA 那篇才是第一篇），从相对简单但工程化程度比较完整的 mem0 开始。本文主要从工程视角出发。&lt;/p&gt;&lt;/blockquote&gt;&lt;hr /&gt;&lt;section&gt;&lt;h2&gt;1. 记忆系统和 RAG&lt;a href=&quot;#1-记忆系统和-rag&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;先从基线讲起：如果只用最朴素的 RAG 来给对话做记忆，一般会怎么做？&lt;/p&gt;&lt;p&gt;常见做法大概是：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;每轮对话结束，把这一轮的文本 append 到某个日志列表里。&lt;/li&gt;
&lt;li&gt;定期或每轮把日志切块、做 embedding，写进向量库。&lt;/li&gt;
&lt;li&gt;用户下一次提问时，用 query 去向量库做相似度搜索，把 topK 结果当成上下文拼给模型。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;如果我们就把这套东西当成“记忆系统”，很快会撞到几个典型问题。&lt;/p&gt;&lt;p&gt;第一是上下文不连贯。现实里的对话是按话题组织的，话题内部高度相关，话题之间又是突变的；而在向量库里，我们只看到一堆碎片化的 chunk。检索拿回来的内容，往往是同一话题被撕成很多段，顺序也乱了。&lt;/p&gt;&lt;p&gt;第二是碎片化和矛盾共存。比如用户连续几次提到“我喜欢 A”，你一直在追加新条目，最后搜出来全是类似的句子；某个时间点用户改口说“其实我现在不喜欢 A 了”，如果没有 update 机制，只能继续 add，新旧偏好会长期并存，最终哪个被模型用到，完全取决于召回运气。&lt;/p&gt;&lt;p&gt;第三是召回不可控。简单的向量搜索 + topK 很难保证那些真正重要、应该进入长期记忆层的内容一定能被抽出来。&lt;/p&gt;&lt;p&gt;这背后其实是一个定义问题：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;RAG 更像是在 &lt;strong&gt;管理原始对话日志&lt;/strong&gt; 的检索。&lt;/li&gt;
&lt;li&gt;记忆系统更关心的是 &lt;strong&gt;长期稳定的语义事实&lt;/strong&gt;，比如用户是谁、偏好什么、有什么长期目标。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;如果把这两件事混在一起，既不好维护，也不方便审计。实践里更合理的做法，是把它们拆开：上层保留一份短期对话上下文，用来回答当前问题；底下再挂一层长期语义记忆，只存经过整理的事实，并且支持更新和回溯。&lt;/p&gt;&lt;p&gt;mem0 就是站在这个位置上，尝试把这层长期记忆做得更像个系统，而不仅仅是一个 append-only 的向量库。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;2. mem0 的目标和定位&lt;a href=&quot;#2-mem0-的目标和定位&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;从项目本身的定位来看，mem0 算是比较早期、而且工程化程度比较高的一批记忆层开源实现之一。官方 README 里给它的角色很直接：给各种 Agent、聊天机器人和应用提供一层通用的长期记忆服务，可以自托管，也可以用托管平台。&lt;/p&gt;&lt;p&gt;从功能上看，它对外主要暴露一个 Memory 抽象：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Python/TS SDK 和 REST API 都是围绕 &lt;code&gt;Memory&lt;/code&gt;​ / &lt;code&gt;AsyncMemory&lt;/code&gt; 这两个类展开；&lt;/li&gt;
&lt;li&gt;Memory 底下统一封装了向量库（pgvector、Qdrant 等）、可选的图数据库（Neo4j、Memgraph 等）、LLM、embedding 模型以及一个本地的 history 数据库；&lt;/li&gt;
&lt;li&gt;对调用方来说，基本就是围绕 &lt;code&gt;add / search / update / delete / history&lt;/code&gt; 这几个方法来用。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;从实现上看，mem0 并没有很复杂的算法，亮点更多在工程完整度和边界控制：Memory 这一层的职责划得比较清楚，下层的向量库、图库、LLM 统一走工厂模式，然后加一个 SQLite 的历史记录。&lt;/p&gt;&lt;p&gt;下面是架构图：&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;3. mem0 Memory 模块总体结构&lt;a href=&quot;#3-mem0-memory-模块总体结构&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;从代码结构看，mem0 的入口相当收敛：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;无论是 REST API 还是 Python / TS SDK，最后都落到 &lt;code&gt;Memory&lt;/code&gt;​（同步）或者 &lt;code&gt;AsyncMemory&lt;/code&gt;（异步）这两个类上。&lt;/li&gt;
&lt;li&gt;这两个类背后，通过工厂模式挂了一整套可插拔组件：embedding 模型、向量库、图数据库、LLM、历史库和遥测。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;可以用一张架构图来解释依赖关系：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart LR
    subgraph ClientSide[客户端 / SDK / 其它服务]
        U[&quot;应用代码 / Agent&quot;]
    end

    subgraph ServerSide[Mem0 进程]
        API[&quot;REST API / SDK 调用&amp;lt;br&amp;gt;server/main.py&quot;]
        M[&quot;Memory / AsyncMemory&amp;lt;br&amp;gt;mem0/memory/main.py&quot;]

        subgraph Core[核心组件]
            E[&quot;Embedder&amp;lt;br&amp;gt;向量化模型&quot;]
            L[&quot;LLM&amp;lt;br&amp;gt;事实抽取 &amp;amp; 决策&quot;]
            VS[&quot;VectorStore 抽象&amp;lt;br&amp;gt;mem0/vector_stores/*&quot;]
            G[(&quot;GraphStore 抽象&amp;lt;br&amp;gt;可选&quot;)]
            H[(&quot;SQLite History DB&amp;lt;br&amp;gt;mem0/memory/storage.py&quot;)]
            T[&quot;Telemetry&amp;lt;br&amp;gt;事件上报&quot;]
        end
    end

    subgraph Backend[后端存储]
        VDB[(&quot;向量数据库&amp;lt;br&amp;gt;pgvector / Qdrant / Milvus ...&quot;)]
        GDB[(&quot;图数据库&amp;lt;br&amp;gt;Neo4j / Memgraph / Neptune ...&quot;)]
    end

    U --&amp;gt;|HTTP / SDK| API
    API --&amp;gt; M

    M --&amp;gt; E
    M --&amp;gt; L
    M --&amp;gt; VS
    M --&amp;gt; G
    M --&amp;gt; H
    M --&amp;gt; T

    VS &amp;lt;--&amp;gt;|insert/search/update/delete| VDB
    G &amp;lt;--&amp;gt;|add/search/get_all/delete_all| GDB&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;从调用者的角度看，Memory 层对外只暴露了一组方法：&lt;code&gt;add / search / get / update / delete / history&lt;/code&gt;。内部则负责：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;把 messages 预处理成统一格式。&lt;/li&gt;
&lt;li&gt;在 add 时，根据配置选择是直接写，还是推理后再写。&lt;/li&gt;
&lt;li&gt;把所有读写请求都带上 user/agent/run 这些过滤条件，做会话隔离。&lt;/li&gt;
&lt;li&gt;把每一次变更都记录到 historydb。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;在这些方法里，最有意思的是 &lt;code&gt;add()&lt;/code&gt;，因为它同时承载了新增、合并、删除三种行为。下面我们单独看 mem0 的流程。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;4. add：一个 API 中的多种记忆操作&lt;a href=&quot;#4-add一个-api-中的多种记忆操作&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在 mem0 里，&lt;code&gt;add()&lt;/code&gt; 并不被视作插入一条记录这么简单，而是一个记忆管理入口：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;在最简单的配置下，它只是把消息切成若干条，逐条 embedding，写入向量库；这一支和前面说的朴素 RAG 差别不大，mem0 真正有特点的是 &lt;code&gt;infer=True&lt;/code&gt; 这条路径。&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;infer=True&lt;/code&gt; 时，它则会调用 LLM 先抽出候选事实，再去对齐已有记忆，最后生成一组 ADD / UPDATE / DELETE / NONE 的操作计划。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;借助下面这张流程图来讲解一下 add 的整体路径（对应 &lt;code&gt;mem0/memory/main.py&lt;/code&gt;​ 中 &lt;code&gt;Memory.add&lt;/code&gt; 及其私有方法）：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart TD
    subgraph Input[对话输入]
        MSG[&quot;多轮消息 messages&quot;]
    end

    subgraph L1[第一阶段: 抽取候选事实]
        PM[&quot;parse_messages&amp;lt;br&amp;gt;整理成带 role 的纯文本&quot;]
        SYS[&quot;选择抽取 prompt&amp;lt;br&amp;gt;USER / AGENT memory prompt&quot;]
        LLM1[&quot;LLM 调用 #1&amp;lt;br&amp;gt;抽取 facts&quot;]
        FACTS[&quot;new_retrieved_facts&amp;lt;br&amp;gt;候选记忆片段&quot;]
    end

    subgraph S1[旧记忆检索]
        EMB1[&quot;Embedder.embed(fact, &apos;add&apos;)&quot;]
        VS1[&quot;VectorStore.search&amp;lt;br&amp;gt;按 user/agent/run 过滤&quot;]
        OLD[&quot;retrieved_old_memory&amp;lt;br&amp;gt;相关旧记忆列表&quot;]
    end

    subgraph L2[第二阶段: 生成操作计划]
        PROMPT2[&quot;get_update_memory_messages&amp;lt;br&amp;gt;构造函数式指令&quot;]
        LLM2[&quot;LLM 调用 #2&amp;lt;br&amp;gt;输出 memory actions&quot;]
        ACTS[&quot;new_memories_with_actions&amp;lt;br&amp;gt;{event, text, id, ...}&quot;]
    end

    subgraph Exec[执行并落盘]
        ADDM[&quot;_create_memory&amp;lt;br&amp;gt;ADD&quot;]
        UPDM[&quot;_update_memory&amp;lt;br&amp;gt;UPDATE&quot;]
        DELM[&quot;_delete_memory&amp;lt;br&amp;gt;DELETE&quot;]
        NONE[&quot;更新元数据&amp;lt;br&amp;gt;NONE&quot;]
        HIST[&quot;SQLite history 表&amp;lt;br&amp;gt;记录 ADD/UPDATE/DELETE&quot;]
    end

    MSG --&amp;gt; PM --&amp;gt; SYS --&amp;gt; LLM1 --&amp;gt; FACTS
    FACTS --&amp;gt; EMB1 --&amp;gt; VS1 --&amp;gt; OLD
    FACTS --&amp;gt; PROMPT2
    OLD --&amp;gt; PROMPT2 --&amp;gt; LLM2 --&amp;gt; ACTS

    ACTS --&amp;gt;|event=ADD| ADDM --&amp;gt; HIST
    ACTS --&amp;gt;|event=UPDATE| UPDM --&amp;gt; HIST
    ACTS --&amp;gt;|event=DELETE| DELM --&amp;gt; HIST
    ACTS --&amp;gt;|event=NONE| NONE&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;下面我们单独看 mem0 的流程。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;4.1 &lt;code&gt;infer=False&lt;/code&gt;：直接写入的路径&lt;a href=&quot;#41-inferfalse直接写入的路径&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在 &lt;code&gt;infer=False&lt;/code&gt;​ 时，&lt;code&gt;add()&lt;/code&gt; 的行为基本等价于「带 metadata 的 RAG 写入」：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;入口做的第一件事，是通过 &lt;code&gt;_build_filters_and_metadata&lt;/code&gt;​ 构造过滤条件和基础元数据。这里要求调用时至少提供 &lt;code&gt;user_id&lt;/code&gt;​ / &lt;code&gt;agent_id&lt;/code&gt;​ / &lt;code&gt;run_id&lt;/code&gt; 之一，用来区分不同会话或不同 Agent。&lt;/li&gt;
&lt;li&gt;​&lt;code&gt;Memory.add&lt;/code&gt;​ 会把 &lt;code&gt;str&lt;/code&gt;​ / &lt;code&gt;dict&lt;/code&gt;​ / &lt;code&gt;list[dict]&lt;/code&gt;​ 这几种形态的 messages 统一规整成 &lt;code&gt;[{&apos;role&apos;: ..., &apos;content&apos;: ...}]&lt;/code&gt;，并处理好视觉消息（图片转描述文本）。&lt;/li&gt;
&lt;li&gt;然后走 &lt;code&gt;_add_to_vector_store(..., infer=False)&lt;/code&gt;​ 这条支路：遍历每条消息（忽略 &lt;code&gt;role == system&lt;/code&gt;​），调用 embedding 模型，把得到的向量连同 payload 一起插入向量库。每一次插入同时在 history 表里写一条 &lt;code&gt;event = &quot;ADD&quot;&lt;/code&gt; 的记录。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;这个分支本身没有什么复杂逻辑，但可以看出，哪怕在最朴素的模式下，mem0 也已经把会话隔离和变更记录做成了默认行为，而不是留给调用方自己维护。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;4.2 &lt;code&gt;infer=True&lt;/code&gt;：LLM 驱动的智能记忆管理&lt;a href=&quot;#42-infertruellm-驱动的智能记忆管理&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;​&lt;code&gt;infer=True&lt;/code&gt;​ 是这套设计的核心。它让 &lt;code&gt;add()&lt;/code&gt; 具备了「判断要不要记、记成什么样」的能力，大致可分成几个阶段。&lt;/p&gt;&lt;p&gt;第一步是从多轮对话中提炼出候选事实。&lt;/p&gt;&lt;p&gt;​&lt;code&gt;Memory.add&lt;/code&gt;​ 会先调用 &lt;code&gt;parse_messages&lt;/code&gt; 把一组 messages 压成带 role 的长文本，形如：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;system: ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;user: ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;assistant: ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;然后根据这是用户记忆还是 Agent 记忆选取不同的 system prompt（也允许自定义 fact 抽取 prompt），调用一次 LLM，请求它输出 JSON 格式的 &lt;code&gt;new_retrieved_facts&lt;/code&gt;。每一个 fact 都是模型认为「有长期价值」的一句或几句描述，比如用户在上海工作、用户对辛辣食物敏感之类。&lt;/p&gt;&lt;p&gt;第二步是围绕这些 facts 去找旧记忆。&lt;/p&gt;&lt;p&gt;对每个 fact，再做一次 embedding，并带着刚才构造好的 user/agent/run 过滤条件，去向量库做语义搜索。搜索结果去重后，得到一组 &lt;code&gt;retrieved_old_memory&lt;/code&gt;，可以理解为「和本次候选事实相关的历史记忆集合」。&lt;/p&gt;&lt;p&gt;第三步是让 LLM 决定具体操作。&lt;/p&gt;&lt;p&gt;这一步会构造一个结构化的 prompt，把「新事实 + 相关旧记忆」一起给 LLM，同时规定输出格式必须是 JSON，其中每个元素都包含：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;​&lt;code&gt;event&lt;/code&gt;：ADD / UPDATE / DELETE / NONE；&lt;/li&gt;
&lt;li&gt;​&lt;code&gt;text&lt;/code&gt;：新记忆文本（ADD/UPDATE 时使用）；&lt;/li&gt;
&lt;li&gt;以及在 UPDATE/DELETE 情况下，指向旧记忆的 id。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这一阶段等于是把「合并还是新增还是删除」的策略交给了 LLM 来做语义判断：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;如果某个 fact 和已有记忆只是在细节上有补充，就倾向于 UPDATE；&lt;/li&gt;
&lt;li&gt;如果代表的是全新的信息，就 ADD；&lt;/li&gt;
&lt;li&gt;如果它明确否定了旧记忆，可能会触发 DELETE；&lt;/li&gt;
&lt;li&gt;如果模型认为这句话没有长期价值，就给出 NONE。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;最后一步是落地这些 actions。&lt;/p&gt;&lt;p&gt;ADD 的情况比较直接：调用 &lt;code&gt;_create_memory&lt;/code&gt;​ 插入向量库，同时在 history 表里写一条 &lt;code&gt;ADD&lt;/code&gt;​；UPDATE 则需要先从向量库读出旧 payload，构造一个新 payload（保留 &lt;code&gt;created_at&lt;/code&gt;​ 和会话相关字段，只替换 &lt;code&gt;data&lt;/code&gt;​ 和 &lt;code&gt;updated_at&lt;/code&gt;​），用 &lt;code&gt;update&lt;/code&gt;​ 写回，再记一条 &lt;code&gt;UPDATE&lt;/code&gt;​ 类型的历史记录，里面同时存 old/new 两个版本；DELETE 类似，先 &lt;code&gt;get&lt;/code&gt;​ 出旧内容，之后从向量库删掉，history 里记一条 &lt;code&gt;DELETE&lt;/code&gt;​ 并标记 &lt;code&gt;is_deleted = 1&lt;/code&gt;​；NONE 则不动向量，只是用 &lt;code&gt;_update_memory_session&lt;/code&gt; 之类的方法更新 metadata 里的会话维度。&lt;/p&gt;&lt;p&gt;从整个 pipeline 流程来看，&lt;code&gt;add(infer=True)&lt;/code&gt; 的职责可以概括成一句话：在短期对话和长期记忆之间做一次带上下文的筛选与重写，让向量库里存的不是原始聊天，而是已经抽象过的事实集合。&lt;/p&gt;&lt;p&gt;为了方便对照，可以再看一张更概括的流程小图，专门对应 &lt;code&gt;infer=True&lt;/code&gt; 模式下的两次 LLM 调用：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;flowchart LR
    subgraph &quot;infer=True 两次调用&quot;
        A[&quot;对话消息 (messages)&quot;]
        B[&quot;LLM 调用 #1：抽取 new_retrieved_facts&quot;]
        C[&quot;向量检索：retrieved_old_memory (按 user/agent/run 过滤)&quot;]
        D[&quot;LLM 调用 #2：生成 actions (ADD/UPDATE/DELETE/NONE)&quot;]
        E[&quot;执行 actions 并写入 history&quot;]
    end
    A --&amp;gt; B --&amp;gt; C --&amp;gt; D --&amp;gt; E&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;这也是为什么在性能上会存在写放大：一次 add 触发了两次 LLM 调用，并且中间还有一轮向量检索。（我测的时候跑的非常慢）&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;5. search / update / delete：读写路径与边界&lt;a href=&quot;#5-search--update--delete读写路径与边界&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;相较于 &lt;code&gt;add()&lt;/code&gt;​，&lt;code&gt;search / update / delete&lt;/code&gt; 这几个接口的逻辑就常规得多，但依然延续了会话隔离和 historydb 这两条主线。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;5.1 search：只读、无 LLM 的查询&lt;a href=&quot;#51-search只读无-llm-的查询&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;​&lt;code&gt;Memory.search&lt;/code&gt; 的实现是典型的 embedding + 向量检索，没有在这一步再引入额外的 LLM 调用。它的调用序列大致如下：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;sequenceDiagram
    participant C as Client 应用
    participant API as REST API / SDK
    participant M as Memory
    participant E as Embedder
    participant VS as Vector Store
    participant G as Graph Store
    participant R as Reranker (可选)
    participant T as Telemetry

    C-&amp;gt;&amp;gt;API: POST /search 或 Memory.search(query,...)
    API-&amp;gt;&amp;gt;M: search(query, user_id/agent_id/run_id, filters, limit,...)
    M-&amp;gt;&amp;gt;M: _build_filters_and_metadata()

    M-&amp;gt;&amp;gt;E: embed(query, &quot;search&quot;)
    E--&amp;gt;&amp;gt;M: 查询向量

    M-&amp;gt;&amp;gt;VS: search(query, vectors, filters, limit)
    VS--&amp;gt;&amp;gt;M: 近邻向量列表(含 score, payload)

    opt 启用图记忆
        M-&amp;gt;&amp;gt;G: graph.search(query, filters, limit)
        G--&amp;gt;&amp;gt;M: relations
    end

    opt 启用 reranker
        M-&amp;gt;&amp;gt;R: rerank(query, memories, limit)
        R--&amp;gt;&amp;gt;M: 重排后的 memories
    end

    M-&amp;gt;&amp;gt;T: capture_event(&quot;mem0.search&quot;, ...)
    M--&amp;gt;&amp;gt;API: {&quot;results&quot;: memories, &quot;relations&quot;?}
    API--&amp;gt;&amp;gt;C: HTTP 200 + JSON&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;可以注意到几点：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;search 只涉及向量库和可选的图库，不触碰 historydb，也不修改任何状态。&lt;/li&gt;
&lt;li&gt;如果配置了 reranker，会在拿到候选结果后再做一次重排，但依然是纯检索逻辑，不会再去叫 LLM。&lt;/li&gt;
&lt;li&gt;图搜索和向量搜索是并行分支，最后把结果合在一起。这和那种先向量检索再扩图邻居的 GraphRAG pipeline 不太一样，更偏向两个视角的独立召回。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;这部分实现比较克制：它只负责取回可能相关的记忆，至于这些记忆要如何组织成上下文、是否要翻页拿前后文，mem0 没有规定做法，留给上层 Agent 或业务代码处理。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;5.2 update / delete：显式操作与历史记录&lt;a href=&quot;#52-update--delete显式操作与历史记录&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;​&lt;code&gt;update&lt;/code&gt;​ 和 &lt;code&gt;delete&lt;/code&gt;​ 的行为可以看作是对 &lt;code&gt;add(infer=True)&lt;/code&gt; 里 UPDATE / DELETE 分支的显式版本：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;​&lt;code&gt;update&lt;/code&gt;​：调用者直接给出 memory_id 和新的 data，Memory 层会做一次 embedding 替换向量，同时读出旧 payload，写入一条 &lt;code&gt;event = &quot;UPDATE&quot;&lt;/code&gt; 的历史记录，保留改前和改后的内容。&lt;/li&gt;
&lt;li&gt;​&lt;code&gt;delete&lt;/code&gt;​：先从向量库 get 出旧内容，再删除对应向量，最后在历史表记一条 &lt;code&gt;DELETE&lt;/code&gt;​，把旧内容放进 &lt;code&gt;old_memory&lt;/code&gt;​ 字段，并打 &lt;code&gt;is_deleted = 1&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这两条路径都不再经过 LLM，逻辑相对简单，但和 &lt;code&gt;add(infer=True)&lt;/code&gt; 共用同一套 history 机制。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;6. historydb：历史日志&lt;a href=&quot;#6-historydb历史日志&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;historydb 是 mem0 里存在感很强的一个组件，它不负责存向量，也不参与检索，只负责记录某条记忆从创建到修改再到删除的全过程。&lt;/p&gt;&lt;p&gt;表结构用了一张 SQLite 的 &lt;code&gt;history&lt;/code&gt; 表，大致包含：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;​&lt;code&gt;memory_id&lt;/code&gt;：对应向量库里的那条记忆；&lt;/li&gt;
&lt;li&gt;​&lt;code&gt;old_memory&lt;/code&gt;​ / &lt;code&gt;new_memory&lt;/code&gt;​：某次变更前后的文本内容（ADD 时 &lt;code&gt;old_memory&lt;/code&gt;​ 为空，DELETE 时 &lt;code&gt;new_memory&lt;/code&gt; 为空）；&lt;/li&gt;
&lt;li&gt;​&lt;code&gt;event&lt;/code&gt;：ADD / UPDATE / DELETE；&lt;/li&gt;
&lt;li&gt;​&lt;code&gt;created_at&lt;/code&gt;​ / &lt;code&gt;updated_at&lt;/code&gt;：这条历史记录自身的时间；&lt;/li&gt;
&lt;li&gt;​&lt;code&gt;is_deleted&lt;/code&gt;：是否代表一条删除记录；&lt;/li&gt;
&lt;li&gt;​&lt;code&gt;actor_id&lt;/code&gt;​ / &lt;code&gt;role&lt;/code&gt;：是谁触发了这次操作，以及当时的角色（user / assistant）。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这种设计的直接效果是：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;向量库只保存当前状态，不负责记历史版本；&lt;/li&gt;
&lt;li&gt;所有「这条记忆经历了什么」的问题，都可以通过 &lt;code&gt;Memory.history(memory_id)&lt;/code&gt; 查出来。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;换一句话说，mem0 把每条记忆当成了一个有限状态机，状态的转换（ADD → UPDATE* → DELETE）全部写进了一张独立的表。这在需要做审计、回滚、可视化的时候，会比覆盖式更新友好得多。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;7. 设计和使用上的一些思考&lt;a href=&quot;#7-设计和使用上的一些思考&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;读完这部分代码之后，个人有几点想法。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;7.1 mem0 更适合作为长期记忆层&lt;a href=&quot;#71-mem0-更适合作为长期记忆层&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;从 &lt;code&gt;add(infer=True)&lt;/code&gt;​ 的设计可以看出，mem0 更偏向长时稳定的语义记忆，而不是每一句话都要写入的日志系统。比如用户只问一句「烤鱼健康吗」，这本身不是 fact，更像是一个即时问题；在这种输入下，LLM 很可能抽不出任何 &lt;code&gt;new_retrieved_facts&lt;/code&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;人类在这里很容易脑补出一个场景：这个用户大概率在考虑今天晚上要不要吃烤鱼，或者他本身就经常吃这类东西。但在 mem0 现在的实现里，如果你把这几轮拆成一次次 &lt;code&gt;add(infer=True)&lt;/code&gt; 调用，模型在每一轮里单独抽事实，很可能认为这几句都不值得记，于是整个片段都进不了长期记忆。这就是我在看代码时感觉比较明显的一点：mem0 的 fact 抽取是一次调用内的，缺少跨多次 add 去拼出一个更大事实的能力。&lt;/p&gt;&lt;p&gt;如果直接把 mem0 接在一个高频群聊后面，每条消息都丢进 &lt;code&gt;add(infer=True)&lt;/code&gt;，就容易出现两种极端：要么什么都没记住，要么记了一堆看上去像事实、实际上很散、不形成完整画像的句子。&lt;/p&gt;&lt;p&gt;更合理的做法，是在上层再加一层短期工作记忆（也就是常说的 working memory）：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;上层维护最近 N 轮对话，专门用来回答当前轮的问题；&lt;/li&gt;
&lt;li&gt;只有当某个阶段性话题结束，或者检测到出现了明确的个人偏好、背景信息、长期目标时，才把这一段对话打包交给 mem0；&lt;/li&gt;
&lt;li&gt;mem0 则专注于把这些内容收敛成一组长期事实，并在后续请求里持续维护和更新。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;可以用一张概念图来表示这两层之间的关系：&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; width=&quot;2668&quot; height=&quot;3026&quot; src=&quot;/_astro/image-20251209012529-qjvses2.B2Pz4U7S_ZArGK2.webp&quot; srcset=&quot;/_astro/image-20251209012529-qjvses2.B2Pz4U7S_Z1UKs6K.webp 640w, /_astro/image-20251209012529-qjvses2.B2Pz4U7S_Zv1MsW.webp 750w, /_astro/image-20251209012529-qjvses2.B2Pz4U7S_1DLgTj.webp 828w, /_astro/image-20251209012529-qjvses2.B2Pz4U7S_2rtTdj.webp 1080w, /_astro/image-20251209012529-qjvses2.B2Pz4U7S_Z2gkkhq.webp 1280w, /_astro/image-20251209012529-qjvses2.B2Pz4U7S_270m5t.webp 1668w, /_astro/image-20251209012529-qjvses2.B2Pz4U7S_U4uEs.webp 2048w, /_astro/image-20251209012529-qjvses2.B2Pz4U7S_ZioHob.webp 2560w, /_astro/image-20251209012529-qjvses2.B2Pz4U7S_ZArGK2.webp 2668w&quot; /&gt;&lt;figcaption&gt;image&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;在这种架构下，&lt;code&gt;new_retrieved_facts&lt;/code&gt; 更像是从短期工作记忆里抽取出来、准备写入长期记忆的候选事实单元，而不是对所有问题的机械记录。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;7.2 写入路径存在明显的写放大&lt;a href=&quot;#72-写入路径存在明显的写放大&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;​&lt;code&gt;infer=True&lt;/code&gt; 这条分支天然带来写放大：一次写入包含两次 LLM 调用和至少一次向量检索。这在低 QPS 的场景下问题不大，但如果想在一个高并发系统里对所有对话都开推理写入，就需要认真评估成本和延迟。&lt;/p&gt;&lt;p&gt;这里可以结合代码简单算一下账：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;第一次 LLM 调用发生在 &lt;code&gt;get_fact_retrieval_messages&lt;/code&gt;，对整理后的整段对话做一次 fact 抽取；&lt;/li&gt;
&lt;li&gt;抽出来的每个 fact 都要走一遍 embedding + VectorStore.search，这一步的复杂度和 fact 个数成正比；&lt;/li&gt;
&lt;li&gt;第二次 LLM 调用发生在 &lt;code&gt;get_update_memory_messages&lt;/code&gt; 之后，把新旧记忆一起喂给模型，让它产出 actions；&lt;/li&gt;
&lt;li&gt;最后根据 actions 分别调用 &lt;code&gt;_create_memory&lt;/code&gt;​、&lt;code&gt;_update_memory&lt;/code&gt;​、&lt;code&gt;_delete_memory&lt;/code&gt;，并同步写 history。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;也就是说，一次 &lt;code&gt;add(infer=True)&lt;/code&gt;，在最坏情况下会有：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;一次对话级别的 LLM 请求；&lt;/li&gt;
&lt;li&gt;N 次向量检索（N 是抽出的 fact 数量）；&lt;/li&gt;
&lt;li&gt;再加一次新旧记忆对齐的 LLM 请求。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;如果你是给单个用户做个人助理，这个开销未必夸张；但如果把 mem0 接在一个高并发入口（比如一个面向大量用户的客服系统）后面，就不太适合每条消息都同步走这条路径。&lt;/p&gt;&lt;p&gt;更现实的用法，是在应用层做两层区分：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;在线链路只依赖短期上下文 + 既有长期记忆的 search，确保延迟可控；&lt;/li&gt;
&lt;li&gt;把 &lt;code&gt;add(infer=True)&lt;/code&gt; 放到后台队列里，按用户或会话做限流，比如每 N 轮对话或每隔一段时间才触发一次。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;从这个角度看，mem0 更接近一个「长期记忆整理服务」，而不是写日志那一层。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;7.3 记忆操作强依赖 LLM 的语义判断&lt;a href=&quot;#73-记忆操作强依赖-llm-的语义判断&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在 &lt;code&gt;add(infer=True)&lt;/code&gt; 里，ADD / UPDATE / DELETE / NONE 的决策完全交给了 LLM。好处是接口非常简洁：调用者只需要给一段对话，不必自己写一堆 if/else 去判断是否重复、是否矛盾。&lt;/p&gt;&lt;p&gt;在代码层面，这部分逻辑主要集中在 &lt;code&gt;get_update_memory_messages&lt;/code&gt;​ 和随后的第二次 &lt;code&gt;llm.generate_response&lt;/code&gt; 上：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;先把刚抽出来的 new facts 和刚刚检索到的旧记忆一起打包成一组 messages，喂给模型；&lt;/li&gt;
&lt;li&gt;要求模型输出一个 JSON，里面列出每个新记忆对应哪个旧记忆、打算执行什么事件（event）、使用什么新文本；&lt;/li&gt;
&lt;li&gt;后面执行分支里，只是严格按照这个 JSON 决策去走 &lt;code&gt;_create_memory&lt;/code&gt;​ / &lt;code&gt;_update_memory&lt;/code&gt;​ / &lt;code&gt;_delete_memory&lt;/code&gt;，并且顺带写 history。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;好处是调用方式非常统一：上层永远只调一个 &lt;code&gt;add(infer=True)&lt;/code&gt;，所有「要不要记、记成什么样」的问题都丢给 LLM 来裁决。你甚至可以通过换 prompt 或换模型，试着调整它对重复、冲突的敏感程度。&lt;/p&gt;&lt;p&gt;代价则在于：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;模型可能过度合并，把一些细节在 UPDATE 时压缩掉；&lt;/li&gt;
&lt;li&gt;也可能不够激进，导致类似内容长期共存；&lt;/li&gt;
&lt;li&gt;fact 的粒度完全由 prompt 和模型行为决定，目前实现里没有额外的 fact 级别约束机制，也没有在代码里做「防御性」检查，比如限定一次更新只能覆盖哪些字段。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这不是 mem0 独有的问题，所有 LLM 驱动的记忆系统都会遇到。mem0 的选择是把这部分逻辑集中到 &lt;code&gt;add(infer=True)&lt;/code&gt; 的一条管线上，至少在工程上是透明的：你可以从 prompt、模型版本和 history 记录三个维度去观测和调参。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;7.4 检索策略与上层架构&lt;a href=&quot;#74-检索策略与上层架构&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;前面提到，mem0 在 search 部分并没有引入很复杂的 GraphRAG 流程，而是保持了向量检索加可选 rerank、可选图检索的组合。这带来的一个结果是：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;上下文的组织方式完全交给上层决定；&lt;/li&gt;
&lt;li&gt;如果想要翻页拿前后文、多轮 search 逐步缩小范围，需要在 Agent 或业务代码里自己实现；&lt;/li&gt;
&lt;li&gt;mem0 的职责止步于给你一批可能相关的记忆。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;如果不考虑成本，只看怎么把上下文接得更顺，在 mem0 这一层之上大致有两条思路，可以和前面的 search 组合在一起。&lt;/p&gt;&lt;p&gt;第一种是给向量检索结果加一个“翻页”能力。比如拿到某条记忆后，再显式去取它前后若干条，类似现在很多代码 agent 里的 Read 工具，支持 offset / limit：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;好处是实现简单，不需要额外的 Agent 结构，直接在应用侧包一层就行；&lt;/li&gt;
&lt;li&gt;坏处是 LLM 一旦走偏，它在翻页过程中看到的一堆无关内容，都会被写进对话上下文里，后面的问题也会继续被这些错误上下文污染，很难「撤销」。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;第二种是写一个专门的 search agent。主 Agent 不直接操纵翻页，而是把“我要找什么”丢给一个专门的检索 Sub Agent，让它负责在向量库里多次 search / 翻页，最后只把一小段结果（比如若干条记忆加上它自己的中间判断）返回：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;好处是主 Agent 看到的是一份已经整理过的结果，过程中的「乱翻页」不会直接污染主对话的历史；&lt;/li&gt;
&lt;li&gt;而且 search agent 可以用一个相对便宜的模型，反复调用也不至于太贵；&lt;/li&gt;
&lt;li&gt;坏处是系统结构更复杂一些，需要你自己定义好主 Agent 和 search agent 之间的接口，以及错误时如何回退。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;如果想把这条线再拉长一点，可以参考 kimi-cli 那种「给自己发 DMail」的做法（命运石之门梗，&lt;a href=&quot;https://github.com/MoonshotAI/kimi-cli/discussions/98&quot; target=&quot;_blank&quot;&gt;DenwaRenji 是啥梗？ || DenwaRenji What is the plot?&lt;/a&gt;，月之暗面真是个有意思的公司）：当你发现一次 search agent 的决策明显是错的时，不是硬着头皮把错上下文往后拖，而是显式给主 Agent 写一条更正消息，相当于在对话历史里打一个“撤销”标记，后面的推理就可以选择性地忽略这一段错误分支。这个思路用在 mem0 上，基本等价于在长期记忆之上再盖一层“可回滚”的检索历史，让系统有机会在犯错之后把自己从错误上下文里拉出来。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;8. 总结&lt;a href=&quot;#8-总结&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;整体来看，mem0 在把记忆这件事工程化上做了几件比较关键的事：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;把 &lt;code&gt;add&lt;/code&gt;​ 设计成一个具备决策能力的入口，在 &lt;code&gt;infer=True&lt;/code&gt; 下通过两次 LLM 调用和一次向量检索，把 ADD / UPDATE / DELETE / NONE 合在一条管线里做完。&lt;/li&gt;
&lt;li&gt;用一个独立的 SQLite history 表记录所有变更，把每条记忆视作一个可以审计的状态机，也可以说是一种血缘追踪，而不是简单的覆盖式更新。&lt;/li&gt;
&lt;li&gt;通过Vector Factory 和 Graph Factory，把底层存储细节屏蔽在统一接口之后，让 Memory 层只关心“存什么、怎么搜”。事实上 mem0 的绝大部分代码都在适配十几种向量库和图数据库上。&lt;/li&gt;
&lt;li&gt;在设计上明确区分了长期记忆和短期工作记忆的角色，前者交给 mem0，后者留给上层框架或应用代码。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;不管怎么说，mem0 的源码是值得读一遍的，哪怕最后不直接使用这个库，它在接口设计、读写路径、历史记录这些细节上的处理，也是一份相对完整的参考实现，而且比较简单，读完可以根据自己的场景做一些增强。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>对 COLMA 认知分层记忆架构的工程化重构与思考</title><link>https://axi.moe/posts/5vhbfhkc/</link><guid isPermaLink="true">https://axi.moe/posts/5vhbfhkc/</guid><pubDate>Sun, 07 Dec 2025 03:57:01 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;对 COLMA 认知分层记忆架构的工程化重构与思考&lt;a href=&quot;#对-colma-认知分层记忆架构的工程化重构与思考&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;最近阅读了四川大学团队发表的论文&lt;a href=&quot;https://arxiv.org/pdf/2509.13235v1&quot; target=&quot;_blank&quot;&gt;《A Scenario-Driven Cognitive Approach to Next-Generation AI Memory》&lt;/a&gt;。论文通过脑科学的分析，指出了当前 AI 记忆系统（主要是 RAG 和向量数据库）存在的“静态性”与“割裂性”问题，并创新性地提出了一种基于认知场景驱动的 COLMA（Cognitive Layered Memory Architecture） 架构。&lt;/p&gt;&lt;section&gt;&lt;h2&gt;先读论文&lt;a href=&quot;#先读论文&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;现有的 AI 记忆系统通常被简化为“向量数据库 + 检索算法”的组合。这篇论文通过六维评估（包括动态更新、抗灾难性遗忘、多模态整合等）指出，这种架构本质上是静态的数据堆砌，缺乏人脑的动态适应性。为了突破这一瓶颈，作者没有直接堆砌技术栈，而是采用了反向工程的思路，从脑科学反思人类记忆的模式，并基于此推导出了下一代记忆系统的核心需求。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;从脑科学看人类记忆&lt;a href=&quot;#从脑科学看人类记忆&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;论文认为，记忆不是单一的存储行为，而是根据不同任务高度动态化的过程：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;场景一：毒蘑菇识别（感知与生存级反应）&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; width=&quot;1677&quot; height=&quot;589&quot; src=&quot;/_astro/image-20251207034147-8bpabl2.Dgnx0L0k_ZzLUKD.webp&quot; srcset=&quot;/_astro/image-20251207034147-8bpabl2.Dgnx0L0k_1PXb1O.webp 640w, /_astro/image-20251207034147-8bpabl2.Dgnx0L0k_1Wbhjh.webp 750w, /_astro/image-20251207034147-8bpabl2.Dgnx0L0k_1HUz2H.webp 828w, /_astro/image-20251207034147-8bpabl2.Dgnx0L0k_2nRVwj.webp 1080w, /_astro/image-20251207034147-8bpabl2.Dgnx0L0k_28WzHY.webp 1280w, /_astro/image-20251207034147-8bpabl2.Dgnx0L0k_Z1eYvuM.webp 1668w, /_astro/image-20251207034147-8bpabl2.Dgnx0L0k_ZzLUKD.webp 1677w&quot; /&gt;&lt;figcaption&gt;image&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;当你由远及近观察一个蘑菇时，你的大脑在毫秒级内整合了颜色、形状（视觉）甚至质感（触觉）。一旦识别出“剧毒”特征，系统会立即触发预警并强行写入长期记忆。&lt;/p&gt;&lt;p&gt;但现有的多模态模型往往将视觉和文本分开存储，且缺乏这种“高优先级写入”的生存机制。因此记忆系统必须具备极低延迟的多模态感知接口和工作记忆集成能力，能够在感知到关键特征时迅速闭环。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;场景二：日常回忆（动态重构机制）&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; width=&quot;1672&quot; height=&quot;611&quot; src=&quot;/_astro/image-20251207034320-1mt3gfy.DiQU93AE_Zyq685.webp&quot; srcset=&quot;/_astro/image-20251207034320-1mt3gfy.DiQU93AE_2lc6w9.webp 640w, /_astro/image-20251207034320-1mt3gfy.DiQU93AE_ZNSuS7.webp 750w, /_astro/image-20251207034320-1mt3gfy.DiQU93AE_1GCAqo.webp 828w, /_astro/image-20251207034320-1mt3gfy.DiQU93AE_Z1OruSB.webp 1080w, /_astro/image-20251207034320-1mt3gfy.DiQU93AE_ZW8Ha7.webp 1280w, /_astro/image-20251207034320-1mt3gfy.DiQU93AE_ZMOEfs.webp 1668w, /_astro/image-20251207034320-1mt3gfy.DiQU93AE_Zyq685.webp 1672w&quot; /&gt;&lt;figcaption&gt;image&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;当你试图回忆“上个月2号做了什么”时，你的大脑并没有直接播放一段录像。你首先会锚定时间（“那天是周几？”），检索碎片线索（“好像开了周会”），然后结合外部提示（查看手机照片）进行迭代式重构（Iterative Reconstruction）。如果发现逻辑不通，大脑会自我否决并重新检索。&lt;/p&gt;&lt;p&gt;而目前的 RAG 检索是一次性的 Key-Value 匹配，缺乏“检索-评估-再检索”的自我修正回路。记忆检索应当是一个生成式重建的过程，包含多轮次的自我验证与修补。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;场景三：数学解题（Mathematical Problem-Solving Process）&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; width=&quot;1660&quot; height=&quot;590&quot; src=&quot;/_astro/image-20251207034329-jm0ymwb.t5TtXEB5_1pHYEg.webp&quot; srcset=&quot;/_astro/image-20251207034329-jm0ymwb.t5TtXEB5_ZFiORD.webp 640w, /_astro/image-20251207034329-jm0ymwb.t5TtXEB5_1eMGw2.webp 750w, /_astro/image-20251207034329-jm0ymwb.t5TtXEB5_Z2r0id7.webp 828w, /_astro/image-20251207034329-jm0ymwb.t5TtXEB5_bEGJ6.webp 1080w, /_astro/image-20251207034329-jm0ymwb.t5TtXEB5_DuNNg.webp 1280w, /_astro/image-20251207034329-jm0ymwb.t5TtXEB5_1pHYEg.webp 1660w&quot; /&gt;&lt;figcaption&gt;image&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;在解决复杂数学题时，人脑通过“系统1”（直觉启发）快速寻找思路，同时利用“系统2”（规则分析）进行严密的逻辑推导。此过程中，工作记忆（Working Memory）负责暂存中间变量，前额叶皮层负责监控逻辑冲突。&lt;/p&gt;&lt;p&gt;但现有记忆缺乏对“中间推理状态”的维护，往往只存结果不存过程。记忆系统必须支持任务分解，并具备双系统验证机制，能够存储“推理链条”而非仅仅是静态知识。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;场景四：历史知识更新（冲突消解与再巩固）&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; width=&quot;1669&quot; height=&quot;589&quot; src=&quot;/_astro/image-20251207034405-m2dyjtg.DiMIQZnX_Z1fTVcc.webp&quot; srcset=&quot;/_astro/image-20251207034405-m2dyjtg.DiMIQZnX_Z1V1SS1.webp 640w, /_astro/image-20251207034405-m2dyjtg.DiMIQZnX_1BItR1.webp 750w, /_astro/image-20251207034405-m2dyjtg.DiMIQZnX_Z244uR8.webp 828w, /_astro/image-20251207034405-m2dyjtg.DiMIQZnX_1so8qy.webp 1080w, /_astro/image-20251207034405-m2dyjtg.DiMIQZnX_1UefuI.webp 1280w, /_astro/image-20251207034405-m2dyjtg.DiMIQZnX_Z1fY0nS.webp 1668w, /_astro/image-20251207034405-m2dyjtg.DiMIQZnX_Z1fTVcc.webp 1669w&quot; /&gt;&lt;figcaption&gt;image&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;当新读到的传记（“拿破仑输于情报失误”）与你原本的记忆（“拿破仑输于固执”）发生冲突时，大脑不会简单地覆盖旧数据，而是进行逻辑验证和情感加权。大脑会激活“记忆再巩固”机制，决定是修正旧记忆，还是将新信息作为一个新的分支版本存储。&lt;/p&gt;&lt;p&gt;向量库难以处理这种事实冲突，往往导致检索时出现相互矛盾的信息。所以必须具备冲突检测和记忆再巩固机制，支持知识的动态进化。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;COLMA&lt;a href=&quot;#colma&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;基于上述需求，论文提出了 COLMA (Cognitive Layered Memory Architecture)：&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; width=&quot;1726&quot; height=&quot;1196&quot; src=&quot;/_astro/image-20251207034004-qfzqa83.DXsKq2ke_Zpm2Hd.webp&quot; srcset=&quot;/_astro/image-20251207034004-qfzqa83.DXsKq2ke_1UUCgO.webp 640w, /_astro/image-20251207034004-qfzqa83.DXsKq2ke_1Unpf9.webp 750w, /_astro/image-20251207034004-qfzqa83.DXsKq2ke_tinUO.webp 828w, /_astro/image-20251207034004-qfzqa83.DXsKq2ke_Z2q2alt.webp 1080w, /_astro/image-20251207034004-qfzqa83.DXsKq2ke_Z2m4lHM.webp 1280w, /_astro/image-20251207034004-qfzqa83.DXsKq2ke_Znlf1E.webp 1668w, /_astro/image-20251207034004-qfzqa83.DXsKq2ke_Zpm2Hd.webp 1726w&quot; /&gt;&lt;figcaption&gt;image&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Layer 1: 物理持久层 (Physical Persistence Layer)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;使用 Apache Cassandra 或 HBase。不同于传统的关系型数据库，这一层利用分布式列式存储的高吞吐和 Schema-free 特性，为海量的多模态数据提供坚实的物理底座。它负责解决“存得下”和“写得快”的问题。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Layer 2: 知识分类层 (Knowledge Category Layer)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;异构数据统一封装。这是一个融合层。它打破了技术栈的壁垒，将知识图谱（结构化关系）、向量数据库（非结构化语义）和常识库统一在一个层面进行管理。无论是文本、图像向量还是逻辑实体，在此层都被视为可被索引的知识对象，解决了多模态数据割裂的问题。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Layer 3: 协调层 (Coordination Layer)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这一层模拟海马体与新皮层的协同。这是架构的“大脑”。它负责管理短时记忆（Working Memory）、中时记忆和长时记忆之间的动态流转。正如海马体负责将短期经历固化为长期记忆，这一层决定了哪些信息值得被持久化，哪些应当被遗忘，实现了认知资源的优化配置。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Layer 4: 功能层 (Functionality Layer)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;提供具体的认知操作接口。这一层向上层暴露了推理 (Reasoning)、回忆 (Recall)、联想 (Association)、预测 (Prediction) 和 反思 (Reflection) 等高级能力。它让上层应用不再直接操作 CRUD 接口，而是调用类似“联想”这样的认知指令。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Layer 5: 用户场景层 (User Scenario Layer)&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;应用场景对接。最顶层，直接对接具体的应用需求（如智能助手、决策代理）。它将业务逻辑翻译为对下层认知功能的调用。&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;个人碎碎念&lt;a href=&quot;#个人碎碎念&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;可惜的是这篇论文没有代码，但个人看下来理论到工程也存在一些盲点。&lt;/p&gt;&lt;p&gt;首先是协调层的逻辑贫血问题。论文将协调层定义为模拟海马体功能的模块，负责管理短时记忆向长时记忆的流转。在论文的描述中，这是一个优雅的漏斗，但在真实的工程实现中，如果仅依靠简单的阈值（如访问频率或语义相似度）来决定记忆的去留，这个漏斗很快就会堵塞。如果没有复杂的清洗逻辑，大量的无效对话和冗余信息会被永久写入底层存储，导致存储成本爆炸且检索信噪比下降。所以我认为这里还需要一个做记忆整理的操作。&lt;/p&gt;&lt;p&gt;其次是被动性，因为数据库本身不会思考。论文隐含的交互模型是标准的请求-响应模式：用户提问，系统检索并存储。这也是当前 AI 记忆系统的痛点：被动性。人类的记忆整理往往发生在睡眠或空闲时，是一个主动的后台过程，数据会随着时间推移逐渐混乱，最终变得非常混乱。一个类脑的记忆系统，应该有办法主动唤醒，对碎片化的记忆进行合并和重组。&lt;/p&gt;&lt;p&gt;最后是搜索状态问题。个人认为在复杂的认知任务中，功能之间存在严格的时序依赖和状态共享。例如，往往是先回忆事实，再进行逻辑推导，最后才进行反思修正。如果将它们拆解为无状态的接口，外部调用者就需要维护复杂的上下文状态。再比如说，如果针对同一个会话连续调用两次“反思”，第二次应当基于第一次的结果进行深化，而不是重头再来或者返回一样的结果。因此，功能层内部应该还需要维护认知任务的生命周期和中间状态。&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;重构&lt;a href=&quot;#重构&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;思考到上面的内容之后，我认为可以重新定义论文中说到的分层，特别是中间三层（持久层、分类层、协调层）的交互逻辑。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;Layer 1: 物理持久层&lt;a href=&quot;#layer-1-物理持久层&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这一层其实没什么好讨论的，用 Cassandra 还是 HBase 其实是一个工程问题，不过最重要的洞见是它必须存原始数据（论文中也提到生态知觉理论，Ecological Perception Theory，核心思想是环境刺激的直接特征直接形成了初始的知觉表征），也就是作为事实的唯一来源。因为之前许多实践着重于将大模型的处理结果放到这一层，然而经常丢失一部分细节。至于索引那必然是要存的，否则性能很差，不过这个索引并不是语义索引，而是一个性能索引，这就是数据库的事情了，我们不在此详细讨论。&lt;/p&gt;&lt;p&gt;不过很容易想到一个问题，全部都是原始数据的话，上下文会变得特别长，且不符合我们认知的逻辑。起码我们知道，分层记忆是必然的（比如说目前主要包括短期、中期、长期记忆）。所以，处理是必须的，原始数据也是必须的，怎么办？&lt;/p&gt;&lt;p&gt;我想到一种方法是血缘追踪 (Data Lineage)。例如说某条记忆进行重组、合并、分裂、概括等等操作之后，需要保留一个血缘关系，即用一个 &lt;code&gt;prev&lt;/code&gt;​ 指针去指向原来的数据，并将原来的数据标为 &lt;code&gt;dirty&lt;/code&gt;​（或者 &lt;code&gt;archived&lt;/code&gt;），也就是不会作为数据被搜索到，只能溯源。如果上层使用这条操作后的数据之后发现它过于概括（Hallucination 的一种），可以直接溯源找到原始数据，以求真伪或更细节的认知。但时间久了这条链也会变得过长，所以这里面可能还需要引入一定的定期压缩或快照机制，但这属于更后期的优化了。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Layer 2: 知识分类层&lt;a href=&quot;#layer-2-知识分类层&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这一层在很多架构图中被画得花里胡哨，但如果剥离掉那些名词，在工程实现上它其实就是一个DAO层。&lt;/p&gt;&lt;p&gt;我不建议在这里做太多的“智能”处理。为什么？因为这一层的核心职责提供抽象原语。很多系统设计失败的原因，就是把业务逻辑下沉得太深，导致想改策略的时候改不动。所以我认为这一层应该做得“薄”一点，它只需要把底层那堆复杂的宽表、图数据库封装成大概几个简单的原子操作：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;文字匹配搜索：最朴素的正则或关键词匹配，用于精确查找。&lt;/li&gt;
&lt;li&gt;知识图谱遍历：给一个节点，查它的 N 跳邻居。&lt;/li&gt;
&lt;li&gt;向量最近邻：给一个 Embedding，找 Top-K。&lt;/li&gt;
&lt;li&gt;血缘溯源：这个在上面提到&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;这一层就是给上面的协调层递砖头的。它不需要知道“为什么要查这个”，它只需要保证“查得快、查得准”。把多模态的差异在这里抹平，对上层暴露统一的接口，这就足够了。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Layer 3: 协调层&lt;a href=&quot;#layer-3-协调层&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是我认为整篇论文最关键、但也最需要工程填坑的地方。论文里说这一层负责“动态流转”，听起来很美，但在代码里怎么写？如果只是写几个 &lt;code&gt;if (access_count &amp;lt; 5) move_to_long_term()&lt;/code&gt; 这样的阈值判断，那这个系统就太“薄”了，根本撑不起复杂的认知任务。&lt;/p&gt;&lt;p&gt;我认为协调层的本质不应该是简单的流转，而应该是&lt;strong&gt;记忆治理&lt;/strong&gt;。目前的 AI Memory 系统最大的问题是“只进不出”和“被动响应”，时间一长，垃圾数据堆积如山。&lt;/p&gt;&lt;p&gt;所以，这一层必须具备类似 ETL 的能力，它需要主动地去做几件事：&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;ol&gt;
&lt;li&gt;事件触发：上一次操作发现数据脏了，异步写个任务到队列里，后台慢慢修。&lt;/li&gt;
&lt;li&gt;时间触发：像人睡觉一样，系统闲的时候，Cron Job 起来扫一遍，把碎片化的记忆整理一下。&lt;/li&gt;
&lt;li&gt;阈值触发：当检索失败率飙升或者幻觉严重时，强制触发一次深度整理。这里面就包括之前的链长，或者说这个类型应该叫“系统事件”。&lt;/li&gt;
&lt;/ol&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Layer 4: 功能层&lt;a href=&quot;#layer-4-功能层&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;到了这一层，其实就是面向大模型的 硬封装 了。论文里列了推理、回忆、联想、预测、反思这些功能，但在实际调用中，你不能指望外部调用者来维护这些功能之间的状态。&lt;/p&gt;&lt;p&gt;这里最容易被忽视的是序列关系。&lt;/p&gt;&lt;p&gt;比如，“先反思，再预测”。如果你直接调两次接口，第一次反思完了，第二次预测的时候，系统怎么知道你刚才反思了什么？难道要把反思的结果再传一遍？这太低效了。&lt;/p&gt;&lt;p&gt;所以这一层内部必须维护一个Session 级的状态机。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;如果传入的是同一个 &lt;code&gt;session_id&lt;/code&gt;，系统应该知道当前上下文已经走到了“反思完成”的状态。&lt;/li&gt;
&lt;li&gt;这时候再调“预测”，它应该直接利用缓存中的反思结果，或者基于该状态继续推进。&lt;/li&gt;
&lt;li&gt;如果我不想要上次的结果，我应该显式地开启新 Session。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这一层存在的意义，就是屏蔽掉下面那些复杂的血缘追踪、索引查询、ETL 治理，给大模型提供一个干净、有状态的认知接口。外部看起来是在调函数，内部其实是在跑一个复杂的认知工作流。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>VMware 虚拟机性能优化：CPU Stuck 问题</title><link>https://axi.moe/posts/fyx0ohwb/</link><guid isPermaLink="true">https://axi.moe/posts/fyx0ohwb/</guid><pubDate>Sat, 20 Sep 2025 16:59:19 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;VMware 虚拟机性能优化：CPU Stuck 问题&lt;a href=&quot;#vmware-虚拟机性能优化cpu-stuck-问题&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h4&gt;&lt;strong&gt;1. 问题&lt;/strong&gt;&lt;a href=&quot;#1-问题&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;在 Windows 主机上通过 VMware Workstation Pro 运行 Linux 虚拟机时，即便物理机配置很高，有时也会遇到虚拟机内核报错：&lt;code&gt;watchdog: BUG: soft lockup - CPU#X stuck for XXs!&lt;/code&gt;。&lt;/p&gt;&lt;p&gt;该问题通常表现为虚拟机卡顿，或导致 VS Code 远程 SSH 会话中断。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;&lt;strong&gt;2. 原理：虚拟化架构冲突&lt;/strong&gt;&lt;a href=&quot;#2-原理虚拟化架构冲突&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Type-1 Hypervisor (裸金属型)&lt;/strong&gt;&lt;br /&gt;
直接安装在物理硬件上，操作系统（如 Windows）本身都运行在它之上。Windows 自带的 &lt;strong&gt;Hyper-V&lt;/strong&gt; 就是典型的 Type-1。它会优先、且完全地控制 CPU 的硬件虚拟化扩展（AMD-V / Intel VT-x）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type-2 Hypervisor (托管型)&lt;/strong&gt;&lt;br /&gt;
作为一款应用程序，安装在操作系统（如 Windows）之上。&lt;strong&gt;VMware Workstation&lt;/strong&gt; 就是典型的 Type-2。在理想情况下，它需要直接访问 CPU 的硬件虚拟化扩展来实现高性能。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;当 Windows 系统启用了 Hyper-V（或依赖它的功能，如 WSL2、虚拟机平台），Type-1 的 Hyper-V 就已经霸占了硬件控制权。这迫使 Type-2 的 VMware 降级到一种低性能的软件兼容模式（WHPX）运行，性能和稳定性都大打折扣，从而引发 &lt;code&gt;CPU stuck&lt;/code&gt; 等问题。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;&lt;strong&gt;3. 优化实践&lt;/strong&gt;&lt;a href=&quot;#3-优化实践&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;测试环境与命令：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;物理机: Windows 11 Host, AMD R7 5800H, 64GB RAM, NVMe SSD&lt;/li&gt;
&lt;li&gt;虚拟机: VMware Workstation Pro, Guest OS 为 Arch Linux (6核, 16GB RAM)&lt;/li&gt;
&lt;li&gt;测试命令: &lt;code&gt;sysbench cpu --cpu-max-prime=20000 --threads=6 run&lt;/code&gt;​&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;步骤一：关闭 Hyper-V&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;解除 Hyper-V 对硬件的占用，让 VMware 能直接与硬件通信。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;配置方法：&lt;/strong&gt;&lt;br /&gt;
以管理员身份打开 CMD 或 PowerShell，执行以下命令，然后&lt;strong&gt;必须重启电脑&lt;/strong&gt;。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;bcdedit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/set&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hypervisorlaunchtype&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;off&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;效果验证：&lt;/strong&gt;&lt;/p&gt;






















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;测试项&lt;/th&gt;&lt;th&gt;Test 1 (Hyper-V 开启)&lt;/th&gt;&lt;th&gt;Test 2 (Hyper-V 关闭)&lt;/th&gt;&lt;th&gt;变化&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CPU 速度 (events/sec)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;6142.24&lt;/td&gt;&lt;td&gt;6809.48&lt;/td&gt;&lt;td&gt;&lt;strong&gt;+10.86%&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;最大延迟 (max latency)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;41.12 ms&lt;/td&gt;&lt;td&gt;4.02 ms&lt;/td&gt;&lt;td&gt;&lt;strong&gt;-90.2%&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;步骤二：绑定专属核心&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;为虚拟机分配专属的 CPU 核心，消除宿主机其他进程的干扰。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;配置方法：&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;分配核心&lt;/strong&gt;：在 VMware Pro 中，关闭虚拟机，进入“设置”-&amp;gt;“处理器”。将核心数设置为你希望分配的数量（例如，我的物理机有 16 个逻辑核心，我为虚拟机分配 12 个，为 Windows 保留 4 个）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;绑定亲和性&lt;/strong&gt;：点击“亲和性”按钮，在弹窗中只勾选你想让虚拟机使用的物理 CPU 核心。例如，我只勾选了 &lt;code&gt;CPU 4&lt;/code&gt; 到 &lt;code&gt;CPU 15&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;提升优先级 (可选)&lt;/strong&gt; ：启动虚拟机后，在 Windows 任务管理器中找到 &lt;code&gt;vmware-vmx.exe&lt;/code&gt; 进程，将其优先级设置为“高”或“实时”。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;效果验证：&lt;/strong&gt;&lt;/p&gt;
















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;测试项&lt;/th&gt;&lt;th&gt;Test 2 (仅关闭Hyper-V)&lt;/th&gt;&lt;th&gt;Test 3 (亲和性+优先级)&lt;/th&gt;&lt;th&gt;变化&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CPU 速度 (events/sec)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;6809.48&lt;/td&gt;&lt;td&gt;10204.25&lt;/td&gt;&lt;td&gt;&lt;strong&gt;+49.85%&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;&lt;strong&gt;4. 最终结果&lt;/strong&gt;&lt;a href=&quot;#4-最终结果&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;关键指标&lt;/th&gt;&lt;th&gt;Test 1 (初始状态)&lt;/th&gt;&lt;th&gt;Test 3 (最终优化)&lt;/th&gt;&lt;th&gt;总提升&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CPU 速度 (events/sec)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;6142.24&lt;/td&gt;&lt;td&gt;&lt;strong&gt;10204.25&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;+66.13%&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;在绑定了专属核心后，CPU 性能再次&lt;strong&gt;暴涨近 50%&lt;/strong&gt; ！这是因为虚拟机不再需要和宿主机进程争抢 CPU 时间片，并且极大地提高了 CPU 缓存命中率。&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>K8s 持久化 Pod 控制台日志到节点本地：使用 Fluent Bit</title><link>https://axi.moe/posts/s7z75nvl/</link><guid isPermaLink="true">https://axi.moe/posts/s7z75nvl/</guid><pubDate>Sat, 30 Aug 2025 20:21:11 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h2&gt;K8s 持久化 Pod 控制台日志到节点本地：一个 Fluent Bit 实战指南&lt;a href=&quot;#k8s-持久化-pod-控制台日志到节点本地一个-fluent-bit-实战指南&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;动机&lt;a href=&quot;#动机&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在 Kubernetes 的日常使用中，我们通常会把日志接入云服务商或自建的中心化日志系统（如 ELK、Loki）。但在某些场景下，这并不是最佳选择，甚至不可行。&lt;/p&gt;&lt;p&gt;比如，你可能遇到了以下情况：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;环境限制&lt;/strong&gt;：无法将日志上报到外部网络，或者压根就不想依赖外部服务。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;简单持久化需求&lt;/strong&gt;：不需要复杂的搜索和分析，只希望 Pod 销毁后，日志能作为文件留在节点上，方便以后排查。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;快速调试需求&lt;/strong&gt;：在开发测试时，只想快速、直接地看到某个应用的日志，不想经过层层转发和复杂的平台。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;针对这些需求，我们可以采用一个更直接的方案：在 K8s 集群里部署一个日志代理，精确抓取特定应用的控制台日志，并把它写入每个节点主机的特定目录下。&lt;/p&gt;&lt;p&gt;本文将通过一个完整的实战案例，介绍如何使用 &lt;strong&gt;Fluent Bit&lt;/strong&gt;（一个轻量级、高性能的日志处理工具）作为 &lt;code&gt;DaemonSet&lt;/code&gt; 来实现这个目标。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;解决方案架构&lt;a href=&quot;#解决方案架构&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;我们的方案由三个核心的 K8s 资源组成，它们协同工作，构成了一条完整的日志采集流水线：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;RBAC 权限 (ServiceAccount, ClusterRole, ClusterRoleBinding)&lt;/strong&gt;：这是“通行证”。Fluent Bit 需要权限查询 K8s API，以获取 Pod 的标签等元数据，否则它就无法分辨日志的来源。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ConfigMap (配置中心)&lt;/strong&gt;：这是“大脑”。它包含了 Fluent Bit 的所有配置，告诉它该做什么、怎么做。我们在这里定义日志的输入、解析、过滤和输出规则。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DaemonSet (执行者)&lt;/strong&gt;：这是“工人”。通过 DaemonSet，我们确保每个节点上都运行一个 Fluent Bit Pod，负责采集该节点上所有容器的日志。&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;原理&lt;a href=&quot;#原理&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;为了让我们的 Fluent Bit 配置更加清晰，我们有必要了解一下 K8s 节点上日志文件的命名规范。当你 SSH 登录到任何一个 K8s 工作节点并查看 &lt;code&gt;/var/log/containers/&lt;/code&gt; 目录时，你会看到一系列遵循严格格式的文件。&lt;/p&gt;&lt;p&gt;这个目录存放着节点上所有容器日志的&lt;strong&gt;实际物理文件&lt;/strong&gt;。&lt;/p&gt;&lt;section&gt;&lt;h4&gt;标准格式&lt;a href=&quot;#标准格式&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;每个日志文件的名称都由几个部分拼接而成，格式如下：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;lt;pod_name&amp;gt;_&amp;lt;namespace&amp;gt;_&amp;lt;container_name&amp;gt;-&amp;lt;container_id&amp;gt;.log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;让我们来逐一拆解：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;pod_name&amp;gt;&lt;/code&gt;&lt;/strong&gt;: 产生这条日志的 Pod 的完整名称。例如，&lt;code&gt;my-app-7b5d8f9c6c-xyz&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;namespace&amp;gt;&lt;/code&gt;&lt;/strong&gt;: 该 Pod所在的 Kubernetes 命名空间。例如，&lt;code&gt;my-app-ns&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;container_name&amp;gt;&lt;/code&gt;&lt;/strong&gt;: Pod 中产生日志的具体容器的名称。这对于一个 Pod 内有多个容器（例如，一个主应用容器和一个 sidecar 容器）的场景非常重要。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;container_id&amp;gt;&lt;/code&gt;&lt;/strong&gt;: 由容器运行时（如 containerd 或 Docker）分配给该容器的一个唯一哈希值（ID）。这个 ID 确保了即使容器重启（Pod 不变，但容器实例是新的），日志文件也不会发生冲突。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;举个例子&lt;a href=&quot;#举个例子&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;假设我们有一个 Pod，信息如下：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;Pod 名称: &lt;code&gt;my-app-7b5d8f9c6c-xyz&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;命名空间: &lt;code&gt;my-app-ns&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;容器名称: &lt;code&gt;my-app-container&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;那么，它在节点上对应的日志文件名称就会是这样的：
&lt;code&gt;my-app-7b5d8f9c6c-xyz_my-app-ns_my-app-container-a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2.log&lt;/code&gt;&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;一个有用的快捷方式：&lt;code&gt;/var/log/pods&lt;/code&gt; 目录&lt;a href=&quot;#一个有用的快捷方式varlogpods-目录&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;除了 &lt;code&gt;/var/log/containers/&lt;/code&gt;，你可能还会注意到一个名为 &lt;code&gt;/var/log/pods/&lt;/code&gt; 的目录。这个目录提供了一套更具可读性的&lt;strong&gt;符号链接&lt;/strong&gt;（Symbolic Links），方便我们手动查找日志。&lt;/p&gt;&lt;p&gt;它的目录结构是这样的：
&lt;code&gt;/var/log/pods/&amp;lt;namespace&amp;gt;_&amp;lt;pod_name&amp;gt;_&amp;lt;pod_uid&amp;gt;/&amp;lt;container_name&amp;gt;/0.log&lt;/code&gt;&lt;/p&gt;&lt;p&gt;这里的 &lt;code&gt;0.log&lt;/code&gt; 文件就是一个符号链接，它最终指向了 &lt;code&gt;/var/log/containers/&lt;/code&gt; 目录中对应的那个长长的、带有哈希值的实际日志文件。&lt;/p&gt;&lt;p&gt;理解了这个文件结构，我们 Fluent Bit 配置中的 &lt;code&gt;Path /var/log/containers/*.log&lt;/code&gt; 就变得非常清晰了：它告诉 Fluent Bit 去监控这个目录下所有符合命名规范的日志文件，从而捕获节点上所有容器的输出。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;完整配置清单&lt;a href=&quot;#完整配置清单&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;要实现我们的目标，你需要将以下所有 K8s 资源清单整合到一个 YAML 文件中（例如 &lt;code&gt;fluent-bit-daemonset.yaml&lt;/code&gt;）。&lt;/p&gt;&lt;p&gt;这个配置文件会创建一个 &lt;code&gt;my-app-ns&lt;/code&gt; 命名空间，并部署所有需要的资源。它经过精心设计，能够：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;监控节点上所有容器的控制台输出。&lt;/li&gt;
&lt;li&gt;为每条日志附加其来源 Pod 的 K8s 标签。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;只保留&lt;/strong&gt;那些带有 &lt;code&gt;app: my-app&lt;/code&gt; 标签的 Pod 的日志。&lt;/li&gt;
&lt;li&gt;将这些日志的&lt;strong&gt;纯净、原始内容&lt;/strong&gt;（不含任何 JSON 包装或时间戳前缀）写入到每个节点主机的 &lt;code&gt;/var/log/my-app/app.log&lt;/code&gt; 文件中。&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# --- 第 1 部分：RBAC 权限 ---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Fluent Bit 需要从 K8s API 读取 Pod 和 Namespace 元数据的权限。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apiVersion&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ServiceAccount&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;my-app-ns&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 替换为你的目标命名空间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apiVersion&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ClusterRole&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit-read&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;rules&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;apiGroups&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;resources&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;namespaces&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;pods&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;verbs&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;span&gt;&quot;get&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;list&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;watch&quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apiVersion&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ClusterRoleBinding&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit-read&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;roleRef&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;apiGroup&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;rbac.authorization.k8s.io&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ClusterRole&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit-read&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;subjects&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ServiceAccount&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;my-app-ns&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 替换为你的目标命名空间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# --- 第 2 部分：FLUENT BIT 配置 ---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apiVersion&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ConfigMap&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit-config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;my-app-ns&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 替换为你的目标命名空间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;labels&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;k8s-app&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;41&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;42&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# 主配置文件&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;43&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;fluent-bit.conf&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;44&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[SERVICE]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;45&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Flush         5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;46&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Log_Level     info&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;47&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Parsers_File  parsers.conf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;48&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;49&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[INPUT]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;50&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# &apos;tail&apos; 插件是我们的输入源，用于监控文件内容&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;51&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Name              tail&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;52&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Tag               kube.*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;53&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 这是 K8s 节点上所有容器日志的标准路径&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;54&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Path              /var/log/containers/*.log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;55&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 使用下面定义的 &apos;cri&apos; 解析器来提取原始的日志消息&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;56&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Parser            cri&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;57&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 一个数据库文件，用于记录已读取的日志位置，防止重启后重复采集&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;58&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;DB                /var/fluent-bit/db/flb_kube.db&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;59&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Mem_Buf_Limit     5MB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;60&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;61&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[FILTER]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;62&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# &apos;kubernetes&apos; 过滤器会用 K8s API 中的元数据来丰富日志记录&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;63&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Name                kubernetes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;64&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Match               kube.*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;65&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 将解析出的日志消息合并回主记录中&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;66&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Merge_Log           On&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;67&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 指定合并后日志消息所使用的键名&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;68&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Merge_Log_Key       log_processed&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;69&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;70&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[FILTER]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;71&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# &apos;grep&apos; 过滤器用于筛选来自特定应用的日志&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;72&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Name                grep&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;73&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Match               kube.*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;74&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 这是核心过滤逻辑：只保留 &apos;app&apos; 标签为 &apos;my-app&apos; 的日志&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;75&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Regex               $kubernetes[&apos;labels&apos;][&apos;app&apos;] ^my-app$ # 将 &apos;my-app&apos; 替换为你的应用标签值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;76&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;77&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[OUTPUT]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;78&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# &apos;file&apos; 输出插件将日志写入文件&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;79&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Name          file&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;80&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Match         kube.*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;81&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 日志将被写入到宿主机的这个目录下&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;82&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Path          /host-logs/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;83&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 指定输出日志文件的名称&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;84&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;File          app.log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;85&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 使用自定义模板来格式化输出&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;86&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Format        template&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;87&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Template      {log}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;88&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;89&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# 解析器配置文件&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;90&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;parsers.conf&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;91&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[PARSER]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;92&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Name   cri&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;93&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Format regex&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;94&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 这个正则表达式用于剥离容器运行时添加的时间戳和流信息（stdout/stderr），&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;95&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 只捕获原始的日志内容并存入 &apos;log&apos; 字段。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;96&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Regex  ^(?&amp;lt;time&amp;gt;[^ ]+) (?&amp;lt;stream&amp;gt;stdout|stderr) (?&amp;lt;logtag&amp;gt;[^ ]*) (?&amp;lt;log&amp;gt;.*)$&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;97&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Time_Key time&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;98&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;Time_Format %Y-%m-%dT%H:%M:%S.%L%z&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;99&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;100&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# --- 第 3 部分：DAEMONSET 部署 ---&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;101&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 这个 DaemonSet 确保集群中的每个节点上都运行一个 Fluent Bit Pod，&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;102&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 从而能够采集该节点上所有应用的日志。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;103&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;104&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apiVersion&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;apps/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;105&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;DaemonSet&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;106&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;107&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;108&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;my-app-ns&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 替换为你的目标命名空间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;109&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;labels&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;110&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;k8s-app&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;111&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;112&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;113&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;matchLabels&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;114&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;k8s-app&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;115&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;116&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;117&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;labels&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;118&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;k8s-app&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;119&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;120&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;# 使用我们在第 1 部分中创建的 Service Account&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;121&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;serviceAccountName&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;122&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;terminationGracePeriodSeconds&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;123&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;124&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;# 定义卷，用于将宿主机路径和 ConfigMap 挂载到 Pod 中&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;125&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;volumes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;126&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;# 用于从宿主机读取容器日志的卷&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;127&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;varlog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;128&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;hostPath&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;129&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/var/log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;130&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;# 用于容器运行时状态的卷（某些运行时需要）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;131&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;varlibdockercontainers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;132&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;hostPath&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;133&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/var/lib/docker/containers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;134&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;# 用于将最终的日志文件写入宿主机的卷&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;135&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;host-log-output&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;136&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;hostPath&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;137&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/var/log/my-app&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 替换为你期望的宿主机输出目录&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;138&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;DirectoryOrCreate&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;139&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;# 用于从 ConfigMap 挂载配置文件的卷&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;140&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;141&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;configMap&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;142&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit-config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;143&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;# 用于在宿主机上存放 Fluent Bit 数据库文件的可写卷&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;144&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit-db&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;145&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;hostPath&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;146&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/var/lib/fluent-bit/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;147&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;DirectoryOrCreate&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;148&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;149&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;# 定义 Fluent Bit 容器&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;150&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;containers&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;151&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;152&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent/fluent-bit:latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;153&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# 将上面定义的卷挂载到容器的文件系统中&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;154&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;volumeMounts&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;155&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;varlog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;156&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;mountPath&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/var/log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;157&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;readOnly&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;158&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;varlibdockercontainers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;159&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;mountPath&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/var/lib/docker/containers&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;160&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;readOnly&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;161&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;host-log-output&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;162&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;mountPath&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/host-logs&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;163&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;164&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;mountPath&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/fluent-bit/etc/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;165&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fluent-bit-db&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;166&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;mountPath&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/var/fluent-bit/db/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;部署与验证&lt;a href=&quot;#部署与验证&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;应用配置&lt;/strong&gt;：
将上面的配置保存为 &lt;code&gt;fluent-bit-daemonset.yaml&lt;/code&gt;，然后执行：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fluent-bit-daemonset.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;检查 DaemonSet 状态&lt;/strong&gt;：
确认 Fluent Bit 的 Pod 已经在你的节点上成功运行。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ds&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-app-ns&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 期望输出中 DESIRED, CURRENT, READY 的数量应该一致&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;验证日志文件&lt;/strong&gt;：
SSH 登录到运行你目标应用 (&lt;code&gt;my-app&lt;/code&gt;) 的任一节点，然后查看目标文件：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;tail&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/var/log/my-app/app.log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;此时，当你与 &lt;code&gt;my-app&lt;/code&gt; 应用交互时，应该能在这里看到实时输出的原始日志行。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;常见问题排查 (Troubleshooting)&lt;a href=&quot;#常见问题排查-troubleshooting&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;如果你发现日志文件为空，别慌，这很常见。我们可以按以下步骤排查：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;确认源头有日志&lt;/strong&gt;：你的应用真的在向控制台输出日志吗？我们可以绕过 Fluent Bit，直接用 &lt;code&gt;kubectl&lt;/code&gt; 检查。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 确保你的应用正在运行并处理流量&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;logs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deployment/my-app&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-app-ns&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;如果这里没输出，那问题就在你的应用本身，而不是日志采集。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;确认标签完全匹配&lt;/strong&gt;：我们的过滤规则依赖精确的标签。检查一下 Pod 是否真的拥有我们指定的标签。&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pods&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-app-ns&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--show-labels&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;仔细核对 &lt;code&gt;LABELS&lt;/code&gt; 列，确保目标 Pod 拥有 &lt;code&gt;app: my-app&lt;/code&gt;。任何拼写错误都会导致过滤失败。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;检查 Fluent Bit 自身日志&lt;/strong&gt;：Fluent Bit Pod 在启动或运行时报错了吗？&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;logs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;my-app-ns&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-l&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;k8s-app=fluent-bit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;常见的错误包括权限不足（RBAC 问题）、配置文件语法错误或无法访问挂载目录。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;总结与扩展&lt;a href=&quot;#总结与扩展&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;通过上面的步骤，我们就成功构建了一个轻量级、高针对性的 K8s 日志持久化系统。它不依赖任何外部服务，将指定应用的控制台日志以最纯粹的形式保存在了节点本地，完美解决了特定场景下的日志采集需求。&lt;/p&gt;&lt;p&gt;这个方案的真正强大之处在于它的扩展性。通过简单修改 &lt;code&gt;ConfigMap&lt;/code&gt;，你可以：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;更改过滤规则&lt;/strong&gt;：采集不同应用或整个命名空间的日志。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更改输出目标&lt;/strong&gt;：将日志发送到 Elasticsearch、S3、Loki 或其他任何 Fluent Bit 支持的后端，轻松从本地持久化方案升级为中心化日志系统。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>arch安装笔记</title><link>https://axi.moe/posts/0mmwg442/</link><guid isPermaLink="true">https://axi.moe/posts/0mmwg442/</guid><pubDate>Thu, 07 Aug 2025 21:28:10 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;第一部分：安装流程日志&lt;a href=&quot;#第一部分安装流程日志&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;1.1 预备操作及网络验证&lt;a href=&quot;#11-预备操作及网络验证&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在虚拟机中通过 Arch Linux ISO 镜像启动后，进入 Live 环境。首要步骤是验证网络连通性，以确保后续软件包的下载。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 测试与 Arch Linux 官方服务器的连通性&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ping&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;archlinux.org&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;确认收到 ICMP 回复后，网络验证通过。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;1.2 磁盘分区方案定义与实施&lt;a href=&quot;#12-磁盘分区方案定义与实施&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;本节详述使用 &lt;code&gt;cfdisk&lt;/code&gt; 交互式工具在目标磁盘 (&lt;code&gt;/dev/sda&lt;/code&gt;) 上进行分区的具体操作步骤。本次安装遵循 GPT (GUID Partition Table) 分区方案。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;首先，使用 &lt;code&gt;lsblk&lt;/code&gt; 命令列出所有块设备，确认您要安装系统的目标磁盘。&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 检查磁盘列表和大小，确定目标磁盘符（例如 /dev/sda）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;lsblk&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;警告：接下来的操作是破坏性的，请务必确认选择了正确的磁盘。本文档以 &lt;code&gt;/dev/sda&lt;/code&gt; 为例。&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;首先，执行以下命令启动分区工具，并将其指向目标磁盘：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cfdisk&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/sda&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;该命令将打开一个全屏的交互式界面。后续所有操作均在此界面中通过键盘完成。&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;选择分区表类型 (Label Type)&lt;/strong&gt;
若目标磁盘为空盘或无有效分区表，&lt;code&gt;cfdisk&lt;/code&gt; 会首先提示选择分区表类型。使用方向键选择 &lt;code&gt;gpt&lt;/code&gt;，然后按 Enter 键确认。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;创建分区&lt;/strong&gt;
接下来，根据下表的规划逐一创建分区。在 &lt;code&gt;cfdisk&lt;/code&gt; 界面中，通过方向键 &lt;code&gt;↑&lt;/code&gt;/&lt;code&gt;↓&lt;/code&gt; 选择磁盘上的 &lt;code&gt;Free space&lt;/code&gt;，然后使用 &lt;code&gt;←&lt;/code&gt;/&lt;code&gt;→&lt;/code&gt; 键选择底部菜单项。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;目标分区规划表:&lt;/strong&gt;&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;分区设备&lt;/th&gt;&lt;th&gt;规划容量&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;&lt;code&gt;/dev/sda1&lt;/code&gt;&lt;/td&gt;&lt;td&gt;512 MiB&lt;/td&gt;&lt;td&gt;&lt;code&gt;EFI System&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;/boot/efi&lt;/code&gt; (EFI 系统分区)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;/dev/sda2&lt;/code&gt;&lt;/td&gt;&lt;td&gt;2.5 GiB&lt;/td&gt;&lt;td&gt;&lt;code&gt;Linux swap&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Swap (交换空间)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;/dev/sda3&lt;/code&gt;&lt;/td&gt;&lt;td&gt;50 GiB&lt;/td&gt;&lt;td&gt;&lt;code&gt;Linux filesystem&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;/&lt;/code&gt; (根文件系统)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;/dev/sda4&lt;/code&gt;&lt;/td&gt;&lt;td&gt;47 GiB&lt;/td&gt;&lt;td&gt;&lt;code&gt;Linux filesystem&lt;/code&gt;&lt;/td&gt;&lt;td&gt;预留给 ZFS，本次安装不使用&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;规划理由:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;/dev/sda1 (EFI):&lt;/strong&gt; 512 MiB 是 UEFI 规范推荐的最小尺寸之一，对于存放多个引导加载程序绰绰有余。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;/dev/sda2 (Swap):&lt;/strong&gt; 2.5 GiB 是基于本虚拟机计划运行的内存大小（例如 2 GiB）设定的，用于休眠或内存压力较大时的补充。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;/dev/sda3 (Root):&lt;/strong&gt; 50 GiB 为操作系统和常用软件提供了充足的空间。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;创建 &lt;code&gt;/dev/sda1&lt;/code&gt; (EFI System Partition):&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;确保选中了磁盘开头的 &lt;code&gt;Free space&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;在底部菜单选择 &lt;code&gt;[ New ]&lt;/code&gt; 并按 Enter。&lt;/li&gt;
&lt;li&gt;当提示输入 &lt;code&gt;Partition size&lt;/code&gt; 时，键入 &lt;code&gt;512M&lt;/code&gt; 并按 Enter。&lt;/li&gt;
&lt;li&gt;此时分区已创建，但类型不正确。在底部菜单选择 &lt;code&gt;[ Type ]&lt;/code&gt; 并按 Enter。&lt;/li&gt;
&lt;li&gt;在分区类型列表中，使用方向键找到并选中 &lt;code&gt;EFI System&lt;/code&gt;，按 Enter 确认。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;创建 &lt;code&gt;/dev/sda2&lt;/code&gt; (Linux Swap):&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用 &lt;code&gt;↓&lt;/code&gt; 键选中 &lt;code&gt;/dev/sda1&lt;/code&gt; 下方的 &lt;code&gt;Free space&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;选择 &lt;code&gt;[ New ]&lt;/code&gt;，输入 &lt;code&gt;2.5G&lt;/code&gt; 并按 Enter。&lt;/li&gt;
&lt;li&gt;选择 &lt;code&gt;[ Type ]&lt;/code&gt;，在列表中找到并选中 &lt;code&gt;Linux swap&lt;/code&gt;，按 Enter 确认。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;创建 &lt;code&gt;/dev/sda3&lt;/code&gt; (Root Filesystem):&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;选中剩余的 &lt;code&gt;Free space&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;选择 &lt;code&gt;[ New ]&lt;/code&gt;，输入 &lt;code&gt;50G&lt;/code&gt; 并按 Enter。&lt;/li&gt;
&lt;li&gt;分区类型默认为 &lt;code&gt;Linux filesystem&lt;/code&gt;，符合根分区的要求，无需更改。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;创建 &lt;code&gt;/dev/sda4&lt;/code&gt; (ZFS Placeholder):&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;选中最后剩余的 &lt;code&gt;Free space&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;选择 &lt;code&gt;[ New ]&lt;/code&gt;，直接按 Enter 键以使用所有剩余空间（应约为 47 GiB）。&lt;/li&gt;
&lt;li&gt;分区类型同样默认为 &lt;code&gt;Linux filesystem&lt;/code&gt;，符合要求。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;写入更改并退出&lt;/strong&gt;
分区规划完成后，界面顶部会显示新规划的分区表，但此时更改仅存在于内存中，尚未写入磁盘。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在底部菜单中选择 &lt;code&gt;[ Write ]&lt;/code&gt; 并按 Enter。&lt;/li&gt;
&lt;li&gt;程序会要求确认操作，这是最后防止误操作的机会。输入 &lt;code&gt;yes&lt;/code&gt; 并按 Enter。&lt;/li&gt;
&lt;li&gt;待写入完成后，选择 &lt;code&gt;[ Quit ]&lt;/code&gt; 并按 Enter，退出 &lt;code&gt;cfdisk&lt;/code&gt; 工具。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;完成上述步骤后，可以使用 &lt;code&gt;lsblk&lt;/code&gt; 命令检查磁盘分区是否与规划一致，以确认操作成功。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;1.3 文件系统格式化与挂载&lt;a href=&quot;#13-文件系统格式化与挂载&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;对已定义的分区进行格式化，并按照预定结构挂载至 Live 环境的 &lt;code&gt;/mnt&lt;/code&gt; 目录。&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;文件系统创建&lt;/strong&gt;:
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 格式化 EFI 系统分区为 FAT32&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkfs.fat&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-F32&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/sda1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 初始化 Swap 分区&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkswap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/sda2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 格式化根分区为 ext4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkfs.ext4&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/sda3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文件系统挂载&lt;/strong&gt;:
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 激活 Swap 分区&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;swapon&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/sda2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 挂载根分区至 /mnt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mount&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/sda3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/mnt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 创建并挂载 EFI 分区&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/mnt/boot/efi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mount&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/dev/sda1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/mnt/boot/efi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;1.4 基础系统安装&lt;a href=&quot;#14-基础系统安装&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;使用 &lt;code&gt;pacstrap&lt;/code&gt; 脚本将基础软件包及必要的工具集安装到目标根文件系统 (&lt;code&gt;/mnt&lt;/code&gt;)。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;pacstrap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/mnt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;base&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;linux&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;linux-firmware&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;vim&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;networkmanager&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;p&gt;-K 选项会使用 Live 环境的密钥环来初始化新系统的 pacman 密钥环&lt;/p&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;1.5 核心系统配置&lt;a href=&quot;#15-核心系统配置&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;生成 fstab&lt;/strong&gt;: 创建文件系统表，用于定义系统启动时的挂载规则。
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;genfstab&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-U&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/mnt&lt;/span&gt;&lt;span&gt; &amp;gt;&amp;gt; &lt;/span&gt;&lt;span&gt;/mnt/etc/fstab&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;切换根环境&lt;/strong&gt;: 使用 &lt;code&gt;arch-chroot&lt;/code&gt; 进入新安装的系统内部，以执行系统级别的配置。
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;arch-chroot&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/mnt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;时区与本地化 (Chroot 环境内)&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;设置系统时区为 &lt;code&gt;Asia/Shanghai&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;编辑 &lt;code&gt;/etc/locale.gen&lt;/code&gt;，启用 &lt;code&gt;en_US.UTF-8&lt;/code&gt; 和 &lt;code&gt;zh_CN.UTF-8&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;执行 &lt;code&gt;locale-gen&lt;/code&gt; 生成本地化信息。&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;/etc/locale.conf&lt;/code&gt; 中设定 &lt;code&gt;LANG=en_US.UTF-8&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;主机与网络配置 (Chroot 环境内)&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;在 &lt;code&gt;/etc/hostname&lt;/code&gt; 中定义主机名为 &lt;code&gt;arch-vm&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;相应地更新 &lt;code&gt;/etc/hosts&lt;/code&gt; 文件。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;设置 Root 密码 (Chroot 环境内)&lt;/strong&gt;:
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;passwd&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;安装并配置引导加载程序 (Chroot 环境内)&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;安装 GRUB 及 UEFI 相关工具。
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;pacman&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-S&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;grub&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;efibootmgr&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;执行 GRUB 安装，目标为 x86_64-efi 架构，EFI 目录为 &lt;code&gt;/boot/efi&lt;/code&gt;。
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;grub-install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--target=x86_64-efi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--efi-directory=/boot/efi&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--bootloader-id=GRUB&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;生成 GRUB 配置文件。
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;grub-mkconfig&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/boot/grub/grub.cfg&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;创建管理员用户 (Chroot 环境内)&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;创建新用户 &lt;code&gt;nolan&lt;/code&gt; 并将其加入 &lt;code&gt;wheel&lt;/code&gt; 用户组，以备后续提权。
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;useradd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-m&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-G&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wheel&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nolan&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;为新用户 &lt;code&gt;nolan&lt;/code&gt; 设置密码。&lt;/li&gt;
&lt;li&gt;使用 &lt;code&gt;visudo&lt;/code&gt; 编辑 sudoers 配置，解除对 &lt;code&gt;%wheel&lt;/code&gt; 组的注释，授予其 &lt;code&gt;sudo&lt;/code&gt; 权限。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;启用网络服务 (Chroot 环境内)&lt;/strong&gt;:
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;enable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;NetworkManager&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;1.6 安装收尾与首次启动&lt;a href=&quot;#16-安装收尾与首次启动&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;退出 chroot 环境 (&lt;code&gt;exit&lt;/code&gt;)。&lt;/li&gt;
&lt;li&gt;卸载所有已挂载的分区 (&lt;code&gt;umount -R /mnt&lt;/code&gt;)。&lt;/li&gt;
&lt;li&gt;重启系统 (&lt;code&gt;reboot&lt;/code&gt;)。&lt;/li&gt;
&lt;li&gt;在首次启动后，使用 &lt;code&gt;nolan&lt;/code&gt; 用户登录，并安装 &lt;code&gt;htop&lt;/code&gt; 软件包作为系统初步验证。
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pacman&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-Syu&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;htop&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;安装流程至此结束。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;第二部分：附录：关键技术概念解析&lt;a href=&quot;#第二部分附录关键技术概念解析&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;2.1 磁盘分区方案：GPT 与 MBR&lt;a href=&quot;#21-磁盘分区方案gpt-与-mbr&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;磁盘分区方案是定义存储设备上分区布局的底层规范。GPT (GUID Partition Table) 是替换传统 MBR (Master Boot Record) 的现代标准。其主要优势在于：突破了 MBR 的 2TB 磁盘容量和 4 个主分区的限制；通过在磁盘两端存储分区表备份，显著提高了数据结构的冗余度和可靠性；原生支持 UEFI 启动模式。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;2.2 固件接口与启动模式：UEFI 与 Legacy BIOS&lt;a href=&quot;#22-固件接口与启动模式uefi-与-legacy-bios&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;固件是嵌入在硬件设备中的低级别软件，负责在操作系统接管之前执行硬件初始化。UEFI (Unified Extensible Firmware Interface) 是取代传统 BIOS (Basic Input/Output System) 的现代固件接口规范。&lt;/p&gt;&lt;p&gt;与 BIOS 相比，UEFI 提供模块化设计、64 位寻址能力、图形化界面、网络功能和安全启动 (Secure Boot) 等高级特性。UEFI 规范规定，引导加载程序必须是存放于一个被称为 EFI 系统分区 (ESP) 内的 &lt;code&gt;.efi&lt;/code&gt; 可执行文件。该分区必须采用 FAT 文件系统格式，以便固件能够识别和执行。&lt;/p&gt;&lt;p&gt;市面上有很多主板进入后显示图形化界面，用户界面可能标注为”BIOS设置”，但实际上这些现代主板都使用的是UEFI固件。这不应被简单理解为“BIOS加了个皮肤”。真正的区别在于底层架构：传统 BIOS 是一个中断驱动的、16位汇编代码的集合，而 UEFI 是一个更像微型操作系统的、可扩展的 C 语言平台。图形化界面、网络启动等高级功能都是这种现代架构带来的自然产物。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;2.3 引导加载程序：GRUB&lt;a href=&quot;#23-引导加载程序grub&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;引导加载程序 (Bootloader) 是一个在固件完成硬件初始化之后、操作系统内核启动之前的程序。它的核心职责是定位并加载操作系统内核到内存中，然后将执行控制权移交给内核。&lt;/p&gt;&lt;p&gt;GRUB (GRand Unified Bootloader) 是 Linux 生态系统中最常用的引导加载程序之一。在 UEFI 启动流程中，UEFI 固件负责从 ESP 分区加载并执行 GRUB 的 &lt;code&gt;.efi&lt;/code&gt; 文件。随后，GRUB 接管控制权，凭借其识别 ext4 等复杂文件系统的能力，从根分区加载 Linux 内核 (&lt;code&gt;vmlinuz-linux&lt;/code&gt;) 和初始内存盘 (&lt;code&gt;initramfs-linux.img&lt;/code&gt;)，最终启动操作系统。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;2.4 根环境切换工具：&lt;code&gt;arch-chroot&lt;/code&gt;&lt;a href=&quot;#24-根环境切换工具arch-chroot&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;chroot&lt;/code&gt; (Change Root) 是一项允许进程将其根目录临时更改为文件系统中某个指定目录的操作。在 Arch Linux 安装过程中，此操作是必需的，因为它允许我们在新安装的系统能够独立启动之前，进入其内部环境执行配置命令。&lt;/p&gt;&lt;p&gt;&lt;code&gt;arch-chroot&lt;/code&gt; 是 Arch Linux 提供的 &lt;code&gt;chroot&lt;/code&gt; 封装脚本。相较于标准 &lt;code&gt;chroot&lt;/code&gt; 命令，它额外执行了关键的准备工作，包括：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;挂载 API 文件系统&lt;/strong&gt;：自动将 Live 环境的 &lt;code&gt;/proc&lt;/code&gt;、&lt;code&gt;/sys&lt;/code&gt;、&lt;code&gt;/dev&lt;/code&gt; 等内核接口文件系统挂载到新的根环境中，确保系统工具（如 &lt;code&gt;pacman&lt;/code&gt;, &lt;code&gt;grub-install&lt;/code&gt;）能够正常工作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;复制 DNS 配置&lt;/strong&gt;：自动将 Live 环境的 &lt;code&gt;/etc/resolv.conf&lt;/code&gt; 复制到新根环境中，保证在 chroot 状态下依然具备网络域名解析能力。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>从面试题开始的Golang map</title><link>https://axi.moe/posts/8phjex9s/</link><guid isPermaLink="true">https://axi.moe/posts/8phjex9s/</guid><pubDate>Sat, 28 Jun 2025 11:52:02 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;从面试题开始的Golang map&lt;a href=&quot;#从面试题开始的golang-map&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;问题：假设有一个golang的 &lt;code&gt;map[int64]int64&lt;/code&gt;​ 存储了10亿（可以认为是）个用户的信息，key是用户的user id（唯一），估算至少需要多少内存？如果value无意义，退化为集合类型，又可以有什么优化？&lt;/p&gt;&lt;p&gt;理论最小值的估算非常简单，即16GB。但这个 16GB 只是纯粹的数据大小，完全忽略了 Go 为了实现 map 这个高效的哈希表结构而引入的巨大开销（Overhead）。&lt;/p&gt;&lt;section&gt;&lt;h2&gt;golang map的真实内存&lt;a href=&quot;#golang-map的真实内存&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;要精确计算，我们必须先了解 Go &lt;code&gt;map&lt;/code&gt;​ 的底层结构。其核心是 &lt;code&gt;hmap&lt;/code&gt;​ 和 &lt;code&gt;bmap&lt;/code&gt;​ 两个结构体（源码位于 &lt;code&gt;runtime/map.go&lt;/code&gt;​）。&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// A header for a Go map.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hmap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// map中的元素个数，即 len()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;flags&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;uint8&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;uint8&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;// buckets 数量的对数，即 buckets 数组的长度 = 2^B&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;noverflow&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;uint16&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// 溢出桶的大约数量&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;hash0&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;uint32&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// 哈希种子&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;buckets&lt;/span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;unsafe&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Pointer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// 指向 bucket 数组的指针，数组大小为 2^B&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;oldbuckets&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;unsafe&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Pointer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// 扩容时，指向旧的 bucket 数组&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;nevacuate&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;uintptr&lt;/span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// 扩容进度计数器&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;extra&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt;mapextra&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// 指向溢出桶等额外信息&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// A bucket for a Go map.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bmap&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// tophash 存储了每个 key 哈希值的高8位&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// 用于在 bucket 中快速筛选，避免逐一比较 key&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;tophash&lt;/span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;uint8&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// tophash 后面紧跟着 8 个 key 和 8 个 value&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// keys    [8]keytype&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// values  [8]valuetype&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// ...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;overflow&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;uintptr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// 指向下一个溢出桶&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;​&lt;code&gt;map&lt;/code&gt;​ 的核心是一个 &lt;strong&gt;bucket 数组&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;每个 &lt;strong&gt;bucket&lt;/strong&gt; 通常可以存放 &lt;strong&gt;8 个&lt;/strong&gt; 键值对。&lt;/li&gt;
&lt;li&gt;为了保证查询效率，当 map 的&lt;strong&gt;负载因子（Load Factor）&lt;/strong&gt; 超过 6.5 时，就会触发扩容。负载因子即 &lt;code&gt;map元素总数 / bucket总数&lt;/code&gt;​。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;现在，我们可以根据数据结构计算存储 10 亿个元素所需的内存。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Bucket 数量&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;根据负载因子 6.5，我们需要的最小 Bucket 数为：&lt;br /&gt;
Buckets=6.5109 个元素≈153,846,154&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;由于 Bucket 数量必须是 2 的幂（2B），我们需要找到大于该值的最小 2 的幂。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;227=134,217,728 (不够)&lt;/li&gt;
&lt;li&gt;228=268,435,456 (足够)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;因此，Go 运行时会为这个 &lt;code&gt;map&lt;/code&gt;​ 分配 &lt;strong&gt;228&lt;/strong&gt; 个 Bucket。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;计算各部分内存占用&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;​&lt;code&gt;map&lt;/code&gt;​ 的总内存由 &lt;strong&gt;Keys&lt;/strong&gt;、&lt;strong&gt;Values&lt;/strong&gt; 和&lt;strong&gt;结构开销&lt;/strong&gt;三部分组成。由于 &lt;code&gt;map&lt;/code&gt;​ 预分配了 228 个 bucket，每个 bucket 有 8 个槽位，所以总槽位数为 。&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;存储 Keys 的总空间:&lt;br /&gt;
2.147×109 个槽位×8 字节/key≈17.18×109 字节≈16.0 GB&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;存储 Values 的总空间:&lt;br /&gt;
2.147×109 个槽位×8 字节/value≈17.18×109 字节≈16.0 GB&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;结构开销:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;tophash: 每个槽位 1 字节。&lt;br /&gt;
2.147×109 个槽位×1 字节≈2.15×109 字节≈2.0 GB&lt;/li&gt;
&lt;li&gt;溢出指针 (overflow pointers): 每个 Bucket 1 个指针（64位系统占8字节）。&lt;br /&gt;
228 个 buckets×8 字节/指针≈2.15×109 字节≈2.0 GB&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;‍&lt;/p&gt;&lt;p&gt;将以上各项相加：&lt;/p&gt;&lt;p&gt;结论： 一个存储 10 亿 &lt;code&gt;int64:int64&lt;/code&gt;​ 的 map，实际需要 &lt;strong&gt;36GB&lt;/strong&gt; 的内存，是理论最小值的 2.5 倍以上。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;如果改成集合呢？&lt;a href=&quot;#如果改成集合呢&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在很多场景中，我们只关心 Key 是否存在，而 Value 本身没有意义，比如用 map 来去重。这时，问题就从一个键值映射（Map）退化成了一个&lt;strong&gt;集合（Set）&lt;/strong&gt; 。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;map[int64]struct{}&lt;a href=&quot;#mapint64struct&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;你可能会想用 &lt;code&gt;map[int64]bool&lt;/code&gt;​，但这是一个陷阱。&lt;code&gt;bool&lt;/code&gt;​ 类型虽只占 1 字节，但因内存对齐，在 map 的 bucket 中仍会占据 8 字节的槽位，几乎没有优化效果。正确的姿势是使用空结构体 &lt;code&gt;struct{}&lt;/code&gt;​。&lt;/p&gt;&lt;p&gt;采用这种方法后，我们之前计算中的 Values 部分（16.0 GB）的开销就直接消失了。&lt;/p&gt;总内存&lt;/section&gt;&lt;section&gt;&lt;h3&gt;更优解：bitmap&lt;a href=&quot;#更优解bitmap&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;其实我们还有一个条件没用到，即key是int64类型，并非普通的哈希表key，那么对于“整数集合”这个特定的问题，存在一种效率极高的数据结构——&lt;strong&gt;位图（Bitmap）&lt;/strong&gt; 。其原理非常简单：用一个 bit 的状态（0 或 1）来表示一个整数是否存在。&lt;/p&gt;&lt;p&gt;如果使用 &lt;code&gt;bitmap&lt;/code&gt;​，则内存为：&lt;/p&gt;&lt;p&gt;但 bitmap 的问题是，如果user id分布不均衡，或者非常稀疏，在 int64 空间下需要分配非常大的内存：&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Roaring Bitmap&lt;a href=&quot;#roaring-bitmap&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;为了解决传统位图的稀疏数据难题，&lt;strong&gt;Roaring Bitmap&lt;/strong&gt; 横空出世。它是一种高度优化的压缩位图，专门为高效存储大量整数集合而设计，早已成为许多大数据框架（如 Spark, Druid）的内置组件。&lt;/p&gt;&lt;p&gt;Roaring Bitmap 将整数空间按高16位和低16位分成不同的chunk块，每个chunk存储个整数。&lt;/p&gt;&lt;p&gt;根据chunk的稀疏程度：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;如果整数非常稀疏，就用一个有序数组存储&lt;/li&gt;
&lt;li&gt;如果整数非常密集，则使用bitmap&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;扩展阅读：&lt;a href=&quot;https://arxiv.org/abs/1603.06549&quot; target=&quot;_blank&quot;&gt;Consistently faster and smaller compressed bitmaps with Roaring&lt;/a&gt;&lt;/p&gt;&lt;p&gt;golang Roaring Bitmap实现：&lt;a href=&quot;https://github.com/RoaringBitmap/roaring&quot; target=&quot;_blank&quot;&gt;roaring&lt;/a&gt;&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Python 更新记录</title><link>https://axi.moe/posts/m8is8z4h/</link><guid isPermaLink="true">https://axi.moe/posts/m8is8z4h/</guid><pubDate>Sun, 01 Jun 2025 18:44:16 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Python 各版本重大更新&lt;a href=&quot;#python-各版本重大更新&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;Python 发布策略&lt;a href=&quot;#python-发布策略&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Python的版本采用年度更新策略，每年十月发布新版本，如3.10版本在2020年10月5日发布，3.11版本在2021年10月4日发布。
本文旨在记录各重大特性的变更记录，方便使用新特性时参考版本。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;python 3.9 2020年10月5日&lt;a href=&quot;#python-39-2020年10月5日&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;字典合并(PEP 584)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;d1 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;a&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;b&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;d2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;b&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;c&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;merged &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; d1 &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; d2  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# {&apos;a&apos;: 1, &apos;b&apos;: 3, &apos;c&apos;: 4}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;d1 &lt;/span&gt;&lt;span&gt;|=&lt;/span&gt;&lt;span&gt; d2          &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# d1 = {&apos;a&apos;: 1, &apos;b&apos;: 3, &apos;c&apos;: 4}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;str.removeprefix()&lt;/code&gt; 和 &lt;code&gt;str.removesuffix()&lt;/code&gt;(PEP 616)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;s &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;hello world&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;s.&lt;/span&gt;&lt;span&gt;removeprefix&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;hello&quot;&lt;/span&gt;&lt;span&gt;)  &lt;/span&gt;&lt;span&gt;# &quot; world&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;s.&lt;/span&gt;&lt;span&gt;removesuffix&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;world&quot;&lt;/span&gt;&lt;span&gt;)  &lt;/span&gt;&lt;span&gt;# &quot;hello &quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;集合泛型(PEP 585)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# old&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; typing.List&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; typing.List[&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; list[&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;再也不需要导入typing.List了，直接使用list[int]即可。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;PEG解析器(PEP 617)
语法上无影响，主要影响解析器的实现，为后续的一些语法提供支撑。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;zoneinfo(PEP 615) 和graphlib&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; zoneinfo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;tz &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; zoneinfo.&lt;/span&gt;&lt;span&gt;ZoneInfo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;Asia/Shanghai&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;方便了对时区（包括夏令时）的处理。&lt;/p&gt;&lt;p&gt;graphlib主要增加了&lt;code&gt;TopologicalSorter&lt;/code&gt;，用于拓扑排序。&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;性能优化
Vectorcall 协议(PEP 590)使用范围扩大，范围扩大到&lt;code&gt;range&lt;/code&gt;、&lt;code&gt;tuple&lt;/code&gt;、&lt;code&gt;set&lt;/code&gt;、&lt;code&gt;frozenset&lt;/code&gt;、&lt;code&gt;list&lt;/code&gt;、&lt;code&gt;dict&lt;/code&gt;的调用。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;优化了多线程信号处理机制。&lt;/p&gt;&lt;p&gt;提高短ASCII字符串的性能。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;python 3.10 2021年10月4日&lt;a href=&quot;#python-310-2021年10月4日&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;结构化模式匹配 (PEP 634, 635, 636):
引入&lt;code&gt;match&lt;/code&gt;和&lt;code&gt;case&lt;/code&gt;语句，用于模式匹配。&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;http_error&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;match&lt;/span&gt;&lt;span&gt; status:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;400&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Bad request&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;404&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Not found&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;418&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;I&apos;m a teapot&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; _:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Something&apos;s wrong with the internet&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;401&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;403&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;404&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;Not allowed&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;括号上下文&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;with&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;open&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;file1.txt&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; f1,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;open&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;file2.txt&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; f2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# do with f1, f2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;使用”|“定义联合类型而不是typing.Union(PEP 604)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# old&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; typing.Union[&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# new&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;|&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;C API
int 类型新增了 int.bit_count() 方法。&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;zip() 函数新增了一个 strict 标志 (PEP 618)，用于强制所有可迭代对象的长度相等。&lt;/p&gt;&lt;p&gt;新增了两个内置函数 aiter() 和 anext()，用于异步迭代。&lt;/p&gt;&lt;p&gt;@staticmethod 和 @classmethod 装饰器得到改进，现在可以继承方法属性并拥有一个新的 &lt;strong&gt;wrapped&lt;/strong&gt; 属性。&lt;/p&gt;&lt;p&gt;新增了 inspect.get_annotations() 函数，用于安全地计算注解，包括对字符串化注解进行反字符串化。&lt;/p&gt;&lt;p&gt;ssl 模块现在要求 OpenSSL 1.1.1 或更新版本，并具有更安全的默认设置。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;python 3.11 2022年10月24日&lt;a href=&quot;#python-311-2022年10月24日&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;性能提升&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;与 3.10 相比平均提升 25%（部分场景提升 10-60%）&lt;/li&gt;
&lt;li&gt;更快的启动速度：通过”冻结导入”实现&lt;/li&gt;
&lt;li&gt;专门化自适应解释器：运行时识别热点代码，用更快的版本替换通用字节码&lt;/li&gt;
&lt;li&gt;更廉价、惰性的 Python 帧&lt;/li&gt;
&lt;li&gt;内联 Python 函数调用&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;异常处理增强&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;细粒度错误定位 (PEP 657)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 现在错误信息会精确指向问题表达式&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 例如：TypeError: unsupported operand type(s) for +: &apos;int&apos; and &apos;str&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 错误位置会用 ~^~~ 标记&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;异常组 (PEP 654)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;raise&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ExceptionGroup&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;多个错误&quot;&lt;/span&gt;&lt;span&gt;, [&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ValueError&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;值错误&quot;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;TypeError&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;类型错误&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;except&lt;/span&gt;&lt;span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ValueError&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;处理值错误&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;except&lt;/span&gt;&lt;span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;TypeError&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;处理类型错误&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;异常注解 (PEP 678)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;raise&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ValueError&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;原始错误&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;except&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ValueError&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;as&lt;/span&gt;&lt;span&gt; e:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;e.&lt;/span&gt;&lt;span&gt;add_note&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;这是额外的上下文信息&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;raise&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;类型系统增强
&lt;ul&gt;
&lt;li&gt;可变参数泛型 (PEP 646)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; typing &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; TypeVarTuple, TypeVar&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;Shape &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TypeVarTuple&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;Shape&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;T &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;TypeVar&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;T&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Array&lt;/span&gt;&lt;span&gt;(Generic[T, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;Shape])&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;TypedDict 增强 (PEP 655)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; typing &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; TypedDict, Required, NotRequired&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Movie&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;TypedDict&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;title: Required[&lt;/span&gt;&lt;span&gt;str&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;year: Required[&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;rating: NotRequired[&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Self 类型 (PEP 673)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; typing &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Self&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Shape&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;set_scale&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;scale&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;) -&amp;gt; Self:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&lt;span&gt;.scale &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; scale&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;标准库更新
&lt;ul&gt;
&lt;li&gt;tomllib 模块 (PEP 680)：用于解析 TOML 文件&lt;/li&gt;
&lt;li&gt;asyncio 新增 TaskGroup&lt;/li&gt;
&lt;li&gt;enum 模块增强：新增 StrEnum、ReprEnum 和 EnumType&lt;/li&gt;
&lt;li&gt;re 模块支持原子组和所有格量词&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;python 3.12 2023年10月2日&lt;a href=&quot;#python-312-2023年10月2日&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;类型系统增强
&lt;ul&gt;
&lt;li&gt;类型参数语法 (PEP 695)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 新的类型别名语法&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;&lt;span&gt; Point &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; tuple[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 新的泛型类语法&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; Vector[T]:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__init__&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; T&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; T&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&lt;span&gt;.x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; x&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;&lt;span&gt;.y &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; y&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 新的泛型函数语法&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; first[T](items: list[T]) &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; T:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; items[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;TypedDict 增强 (PEP 692)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; typing &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; TypedDict, Unpack&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;TypedDict&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;timeout: &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;retries: &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;(**&lt;/span&gt;&lt;span&gt;options&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Unpack[Options]&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;@typing.override 装饰器 (PEP 698)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; typing &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; override&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Parent&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;None&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Child&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;Parent&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;@override&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;None&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;语法增强
&lt;ul&gt;
&lt;li&gt;f-string 语法规范化 (PEP 701)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 支持多行表达式&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;{{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;name&apos;: &apos;Alice&apos;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;age&apos;: 30&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 支持注释&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;Value: &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;value  # 这是一个注释&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 支持任意嵌套&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;推导式内联 (PEP 709)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 性能提升的列表推导式&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;squares &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [x &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1000&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;并发与性能
&lt;ul&gt;
&lt;li&gt;每个解释器独立的 GIL (PEP 684)&lt;/li&gt;
&lt;li&gt;低影响监控 API (PEP 669)&lt;/li&gt;
&lt;li&gt;缓冲协议可访问性 (PEP 688)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; collections.abc &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Buffer&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;MyBuffer&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__buffer__&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;flags&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;) -&amp;gt; Buffer:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# 实现缓冲区协议&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;标准库更新
&lt;ul&gt;
&lt;li&gt;itertools.batched() 新增&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; itertools &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; batched&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 将元素分组为大小为3的元组&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; batch &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;batched&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;), &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(batch)  &lt;/span&gt;&lt;span&gt;# (0, 1, 2), (3, 4, 5), (6, 7, 8), (9,)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;pathlib.Path 增强&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; pathlib &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Path&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CustomPath&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;Path&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;custom_method&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 新增 walk() 方法&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; root, dirs, files &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Path&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;.&quot;&lt;/span&gt;&lt;span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;walk&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;sqlite3 模块增强&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; sqlite3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 自动提交模式&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;conn &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sqlite3.&lt;/span&gt;&lt;span&gt;connect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;:memory:&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;autocommit&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;True&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;错误信息改进&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NameError 提供更智能的建议&lt;/li&gt;
&lt;li&gt;ImportError 提供更精确的导入建议&lt;/li&gt;
&lt;li&gt;改进的语法错误提示&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;性能优化&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;推导式执行速度提升（最高2倍）&lt;/li&gt;
&lt;li&gt;re.sub() 和 re.subn() 性能提升（2-3倍）&lt;/li&gt;
&lt;li&gt;asyncio.Task 创建速度提升&lt;/li&gt;
&lt;li&gt;tokenize 模块性能提升（最高64%）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;弃用与移除&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;计划在 3.13 中移除的模块：aifc、cgi、crypt 等&lt;/li&gt;
&lt;li&gt;lib2to3 和 2to3 程序被弃用&lt;/li&gt;
&lt;li&gt;移除 asynchat 和 asyncore 模块&lt;/li&gt;
&lt;li&gt;移除 distutils 包&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;python 3.13 2024年10月7日&lt;a href=&quot;#python-313-2024年10月7日&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;交互式解释器 (REPL) 增强
&lt;ul&gt;
&lt;li&gt;基于 PyPy 代码的新 REPL&lt;/li&gt;
&lt;li&gt;多行编辑支持&lt;/li&gt;
&lt;li&gt;彩色提示符和回溯信息&lt;/li&gt;
&lt;li&gt;交互式帮助 (F1)&lt;/li&gt;
&lt;li&gt;历史记录浏览 (F2)&lt;/li&gt;
&lt;li&gt;粘贴模式 (F3)&lt;/li&gt;
&lt;li&gt;直接 REPL 命令支持&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 示例：新的 REPL 特性&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;help&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# 显示帮助信息&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;exit&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# 退出解释器&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 支持多行编辑&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hello&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Hello, World!&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&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;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 示例：改进的错误提示&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;greet&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;age&lt;/span&gt;&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 旧版本&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;greet&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;nam&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Alice&quot;&lt;/span&gt;&lt;span&gt;)  &lt;/span&gt;&lt;span&gt;# TypeError: greet() got an unexpected keyword argument &apos;nam&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 新版本&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;greet&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;nam&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Alice&quot;&lt;/span&gt;&lt;span&gt;)  &lt;/span&gt;&lt;span&gt;# TypeError: greet() got an unexpected keyword argument &apos;nam&apos;. Did you mean &apos;name&apos;?&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;实验性特性
&lt;ul&gt;
&lt;li&gt;自由线程 CPython (PEP 703)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 需要特殊构建和运行时标志&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 编译时：--enable-free-threading&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 运行时：PYTHON_GIL=0 或 -X gil=0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; threading&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;worker&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 现在可以真正并行执行&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;pass&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;threads &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; [threading.&lt;/span&gt;&lt;span&gt;Thread&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;worker) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; _ &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;)]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; t &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; threads:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;t.&lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;即时编译器 (JIT) (PEP 744)&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 需要特殊构建和运行时标志&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 编译时：--enable-experimental-jit&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 运行时：PYTHON_JIT=1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# JIT 会自动优化热点代码&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;compute&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1000000&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;result &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; i&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; result&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;语言特性
&lt;ul&gt;
&lt;li&gt;locals() 确定性突变语义 (PEP 667)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;local_vars &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;locals&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;local_vars[&lt;/span&gt;&lt;span&gt;&apos;x&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# 不会影响实际的 x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(x)  &lt;/span&gt;&lt;span&gt;# 输出: 1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 使用 f_locals 进行可靠更新&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; sys&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;frame &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sys.&lt;/span&gt;&lt;span&gt;_getframe&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;frame.f_locals[&lt;/span&gt;&lt;span&gt;&apos;x&apos;&lt;/span&gt;&lt;span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;# 会更新 x&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(x)  &lt;/span&gt;&lt;span&gt;# 输出: 2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;标准库更新
&lt;ul&gt;
&lt;li&gt;argparse 支持弃用选项&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; argparse&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;parser &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; argparse.&lt;/span&gt;&lt;span&gt;ArgumentParser&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;parser.&lt;/span&gt;&lt;span&gt;add_argument&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&apos;--old-option&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                   &lt;/span&gt;&lt;span&gt;help&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;Deprecated. Use --new-option instead.&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                   &lt;/span&gt;&lt;span&gt;deprecated&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;True&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;base64 模块增强&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; base64&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 新增 Z85 编码支持&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;data &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;&quot;Hello, World!&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;encoded &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; base64.&lt;/span&gt;&lt;span&gt;z85encode&lt;/span&gt;&lt;span&gt;(data)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;decoded &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; base64.&lt;/span&gt;&lt;span&gt;z85decode&lt;/span&gt;&lt;span&gt;(encoded)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;性能优化&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;标准库模块导入时间优化&lt;/li&gt;
&lt;li&gt;textwrap.indent() 性能提升（约30%）&lt;/li&gt;
&lt;li&gt;subprocess 模块优化&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;移除内容&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;完成 PEP 594 “死电池”移除
&lt;ul&gt;
&lt;li&gt;aifc&lt;/li&gt;
&lt;li&gt;cgi&lt;/li&gt;
&lt;li&gt;crypt&lt;/li&gt;
&lt;li&gt;nntplib&lt;/li&gt;
&lt;li&gt;telnetlib
等19个模块&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;移除 2to3 工具和 lib2to3 模块&lt;/li&gt;
&lt;li&gt;移除 tkinter.tix 模块&lt;/li&gt;
&lt;li&gt;移除 locale.resetlocale() 函数&lt;/li&gt;
&lt;li&gt;移除 typing.io 和 typing.re 命名空间&lt;/li&gt;
&lt;li&gt;移除链式 classmethod 描述符支持&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;移动平台支持&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新增 iOS 和 Android 的 Tier 3 级别支持&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>证书签发与自签名证书</title><link>https://axi.moe/posts/ivrdcc96/</link><guid isPermaLink="true">https://axi.moe/posts/ivrdcc96/</guid><pubDate>Sat, 19 Apr 2025 16:15:50 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;证书签发与自签名证书&lt;a href=&quot;#证书签发与自签名证书&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;密钥生成&lt;a href=&quot;#密钥生成&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;一般是ssh/github/WireGuard使用，生成一对公私钥&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ssh-keygen&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-t&lt;/span&gt;&lt;span&gt; [rsa/ecdsa/ed25519] -f [path] -C &lt;/span&gt;&lt;span&gt;&quot;comment&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;目前RSA不建议使用，又长还不安全，建议使用ed25519,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;证书生成&lt;a href=&quot;#证书生成&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;几个概念和文件解释&lt;a href=&quot;#几个概念和文件解释&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;文件&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;.key: 证书对应的私钥文件&lt;/li&gt;
&lt;li&gt;.crt: CA认证后的文件，即证书&lt;/li&gt;
&lt;li&gt;.csr: 证书签名请求, 用私钥签名得到的文件&lt;/li&gt;
&lt;li&gt;.crl: 证书吊销列表&lt;/li&gt;
&lt;li&gt;.pem; 导出导入证书用的格式, .crt+.key, 使用base64存储&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;根证书和用户证书: 根证书是信任链顶级, 用户证书是根证书签发的&lt;/p&gt;
&lt;p&gt;对于自签证书, 只要根证书是有效的(安装在电脑上), 则由它签发的用户证书就是可信的&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;.x509: 证书格式标准&lt;/p&gt;
&lt;p&gt;生成证书有两种, 自签名和CA签发, 只有CA签发的才有https锁标志, 但是加密功能来说两者等效&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;自签名证书&lt;a href=&quot;#自签名证书&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;下面讲解如何生成自己的证书&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;section&gt;&lt;h4&gt;根证书生成&lt;a href=&quot;#根证书生成&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;首先需要一个根证书，我们自己就是CA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;创建工作目录&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;./myca/{certs,crl,newcerts,private}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;myca&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;touch&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;index.txt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;echo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1000&lt;/span&gt;&lt;span&gt; &amp;gt; &lt;/span&gt;&lt;span&gt;serial&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;chmod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;700&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;目录应该是这样的&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 证书位置&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;crl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 吊销列表&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;index.txt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 证书目录&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newcerts&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 新证书&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 私钥&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;└──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;serial&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 自增的index&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;准备OpenSSL文件&lt;code&gt;(openssl.cnf)&lt;/code&gt;​&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ ca ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;default_ca&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CA_default&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ CA_default ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;dir&lt;/span&gt;&lt;span&gt;&lt;span&gt;               &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; /home/nolan/code/myca  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# CA 根目录&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;certs&lt;/span&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; $dir/certs&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;new_certs_dir&lt;/span&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; $dir/newcerts&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;database&lt;/span&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; $dir/index.txt&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;serial&lt;/span&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; $dir/serial&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;private_key&lt;/span&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; $dir/private/ca.key.pem&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;certificate&lt;/span&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; $dir/certs/ca.cert.pem&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;default_md&lt;/span&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sha256&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;policy&lt;/span&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; policy_loose&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;default_days&lt;/span&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 3650&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;x509_extensions&lt;/span&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; v3_ca&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ policy_loose ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# policy设置&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# optional指后面的CSR可以不写，supplied需要写&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# match是必须写且值必须和CA的相同&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;countryName&lt;/span&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; optional&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;stateOrProvinceName&lt;/span&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; optional&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;organizationName&lt;/span&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; optional&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;commonName&lt;/span&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; supplied&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ req ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;prompt&lt;/span&gt;&lt;span&gt;&lt;span&gt;             &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; no &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# 设置为No直接使用下面的默认值，否则交互式询问&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;default_bits&lt;/span&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 4096 &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# RSA有效，ED25519是没用的&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;distinguished_name&lt;/span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; req_distinguished_name&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;string_mask&lt;/span&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; utf8only&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ req_distinguished_name ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 证书主题默认值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CN &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# Country Name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ST&lt;/span&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Hubei &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# State or Province Name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;L&lt;/span&gt;&lt;span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; WuHan &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# Locality Name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;O&lt;/span&gt;&lt;span&gt;&lt;span&gt;           &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Apeiria &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# Organization Name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;CN&lt;/span&gt;&lt;span&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Apeiria &lt;/span&gt;&lt;/span&gt;&lt;span&gt;# Common Name&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ v3_ca ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;41&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# CA:TRUE=CA标识，critical=客户端验证时，不认识就直接拒绝&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;42&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;basicConstraints&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; critical, CA:TRUE&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;43&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 用途，keyCertSign/cRLSign=签发下级证书/吊销列表，critical=拒绝其他用途&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;44&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;keyUsage&lt;/span&gt;&lt;span&gt;&lt;span&gt;         &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; critical, keyCertSign, cRLSign&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;45&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# Subject Key Identifier 扩展，快速找到上级证书&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;46&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;subjectKeyIdentifier&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; hash&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;生成根CA私钥&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 签发证书&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;genrsa&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-out&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;private/ca.key.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;4096&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 用ED25519，上面默认RSA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;genpkey&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-algorithm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ed25519&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-out&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;private/ca.key.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;chmod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;400&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;private/ca.key.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;签发根 CA 证书&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;openssl.cnf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;private/ca.key.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-x509&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-days&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3650&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sha256&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-extensions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v3_ca&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-out&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certs/ca.cert.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;chmod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;444&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certs/ca.cert.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;验证&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x509&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certs/ca.cert.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-noout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-text&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;结果&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Certificate:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Data:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt; (0x2)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Serial&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Number:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;18:09:35:aa:82:e4:6a:e4:8d:d2:35:5d:f2:51:49:83:55:84:5e:e1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Signature&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Algorithm:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ED25519&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Issuer:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;C=CN,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ST=Hubei,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;L=WuHan,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;O=Apeiria,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CN=Apeiria&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Validity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;Not&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Before:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Apr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;08:41:35&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2025&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GMT&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;Not&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;After&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Apr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;08:41:35&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2035&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GMT&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Subject:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;C=CN,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ST=Hubei,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;L=WuHan,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;O=Apeiria,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CN=Apeiria&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Subject&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Info:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;Public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Algorithm:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ED25519&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;ED25519&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Public-Key:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;pub:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;e5:ac:18:8f:81:7c:d9:e4:59:8d:a3:b0:79:8d:70:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;fb:04:c2:4f:27:7b:34:3c:6b:a6:15:c0:a5:29:46:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;ab:97&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;X509v3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;extensions:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;X509v3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Basic&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Constraints:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;critical&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;CA:TRUE&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;X509v3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Usage:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;critical&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;Certificate&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Sign,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CRL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Sign&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;X509v3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Subject&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Identifier:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;DE:05:5A:55:8B:F6:63:FD:C7:0F:EC:BE:70:7C:55:9E:8A:84:92:1E&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Signature&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Algorithm:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ED25519&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Signature&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Value:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;57:ba:4b:ba:3d:ea:fa:0d:e1:cf:cc:74:e0:03:9b:f4:94:56:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;24:dc:f7:e5:d4:3e:47:21:b5:df:e4:8c:e1:c1:2f:84:46:fc:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;4a:90:60:e2:df:77:97:0f:e4:2c:c0:60:92:32:d6:69:0d:40:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;fb:14:cb:39:f9:81:7d:cd:aa:08&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;最终我们得到了&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certs&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│  &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;└──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ca.cert.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# CA证书&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;crl&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;index.txt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;newcerts&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;openssl.cnf&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;├──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;private&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;│  &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;└──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ca.key.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# CA私钥&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;└──&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;serial&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;用户证书签发&lt;a href=&quot;#用户证书签发&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;上面已经有了 CA 和私钥，下面讲解如何签发自己的证书&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;生成用户的私钥，其实和CA生成私钥是一样的，私钥并不分是否是CA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;总之需要一个私钥&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;genpkey&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-algorithm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Ed25519&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-out&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nolan.key.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;chmod&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;400&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nolan.key.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;生成CSR，也就是提交给CA的证书签名请求，通过私钥获取到证书&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;req&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nolan.key.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-out&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nolan.csr.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;这一步需要调整`openssl.cnf`​,末尾添加 user_crt 相关配置&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ usr_cert ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 普通用户证书，非 CA&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;basicConstraints&lt;/span&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; critical, CA:FALSE&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 标识这个证书用作客户端认证&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;keyUsage&lt;/span&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; critical, digitalSignature, keyEncipherment&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;extendedKeyUsage&lt;/span&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; clientAuth&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;subjectKeyIdentifier&lt;/span&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; hash&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;authorityKeyIdentifier&lt;/span&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; keyid,issuer&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;签发证书&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# -extensions usr_cert 就指定了刚刚的配置&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ca&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-config&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;openssl.cnf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-extensions&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;usr_cert&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-days&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3650&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-notext&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-md&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sha256&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nolan.csr.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-out&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certs/nolan.cert.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;验证&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x509&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certs/nolan.cert.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-noout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-text&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;结果&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Certificate:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Data:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Version:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt; (0x2)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Serial&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Number:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;4096&lt;/span&gt;&lt;span&gt; (0x1000)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Signature&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Algorithm:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ED25519&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Issuer:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;C=CN,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ST=Hubei,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;L=WuHan,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;O=Apeiria,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CN=Apeiria&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Validity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;Not&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Before:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Apr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;09:01:42&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2025&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GMT&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;Not&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;After&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Apr&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;09:01:42&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2035&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GMT&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Subject:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;C=CN,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ST=Hubei,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;O=Apeiria,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CN=Apeiria&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;Subject&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Info:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;Public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Algorithm:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ED25519&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;ED25519&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Public-Key:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;pub:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;03:cb:ee:2b:b6:62:0d:4f:86:6b:37:45:f1:c0:ad:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;c8:af:1a:0c:01:5e:6b:ab:c7:a1:ee:5a:46:87:38:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                    &lt;/span&gt;&lt;span&gt;6b:dc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;X509v3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;extensions:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;X509v3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Basic&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Constraints:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;critical&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;CA:FALSE&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;X509v3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Usage:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;critical&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;Digital&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Signature,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Encipherment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;X509v3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Extended&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Usage:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;TLS&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Web&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Client&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Authentication&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;X509v3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Subject&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Identifier:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;DD:0B:04:82:65:DA:6E:76:7A:50:39:AC:C5:E9:9B:9B:35:3F:CC:84&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;X509v3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Authority&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Identifier:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;DE:05:5A:55:8B:F6:63:FD:C7:0F:EC:BE:70:7C:55:9E:8A:84:92:1E&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Signature&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Algorithm:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ED25519&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Signature&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;Value:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;af:6b:79:2b:a4:fb:c3:84:33:9d:9a:3a:02:1a:df:c4:70:ac:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;8d:7b:42:bf:e3:b3:63:98:f7:12:db:83:89:b2:0c:3b:c8:7e:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;ad:e3:e5:25:00:e3:c7:fb:af:1b:67:70:0c:af:47:3e:39:13:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;6e:66:5e:11:c3:6b:3a:c8:95:05&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;Let’s Encrypt 申请&lt;a href=&quot;#lets-encrypt-申请&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;section&gt;&lt;h4&gt;certbot方法&lt;a href=&quot;#certbot方法&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 安装certbot ACME&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apt-get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certbot&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 验证域名所有权, 并获取证书, 不过需要确保80和443没有占用&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certbot&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certonly&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--standalone&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;​	Let’s Encrypt证书有效期一般只有90天, 需要续订&lt;/p&gt;&lt;p&gt;​	certbot一般会自动设置定时任务自动续订证书, 也可以用下面的命令测试&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;certbot&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;renew&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--dry-run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 查看续订（dry-run）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;OpenSSL常用命令&lt;a href=&quot;#openssl常用命令&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;解析 pem 证书&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x509&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-in&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cert.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-noout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-text&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;验证证书链&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;verify&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-CAfile&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ca-chain.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cert.pem&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;检查服务器证书&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s_client&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-connect&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;axi.moe:443&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;-servername&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;axi.moe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-showcerts&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;/dev/null&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;2&amp;gt;/dev/null&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;x509&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-noout&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-text&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;DEBUG 用，Serve AS TLS&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;s_server&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-key&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;key.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-cert&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cert.pem&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-accept&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;8443&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>k3s 安装笔记</title><link>https://axi.moe/posts/bkda9kql/</link><guid isPermaLink="true">https://axi.moe/posts/bkda9kql/</guid><pubDate>Thu, 17 Apr 2025 00:01:08 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;k3s 安装笔记&lt;a href=&quot;#k3s-安装笔记&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;k3s 是轻量级单节点集群，当然也可以加入多节点。&lt;/p&gt;&lt;section&gt;&lt;h2&gt;集群引导&lt;a href=&quot;#集群引导&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;单master节点&lt;a href=&quot;#单master节点&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sfL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://get.k3s.io&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 中国区加速&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sfL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://rancher-mirror.rancher.cn/k3s/k3s-install.sh&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;INSTALL_K3S_MIRROR&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;cn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;运行完就安装完成了，需要保证 6443 和 443 端口可用。&lt;/p&gt;&lt;p&gt;安装完，集群默认配置文件在&lt;code&gt;/etc/rancher/k3s/k3s.yaml&lt;/code&gt;​，如果不想sudo使用的话，可以移动配置文件：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mkdir&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-p&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/.kube&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cp&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/rancher/k3s/k3s.yaml&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/.kube/config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;chown&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;$USER&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;$USER&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;~/.kube/config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;设置环境变量&lt;code&gt;export KUBECONFIG=~/.kube/config&lt;/code&gt;​&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;加入agent节点&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;查看&lt;code&gt;/var/lib/rancher/k3s/server/node-token&lt;/code&gt;​得到token，加入&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sfL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://rancher-mirror.rancher.cn/k3s/k3s-install.sh&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;INSTALL_K3S_MIRROR&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;cn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;INSTALL_K3S_EXEC&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;agent --node-ip=10.0.0.14 --node-name=p4&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K3S_URL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;master url&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K3S_TOKEN&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;token&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 建议指定--node-ip和-node-name，多网卡下自动获取的node-ip可能不对，而node-name一般不太标准&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;多主节点&lt;a href=&quot;#多主节点&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;上面的初始化是单master节点的，因为使用的是sqlite，如果要使用多节点，需要在第一台机器上加入&lt;code&gt;--cluster-init&lt;/code&gt;​，即：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sfL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://rancher-mirror.rancher.cn/k3s/k3s-install.sh&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;INSTALL_K3S_MIRROR&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;cn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;INSTALL_K3S_EXEC&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;server --node-ip=10.0.0.21 --node-name=h1 --flannel-backend=none --disable-network-policy --disable=traefik --cluster-init&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# --flannel-backend=none --disable-network-policy --disable=traefik&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 是禁用自带的CNI和网络配置，为后面的cilium做准备&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;后面的server节点不需要，即：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sfL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://rancher-mirror.rancher.cn/k3s/k3s-install.sh&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;INSTALL_K3S_MIRROR&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;cn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;INSTALL_K3S_EXEC&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;server --node-ip=10.0.0.24 --node-name=h4 --flannel-backend=none --disable-network-policy --disable=traefik&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K3S_URL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;https://10.0.0.21:6443&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K3S_TOKEN&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;token&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 除此之外的INSTALL_K3S_EXEC参数需要和第一个节点相同，否则无法同步&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;其他agent加入与server相同，但注意不要INSTALL_K3S_EXEC参数控制网络插件&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sfL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://rancher-mirror.rancher.cn/k3s/k3s-install.sh&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;INSTALL_K3S_MIRROR&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;cn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;INSTALL_K3S_EXEC&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;agent --node-ip=10.0.0.14 --node-name=p4&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K3S_URL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;https://10.0.0.21:6443&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K3S_TOKEN&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;token&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;删除&lt;a href=&quot;#删除&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# master&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;/usr/local/bin/k3s-uninstall.sh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# agent&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;/usr/local/bin/k3s-agent-uninstall.sh&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;删除后集群数据并不会完全删除，可能残留有网络插件数据，查阅文档删除即可。&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;集群网络&lt;a href=&quot;#集群网络&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;CNI cilium&lt;a href=&quot;#cni-cilium&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;由于自带的是flannel+vxlan，性能比较差，一般希望换成cilium，&lt;a href=&quot;https://docs.cilium.io/en/stable/installation/k3s/&quot; target=&quot;_blank&quot;&gt;官方文档&lt;/a&gt;：&lt;/p&gt;&lt;p&gt;由于cilium是取代了kube-proxy的，这里面还需要处理一下，安装server的时候：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sfL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://get.k3s.io&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;INSTALL_K3S_EXEC&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&apos;--flannel-backend=none --disable-network-policy&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 如果不想使用自带的LB，再加入--disable=traefik&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;来diable network&lt;/p&gt;&lt;p&gt;然后照官方文档安装cilium就可以了&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;helm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cilium&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;./cilium&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--version&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1.17.0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;--namespace&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cilium&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;--set&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hubble.relay.enabled=&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;--set&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operator.replicas=&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;--set&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;hubble.ui.enabled=&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;/span&gt;&lt;span&gt;--create-namespace&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# operator.replicas=1建议只使用1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;另外注意的是ip段，cilium默认使用&lt;strong&gt;10.0.0.0/8&lt;/strong&gt;，如果CIDR冲突，需要更改集群IP段，用helm拉下找到CIDR即可，不然cilium修改route后会断网&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;集群存储&lt;a href=&quot;#集群存储&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;Longhorn&lt;a href=&quot;#longhorn&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;按照官网的安装教程来，使用helm，但是需要做一些初始化工作，每个节点都需要达到要求&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 基础工具nfs-common&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nfs-common&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;cryptsetup&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# dm_crypt 模块&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;lsmod&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;grep&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dm_crypt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;modprobe&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;dm_crypt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;echo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;dm_crypt&quot;&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tee&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-a&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;/etc/modules&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 加入启动列表自动加载&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 关闭multipathd&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stop&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;multipathd.socket&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;disable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;multipathd.socket&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;stop&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;multipathd.service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;systemctl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;disable&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;multipathd.service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;完毕后，安装：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;helm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;longhorn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;longhorn/longhorn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--namespace&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;longhorn-system&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--create-namespace&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--version&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1.8.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;longhorn自带一个UI来设置所有的values，所以我们不需要改&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;集群LB&lt;a href=&quot;#集群lb&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;Ingress Gateway&lt;a href=&quot;#ingress-gateway&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;安装&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;helm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;eg&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;oci://docker.io/envoyproxy/gateway-helm&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--version&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;v0.0.0-latest&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;envoy-gateway-system&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--create-namespace&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 测试&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wait&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--timeout=5m&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;envoy-gateway-system&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;deployment/envoy-gateway&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--for=condition=Available&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://github.com/envoyproxy/gateway/releases/download/latest/quickstart.yaml&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;HA Loadbalance&lt;a href=&quot;#ha-loadbalance&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;‍&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;frontend&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;k3s-frontend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;bind&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;:16443&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 这里必须是*，否则没拿到IP的backup节点启动失败&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;mode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tcp&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;option&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tcplog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;default_backend&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;k3s-backend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;backend&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;k3s-backend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;mode&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tcp&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;option&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tcp-check&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;balance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;roundrobin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;default-server&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;inter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10s&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;downinter&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;5s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;server-1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10.0.0.21:6443&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;check&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;server-2&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10.0.0.22:6443&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;check&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;server-3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;10.0.0.24:6443&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;check&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;‍&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;global_defs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;enable_script_security&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;script_user&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vrrp_script&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;chk_haproxy&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;script&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&apos;killall -0 haproxy&apos;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 测试haproxy进程是否存在&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;interval&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;vrrp_instance&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;haproxy-vip&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;eth1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 修改通信网卡&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;state&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;STATE&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# MASTER, BACKUP, BACKUP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;priority&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;PRIORITY&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 200, 150, 100&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;virtual_router_id&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;51&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;virtual_ipaddress&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;10.0.0.99/24&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;track_script&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;chk_haproxy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;其他&lt;a href=&quot;#其他&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;集群调试&lt;a href=&quot;#集群调试&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;实践中关键数据库一般不会暴露到集群外，如 mysql，假设上面我们只有一个 mysql-ci-service 可用，怎么连上mysql 进行调试呢？&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;port-forward：使用 kubectl 端口转发：可以转发到 pod 和服务，只转发端口&lt;/li&gt;
&lt;li&gt;proxy：通过 k8s api 访问集群服务，但只能访问 http 服务&lt;/li&gt;
&lt;li&gt;使用 telepresence：推荐&lt;/li&gt;
&lt;/ol&gt;&lt;section&gt;&lt;h4&gt;port-forward&lt;a href=&quot;#port-forward&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;我们已知上面的service 名称为 mysql-ci-service，端口为 30002，则可以输入：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;port-forward&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;service/mysql-ci-service&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3306:30002&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;就把本地端口转发到 service 的 30002，service 再转发到 pod 3306&lt;/p&gt;&lt;p&gt;如果要转发 pod（比如说可能想绕过 service 的负载均衡到达指定 pod），则需要得到 pod 名称，然后输入：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;port-forward&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pod/mysql-6d57fdf866-f492r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3306:3306&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;proxy&lt;a href=&quot;#proxy&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;输入 kubectl proxy 即可使用&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;telepresence&lt;a href=&quot;#telepresence&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;telepresence 可以直接拦截本地流量发送到 k8s 上，看起来就好像身处集群中。&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.telepresence.io/docs/latest/quick-start/&quot; target=&quot;_blank&quot;&gt;telepresence&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;telepresence&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;connect&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;如果想要拦截云上服务的流量，telepresence 也能做到，详细参考文档。&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;其他问题&lt;a href=&quot;#其他问题&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;本地私有仓库配置&lt;a href=&quot;#本地私有仓库配置&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;k3s不是在containerd的配置文件中配置本地仓库，而是配置k3s，自动生成containerd的配置文件，假设10.0.0.21:5000上有一个镜像站：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;/etc/rancher/k3s/registries.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo mkdir -p /etc/rancher/k3s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 添加&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;mirrors&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&quot;10.0.0.21:5000&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;endpoint&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;&quot;http://10.0.0.21:5000&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;然后重启k3s服务&lt;/p&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;命名空间无法删除的问题&lt;a href=&quot;#命名空间无法删除的问题&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;查看命名空间存在的资源：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;api-resources&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--verbs=list&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--namespaced&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-o&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;xargs&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;name-of-namespace&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;然后删除对应的资源&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>k3s 本地存储</title><link>https://axi.moe/posts/bhg4lg3q/</link><guid isPermaLink="true">https://axi.moe/posts/bhg4lg3q/</guid><pubDate>Thu, 17 Apr 2025 00:01:08 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;k3s 本地存储&lt;a href=&quot;#k3s-本地存储&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;k3s 是轻量级单节点集群，当然也可以加入多节点。&lt;/p&gt;&lt;section&gt;&lt;h2&gt;安装&lt;a href=&quot;#安装&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sfL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://get.k3s.io&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 中国区加速&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-sfL&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;https://rancher-mirror.rancher.cn/k3s/k3s-install.sh&lt;/span&gt;&lt;span&gt; | &lt;/span&gt;&lt;span&gt;INSTALL_K3S_MIRROR&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;cn&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sh&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;运行完就安装完成了，需要保证 6443 和 443 端口可用。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;卷和存储&lt;a href=&quot;#卷和存储&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;本地存储&lt;a href=&quot;#本地存储&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;添加一个 pvc.yaml&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apiVersion&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;PersistentVolumeClaim&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql-pvc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# pvc的名字，可自定义&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;namespace&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;accessModes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;ReadWriteOnce&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 只能被单节点读写&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;storageClassName&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;local-path&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# k3s 内置的存储类，如果用 k8s 要自己添加 sc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;resources&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;requests&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;storage&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;2Gi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;再添加一个使用 pvc 的 deployment：mysql.yaml&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apiVersion&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;apps/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Deployment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;matchLabels&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 选择 app: mysql 标签的 pod&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;# 创建 pod 的模板&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;labels&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 创建 pod 时添加 app: mysql 标签，以便 Deployment 可以识别&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;containers&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;env&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;123456&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;ports&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;containerPort&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3306&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;volumeMounts&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql-volume&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 和下面的 volumeMounts 一致才能 bind&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;              &lt;/span&gt;&lt;span&gt;mountPath&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/var/lib/mysql&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# mysql的 data 所在位置&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;volumes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql-volume&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 和上面的 volumeMounts 一致才能bind&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;          &lt;/span&gt;&lt;span&gt;persistentVolumeClaim&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;claimName&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql-pvc&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 和刚刚的pvc保持一致&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;分别使用 kubectl apply 添加，pvc 没有 bind 的时候是 pending 状态，成功之后变成 bound&lt;/p&gt;&lt;p&gt;注意 mysql.yaml 的模板中 version 是 apps/v1，这是资源路径。&lt;/p&gt;&lt;p&gt;如果一直显示 pending 可以使用 kubectl describe pods &amp;lt;container_name&amp;gt; 查看原因，container_name需要 get pods 查看&lt;/p&gt;&lt;p&gt;例如这里一开始搞错了 pvc 名字，修正后 describe 得到成功。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image-20240704151857876&quot; loading=&quot;lazy&quot; width=&quot;3478&quot; height=&quot;636&quot; src=&quot;/_astro/image-20240704151857876.Dn0au27T_ZJSkFr.webp&quot; srcset=&quot;/_astro/image-20240704151857876.Dn0au27T_Z1GFTT3.webp 640w, /_astro/image-20240704151857876.Dn0au27T_1CX8cf.webp 750w, /_astro/image-20240704151857876.Dn0au27T_Z1qDTN9.webp 828w, /_astro/image-20240704151857876.Dn0au27T_Z11EYas.webp 1080w, /_astro/image-20240704151857876.Dn0au27T_1vAcdF.webp 1280w, /_astro/image-20240704151857876.Dn0au27T_Z1wQCfv.webp 1668w, /_astro/image-20240704151857876.Dn0au27T_ZipzGb.webp 2048w, /_astro/image-20240704151857876.Dn0au27T_Z1fFD7u.webp 2560w, /_astro/image-20240704151857876.Dn0au27T_ZJSkFr.webp 3478w&quot; /&gt;&lt;figcaption&gt;image-20240704151857876&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;但此时还不能访问 mysql，因为它目前只在集群内部使用&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;集群服务&lt;a href=&quot;#集群服务&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;集群内的 pod 需要变成 service 才能使用，有三种类型：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;ClusterIP Service：仅限集群内&lt;/li&gt;
&lt;li&gt;NodePort Service：集群外&lt;/li&gt;
&lt;li&gt;LoadBalancer Service：集群外+负载均衡&lt;/li&gt;
&lt;/ul&gt;&lt;section&gt;&lt;h3&gt;NodePort&lt;a href=&quot;#nodeport&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;NodePort 实际上并不推荐使用，推荐 LoadBalancer&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apiVersion&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql-service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ports&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;protocol&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;TCP&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# TCP|UDP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3306&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 客户端访问服务的端口&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;targetPort&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3306&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 容器端口(mysql)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;nodePort&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;30000&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 在每个节点都开放30000，并转发到3306，省略则不分配&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;NodePort&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# ClusterIP|NodePort|LoadBalancer&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;注意 nodePort 要求30000-32767（可设置）&lt;/p&gt;&lt;p&gt;外部访问服务的路线为：外部—&amp;gt;30000—&amp;gt;3306(service)—&amp;gt;3306(pod)&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;LoadBalancer&lt;a href=&quot;#loadbalancer&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一般推荐使用 loadbalancer：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apiVersion&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql-lb-service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ports&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;protocol&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;TCP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;30001&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;targetPort&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3306&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;LoadBalancer&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这时可以直接使用[集群外部IP:端口（30001）]访问。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;ClusterIP&lt;a href=&quot;#clusterip&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;仅限集群内访问的 ClusterIP：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apiVersion&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;metadata&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql-ci-service&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;spec&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;selector&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;ports&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;protocol&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;TCP&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# TCP|UDP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;port&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;30002&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;targetPort&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3306&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;ClusterIP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;运行后得到：&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image-20240704161628962&quot; loading=&quot;lazy&quot; width=&quot;2076&quot; height=&quot;314&quot; src=&quot;/_astro/image-20240704161628962.CaPIQT0q_6xwEF.webp&quot; srcset=&quot;/_astro/image-20240704161628962.CaPIQT0q_Z1m8kcs.webp 640w, /_astro/image-20240704161628962.CaPIQT0q_1BIGHT.webp 750w, /_astro/image-20240704161628962.CaPIQT0q_ZXPtcW.webp 828w, /_astro/image-20240704161628962.CaPIQT0q_ZYH9Fp.webp 1080w, /_astro/image-20240704161628962.CaPIQT0q_fkuop.webp 1280w, /_astro/image-20240704161628962.CaPIQT0q_ZqQdS2.webp 1668w, /_astro/image-20240704161628962.CaPIQT0q_zGE0o.webp 2048w, /_astro/image-20240704161628962.CaPIQT0q_6xwEF.webp 2076w&quot; /&gt;&lt;figcaption&gt;image-20240704161628962&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;一般来说会得到一个 CLUSTER-IP，这个 IP 不会变（自动路由到对应 pod），除非重启服务。&lt;/p&gt;&lt;p&gt;但推荐使用 Service Name 访问（这里是 mysql-ci-service）。这样 IP 变了也无所谓，此外 ClusterIP 还可以指定 IP。&lt;/p&gt;&lt;p&gt;深入：&lt;a href=&quot;https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/&quot; target=&quot;_blank&quot;&gt;k8s 服务&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;本地调试&lt;a href=&quot;#本地调试&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;实践中关键数据库一般不会暴露到集群外，如 mysql，假设上面我们只有一个 mysql-ci-service 可用，怎么连上mysql 进行调试呢？&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;port-forward：使用 kubectl 端口转发：可以转发到 pod 和服务，只转发端口&lt;/li&gt;
&lt;li&gt;proxy：通过 k8s api 访问集群服务，但只能访问 http 服务&lt;/li&gt;
&lt;li&gt;使用 telepresence：推荐&lt;/li&gt;
&lt;/ol&gt;&lt;section&gt;&lt;h3&gt;port-forward&lt;a href=&quot;#port-forward&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;我们已知上面的service 名称为 mysql-ci-service，端口为 30002，则可以输入：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;port-forward&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;service/mysql-ci-service&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3306:30002&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;就把本地端口转发到 service 的 30002，service 再转发到 pod 3306&lt;/p&gt;&lt;p&gt;如果要转发 pod（比如说可能想绕过 service 的负载均衡到达指定 pod），则需要得到 pod 名称，然后输入：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;kubectl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;port-forward&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;pod/mysql-6d57fdf866-f492r&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;3306:3306&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;proxy&lt;a href=&quot;#proxy&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;输入 kubectl proxy 即可使用&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;telepresence&lt;a href=&quot;#telepresence&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;telepresence 可以直接拦截本地流量发送到 k8s 上，看起来就好像身处集群中。&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.telepresence.io/docs/latest/quick-start/&quot; target=&quot;_blank&quot;&gt;telepresence&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;telepresence&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;connect&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;如果想要拦截云上服务的流量，telepresence 也能做到，详细参考文档。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>cuda 编程学习：Grid-Block-Thread</title><link>https://axi.moe/posts/fsy0ovjt/</link><guid isPermaLink="true">https://axi.moe/posts/fsy0ovjt/</guid><pubDate>Sat, 05 Apr 2025 18:50:43 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;cuda 编程学习：Grid-Block-Thread&lt;a href=&quot;#cuda-编程学习grid-block-thread&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;cuda的软件层级&lt;a href=&quot;#cuda的软件层级&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image&quot; loading=&quot;lazy&quot; width=&quot;378&quot; height=&quot;438&quot; src=&quot;/_astro/image-20250405170755-asqd42r.Crc5m9zh_Z1oyJwL.webp&quot; srcset=&quot;/_astro/image-20250405170755-asqd42r.Crc5m9zh_Z1oyJwL.webp 378w&quot; /&gt;&lt;figcaption&gt;image&lt;/figcaption&gt;&lt;/figure&gt;​&lt;p&gt;&lt;/p&gt;&lt;p&gt;cuda的软件逻辑上包含Grid-Block-Thread三级结构，kernel可以理解为一次函数调用，生成一个Grid。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;矩阵乘kernel为例编写cuda代码&lt;a href=&quot;#矩阵乘kernel为例编写cuda代码&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;调用kernel时，实际上传入了&lt;code&gt;kernel_name&amp;lt;&amp;lt;&amp;lt;grid,block&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;​参数。如上图，&lt;code&gt;grid&lt;/code&gt;​参数控制了一个Grid有多少个Block，&lt;code&gt;block&lt;/code&gt;​参数控制了一个Block里需要多少Thread，这两个参数都是三维向量，如下方矩阵乘的kernel定义：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 定义线程组织结构&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 每个 block 包含 BLOCK_SIZE x BLOCK_SIZE 个线程&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;dim3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;THREAD_SIZE_X&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;THREAD_SIZE_Y&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;THREAD_SIZE_Z&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// grid 的维度，根据输出矩阵 C 的尺寸（M x N）确定&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;dim3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;grid&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;grid_size_x&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;grid_size_y&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;grid_size_z&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 启动 kernel&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;matrixMulKernel&lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt;grid, block&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt;(A, B, C, M, N, K);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;dim block也可以写成，Z方向默认为1&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;dim3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;THREAD_SIZE_X&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;THREAD_SIZE_Y&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;定义好维度之后，在kernel函数里面就可以通过变量拿到执行thread的信息：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; grid_x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;gridDim&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt; // grid 在x方向的线程块数量&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; block_y &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blockIdx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; block_y_dim &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blockDim&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span&gt; // block在y方向的线程数量&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; thread_x &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;threadIdx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;如果我们要计算一个矩阵乘，可以这么写，注意B是转置后的矩阵，具有局部性，和数学上的不一样，这是一般矩阵乘编写时的习惯&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;__global__ &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;matrixMulKernel&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; __restrict__ A, &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; __restrict__ B, &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; __restrict__ C, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; m, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; n, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; k) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// A[M][K]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// B[N][K]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// C[M][N]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blockIdx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blockDim&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;threadIdx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; j &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blockIdx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blockDim&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;threadIdx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 每个thread执行一行和一列的计算&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; m &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; j &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; n) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; sum &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;0.0&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; l &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; l &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; k; l&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sum &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;[i &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; k &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; l] &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;[j &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; k &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; l];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;[i &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; j] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sum;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;section&gt;&lt;h3&gt;调用kernel前后的操作&lt;a href=&quot;#调用kernel前后的操作&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;调用kernel之前需要做一些准备工作：申请内存，内存拷贝，定义grid和block大小&lt;/p&gt;&lt;p&gt;调用kernel后需要&lt;code&gt;cudaDeviceSynchronize();&lt;/code&gt;​等待结果，这是因为kernel的调用是异步提交的任务，完成后拷贝内存和释放device内存。&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sgemm_cuda&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;k&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 在设备端分配内存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;d_A, &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;d_B, &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;d_C;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMalloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;d_A, M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; K &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMalloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;d_B, K &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMalloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;d_C, M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 将数据从主机拷贝到设备&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMemcpy&lt;/span&gt;&lt;span&gt;(d_A, A, M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; K &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;), cudaMemcpyHostToDevice);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMemcpy&lt;/span&gt;&lt;span&gt;(d_B, B, K &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;), cudaMemcpyHostToDevice);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 定义线程组织结构&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 每个 block 包含 BLOCK_SIZE x BLOCK_SIZE 个线程&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dim3 &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;(THREAD_SIZE, THREAD_SIZE);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// grid 的维度，根据输出矩阵 C 的尺寸（M x N）确定&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dim3 &lt;/span&gt;&lt;span&gt;grid&lt;/span&gt;&lt;span&gt;((N &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, (M &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 启动 kernel，传入矩阵维度 m, n, k&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;matrixMulKernel&lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt;grid, block&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt;(d_A, d_B, d_C, M, N, K);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 等待 kernel 执行完成&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaDeviceSynchronize&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 将结果从设备拷贝回主机&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMemcpy&lt;/span&gt;&lt;span&gt;(C, d_C, M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;), cudaMemcpyDeviceToHost);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 释放设备和主机内存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaFree&lt;/span&gt;&lt;span&gt;(d_A);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaFree&lt;/span&gt;&lt;span&gt;(d_B);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaFree&lt;/span&gt;&lt;span&gt;(d_C);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;‍&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;cuda实际上的调度&lt;a href=&quot;#cuda实际上的调度&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;软件层级是编写kernel代码才会出现的，实际上GPU在计算时只有SM存在，可以理解为CPU的一个core，一个SM可以执行成百上千thread的执行。&lt;/p&gt;&lt;p&gt;GPU在调度kernel的时候，会保证一个Block内的thread被分配到同一个SM（SIMT）。&lt;/p&gt;&lt;p&gt;NVIDIA在调度时，32个thread是一个wrap，wrap才是SM调度和运行的基本单元，一次并行执行相同的指令，一个wrap占用一个SM运行，可以理解为CPU的一个线程。&lt;/p&gt;&lt;p&gt;这样一来，一个block内的thread如果很多，就会有多个wrap，假如是512，则有512/32=16个wrap，这16个wrap的运行是轮流进入SM的，由SM的硬件（wrap schedule）负责调度。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;完整代码&lt;a href=&quot;#完整代码&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;cuda_runtime.h&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#include&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;time.h&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;span&gt;           // 矩阵 A 的行数，矩阵 C 的行数&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;512&lt;/span&gt;&lt;span&gt;           // 矩阵 B 的列数，矩阵 C 的列数&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;K&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;512&lt;/span&gt;&lt;span&gt;           // 矩阵 A 的列数，同时也是矩阵 B 的行数&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;BLOCK_SIZE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#define&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;THREAD_SIZE&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int64_t&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get_current_time_ns&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;timespec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ts&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;clock_gettime&lt;/span&gt;&lt;span&gt;(CLOCK_MONOTONIC, &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;ts);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ts&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;tv_sec&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1000000000&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ts&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;tv_nsec&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;__global__ &lt;/span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;matrixMulKernel&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; __restrict__ A, &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; __restrict__ B, &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; __restrict__ C, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; m, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; n, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; k) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blockIdx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blockDim&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;threadIdx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; j &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blockIdx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;blockDim&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;threadIdx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 每个thread执行一行和一列的计算&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; m &lt;/span&gt;&lt;span&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; j &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; n) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; sum &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;0.0&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; l &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; l &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; k; l&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sum &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;[i &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; k &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; l] &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;[j &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; k &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; l];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;[i &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; j] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sum;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sgemm_cpu&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__restrict__&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__restrict__&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;__restrict__&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;k&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; m; i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; j &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; j &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; n; j&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; sum &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;0.0&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; l &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; l &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; k; l&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sum &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;[i &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; k &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; l] &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;[j &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; k &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; l];&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;[i &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; n &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; j] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sum;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;41&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;42&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;43&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;44&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sgemm_cuda&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;k&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;45&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 在设备端分配内存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;46&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;d_A, &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;d_B, &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;d_C;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;47&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMalloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;d_A, M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; K &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;48&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMalloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;d_B, K &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;49&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMalloc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;span&gt;d_C, M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;50&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;51&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 将数据从主机拷贝到设备&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;52&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMemcpy&lt;/span&gt;&lt;span&gt;(d_A, A, M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; K &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;), cudaMemcpyHostToDevice);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;53&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMemcpy&lt;/span&gt;&lt;span&gt;(d_B, B, K &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;), cudaMemcpyHostToDevice);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;54&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;55&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 定义线程组织结构&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;56&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 每个 block 包含 BLOCK_SIZE x BLOCK_SIZE 个线程&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;57&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dim3 &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;(THREAD_SIZE, THREAD_SIZE);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;58&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// grid 的维度，根据输出矩阵 C 的尺寸（M x N）确定&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;59&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;dim3 &lt;/span&gt;&lt;span&gt;grid&lt;/span&gt;&lt;span&gt;((N &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;, (M &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;block&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;60&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;61&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 启动 kernel，传入矩阵维度 m, n, k&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;62&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;matrixMulKernel&lt;/span&gt;&lt;span&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span&gt;grid, block&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt;(d_A, d_B, d_C, M, N, K);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;63&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;64&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 等待 kernel 执行完成&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;65&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaDeviceSynchronize&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;66&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;67&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 将结果从设备拷贝回主机&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;68&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaMemcpy&lt;/span&gt;&lt;span&gt;(C, d_C, M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;), cudaMemcpyDeviceToHost);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;69&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;70&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 释放设备和主机内存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;71&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaFree&lt;/span&gt;&lt;span&gt;(d_A);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;72&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaFree&lt;/span&gt;&lt;span&gt;(d_B);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;73&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;cudaFree&lt;/span&gt;&lt;span&gt;(d_C);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;74&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;75&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;76&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;77&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// C = A * B, 注意B的存储模式并非常规的行优先，而是列优先（转置），这是为了局部性&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;78&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// A[M][K], B[N][K], C[M][N]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;79&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;A &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;float*&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;malloc&lt;/span&gt;&lt;span&gt;(M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; K &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;80&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;B &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;float*&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;malloc&lt;/span&gt;&lt;span&gt;(K &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;81&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;C &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;float*&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;malloc&lt;/span&gt;&lt;span&gt;(M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sizeof&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;82&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;83&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;// 初始化矩阵 A 和 B&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;84&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; K; i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;85&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;A&lt;/span&gt;&lt;span&gt;[i] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;rand&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; RAND_MAX;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;86&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;87&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; K &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N; i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;88&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;B&lt;/span&gt;&lt;span&gt;[i] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;rand&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; RAND_MAX;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;89&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;90&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;; i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; M &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; N; i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;91&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;[i] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;0.0&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;92&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;93&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;94&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int64_t&lt;/span&gt;&lt;span&gt; start_time &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get_current_time_ns&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;95&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;sgemm_cpu&lt;/span&gt;&lt;span&gt;(A, B, C, M, N, K);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;96&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;int64_t&lt;/span&gt;&lt;span&gt; end_time &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get_current_time_ns&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;97&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;printf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;sgemm_cpu time: &lt;/span&gt;&lt;span&gt;%ld&lt;/span&gt;&lt;span&gt; ns = &lt;/span&gt;&lt;span&gt;%f&lt;/span&gt;&lt;span&gt; ms&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, end_time &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; start_time, (end_time &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; start_time) &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1000000.0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;98&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;99&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;start_time &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get_current_time_ns&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;100&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;sgemm_cuda&lt;/span&gt;&lt;span&gt;(A, B, C, M, N, K);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;101&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;end_time &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;get_current_time_ns&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;102&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;printf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;sgemm_cuda time: &lt;/span&gt;&lt;span&gt;%ld&lt;/span&gt;&lt;span&gt; ns = &lt;/span&gt;&lt;span&gt;%f&lt;/span&gt;&lt;span&gt; ms&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, end_time &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; start_time, (end_time &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; start_time) &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1000000.0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;103&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>Minitorch-1</title><link>https://axi.moe/posts/87mb4ddd/</link><guid isPermaLink="true">https://axi.moe/posts/87mb4ddd/</guid><pubDate>Fri, 04 Apr 2025 16:15:50 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Minitorch-1 Fundamentals 基础&lt;a href=&quot;#minitorch-1-fundamentals-基础&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;Task 0.1 Operators&lt;a href=&quot;#task-01-operators&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;第一关是完成一些简单的函数。需要注意下 relu 的定义。&lt;/p&gt;&lt;p&gt;此外还有 xx_back 系列函数，指的是反向传播的求导：​，一开始没看懂什么意思。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Task 0.2 Testing and Debuging&lt;a href=&quot;#task-02-testing-and-debuging&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;第二关要完成 tests/test_operators.py 下面的测试函数&lt;/p&gt;&lt;p&gt;在做 test_sigmod 的时候遇到精度问题：测试函数递增性的时候怎么都过不了，想出直接排除掉相近的结果，不知道是否可行？&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&lt;span&gt; math.&lt;/span&gt;&lt;span&gt;fabs&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;sigmoid&lt;/span&gt;&lt;span&gt;(a) &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sigmoid&lt;/span&gt;&lt;span&gt;(b)) &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;1e-6&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;assert&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sigmoid&lt;/span&gt;&lt;span&gt;(a) &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sigmoid&lt;/span&gt;&lt;span&gt;(b) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&lt;span&gt; a &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; b &lt;/span&gt;&lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sigmoid&lt;/span&gt;&lt;span&gt;(a) &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sigmoid&lt;/span&gt;&lt;span&gt;(b)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Task 0.3 Functional Python 函数式编程&lt;a href=&quot;#task-03-functional-python-函数式编程&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;第三关涉及到 python 的高级特性，因为之前没有用过 python 的高阶用法，有点难度。&lt;/p&gt;&lt;p&gt;map 将第一个函数 &lt;strong&gt;作用于&lt;/strong&gt; 后面的 list，并且每次调用是传递 list 的一个值并修改&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;square&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;**&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;res &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(square, [&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;])&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;(res))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# [1, 4, 9, 16, 25]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Callable 类型提示：可以理解为限定了参数和返回值的函数&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; typing &lt;/span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; Callable&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 使用Callable类型提示&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operate_on_two_integers&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;op&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Callable[[&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;op&lt;/span&gt;&lt;span&gt;(a, b)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 符合上面的 op 的一个实例&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; y&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;operate_on_two_integers&lt;/span&gt;&lt;span&gt;(add, &lt;/span&gt;&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(result)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Iterable 类型：可以迭代的类型：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;print_elements&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;elements&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Iterable&lt;/span&gt;&lt;span&gt;) -&amp;gt; &lt;/span&gt;&lt;span&gt;None&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; element &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; elements:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(element)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;最后是装饰器，把一个处理值的函数变成处理 list-&amp;gt;list 的函数：&lt;/p&gt;&lt;p&gt;先看返回值，根据返回值写出改返回的函数（如 process），然后再考虑怎么写这个函数内容。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;fn&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Callable[[&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;], &lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;) -&amp;gt; Callable[[Iterable[&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;]], Iterable[&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;]]:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;def&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ls&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Iterable[&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;) -&amp;gt; Iterable[&lt;/span&gt;&lt;span&gt;float&lt;/span&gt;&lt;span&gt;]:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; [&lt;/span&gt;&lt;span&gt;fn&lt;/span&gt;&lt;span&gt;(x) &lt;/span&gt;&lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; x &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; ls]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; process&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;一旦学会了这种装饰器写法后面的就简单了&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Task 0.4 Modules&lt;a href=&quot;#task-04-modules&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;第四关是完成一棵树，读一下 class module 和 class parameter 就知道在干嘛了。&lt;/p&gt;&lt;p&gt;主要都是用到递归的写法，不过要稍微注意一下 named_parameters，它有独特的命名规则，写的不是很清楚，需要去 test_module.py 看它需要的命名规则是什么。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;Task 0.5 Visualization 可视化&lt;a href=&quot;#task-05-visualization-可视化&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;第五关可以运行一个交互式应用：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;streamlit&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;app.py&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;不过会报&lt;code&gt;ModuleNotFoundError: No module named &apos;altair.vegalite.v4&apos;&lt;/code&gt;错误，是因为最新版是 v5，没有安装 v4 版本，需要 &lt;code&gt;pip install --upgrade altair==4&lt;/code&gt;&lt;/p&gt;&lt;p&gt;成功运行之后发现导入失败：&lt;code&gt;ModuleNotFoundError: No module named &apos;minitorch&apos;&lt;/code&gt;&lt;/p&gt;&lt;p&gt;应该是包未安装，研究发现应该运行：&lt;code&gt;python -m pip install -Ue .&lt;/code&gt;这个是更新minitorch 包的命令，从而让 streamlit 可以导入这个包，一开始没有运行：&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image-20240711114137559&quot; loading=&quot;lazy&quot; width=&quot;2680&quot; height=&quot;280&quot; src=&quot;/_astro/image-20240711114137559.B3jk66xf_ZIUmUo.webp&quot; srcset=&quot;/_astro/image-20240711114137559.B3jk66xf_1Rs7QI.webp 640w, /_astro/image-20240711114137559.B3jk66xf_ZMAJlp.webp 750w, /_astro/image-20240711114137559.B3jk66xf_15le0e.webp 828w, /_astro/image-20240711114137559.B3jk66xf_ZWyd74.webp 1080w, /_astro/image-20240711114137559.B3jk66xf_VLImt.webp 1280w, /_astro/image-20240711114137559.B3jk66xf_2rn0X6.webp 1668w, /_astro/image-20240711114137559.B3jk66xf_1WOcRj.webp 2048w, /_astro/image-20240711114137559.B3jk66xf_2grQ7e.webp 2560w, /_astro/image-20240711114137559.B3jk66xf_ZIUmUo.webp 2680w&quot; /&gt;&lt;figcaption&gt;image-20240711114137559&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;最后成功：&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;figure&gt;&lt;img alt=&quot;image-20240711115647859&quot; loading=&quot;lazy&quot; width=&quot;3208&quot; height=&quot;1806&quot; src=&quot;/_astro/image-20240711115647859.Bjz2ZRCP_1eR8OR.webp&quot; srcset=&quot;/_astro/image-20240711115647859.Bjz2ZRCP_7oa2V.webp 640w, /_astro/image-20240711115647859.Bjz2ZRCP_RxVEy.webp 750w, /_astro/image-20240711115647859.Bjz2ZRCP_Z1nqmRy.webp 828w, /_astro/image-20240711115647859.Bjz2ZRCP_Z2s30cz.webp 1080w, /_astro/image-20240711115647859.Bjz2ZRCP_Zk7JBJ.webp 1280w, /_astro/image-20240711115647859.Bjz2ZRCP_Z4A8cn.webp 1668w, /_astro/image-20240711115647859.Bjz2ZRCP_Z1M21CH.webp 2048w, /_astro/image-20240711115647859.Bjz2ZRCP_2cp9hP.webp 2560w, /_astro/image-20240711115647859.Bjz2ZRCP_1eR8OR.webp 3208w&quot; /&gt;&lt;figcaption&gt;image-20240711115647859&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;试了一下 Torch Example的几个简单任务，Module 0还没有 train 的选项，因为我们还没做到，不过这是最初的一步！&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>nginx</title><link>https://axi.moe/posts/zlaqhno1/</link><guid isPermaLink="true">https://axi.moe/posts/zlaqhno1/</guid><pubDate>Fri, 04 Apr 2025 16:15:50 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;nginx&lt;a href=&quot;#nginx&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;section&gt;&lt;h2&gt;安装Nginx&lt;a href=&quot;#安装nginx&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;docker安装&lt;a href=&quot;#docker安装&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-d&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--restart=always&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;--net &lt;/span&gt;&lt;span&gt;host&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;--name &lt;/span&gt;&lt;span&gt;nginx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-v &lt;/span&gt;&lt;span&gt;./nginx.conf:/etc/nginx/nginx.conf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-v &lt;/span&gt;&lt;span&gt;./log:/var/log/nginx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\ &lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;./cert:/etc/nginx/cert&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\ &lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SSL证书文件,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;没有可以去掉&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-v&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;./html:/usr/share/nginx/html&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;nginx:1.24.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;​	net=host是因为懒得配端口了, 这样好一些&lt;/p&gt;&lt;p&gt;​	shell启动不够优雅, 建议使用docker compose&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&apos;3.8&apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;services&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;nginx&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;image&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;nginx:1.24.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;container_name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;nginx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;restart&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;always&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;network_mode&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;host&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;volumes&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;./nginx.conf:/etc/nginx/nginx.conf:ro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;./logs:/var/log/nginx:rw&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;./cert:/etc/nginx/cert:ro&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span&gt;- &lt;/span&gt;&lt;span&gt;./html:/usr/share/nginx/html:ro&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 一些html或者error.json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;​	注意:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;network_mode是linux专用, docker desktop没用&lt;/li&gt;
&lt;li&gt;host网络模式不是最佳实践, 如果有确定的后端编排还是一起编排比较合适&lt;/li&gt;
&lt;/ol&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;apt下载安装启动(不建议)&lt;a href=&quot;#apt下载安装启动不建议&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;​	&lt;strong&gt;为了不找不自在, 还是用docker部署吧!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;​	不建议使用apt安装, 因为会缺少很多模块, 而且版本较老&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apt&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nginx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nginx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;start&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 启动nginx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;​	然后打开80端口查看情况, 如果出现nginx主页说明成功&lt;/p&gt;&lt;section&gt;&lt;h4&gt;从源码编译安装并配置SSL模块&lt;a href=&quot;#从源码编译安装并配置ssl模块&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;参考: &lt;a href=&quot;https://developer.aliyun.com/article/766958&quot; target=&quot;_blank&quot;&gt;https://developer.aliyun.com/article/766958&lt;/a&gt;&lt;/p&gt;&lt;p&gt;​	先安装好nginx&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;去官网下载源码: &lt;a href=&quot;https://nginx.org/en/download.html&quot; target=&quot;_blank&quot;&gt;https://nginx.org/en/download.html&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;建议下载Stable version&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;解压安装包&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;tar&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-zxvf&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;包的名字&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;安装SSL模块&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;到nginx目录下, 输入&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;./configure&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--prefix=/etc/nginx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;--with-http_ssl_module&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;/ect/nginx是你的nginx安装位置, 也可以是/usr/local/nginx&lt;/p&gt;&lt;p&gt;如果用apt安装的话, 为/etc/nginx&lt;/p&gt;&lt;p&gt;如果出现 the HTTP rewrite module requires the PCRE library, 则安装:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;apt-get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;libpcre3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;libpcre3-dev&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;​	上面的命令是配置ssl模块&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;用make命令编译, 注意不要使用make install, 会重新安装nginx, 当然, 想重新安装也可以输入&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;make&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这里面可能会出现errors, 不用管&lt;/p&gt;&lt;p&gt;如果出现了缺少包依赖的错误, 直接安装即可, 这里提供一些可能出现的:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apt-get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;libpcre3&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;libpcre3-dev&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 缺少pcre&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apt-get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;openssl&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;libssl-dev&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 缺少openssl&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;apt-get&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;install&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;zlib1g-dev&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;# 缺少zlib&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;将obj的文件复制到nginx上覆盖原来的文件&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;查看是否安装成功&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;nginx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-V&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;如果出现**—with-http_ssl_module**则成功&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;nginx文件树&lt;a href=&quot;#nginx文件树&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;nginx配置文件在/etc/nginx中&lt;/p&gt;&lt;p&gt;nginx启动时加载nginx.conf&lt;/p&gt;&lt;p&gt;其中有两行:&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;include &lt;/span&gt;&lt;span&gt;/etc/nginx/conf.d/*.conf;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;include &lt;/span&gt;&lt;span&gt;/etc/nginx/sites-enabled/*;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;意思是引用了这两个目录下的所有文件&lt;/p&gt;&lt;p&gt;其中, sites-enabled 是 sites-available的链接, 把想启动的配置放在这里即可, 同理当想临时关闭某个站点时, 把sites-enabled对应的链接删去即可&lt;/p&gt;&lt;p&gt;当然,也可以在conf.d中放配置文件, 不过&lt;strong&gt;不建议&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;注意:&lt;/strong&gt;
由于 sites-enabled 有默认的nginx界面,所有访问均会导向默认界面
所以要使我们的配置生效, 需要把sites-enabled的链接删去&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;nginx架构&lt;a href=&quot;#nginx架构&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://juejin.cn/post/7306041273822527514&quot; target=&quot;_blank&quot;&gt;nginx 一把梭！（超详细讲解+实操）&lt;/a&gt;&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;配置模板开箱即用&lt;a href=&quot;#配置模板开箱即用&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;​	注意, 需要使用上面的docker-compose.yaml启动, 目录下放这个配置文件(nginx.conf)&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;user &lt;/span&gt;&lt;span&gt;nginx;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;worker_processes &lt;/span&gt;&lt;span&gt; auto;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;error_log &lt;/span&gt;&lt;span&gt; /var/log/nginx/error.log &lt;/span&gt;&lt;span&gt;notice&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;# notice级别&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;pid &lt;/span&gt;&lt;span&gt;       /var/run/nginx.pid; &lt;/span&gt;&lt;span&gt;# nginx进程id&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;events&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;worker_connections &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;1024&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;include &lt;/span&gt;&lt;span&gt;      /etc/nginx/mime.types;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;default_type &lt;/span&gt;&lt;span&gt; application/octet-stream;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# --------------------日志 配置---------------------&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 格式:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# remote_addr - remote_user [time_local] &quot;request&quot; status body_bytes_sent &quot;http_referer&quot; &quot;http_user_agent&quot; &quot;http_x_forwarded_for&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 远程地址       用户名      时间            请求     状态   响应大小         来源网址         用户UA          代理地址&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# log_format  debug  &apos;$remote_addr - $remote_user [$time_local] &quot;$request&quot; &apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#                  &apos;$status $body_bytes_sent &quot;$http_referer&quot; &apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#                  &apos;&quot;$http_user_agent&quot; &quot;$http_x_forwarded_for&quot;&apos;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;log_format &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;debug&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;&apos; $&lt;/span&gt;&lt;span&gt;remote_user&lt;/span&gt;&lt;span&gt; [$&lt;/span&gt;&lt;span&gt;time_local&lt;/span&gt;&lt;span&gt;]  $&lt;/span&gt;&lt;span&gt;http_x_Forwarded_for&lt;/span&gt;&lt;span&gt; $&lt;/span&gt;&lt;span&gt;remote_addr&lt;/span&gt;&lt;span&gt;  $&lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span&gt; &apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                      &lt;/span&gt;&lt;span&gt;&apos;$&lt;/span&gt;&lt;span&gt;http_x_forwarded_for&lt;/span&gt;&lt;span&gt; &apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                      &lt;/span&gt;&lt;span&gt;&apos;$&lt;/span&gt;&lt;span&gt;upstream_addr&lt;/span&gt;&lt;span&gt; &apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                      &lt;/span&gt;&lt;span&gt;&apos;ups_resp_time: $&lt;/span&gt;&lt;span&gt;upstream_response_time&lt;/span&gt;&lt;span&gt; &apos;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                      &lt;/span&gt;&lt;span&gt;&apos;request_time: $&lt;/span&gt;&lt;span&gt;request_time&lt;/span&gt;&lt;span&gt;&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;access_log &lt;/span&gt;&lt;span&gt; /var/log/nginx/access.log  &lt;/span&gt;&lt;span&gt;debug&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;# debug级别&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# --------------------网络 配置---------------------&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;sendfile &lt;/span&gt;&lt;span&gt;       &lt;/span&gt;&lt;span&gt;on&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;# 零拷贝传输(内核和用户)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#tcp_nopush     on; # 优化网络传输，减少网络报文, 把多个小包合并成一个大包发送&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;keepalive_timeout &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;65&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;# 保持长连接的时间, 如果有客户端在65s内没有任何请求, 则关闭连接&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# --------------------压缩 配置---------------------&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 开启/关闭 压缩机制&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gzip &lt;/span&gt;&lt;span&gt;on&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 根据文件类型选择 是否开启压缩机制&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;41&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gzip_types &lt;/span&gt;&lt;span&gt;text/plain application/javascript text/css application/xml text/javascript image/jpeg image/jpg image/gif image/png  application/json;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;42&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 设置压缩级别，越高资源消耗越大越耗时，但压缩效果越好&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;43&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gzip_comp_level &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;44&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 设置是否携带Vary:Accept-Encoding 的响应头&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;45&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gzip_vary &lt;/span&gt;&lt;span&gt;on&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;46&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 处理压缩请求的 缓冲区数量和大小&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;47&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gzip_buffers &lt;/span&gt;&lt;span&gt;32&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;64k&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;48&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 对于不支持压缩功能的客户端请求 不开启压缩机制&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;49&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gzip_disable &lt;/span&gt;&lt;span&gt;&quot;MSIE [1-6]\.&quot;&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;# 比如低版本的IE浏览器不支持压缩&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;50&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 设置压缩功能所支持的HTTP最低版本&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;51&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gzip_http_version &lt;/span&gt;&lt;span&gt;1.1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;52&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 设置触发压缩的最小阈值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;53&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gzip_min_length &lt;/span&gt;&lt;span&gt;2k&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;54&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# off/any/expired/no-cache/no-store/private/no_last_modified/no_etag/auth 根据不同配置对后端服务器的响应结果进行压缩&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;55&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;gzip_proxied &lt;/span&gt;&lt;span&gt;any;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;56&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;57&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# --------------------缓存 配置---------------------&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;58&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 指定缓存存放目录为/usr/local/nginx/test/nginx_cache_storage，并设置缓存名称为mycache，大小为64m， 1天未被访问过的缓存将自动清除，磁盘中缓存的最大容量为1gb&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;59&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;proxy_cache_path &lt;/span&gt;&lt;span&gt;/usr/local/nginx/test/nginx_cache_storage levels=1:2 keys_zone=mycache:64m inactive=1d max_size=1g;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;60&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;61&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# --------------------限流 配置---------------------&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;62&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 对请求速率限流&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;63&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=5r/s;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;64&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# 对请求连接数限流&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;65&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;   &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;limit_conn_zone &lt;/span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt;binary_remote_addr&lt;/span&gt;&lt;span&gt; zone=myConnLimit:10m;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;66&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;67&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# --------------------重定向 配置---------------------&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;68&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;69&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;     &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;listen &lt;/span&gt;&lt;span&gt;80&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;70&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;     &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;charset &lt;/span&gt;&lt;span&gt;utf-8;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;71&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;     &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;server_name &lt;/span&gt;&lt;span&gt;www.example.com example.com;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;72&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;      &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;301&lt;/span&gt;&lt;span&gt; https://$&lt;/span&gt;&lt;span&gt;server_name&lt;/span&gt;&lt;span&gt;$&lt;/span&gt;&lt;span&gt;request_uri&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;# 301永久重定向到https&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;73&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;74&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;75&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# --------------------负载均衡 配置---------------------&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;76&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# upstream backendserver {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;77&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#     server 172.30.128.64:8081 fail_timeout=60s max_fails=3; # 60秒内 如果请求某一个应用失败3次，则认为该应用宕机 时间到后再有请求进来继续尝试连接宕机应用且仅尝试 1 次，如果还是失败，则继续等待 60 秒...以此循环，直到恢复&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;78&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#     server 172.30.128.64:8082;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;79&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;#     server 172.30.128.64:8083 backup; # 设置8083位备机&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;80&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;81&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;upstream&lt;/span&gt;&lt;span&gt; backendserver {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;82&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt; 127.0.0.1:9000;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;83&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;84&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;85&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# --------------------HTTPS 配置---------------------&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;86&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;87&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#SSL 默认访问端口号为 443&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;88&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;       &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;listen &lt;/span&gt;&lt;span&gt;443&lt;/span&gt;&lt;span&gt; ssl;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;89&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#填写绑定证书的域名&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;90&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;       &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;server_name &lt;/span&gt;&lt;span&gt;www.example.com example.com;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;91&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#请填写证书文件的相对路径或绝对路径&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;92&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;       &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ssl_certificate &lt;/span&gt;&lt;span&gt;/etc/nginx/cert/xxx.pem;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;93&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#请填写私钥文件的相对路径或绝对路径&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;94&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;       &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ssl_certificate_key &lt;/span&gt;&lt;span&gt;/etc/nginx/cert/xxx.key;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;95&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#停止通信时，加密会话的有效期，在该时间段内不需要重新交换密钥&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;96&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;       &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ssl_session_timeout &lt;/span&gt;&lt;span&gt;5m&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;97&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#服务器支持的TLS版本&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;98&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;       &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ssl_protocols &lt;/span&gt;&lt;span&gt;TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;99&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#请按照以下套件配置，配置加密套件，写法遵循 openssl 标准。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;100&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;       &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ssl_ciphers &lt;/span&gt;&lt;span&gt;ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;101&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#开启由服务器决定采用的密码套件&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;102&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;       &lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;ssl_prefer_server_ciphers &lt;/span&gt;&lt;span&gt;on&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;103&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;104&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# # 指定 username 参数中只要有字母 就不走nginx缓存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;105&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# if ($arg_username ~ [a-z]) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;106&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#     set $cache_name &quot;no cache&quot;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;107&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;108&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# # 前端页面资源&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;109&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# location  /page {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;110&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   alias  &apos;/usr/local/nginx/test/static/&apos;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;111&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   index index_page.html;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;112&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;113&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   allow all;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;114&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;115&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# # 后端服务&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;116&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# location  /interface {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;117&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_pass http://backendserver/;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;118&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;119&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 指定哪些错误状态才执行 重试&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;120&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_404;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;121&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;122&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;123&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 使用名为 mycache 的缓存空间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;124&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache mycache;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;125&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 对于200 206 状态码的数据缓存2分钟&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;126&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache_valid 200 206 1m;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;127&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 定义生成缓存键的规则（请求的url+参数作为缓存key）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;128&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache_key $host$uri$is_args$args;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;129&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 资源至少被重复访问2次后再加入缓存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;130&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache_min_uses 3;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;131&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 出现重复请求时，只让其中一个去后端读数据，其他的从缓存中读取&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;132&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache_lock on;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;133&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 上面的锁 超时时间为4s，超过4s未获取数据，其他请求直接去后端&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;134&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache_lock_timeout 4s;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;135&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 对于请求参数中有字母的 不走nginx缓存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;136&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_no_cache $cache_name; # 判断该变量是否有值，如果有值则不进行缓存，没有值则进行缓存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;137&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 在响应头中添加一个缓存是否命中的状态（便于调试）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;138&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   add_header Cache-status $upstream_cache_status;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;139&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;140&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   limit_conn myConnLimit 12;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;141&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;142&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# # limit_req zone=myRateLimit burst=5  nodelay;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;143&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# # limit_req_status 520;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;144&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# # limit_req_log_level info;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;145&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;146&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;147&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# # 后端服务&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;148&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# location  /interface2 {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;149&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_pass http://backendserver;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;150&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 使用名为 mycache 的缓存空间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;151&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache mycache;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;152&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 对于200 206 状态码的数据缓存2分钟&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;153&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache_valid 200 206 1m;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;154&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 定义生成缓存键的规则（请求的url+参数作为缓存key）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;155&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache_key $host$uri$is_args$args;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;156&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 资源至少被重复访问2次后再加入缓存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;157&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache_min_uses 3;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;158&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 出现重复请求时，只让其中一个去后端读数据，其他的从缓存中读取&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;159&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache_lock on;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;160&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 上面的锁 超时时间为4s，超过4s未获取数据，其他请求直接去后端&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;161&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_cache_lock_timeout 4s;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;162&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 对于请求参数中有字母的 不走nginx缓存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;163&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   proxy_no_cache $cache_name; # 判断该变量是否有值，如果有值则不进行缓存，没有值则进行缓存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;164&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   # 在响应头中添加一个缓存是否命中的状态（便于调试）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;165&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   add_header Cache-status $upstream_cache_status;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;166&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;167&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;#   limit_conn myConnLimit 12;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;168&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;169&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# # limit_req zone=myRateLimit burst=5  nodelay;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;170&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# # limit_req_status 520;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;171&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# # limit_req_log_level info;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;172&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;# }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;173&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;174&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;175&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;176&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;# include /etc/nginx/conf.d/*.conf;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;177&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;配置示例&lt;a href=&quot;#配置示例&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;修改错误返回值&lt;a href=&quot;#修改错误返回值&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;​	有些时候希望返回的不是service unavailable, 希望返回某段json, 可以这样设置&lt;/p&gt;&lt;p&gt;​	/50x.json是返回的json内容, 也可以返回其他网页&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;error_page 5xx /5xx.json;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;location = /5xx.json {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;root /usr/share/nginx/html;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;internal; # 保证这个路径只能内部请求&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;websocket配置&lt;a href=&quot;#websocket配置&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;​	websocket比较特殊, 需要加入upgrade和connection&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;location /api/ws/ {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;proxy_redirect off;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;proxy_set_header Upgrade $http_upgrade;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;proxy_set_header Connection &quot;upgrade&quot;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;proxy_pass       http://127.0.0.1:9000/api/ws/;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;SSE配置&lt;a href=&quot;#sse配置&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;​	SSE配置需要去掉缓存, 不然SSE失效&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;location /api/sse {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;proxy_redirect off;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;proxy_pass         http://127.0.0.1:9000/api/sse;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;proxy_buffering off; # 去掉缓存&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;请求速率限流&lt;a href=&quot;#请求速率限流&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;http{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 对请求速率限流&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=5r/s;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;server{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;location /api {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;limit_req zone=myRateLimit burst=5 nodelay;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;limit_req_status 520; # 返回码&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;limit_req_log_level info;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;$binary_remote_addr: 基于客户端IP做限流&lt;/p&gt;
&lt;p&gt;zone=myRateLimit:10m 指myRateLimit作为内存区域, 大小10M(16万)IP地址&lt;/p&gt;
&lt;p&gt;rate=5r/s 指相同IP每秒最多请求5次(200ms一个请求)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;burst=5: 削峰, 如果峰值超过rate(比如说200ms来了两个), 则会用一个大小为burst的队列削峰, 然后慢慢根据rate速率处理, 多余的直接503&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;nodelay: 如果是nodelay, 则burst削峰会立即处理, 而不是每200ms取一个&lt;/p&gt;
&lt;p&gt;nodelay立即处理, 那么nginx怎么控制并发? 是通过处理但不释放的方式控制. 后面的请求会阻塞&lt;/p&gt;
&lt;p&gt;一般建议burst和nodelay一起用, 可以处理突发流量&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;请求连接数限流&lt;a href=&quot;#请求连接数限流&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;http{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 针对ip  对请求连接数限流&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;limit_conn_zone $binary_remote_addr zone=myConnLimit:10m;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;server{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span&gt;limit_conn myConnLimit 12;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;https/SSL&lt;a href=&quot;#httpsssl&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;​	注意需要http_ssl_module&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#SSL 默认访问端口号为 443&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;listen 443 ssl;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#填写绑定证书的域名&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server_name www.hzznb-xzll.xyz hzznb-xzll.xyz;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#请填写证书文件的相对路径或绝对路径&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ssl_certificate 证书路径;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#请填写私钥文件的相对路径或绝对路径&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ssl_certificate_key 私钥路径;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#停止通信时，加密会话的有效期，在该时间段内不需要重新交换密钥&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ssl_session_timeout 5m;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#服务器支持的TLS版本&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#请按照以下套件配置，配置加密套件，写法遵循 openssl 标准。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;#开启由服务器决定采用的密码套件&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ssl_prefer_server_ciphers on;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;ssl_certificate: .pem或者/csr文件&lt;/p&gt;&lt;p&gt;ssl_certificate_key: 一般是.key文件&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;80重定向到443&lt;a href=&quot;#80重定向到443&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server_name www.hzznb-xzll.xyz hzznb-xzll.xyz;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 重定向到目标地址&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;return 301 https://$server_name$request_uri;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;压缩&lt;a href=&quot;#压缩&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;http {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 开启/关闭 压缩机制&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;gzip on;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 根据文件类型选择 是否开启压缩机制&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/jpg image/gif image/png  application/json;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 设置压缩级别，一共9个级别  1-9   ，越高资源消耗越大 越耗时，但压缩效果越好，&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;gzip_comp_level 5;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 设置是否携带Vary:Accept-Encoding 的响应头&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;gzip_vary on;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 处理压缩请求的 缓冲区数量和大小&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;gzip_buffers 32 64k;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 对于不支持压缩功能的客户端请求 不开启压缩机制&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;gzip_disable &quot;MSIE [1-6]\.&quot;; # 比如低版本的IE浏览器不支持压缩&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 设置压缩功能所支持的HTTP最低版本&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;gzip_http_version 1.1;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# 设置触发压缩的最小阈值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;gzip_min_length 2k;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;# off/any/expired/no-cache/no-store/private/no_last_modified/no_etag/auth 根据不同配置对后端服务器的响应结果进行压缩&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;gzip_proxied any;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;负载均衡&lt;a href=&quot;#负载均衡&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;section&gt;&lt;h4&gt;配置热备&lt;a href=&quot;#配置热备&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;upstream mysvr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server 192.168.10.121:3333 max_fails=2 fail_timeout=2;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server 192.168.10.122:3333 backup;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;max_fails: 允许请求失败的最大次数, 超过时返回proxy_next_upstream模块定义的错误&lt;/li&gt;
&lt;li&gt;fail_timeout: 经历了max_fails失败后暂停服务的时间&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;轮询(round-robin)&lt;a href=&quot;#轮询round-robin&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;upstream mysvr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server 127.0.0.1:7878;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server 192.168.10.121:3333;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;请求会分别发送到两个服务器, A-B-A-B…&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;upstream mysvr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server 127.0.0.1:7878 weight=1;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server 192.168.10.121:3333 weight=2;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;给不同服务器设置权重, 上面会变成A-B-B-A-B-B…&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;ip_hash&lt;a href=&quot;#ip_hash&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;upstream mysvr {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server 127.0.0.1:7878;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;server 192.168.10.121:3333;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ip_hash;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;会让相同客户端请求相同的服务器, 实现session等的共享&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item><item><title>redis-lua限流脚本</title><link>https://axi.moe/posts/e4s3i6g9/</link><guid isPermaLink="true">https://axi.moe/posts/e4s3i6g9/</guid><pubDate>Fri, 04 Apr 2025 16:15:50 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;redis-lua 限流脚本&lt;a href=&quot;#redis-lua-限流脚本&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;参考：&lt;a href=&quot;https://gist.github.com/ptarjan/e38f45f2dfe601419ca3af937fff574d&quot; target=&quot;_blank&quot;&gt;https://gist.github.com/ptarjan/e38f45f2dfe601419ca3af937fff574d&lt;/a&gt;&lt;/p&gt;&lt;section&gt;&lt;h2&gt;令牌桶算法(token bucket)&lt;a href=&quot;#令牌桶算法token-bucket&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tokens_key&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;KEYS&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;-- token键&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;timestamp_key&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;KEYS&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;-- 上次更新时间戳&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;rate&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;tonumber&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ARGV&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;-- 每秒加入令牌数&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;capacity&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;tonumber&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ARGV&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;-- 最大容量&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;tonumber&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ARGV&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;-- 当前时间戳&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;requested&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;tonumber&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ARGV&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;-- 请求令牌&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fill_time&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;capacity&lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt;rate&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;-- 填充时间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ttl&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;math.floor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;fill_time&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;-- 填充时间的两倍，避免过期&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- 获取tokens，过期则相当于充满&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;last_tokens&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;tonumber&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;redis&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;GET&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;tokens_key&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;last_tokens&lt;/span&gt;&lt;span&gt; == &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;last_tokens&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;capacity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;last_refreshed&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;tonumber&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;redis&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;GET&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;timestamp_key&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;last_refreshed&lt;/span&gt;&lt;span&gt; == &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;last_refreshed&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- 填充&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;delta&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;math.max&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;last_refreshed&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;filled_tokens&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;math.min&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;capacity&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;last_tokens&lt;/span&gt;&lt;span&gt;+(&lt;/span&gt;&lt;span&gt;delta&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;rate&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allowed&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;filled_tokens&lt;/span&gt;&lt;span&gt; &amp;gt;= &lt;/span&gt;&lt;span&gt;requested&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;new_tokens&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;filled_tokens&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allowed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;new_tokens&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;filled_tokens&lt;/span&gt;&lt;span&gt; - &lt;/span&gt;&lt;span&gt;requested&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;redis&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;SETEX&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;tokens_key&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ttl&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;new_tokens&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;redis&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;SETEX&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;timestamp_key&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ttl&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;-- new_token是消耗令牌后的tokens&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;allowed&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;new_tokens&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;展开&lt;/span&gt;&lt;span&gt;收起&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;并行限制 ZSET实现&lt;a href=&quot;#并行限制-zset实现&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;并行限制可以控制同时并行的请求数，使用zset实现：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;请求来到时，ZCARD查看count数，如果小于则ZADD添加，否则拒绝。&lt;/li&gt;
&lt;li&gt;请求结束时，需要调用ZREM+id删除这个member&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;KEYS&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;capacity&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;tonumber&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ARGV&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;-- 最大请求数&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;timestamp&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;tonumber&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ARGV&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;]) &lt;/span&gt;&lt;span&gt;-- 当前时间戳&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;ARGV&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;-- 请求标识&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;redis&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;ZCARD&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;local&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allowed&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt; &amp;lt; &lt;/span&gt;&lt;span&gt;capacity&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;allowed&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;then&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;redis&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;call&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;ZADD&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;key&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;timestamp&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;allowed&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;count&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;定点刷新&lt;a href=&quot;#定点刷新&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;还可以实现定点刷新脚本：假定每天凌晨四点刷新&lt;/p&gt;&lt;p&gt;利用redis过期机制刷新，先计算现在与下一个刷新点的时间差，检查key是否存在，如果不存在则SET&lt;/p&gt;&lt;p&gt;存在则DECRBY这个key，那么每天到点后，key过期就会自动刷新值。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item></channel></rss>