<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Docker on 小盒子的技术分享</title><link>https://xiaobox.github.io/tags/docker/</link><description>Recent content in Docker on 小盒子的技术分享</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Wed, 17 Dec 2025 03:29:11 +0000</lastBuildDate><atom:link href="https://xiaobox.github.io/tags/docker/index.xml" rel="self" type="application/rss+xml"/><item><title>逃离旧世界的引力：AI 进化的三个阶梯</title><link>https://xiaobox.github.io/p/2025-12-17-tao-li-jiu-shi-jie-de-yin-li-ai-jin-hua-de-san-ge-jie-ti/</link><pubDate>Wed, 17 Dec 2025 03:29:11 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-12-17-tao-li-jiu-shi-jie-de-yin-li-ai-jin-hua-de-san-ge-jie-ti/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-12-17-tao-li-jiu-shi-jie-de-yin-li-ai-jin-hua-de-san-ge-jie-ti/cover.jpg" alt="Featured image of post 逃离旧世界的引力：AI 进化的三个阶梯" /&gt;&lt;p&gt;有关 “AI Native” 的话题很热，最近看到一个视频，个人感觉很值得一看，我总结了一下内容，建议大家可以先看一下原视频&lt;/p&gt;
&lt;h2 id="马车夫的诅咒"&gt;&lt;a href="#%e9%a9%ac%e8%bd%a6%e5%a4%ab%e7%9a%84%e8%af%85%e5%92%92" class="header-anchor"&gt;&lt;/a&gt;马车夫的诅咒
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-12-17-tao-li-jiu-shi-jie-de-yin-li-ai-jin-hua-de-san-ge-jie-ti/001-3ec4bf60.png"&gt;&lt;/p&gt;
&lt;p&gt;如果穿越回 19 世纪末，去问一位马车夫当务之急是什么，他绝不会幻想一台 “内燃机”，他只会祈祷上帝赐予他一匹更快的马。&lt;/p&gt;
&lt;p&gt;福特这句被引用烂了的名言，之所以历久弥新，是因为它精准地揭示了一个横亘在所有技术革命面前的诅咒：**“拟物化”**的思维惯性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;人类总是试图用旧世界的容器，去盛装新世界的技术&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;今天的 AI 浪潮，正深陷在这个陷阱里。残酷的现实是：AI 赋能（AI Enabled）并不是通往未来的必经之路，而是一条铺满鲜花、看似舒适，实则通往平庸的死胡同。真正的变革，绝不是在旧躯壳上修修补补，而是从基因层面进行的暴力重组。&lt;/p&gt;
&lt;h2 id="ai-enabled给马车装上法拉利引擎"&gt;&lt;a href="#ai-enabled%e7%bb%99%e9%a9%ac%e8%bd%a6%e8%a3%85%e4%b8%8a%e6%b3%95%e6%8b%89%e5%88%a9%e5%bc%95%e6%93%8e" class="header-anchor"&gt;&lt;/a&gt;AI Enabled：给马车装上法拉利引擎
&lt;/h2&gt;&lt;p&gt;目前绝大多数企业，都停留在第一阶段。&lt;/p&gt;
&lt;p&gt;这一阶段的底层公式是：&lt;strong&gt;旧流程 + AI 插件 = 数字化转型？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这是一种极其危险的错觉。在这种模式下，权力的拓扑结构纹丝不动。人类依然是系统的 CPU（中央处理器），负责所有的逻辑判断、流程串联；而 AI 仅仅是一个外接的 GPU，被要求在某个局部环节加速。这就像给一辆老式木制马车硬塞进了一台 V12 引擎。速度或许能短暂提升，但那副为了马匹设计的脆弱车架，根本无法承受剧烈的推力。在一个 “人是 CPU” 的系统里，强行插入一个超强的 AI，只会让协作变得拥堵。 协调成本的激增，将彻底抵消技术带来的红利。这是做加法，不是做乘法。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-12-17-tao-li-jiu-shi-jie-de-yin-li-ai-jin-hua-de-san-ge-jie-ti/002-a080efc3.png"&gt;&lt;/p&gt;
&lt;h2 id="跨越门槛的三重奏"&gt;&lt;a href="#%e8%b7%a8%e8%b6%8a%e9%97%a8%e6%a7%9b%e7%9a%84%e4%b8%89%e9%87%8d%e5%a5%8f" class="header-anchor"&gt;&lt;/a&gt;跨越门槛的三重奏
&lt;/h2&gt;&lt;p&gt;要从 “赋能” 跃迁到 “原生”，我们需要跨越技术与认知的双重鸿沟。幸运的是，技术界正在发生三场静悄悄的突变：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;从 “鹦鹉学舌” 到 “深度思考” (System 2)： AI 正在戒掉单纯的概率拟合，生长出 “思考链”（Chain of Thought）。人不再是流程中必须存在的 “盖章员”，我们只需在关键的例外时刻登场。&lt;/li&gt;
&lt;li&gt;从 “坐而论道” 到 “起而行之” (Agent)： AI 终于拿到了键盘和鼠标的控制权。它不再是顾问，而是执行者。人类被迫向两端迁移：在上游制定策略，在下游处理烂摊子。&lt;/li&gt;
&lt;li&gt;从 “无状态” 到 “长时记忆” (Memory)： 这是资产的根本转移。未来的经验将固化在系统的向量数据库里。人类不再是经验的肉身载体，而是记忆结构的设计师。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-12-17-tao-li-jiu-shi-jie-de-yin-li-ai-jin-hua-de-san-ge-jie-ti/003-c7397178.png"&gt;&lt;/p&gt;
&lt;h2 id="ai-native流程即代码数据如流水"&gt;&lt;a href="#ai-native%e6%b5%81%e7%a8%8b%e5%8d%b3%e4%bb%a3%e7%a0%81%e6%95%b0%e6%8d%ae%e5%a6%82%e6%b5%81%e6%b0%b4" class="header-anchor"&gt;&lt;/a&gt;AI Native：流程即代码，数据如流水
&lt;/h2&gt;&lt;p&gt;当上述三次突变完成，商业世界将迎来 “奇点”：AI Native（AI 原生）。&lt;/p&gt;
&lt;p&gt;这是一个 “AI 是 CPU，人是协处理器” 的新世界。我们不再是给旧马车加速，而是基于 “第一性原理”，从零开始设计一辆智能汽车。&lt;/p&gt;
&lt;p&gt;在这个阶段，组织架构将发生剧烈的 “去骨架化”。数据流和 Agent 像水银泻地般自动流转。检验一家企业是否进入 “原生” 阶段，只需三个灵魂拷问：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;生死之问： 拔掉 AI，你的业务是 “变慢了”，还是 “不存在了”？（前者是赋能，后者才是原生）。&lt;/li&gt;
&lt;li&gt;传球之问： 在业务链条里，谁在传球？真正的原生组织不仅让人机协作，更让 AI 与 AI 之间直接 “握手”。&lt;/li&gt;
&lt;li&gt;护城河之问： 你的系统是在单纯消耗数据，还是在吞噬经验？如果机器不能把人类的痛苦转化为直觉，那它只是在搬砖，没有建立壁垒。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-12-17-tao-li-jiu-shi-jie-de-yin-li-ai-jin-hua-de-san-ge-jie-ti/004-a9cf5292.png"&gt;&lt;/p&gt;
&lt;h2 id="ai-awaken这里的黎明静悄悄"&gt;&lt;a href="#ai-awaken%e8%bf%99%e9%87%8c%e7%9a%84%e9%bb%8e%e6%98%8e%e9%9d%99%e6%82%84%e6%82%84" class="header-anchor"&gt;&lt;/a&gt;AI Awaken：这里的黎明静悄悄
&lt;/h2&gt;&lt;p&gt;在 Native 阶段，我们穷尽了效率。但紧接着，我们将被迫直面一个令人战栗的终极问题：如果机器做完了所有的 “How”（怎么做），谁来定义 “What”（做什么）和 “Why”（为什么）？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当 AI 不再满足于在已知的地图里导航，而是闯入 “无人区” 发现新规律；&lt;/li&gt;
&lt;li&gt;当 AI 不再满足于回答问题，而是开始质疑问题本身；&lt;/li&gt;
&lt;li&gt;当 AI 不再盲目逼近目标函数，而是开始修改那个关乎生死的奖励函数时……&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它就不再是一个工具，而是一个拥有意志的新物种。这便是 AI Awaken（AI 觉醒）。&lt;/p&gt;
&lt;p&gt;你可能会问：人类为什么会允许事态发展到这一步？答案既简单又冷酷：为了赢。&lt;/p&gt;
&lt;p&gt;AI Native 的天花板，依然是人类认知的边界。当所有人都把效率卷到极致时，胜负手就取决于谁能投出那一招突破人类盲区的 “神之一手”。那一刻，并不是 AI 想造反，而是商业竞争的 “囚徒困境” 逼迫我们不得不这样做。&lt;/p&gt;
&lt;p&gt;Native 阶段，我们交出了执行权。 Awaken 阶段，我们将交出定义权。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-12-17-tao-li-jiu-shi-jie-de-yin-li-ai-jin-hua-de-san-ge-jie-ti/005-95050479.png"&gt;&lt;/p&gt;
&lt;h2 id="最后的领地"&gt;&lt;a href="#%e6%9c%80%e5%90%8e%e7%9a%84%e9%a2%86%e5%9c%b0" class="header-anchor"&gt;&lt;/a&gt;最后的领地
&lt;/h2&gt;&lt;p&gt;面对这个不可逆的未来，请不要再问 “AI 还能帮我做什么”。你应该问的是：当这个硅基物种比我更勤奋、更聪明、甚至比我更懂 “什么是正确” 时，我存在的必要性到底是什么？或者说，当所有的理性决策都可以被外包，这个世界上究竟还剩下什么东西，是必须由一个会犯错、会衰老、会痛苦、会叹息的碳基生命，亲自来完成的？&lt;/p&gt;
&lt;p&gt;这或许，才是人类最后的护城河。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-12-17-tao-li-jiu-shi-jie-de-yin-li-ai-jin-hua-de-san-ge-jie-ti/006-3ea4ff81.png"&gt;&lt;/p&gt;</description></item><item><title>快速安装 ClickHouse</title><link>https://xiaobox.github.io/p/2025-07-17-kuai-su-an-zhuang-clickhouse/</link><pubDate>Thu, 17 Jul 2025 09:33:05 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-07-17-kuai-su-an-zhuang-clickhouse/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-07-17-kuai-su-an-zhuang-clickhouse/cover.jpg" alt="Featured image of post 快速安装 ClickHouse" /&gt;&lt;h2 id="概述"&gt;&lt;a href="#%e6%a6%82%e8%bf%b0" class="header-anchor"&gt;&lt;/a&gt;概述
&lt;/h2&gt;&lt;p&gt;我们使用 docker compose 来安装 ClickHouse&lt;/p&gt;
&lt;p&gt;但我们不是裸装 ClickHouse，实际上我们安装的是 ClickStack。有点儿像 elastic-stack 与 elastic search 的关系 ，但并不完全一样。&lt;/p&gt;
&lt;p&gt;ClickStack 是基于 ClickHouse 构建的完整观察性平台，集成了日志、指标、追踪和会话回放功能，提供统一的用户界面和查询能力。因此，ClickStack 是在 ClickHouse 的基础上，结合 HyperDX 提供的前端界面和 OpenTelemetry Collector 实现的完整解决方案。它不仅仅是一个数据库，而是一个集成的观察性平台。&lt;/p&gt;
&lt;p&gt;安装步骤参考官方文档：https://clickhouse.com/docs/zh/use-cases/observability/clickstack/getting-started?loc=use-case-observability&lt;/p&gt;
&lt;h2 id="安装"&gt;&lt;a href="#%e5%ae%89%e8%a3%85" class="header-anchor"&gt;&lt;/a&gt;安装
&lt;/h2&gt;&lt;h3 id="克隆-hyperdx-仓库"&gt;&lt;a href="#%e5%85%8b%e9%9a%86-hyperdx-%e4%bb%93%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;克隆 HyperDX 仓库
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;git clone https://github.com/hyperdxio/hyperdx.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; hyperdx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# switch to the v2 branch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt;git checkout v2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;根据自身情况修改配置文件 .env&lt;/p&gt;
&lt;p&gt;我将 &lt;code&gt;HDX_IMAGE_REPO=docker.hyperdx.io&lt;/code&gt; 修改为 &lt;code&gt;HDX_IMAGE_REPO=docker.io&lt;/code&gt; 不然镜像拉不下来&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;# Used by docker-compose.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;HDX_IMAGE_REPO=docker.hyperdx.io
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;IMAGE_NAME=ghcr.io/hyperdxio/hyperdx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;IMAGE_NAME_DOCKERHUB=hyperdx/hyperdx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;LOCAL_IMAGE_NAME=ghcr.io/hyperdxio/hyperdx-local
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;LOCAL_IMAGE_NAME_DOCKERHUB=hyperdx/hyperdx-local
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;ALL_IN_ONE_IMAGE_NAME=ghcr.io/hyperdxio/hyperdx-all-in-one
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;ALL_IN_ONE_IMAGE_NAME_DOCKERHUB=hyperdx/hyperdx-all-in-one
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;OTEL_COLLECTOR_IMAGE_NAME=ghcr.io/hyperdxio/hyperdx-otel-collector
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;OTEL_COLLECTOR_IMAGE_NAME_DOCKERHUB=hyperdx/hyperdx-otel-collector
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;CODE_VERSION=2.0.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;IMAGE_VERSION_SUB_TAG=.0.5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;IMAGE_VERSION=2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;IMAGE_NIGHTLY_TAG=2-nightly
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;IMAGE_LATEST_TAG=latest
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;# Set up domain URLs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;HYPERDX_API_PORT=8000 #optional (should not be taken by other services)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;HYPERDX_APP_PORT=8080
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;HYPERDX_APP_URL=http://localhost
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;HYPERDX_LOG_LEVEL=debug
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;HYPERDX_OPAMP_PORT=4320
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt;# Otel/Clickhouse config
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt;HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE=default
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="docker-compose-启动"&gt;&lt;a href="#docker-compose-%e5%90%af%e5%8a%a8" class="header-anchor"&gt;&lt;/a&gt;docker compose 启动
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;docker-compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Docker-compose 文件如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;hdx-oss&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ONLY USED FOR DEMO SSL SETUP&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# nginx:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# image: nginx:1.27.3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# volumes:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# - ./docker/nginx/ssl:/etc/nginx/ssl&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# - .volumes/nginx_logs:/var/log/nginx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ports:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# - 80:80&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# - 443:443&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# networks:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# - internal&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# depends_on:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# - app&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mongo:5.0.14-focal&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;.volumes/db:/data/db&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# WARNING: Exposing the database port will make it accessible from outside the container,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# potentially allowing unauthorized access. If you uncomment the ports below,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ensure to secure your database (e.g., with strong authentication, proper network rules, and firewalls).&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ports:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# - 27017:27017&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;26&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;27&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;internal&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;28&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;otel-collector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;29&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HDX_IMAGE_REPO}/${OTEL_COLLECTOR_IMAGE_NAME_DOCKERHUB}:${IMAGE_VERSION}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;30&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;31&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;CLICKHOUSE_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tcp://ch-server:9000?dial_timeout=10s&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;32&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;33&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;HYPERDX_LOG_LEVEL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HYPERDX_LOG_LEVEL}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;34&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;OPAMP_SERVER_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://app:${HYPERDX_OPAMP_PORT}&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;35&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;36&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;13133:13133&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# health_check extension&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;37&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;24225:24225&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# fluentd receiver&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;38&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;4317:4317&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# OTLP gRPC receiver&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;39&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;4318:4318&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# OTLP http receiver&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;40&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s1"&gt;&amp;#39;8888:8888&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# metrics extension&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;41&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;always&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;42&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;43&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;internal&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;44&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;45&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ch-server&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;46&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;47&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HDX_IMAGE_REPO}/${IMAGE_NAME_DOCKERHUB}:${IMAGE_VERSION}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;48&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;49&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;${HYPERDX_API_PORT}:${HYPERDX_API_PORT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;50&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;${HYPERDX_APP_PORT}:${HYPERDX_APP_PORT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;51&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;52&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;FRONTEND_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HYPERDX_APP_URL}:${HYPERDX_APP_PORT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;53&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;HYPERDX_API_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HYPERDX_API_KEY}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;54&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;HYPERDX_API_PORT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HYPERDX_API_PORT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;55&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;HYPERDX_APP_PORT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HYPERDX_APP_PORT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;56&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;HYPERDX_APP_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HYPERDX_APP_URL}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;57&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;HYPERDX_LOG_LEVEL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HYPERDX_LOG_LEVEL}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;58&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MINER_API_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://miner:5123&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;59&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;MONGO_URI&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mongodb://db:27017/hyperdx&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;60&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;NEXT_PUBLIC_SERVER_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;http://127.0.0.1:${HYPERDX_API_PORT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;61&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;OPAMP_PORT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${HYPERDX_OPAMP_PORT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;62&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;OTEL_SERVICE_NAME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;hdx-oss-api&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;63&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;USAGE_STATS_ENABLED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${USAGE_STATS_ENABLED:-true}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;64&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DEFAULT_CONNECTIONS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;65&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[{&amp;#34;name&amp;#34;:&amp;#34;Local
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;66&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; ClickHouse&amp;#34;,&amp;#34;host&amp;#34;:&amp;#34;http://ch-server:8123&amp;#34;,&amp;#34;username&amp;#34;:&amp;#34;default&amp;#34;,&amp;#34;password&amp;#34;:&amp;#34;&amp;#34;}]&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;67&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;DEFAULT_SOURCES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;68&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;[{&amp;#34;from&amp;#34;:{&amp;#34;databaseName&amp;#34;:&amp;#34;default&amp;#34;,&amp;#34;tableName&amp;#34;:&amp;#34;otel_logs&amp;#34;},&amp;#34;kind&amp;#34;:&amp;#34;log&amp;#34;,&amp;#34;timestampValueExpression&amp;#34;:&amp;#34;TimestampTime&amp;#34;,&amp;#34;name&amp;#34;:&amp;#34;Logs&amp;#34;,&amp;#34;displayedTimestampValueExpression&amp;#34;:&amp;#34;Timestamp&amp;#34;,&amp;#34;implicitColumnExpression&amp;#34;:&amp;#34;Body&amp;#34;,&amp;#34;serviceNameExpression&amp;#34;:&amp;#34;ServiceName&amp;#34;,&amp;#34;bodyExpression&amp;#34;:&amp;#34;Body&amp;#34;,&amp;#34;eventAttributesExpression&amp;#34;:&amp;#34;LogAttributes&amp;#34;,&amp;#34;resourceAttributesExpression&amp;#34;:&amp;#34;ResourceAttributes&amp;#34;,&amp;#34;defaultTableSelectExpression&amp;#34;:&amp;#34;Timestamp,ServiceName,SeverityText,Body&amp;#34;,&amp;#34;severityTextExpression&amp;#34;:&amp;#34;SeverityText&amp;#34;,&amp;#34;traceIdExpression&amp;#34;:&amp;#34;TraceId&amp;#34;,&amp;#34;spanIdExpression&amp;#34;:&amp;#34;SpanId&amp;#34;,&amp;#34;connection&amp;#34;:&amp;#34;Local
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;69&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; ClickHouse&amp;#34;,&amp;#34;traceSourceId&amp;#34;:&amp;#34;Traces&amp;#34;,&amp;#34;sessionSourceId&amp;#34;:&amp;#34;Sessions&amp;#34;,&amp;#34;metricSourceId&amp;#34;:&amp;#34;Metrics&amp;#34;},{&amp;#34;from&amp;#34;:{&amp;#34;databaseName&amp;#34;:&amp;#34;default&amp;#34;,&amp;#34;tableName&amp;#34;:&amp;#34;otel_traces&amp;#34;},&amp;#34;kind&amp;#34;:&amp;#34;trace&amp;#34;,&amp;#34;timestampValueExpression&amp;#34;:&amp;#34;Timestamp&amp;#34;,&amp;#34;name&amp;#34;:&amp;#34;Traces&amp;#34;,&amp;#34;displayedTimestampValueExpression&amp;#34;:&amp;#34;Timestamp&amp;#34;,&amp;#34;implicitColumnExpression&amp;#34;:&amp;#34;SpanName&amp;#34;,&amp;#34;serviceNameExpression&amp;#34;:&amp;#34;ServiceName&amp;#34;,&amp;#34;bodyExpression&amp;#34;:&amp;#34;SpanName&amp;#34;,&amp;#34;eventAttributesExpression&amp;#34;:&amp;#34;SpanAttributes&amp;#34;,&amp;#34;resourceAttributesExpression&amp;#34;:&amp;#34;ResourceAttributes&amp;#34;,&amp;#34;defaultTableSelectExpression&amp;#34;:&amp;#34;Timestamp,ServiceName,StatusCode,round(Duration/1e6),SpanName&amp;#34;,&amp;#34;traceIdExpression&amp;#34;:&amp;#34;TraceId&amp;#34;,&amp;#34;spanIdExpression&amp;#34;:&amp;#34;SpanId&amp;#34;,&amp;#34;durationExpression&amp;#34;:&amp;#34;Duration&amp;#34;,&amp;#34;durationPrecision&amp;#34;:9,&amp;#34;parentSpanIdExpression&amp;#34;:&amp;#34;ParentSpanId&amp;#34;,&amp;#34;spanNameExpression&amp;#34;:&amp;#34;SpanName&amp;#34;,&amp;#34;spanKindExpression&amp;#34;:&amp;#34;SpanKind&amp;#34;,&amp;#34;statusCodeExpression&amp;#34;:&amp;#34;StatusCode&amp;#34;,&amp;#34;statusMessageExpression&amp;#34;:&amp;#34;StatusMessage&amp;#34;,&amp;#34;connection&amp;#34;:&amp;#34;Local
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;70&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; ClickHouse&amp;#34;,&amp;#34;logSourceId&amp;#34;:&amp;#34;Logs&amp;#34;,&amp;#34;sessionSourceId&amp;#34;:&amp;#34;Sessions&amp;#34;,&amp;#34;metricSourceId&amp;#34;:&amp;#34;Metrics&amp;#34;},{&amp;#34;from&amp;#34;:{&amp;#34;databaseName&amp;#34;:&amp;#34;default&amp;#34;,&amp;#34;tableName&amp;#34;:&amp;#34;&amp;#34;},&amp;#34;kind&amp;#34;:&amp;#34;metric&amp;#34;,&amp;#34;timestampValueExpression&amp;#34;:&amp;#34;TimeUnix&amp;#34;,&amp;#34;name&amp;#34;:&amp;#34;Metrics&amp;#34;,&amp;#34;resourceAttributesExpression&amp;#34;:&amp;#34;ResourceAttributes&amp;#34;,&amp;#34;metricTables&amp;#34;:{&amp;#34;gauge&amp;#34;:&amp;#34;otel_metrics_gauge&amp;#34;,&amp;#34;histogram&amp;#34;:&amp;#34;otel_metrics_histogram&amp;#34;,&amp;#34;sum&amp;#34;:&amp;#34;otel_metrics_sum&amp;#34;,&amp;#34;_id&amp;#34;:&amp;#34;682586a8b1f81924e628e808&amp;#34;,&amp;#34;id&amp;#34;:&amp;#34;682586a8b1f81924e628e808&amp;#34;},&amp;#34;connection&amp;#34;:&amp;#34;Local
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;71&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; ClickHouse&amp;#34;,&amp;#34;logSourceId&amp;#34;:&amp;#34;Logs&amp;#34;,&amp;#34;traceSourceId&amp;#34;:&amp;#34;Traces&amp;#34;,&amp;#34;sessionSourceId&amp;#34;:&amp;#34;Sessions&amp;#34;},{&amp;#34;from&amp;#34;:{&amp;#34;databaseName&amp;#34;:&amp;#34;default&amp;#34;,&amp;#34;tableName&amp;#34;:&amp;#34;hyperdx_sessions&amp;#34;},&amp;#34;kind&amp;#34;:&amp;#34;session&amp;#34;,&amp;#34;timestampValueExpression&amp;#34;:&amp;#34;TimestampTime&amp;#34;,&amp;#34;name&amp;#34;:&amp;#34;Sessions&amp;#34;,&amp;#34;displayedTimestampValueExpression&amp;#34;:&amp;#34;Timestamp&amp;#34;,&amp;#34;implicitColumnExpression&amp;#34;:&amp;#34;Body&amp;#34;,&amp;#34;serviceNameExpression&amp;#34;:&amp;#34;ServiceName&amp;#34;,&amp;#34;bodyExpression&amp;#34;:&amp;#34;Body&amp;#34;,&amp;#34;eventAttributesExpression&amp;#34;:&amp;#34;LogAttributes&amp;#34;,&amp;#34;resourceAttributesExpression&amp;#34;:&amp;#34;ResourceAttributes&amp;#34;,&amp;#34;defaultTableSelectExpression&amp;#34;:&amp;#34;Timestamp,ServiceName,SeverityText,Body&amp;#34;,&amp;#34;severityTextExpression&amp;#34;:&amp;#34;SeverityText&amp;#34;,&amp;#34;traceIdExpression&amp;#34;:&amp;#34;TraceId&amp;#34;,&amp;#34;spanIdExpression&amp;#34;:&amp;#34;SpanId&amp;#34;,&amp;#34;connection&amp;#34;:&amp;#34;Local
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;72&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; ClickHouse&amp;#34;,&amp;#34;logSourceId&amp;#34;:&amp;#34;Logs&amp;#34;,&amp;#34;traceSourceId&amp;#34;:&amp;#34;Traces&amp;#34;,&amp;#34;metricSourceId&amp;#34;:&amp;#34;Metrics&amp;#34;}]&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;73&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;74&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;internal&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;75&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;depends_on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;76&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;ch-server&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;77&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;db&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;78&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ch-server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;79&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;clickhouse/clickhouse-server:24-alpine&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;80&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# WARNING: Exposing the database port will make it accessible from outside the container,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;81&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# potentially allowing unauthorized access. If you uncomment the ports below,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;82&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# ensure to secure your database (e.g., with strong authentication, proper network rules, and firewalls).&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;83&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;84&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;8123&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;8123&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# http api&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;85&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="m"&gt;9050&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;9000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# native&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;86&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# environment:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;87&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# default settings&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;88&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;89&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;90&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./docker/clickhouse/local/config.xml:/etc/clickhouse-server/config.xml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;91&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./docker/clickhouse/local/users.xml:/etc/clickhouse-server/users.xml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;92&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./empty.xml:/etc/clickhouse-server/users.d/default-password.xml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;93&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;.volumes/ch_data:/var/lib/clickhouse&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;94&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;.volumes/ch_logs:/var/log/clickhouse-server&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;95&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;on&lt;/span&gt;-&lt;span class="l"&gt;failure&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;96&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;97&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;internal&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;98&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;99&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;internal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意：environment 部分我注释掉了，另外 加了一行：&lt;code&gt;./empty.xml:/etc/clickhouse-server/users.d/default-password.xml&lt;/code&gt; 作用是解决 clickhouse 连接异常的问题。&lt;/p&gt;
&lt;p&gt;通过 &lt;code&gt;/data/clickhouse/hyperdx/docker/clickhouse/local/users.xml&lt;/code&gt; 可以看到 clickhouse 的账户信息：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;clickhouse&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;profiles&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;default&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;max_memory_usage&amp;gt;&lt;/span&gt;10000000000&lt;span class="nt"&gt;&amp;lt;/max_memory_usage&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;use_uncompressed_cache&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/use_uncompressed_cache&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;load_balancing&amp;gt;&lt;/span&gt;in_order&lt;span class="nt"&gt;&amp;lt;/load_balancing&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;log_queries&amp;gt;&lt;/span&gt;1&lt;span class="nt"&gt;&amp;lt;/log_queries&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/default&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/profiles&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;users&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;default&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;password_sha256_hex&amp;gt;&lt;/span&gt;2d964690ad5ac2d2f78bebadc30895bc519969ffcef4d3c9e7ff04ee1c765d96&lt;span class="nt"&gt;&amp;lt;/password_sha256_hex&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;profile&amp;gt;&lt;/span&gt;default&lt;span class="nt"&gt;&amp;lt;/profile&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;networks&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;ip&amp;gt;&lt;/span&gt;::/0&lt;span class="nt"&gt;&amp;lt;/ip&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/networks&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;quota&amp;gt;&lt;/span&gt;default&lt;span class="nt"&gt;&amp;lt;/quota&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/default&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;api&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;password&amp;gt;&lt;/span&gt;api&lt;span class="nt"&gt;&amp;lt;/password&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;profile&amp;gt;&lt;/span&gt;default&lt;span class="nt"&gt;&amp;lt;/profile&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;networks&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;ip&amp;gt;&lt;/span&gt;::/0&lt;span class="nt"&gt;&amp;lt;/ip&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;26&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/networks&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;27&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;quota&amp;gt;&lt;/span&gt;default&lt;span class="nt"&gt;&amp;lt;/quota&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;28&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/api&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;29&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;worker&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;30&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;password&amp;gt;&lt;/span&gt;worker&lt;span class="nt"&gt;&amp;lt;/password&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;31&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;profile&amp;gt;&lt;/span&gt;default&lt;span class="nt"&gt;&amp;lt;/profile&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;32&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;networks&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;33&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;ip&amp;gt;&lt;/span&gt;::/0&lt;span class="nt"&gt;&amp;lt;/ip&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;34&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/networks&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;35&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;quota&amp;gt;&lt;/span&gt;default&lt;span class="nt"&gt;&amp;lt;/quota&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;36&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/worker&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;37&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/users&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;38&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;39&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;quotas&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;40&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;default&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;41&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;interval&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;42&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;duration&amp;gt;&lt;/span&gt;3600&lt;span class="nt"&gt;&amp;lt;/duration&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;43&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;queries&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/queries&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;44&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;errors&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/errors&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;45&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;result_rows&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/result_rows&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;46&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;read_rows&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/read_rows&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;47&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;execution_time&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/execution_time&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;48&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/interval&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;49&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/default&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;50&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/quotas&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;51&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/clickhouse&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;密码用 sha256sum 处理过&lt;/p&gt;
&lt;p&gt;可以这样生成：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;echo -n &amp;#39;你的密码&amp;#39; | sha256sum
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="运行"&gt;&lt;a href="#%e8%bf%90%e8%a1%8c" class="header-anchor"&gt;&lt;/a&gt;运行
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-07-17-kuai-su-an-zhuang-clickhouse/001-1d333d30.png"&gt;点击登录跳转至首页&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-07-17-kuai-su-an-zhuang-clickhouse/002-f8c34343.png"&gt;&lt;/p&gt;
&lt;h2 id="客户端连接"&gt;&lt;a href="#%e5%ae%a2%e6%88%b7%e7%ab%af%e8%bf%9e%e6%8e%a5" class="header-anchor"&gt;&lt;/a&gt;客户端连接
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;用户名：default&lt;/li&gt;
&lt;li&gt;密码： 你的密码&lt;/li&gt;
&lt;li&gt;端口：8123&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-07-17-kuai-su-an-zhuang-clickhouse/003-39f76698.png"&gt;&lt;/p&gt;
&lt;h2 id="数据库初始化"&gt;&lt;a href="#%e6%95%b0%e6%8d%ae%e5%ba%93%e5%88%9d%e5%a7%8b%e5%8c%96" class="header-anchor"&gt;&lt;/a&gt;数据库初始化
&lt;/h2&gt;&lt;p&gt;初始化 sql 脚本&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 1. 创建数据库（如已存在可先 DROP DATABASE IF EXISTS testdb） */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DATABASE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;EXISTS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 2. 维度表：用户 */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;EXISTS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UInt32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;signup_date&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ENGINE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MergeTree&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 3. 维度表：页面 */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;EXISTS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UInt32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page_url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ENGINE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MergeTree&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 4. 事实表：页面访问日志 */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;EXISTS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pageviews&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event_date&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UInt32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UInt32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;26&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UInt32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;-- 停留秒数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;27&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ENGINE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MergeTree&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;28&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;PARTITION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;toYYYYMM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event_date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;29&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;30&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;31&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 5. 物化视图：每日 PV / UV 聚合 */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;32&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;MATERIALIZED&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VIEW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;IF&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;NOT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;EXISTS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pv_uv_daily&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;33&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ENGINE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;SummingMergeTree&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;34&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;PARTITION&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;toYYYYMM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event_date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;35&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event_date&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;36&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;37&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;38&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;39&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;40&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uniqExact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;41&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pageviews&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;42&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;GROUP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event_date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;43&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;44&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 6. 演示数据插入 ---------------------------------------- */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;45&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;46&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 用户维度 */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;47&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;signup_date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;48&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Alice&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2024-06-01&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;49&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Bob&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2024-07-15&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;50&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Cathy&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2024-11-30&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;51&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;52&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 页面维度 */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;53&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;54&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/home&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;landing&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;55&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/pricing&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;info&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;56&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/blog&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;content&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;57&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;58&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 页面访问日志 */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;59&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pageviews&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event_date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;VALUES&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;60&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2025-07-13&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2025-07-13 09:17:00&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;61&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2025-07-13&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2025-07-13 09:18:07&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;62&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2025-07-13&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2025-07-13 09:19:02&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;63&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2025-07-14&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2025-07-14 10:03:45&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;64&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2025-07-14&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;2025-07-14 10:05:22&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;65&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;66&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 7. 快速验证 --------------------------------------------- */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;67&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;68&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 查看当前数据库已创建的表 */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;69&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SHOW&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TABLES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;70&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;71&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 查询物化视图结果 */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;72&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pv_uv_daily&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;event_date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;73&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;74&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* 联表查询示例 */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;75&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;76&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;77&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;78&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;79&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;80&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pageviews&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;81&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;LEFT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;82&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;LEFT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;testdb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pages&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;83&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>Milvus 向量数据库快速入门（人话版）</title><link>https://xiaobox.github.io/p/2025-06-01-milvus-xiang-liang-shu-ju-ku-kuai-su-ru-men-ren-hua-ban/</link><pubDate>Sun, 01 Jun 2025 04:03:27 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-06-01-milvus-xiang-liang-shu-ju-ku-kuai-su-ru-men-ren-hua-ban/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-06-01-milvus-xiang-liang-shu-ju-ku-kuai-su-ru-men-ren-hua-ban/cover.jpg" alt="Featured image of post Milvus 向量数据库快速入门（人话版）" /&gt;&lt;h2 id="milvus-到底是干嘛的"&gt;&lt;a href="#milvus-%e5%88%b0%e5%ba%95%e6%98%af%e5%b9%b2%e5%98%9b%e7%9a%84" class="header-anchor"&gt;&lt;/a&gt;Milvus 到底是干嘛的？
&lt;/h2&gt;&lt;p&gt;它是“给向量找对象”的超高速数据库——存向量、比相似、返回前 K 名。&lt;/p&gt;
&lt;p&gt;Milvus 就是给「向量」找对象的数据库——它能帮你把一堆高维向量存好、管好、飞快地按“相似度”把最像的几条挑出来。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;和普通数据库比，Milvus天生会“模糊配对”，不是 exact match 而是“谁更像”。&lt;/li&gt;
&lt;li&gt;内核走的是“先分桶/建图，再局部暴力”，所以大规模也能搜得飞快。&lt;/li&gt;
&lt;li&gt;2.x 版本把「数据落盘」「分布式容灾」都外包给 RocksDB + MinIO + etcd——省了你很多心。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="先认几个关键词"&gt;&lt;a href="#%e5%85%88%e8%ae%a4%e5%87%a0%e4%b8%aa%e5%85%b3%e9%94%ae%e8%af%8d" class="header-anchor"&gt;&lt;/a&gt;先认几个关键词
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-06-01-milvus-xiang-liang-shu-ju-ku-kuai-su-ru-men-ren-hua-ban/001-c2fdff5a.png"&gt;&lt;/p&gt;
&lt;h2 id="部署使用"&gt;&lt;a href="#%e9%83%a8%e7%bd%b2%e4%bd%bf%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;部署使用
&lt;/h2&gt;&lt;p&gt;五步跑通「单机体验」+ 三步升级「小集群」&lt;/p&gt;
&lt;h3 id="单机-5-步"&gt;&lt;a href="#%e5%8d%95%e6%9c%ba-5-%e6%ad%a5" class="header-anchor"&gt;&lt;/a&gt;单机 5 步
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;拉镜像 docker run milvusdb/milvus:v2.4.3&lt;/li&gt;
&lt;li&gt;建楼 create_collection()——确定字段维度、主键、向量字段。&lt;/li&gt;
&lt;li&gt;搬人 insert() → flush()。&lt;/li&gt;
&lt;li&gt;装电梯 create_index()；小数据直接 FLAT，大数据先 IVF，再视情况换 HNSW。&lt;/li&gt;
&lt;li&gt;开门找人 load() → search()/query()；用完可 release().&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="变成-3-节点小集群"&gt;&lt;a href="#%e5%8f%98%e6%88%90-3-%e8%8a%82%e7%82%b9%e5%b0%8f%e9%9b%86%e7%be%a4" class="header-anchor"&gt;&lt;/a&gt;变成 3 节点小集群
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-06-01-milvus-xiang-liang-shu-ju-ku-kuai-su-ru-men-ren-hua-ban/002-c0911d8c.png"&gt;&lt;/p&gt;
&lt;h2 id="最常用的-5-步操作"&gt;&lt;a href="#%e6%9c%80%e5%b8%b8%e7%94%a8%e7%9a%84-5-%e6%ad%a5%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;&lt;/a&gt;最常用的 5 步操作
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;建楼：create collection，把字段都定义好&lt;/li&gt;
&lt;li&gt;搬人：insert，把向量和元信息塞进去；记得 flush() 真正落盘&lt;/li&gt;
&lt;li&gt;装电梯：create index，选对索引类型，未来搜索才快&lt;/li&gt;
&lt;li&gt;请保安开门：load，没 load 就像门锁着，啥也搜不到&lt;/li&gt;
&lt;li&gt;找人：search（可加条件 expr），或者只按字段 query&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="索引怎么挑"&gt;&lt;a href="#%e7%b4%a2%e5%bc%95%e6%80%8e%e4%b9%88%e6%8c%91" class="header-anchor"&gt;&lt;/a&gt;索引怎么挑？
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-06-01-milvus-xiang-liang-shu-ju-ku-kuai-su-ru-men-ren-hua-ban/003-0a75133a.png"&gt;&lt;/p&gt;
&lt;h2 id="索引调优口诀"&gt;&lt;a href="#%e7%b4%a2%e5%bc%95%e8%b0%83%e4%bc%98%e5%8f%a3%e8%af%80" class="header-anchor"&gt;&lt;/a&gt;索引调优口诀
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;小样本先 FLAT 做 baseline——它慢但最准，方便肉眼看 Recall。&lt;/li&gt;
&lt;li&gt;百 万级优先 IVF_FLAT：调 nlist=√N 起步；提高 nprobe 越准越慢。&lt;/li&gt;
&lt;li&gt;千万级冲 HNSW：关键参 M (边数) 和 efConstruction (建图宽度)，调高两倍能大幅增 Recall。&lt;/li&gt;
&lt;li&gt;超高并发记得“机＋内存”一起扩——索引放内存，多副本才分摊 QPS。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="别踩这些坑-"&gt;&lt;a href="#%e5%88%ab%e8%b8%a9%e8%bf%99%e4%ba%9b%e5%9d%91-" class="header-anchor"&gt;&lt;/a&gt;别踩这些坑 💡
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;向量维度要统一：128 就全 128，别混着来。&lt;/li&gt;
&lt;li&gt;插完别忘 flush：不 flush 就像东西放购物车没结账，搜索不到。&lt;/li&gt;
&lt;li&gt;没 load 就搜索：会报错，先 load()。&lt;/li&gt;
&lt;li&gt;内存不够全加载：用 Partition，分批 load()。&lt;/li&gt;
&lt;li&gt;精度不满意：调 nprobe（IVF）或换 HNSW 试试。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="十大踩坑--急救方案"&gt;&lt;a href="#%e5%8d%81%e5%a4%a7%e8%b8%a9%e5%9d%91--%e6%80%a5%e6%95%91%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;十大踩坑 + 急救方案
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-06-01-milvus-xiang-liang-shu-ju-ku-kuai-su-ru-men-ren-hua-ban/004-d5e81d65.png"&gt;&lt;/p&gt;
&lt;h2 id="再进阶一点点"&gt;&lt;a href="#%e5%86%8d%e8%bf%9b%e9%98%b6%e4%b8%80%e7%82%b9%e7%82%b9" class="header-anchor"&gt;&lt;/a&gt;再进阶一点点
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Hybrid Search：边比向量相似度，边过滤价格 &amp;lt; 500 这种条件，SQL 味道更浓。&lt;/li&gt;
&lt;li&gt;一致性模式：默认够用；真要跨机房强一致性就选 Strong。&lt;/li&gt;
&lt;li&gt;持久化：Milvus 本身用 RocksDB ＋ MinIO 存数据，你不用操心怎么落盘。&lt;/li&gt;
&lt;li&gt;与 RAG 的关系：大模型把文本→向量，Milvus 负责“最近邻检索”，再把查到的文档喂回模型。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="跟其它工具怎么配"&gt;&lt;a href="#%e8%b7%9f%e5%85%b6%e5%ae%83%e5%b7%a5%e5%85%b7%e6%80%8e%e4%b9%88%e9%85%8d" class="header-anchor"&gt;&lt;/a&gt;跟其它工具怎么配？
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;LangChain / LlamaIndex：把 Milvus VectorStore 接进去即可，RAG 极速上线。&lt;/li&gt;
&lt;li&gt;Spark / Flink：批量离线写入 Milvus；确保分批 1 万条以内避免 RPC 超时。&lt;/li&gt;
&lt;li&gt;Airflow：定时 ETL → Embedding → Milvus；flush、compact 都能写成 task。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="到底需要多大机器粗算公式"&gt;&lt;a href="#%e5%88%b0%e5%ba%95%e9%9c%80%e8%a6%81%e5%a4%9a%e5%a4%a7%e6%9c%ba%e5%99%a8%e7%b2%97%e7%ae%97%e5%85%ac%e5%bc%8f" class="header-anchor"&gt;&lt;/a&gt;“到底需要多大机器？”——粗算公式
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;内存 ≈ （向量维度 × 4 bytes × 向量条数 × 1.4 倍索引系数）﹢ 元数据大小&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;例：1 亿条 768 维 → 768×4×1e8×1.4 ≈ 430 GB（得至少 512 GB 机器，或分区加载）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;硬盘 ≈ 内存 × 1.2（索引 + RocksDB + 日志）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;512G 内存看起来有点儿夸张，所以如果内存吃紧，可以参考以下方法进行优化：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-06-01-milvus-xiang-liang-shu-ju-ku-kuai-su-ru-men-ren-hua-ban/005-35ceb743.png"&gt;&lt;/p&gt;
&lt;h2 id="python-端到端-demo-含增删改查"&gt;&lt;a href="#python-%e7%ab%af%e5%88%b0%e7%ab%af-demo-%e5%90%ab%e5%a2%9e%e5%88%a0%e6%94%b9%e6%9f%a5" class="header-anchor"&gt;&lt;/a&gt;Python 端到端 Demo （含增删改查）
&lt;/h2&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pymilvus&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;connections&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FieldSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CollectionSchema&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;np&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 3&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 4&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;connections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;localhost&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;19530&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 5&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 6&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1. 建楼（如果已存在就删掉重建）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;demo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;drop_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;demo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 8&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt; 9&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CollectionSchema&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;10&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;FieldSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DataType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INT64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_primary&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auto_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;11&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;FieldSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DataType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;12&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;FieldSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;price&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DataType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FLOAT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;13&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;FieldSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;emb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DataType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FLOAT_VECTOR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;14&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;15&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;demo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;16&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;17&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 2. 插 10 条数据&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;18&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;titles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;商品&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;19&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;20&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;vecs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;21&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;titles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vecs&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;22&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;23&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 3. 建 IVF 索引 &amp;amp; 加载&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;24&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;emb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;index_type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;IVF_FLAT&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;metric_type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;L2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;params&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;nlist&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;25&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;26&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;27&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 4. 搜索 + 过滤价格 &amp;lt; 50&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;28&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;qv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;29&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;emb&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;metric_type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;L2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;params&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;nprobe&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;price &amp;lt; 50&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;30&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;([(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;title&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;31&lt;/span&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;32&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 5. 删除一条，再查&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;33&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;del_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;34&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;id in [&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;del_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item><item><title>2025北京 IT技术岗位市场趋势分析</title><link>https://xiaobox.github.io/p/2025-04-17-2025-bei-jing-it-ji-shu-gang-wei-shi-chang-qu-shi-fen-xi/</link><pubDate>Thu, 17 Apr 2025 02:20:56 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-04-17-2025-bei-jing-it-ji-shu-gang-wei-shi-chang-qu-shi-fen-xi/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-04-17-2025-bei-jing-it-ji-shu-gang-wei-shi-chang-qu-shi-fen-xi/cover.jpg" alt="Featured image of post 2025北京 IT技术岗位市场趋势分析" /&gt;&lt;p&gt;过去一年，北京数字经济对 GDP 的贡献继续攀升、AI + 传统产业融合提速，拉动技术岗位需求在 2025 年保持“量稳、质升”——总招聘量与 2024 年大体持平，但 &lt;strong&gt;高端与 AI‑相关职能增幅 15% 以上&lt;/strong&gt;；与此同时，普通开发与测试岗位竞争加剧、薪酬增速放缓。整体呈现“尖端紧缺‑常规内卷”的双轨格局。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-04-17-2025-bei-jing-it-ji-shu-gang-wei-shi-chang-qu-shi-fen-xi/001-91b70463.png"&gt;&lt;/p&gt;
&lt;p&gt;下面按岗位类型分述趋势、薪酬区间与热门技能。&lt;/p&gt;
&lt;h2 id="宏观驱动与整体需求"&gt;&lt;a href="#%e5%ae%8f%e8%a7%82%e9%a9%b1%e5%8a%a8%e4%b8%8e%e6%95%b4%e4%bd%93%e9%9c%80%e6%b1%82" class="header-anchor"&gt;&lt;/a&gt;宏观驱动与整体需求
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;北京仍是全国数字经济第一城，数字产业增加值年均增速 9%，5G、人工智能、信创（国产软硬件）成为新增岗位主引擎&lt;/li&gt;
&lt;li&gt;2025 Hays 人才趋势显示，&lt;strong&gt;生成式 AI 项目扩张&lt;/strong&gt;、&lt;strong&gt;混合办公&lt;/strong&gt;、&lt;strong&gt;用工灵活化&lt;/strong&gt; 是企业技术团队的三大关键词。&lt;/li&gt;
&lt;li&gt;拉勾《一线城市数字科技人才迁徙洞察》指出，北京对高端技术人才的 &lt;strong&gt;净流入率 17.8%&lt;/strong&gt; ，居四大一线城市之首，但应届生流入比例下降 4 pct，反映供给结构趋紧。&lt;/li&gt;
&lt;li&gt;信息技术业 2024Q2‑2025Q1 招聘量同比下滑 27.8%，但算法、运维支持、产品管理等职能逆势增长。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-04-17-2025-bei-jing-it-ji-shu-gang-wei-shi-chang-qu-shi-fen-xi/002-dd656b09.png"&gt;&lt;/p&gt;
&lt;h2 id="细分岗位趋势"&gt;&lt;a href="#%e7%bb%86%e5%88%86%e5%b2%97%e4%bd%8d%e8%b6%8b%e5%8a%bf" class="header-anchor"&gt;&lt;/a&gt;细分岗位趋势
&lt;/h2&gt;&lt;h3 id="前端开发"&gt;&lt;a href="#%e5%89%8d%e7%ab%af%e5%bc%80%e5%8f%91" class="header-anchor"&gt;&lt;/a&gt;前端开发
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&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;strong&gt;框架&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;React18、Vue3 + TypeScript 成主流；大厂面试开始考察 RSC、微前端落地经验。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;多端融合&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;ByteDance、京东等推行 Modular/Universal mode，将 H5 + 小程序 + 桌面统一到一套代码。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;AI‑Assist&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;高频使用 GitHub Copilot、ByteDance CodeGeeX 等 AI 辅助，企业更看重 Prompt‑Engineering 基础。&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;平均月薪区间 2 – 3.5 万元；头部公司核心前端 &amp;gt; 4.5 万元。&lt;/p&gt;
&lt;h3 id="后端全栈开发"&gt;&lt;a href="#%e5%90%8e%e7%ab%af%e5%85%a8%e6%a0%88%e5%bc%80%e5%8f%91" class="header-anchor"&gt;&lt;/a&gt;后端／全栈开发
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Go + Rust&lt;/strong&gt; 在高并发与可信场景快速渗透，Java 依旧占 48% 招聘量。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cloud‑Native&lt;/strong&gt;：K8s、Service Mesh、Sidecar 架构写入 JD；Serverless FaaS 试点项目增多。&lt;/li&gt;
&lt;li&gt;薪酬与前端近似，但 3–6 年经验段的涨幅（+6.8% YoY）高于前端。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="运维--sre"&gt;&lt;a href="#%e8%bf%90%e7%bb%b4--sre" class="header-anchor"&gt;&lt;/a&gt;运维 / SRE
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;自动化 &amp;amp; AIOps&lt;/strong&gt;：日志可观测、LLM‑based Root Cause Analysis 成新卖点。&lt;/li&gt;
&lt;li&gt;大厂 DevOps‑SRE 岗位给出 &lt;strong&gt;15k–50k/月&lt;/strong&gt;，中位值 34k，高于全国均值 21k&lt;/li&gt;
&lt;li&gt;需求集中在云平台运维、容器治理、CI /CD 流水线二次开发。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="测试--qa"&gt;&lt;a href="#%e6%b5%8b%e8%af%95--qa" class="header-anchor"&gt;&lt;/a&gt;测试 / QA
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Shift‑Left&lt;/strong&gt;：招聘 JD 要求能写 E2E、契合 DevSecOps；懂 API/性能/安全一体的 Full‑Stack QA 稀缺。&lt;/li&gt;
&lt;li&gt;普通功能测试招聘量降 12%，月薪中位值 &lt;strong&gt;14k&lt;/strong&gt;；自动化 / 安全测试可达 2 – 2.5 万元。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="架构--ai-大模型"&gt;&lt;a href="#%e6%9e%b6%e6%9e%84--ai-%e5%a4%a7%e6%a8%a1%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;架构 / AI 大模型
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;大模型平台化&lt;/strong&gt;：企业亟需能打通推理服务、RAG、知识治理的“业务 + 算法 + 云”复合型架构师。&lt;/li&gt;
&lt;li&gt;北京人社局薪酬季报：AI 大模型架构师、深度学习研究员一季度月薪中位值 &lt;strong&gt;&amp;gt; 4 万元&lt;/strong&gt;，位列所有 IT 职位之首。&lt;/li&gt;
&lt;li&gt;供应缺口：相关岗位投递比仅 1 : 7，而常规开发已超过 1 : 40。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="薪酬对比中位值税前--月"&gt;&lt;a href="#%e8%96%aa%e9%85%ac%e5%af%b9%e6%af%94%e4%b8%ad%e4%bd%8d%e5%80%bc%e7%a8%8e%e5%89%8d--%e6%9c%88" class="header-anchor"&gt;&lt;/a&gt;薪酬对比（中位值，税前 / 月）
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;职能&lt;/th&gt;
 &lt;th&gt;初级 (0‑3 年)&lt;/th&gt;
 &lt;th&gt;中级 (3‑6 年)&lt;/th&gt;
 &lt;th&gt;高级 / 专家&lt;/th&gt;
 &lt;th&gt;YoY 涨幅&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;前端&lt;/td&gt;
 &lt;td&gt;14 k&lt;/td&gt;
 &lt;td&gt;23 k&lt;/td&gt;
 &lt;td&gt;32 k+&lt;/td&gt;
 &lt;td&gt;+3.5 %&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;后端&lt;/td&gt;
 &lt;td&gt;15 k&lt;/td&gt;
 &lt;td&gt;25 k&lt;/td&gt;
 &lt;td&gt;35 k+&lt;/td&gt;
 &lt;td&gt;+6.8 %&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;运维 / SRE&lt;/td&gt;
 &lt;td&gt;16 k&lt;/td&gt;
 &lt;td&gt;28 k&lt;/td&gt;
 &lt;td&gt;40 k+&lt;/td&gt;
 &lt;td&gt;+5.9 %&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;测试&lt;/td&gt;
 &lt;td&gt;12 k&lt;/td&gt;
 &lt;td&gt;18 k&lt;/td&gt;
 &lt;td&gt;25 k&lt;/td&gt;
 &lt;td&gt;+2.1 %&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;架构 / AI&lt;/td&gt;
 &lt;td&gt;25 k&lt;/td&gt;
 &lt;td&gt;38 k&lt;/td&gt;
 &lt;td&gt;45‑60 k&lt;/td&gt;
 &lt;td&gt;+11.4 %&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;（数据综合北京 HR 局薪酬季报、Indeed、Jobui 与 iHR360 行业库）&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-04-17-2025-bei-jing-it-ji-shu-gang-wei-shi-chang-qu-shi-fen-xi/003-a40bfb60.png"&gt;&lt;/p&gt;
&lt;h2 id="-技能热点与企业偏好"&gt;&lt;a href="#-%e6%8a%80%e8%83%bd%e7%83%ad%e7%82%b9%e4%b8%8e%e4%bc%81%e4%b8%9a%e5%81%8f%e5%a5%bd" class="header-anchor"&gt;&lt;/a&gt;🔥 技能热点与企业偏好
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AI 嵌入&lt;/strong&gt;：Prompt‑based 代码补全、Auto‑Test、知识库问答等场景让 Python / LLM SDK 成为附加加分项。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;安全合规&lt;/strong&gt;：等保 2.0、个人信息保护法落地，带动安全测试、DevSecOps、零信任架构招聘量增 19% YoY&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;信创&lt;/strong&gt;：国资系招募国产 CPU / OS 适配工程师，优惠补贴年包 +20%。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="供需与竞争"&gt;&lt;a href="#%e4%be%9b%e9%9c%80%e4%b8%8e%e7%ab%9e%e4%ba%89" class="header-anchor"&gt;&lt;/a&gt;供需与竞争
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;北京技术岗位投递量继续领跑一线城市；但 AI、大模型方向平均 &lt;strong&gt;每 1 份 JD 仅 7 份简历&lt;/strong&gt;，反之普通 Web 开发超过 40 份简历/岗，显现结构性紧缺。&lt;/li&gt;
&lt;li&gt;北京 2025Q1 IT 岗位平均薪资 2.9 万元，中位值 2.46 万元；同比涨幅 1.1%，明显低于 2021‑22 年两位数增速。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="给企业与求职者的建议"&gt;&lt;a href="#%e7%bb%99%e4%bc%81%e4%b8%9a%e4%b8%8e%e6%b1%82%e8%81%8c%e8%80%85%e7%9a%84%e5%bb%ba%e8%ae%ae" class="header-anchor"&gt;&lt;/a&gt;给企业与求职者的建议
&lt;/h2&gt;&lt;h3 id="企业"&gt;&lt;a href="#%e4%bc%81%e4%b8%9a" class="header-anchor"&gt;&lt;/a&gt;企业
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;拆分 JD&lt;/strong&gt;：将“平台研发”与“AI 应用落地”拆分，便于精准匹配候选人。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;用薪酬+Tech Brand 双重激励&lt;/strong&gt;：高端人才更看重技术氛围与成长空间，可开放技术博客、OSS 贡献等展示窗口。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;培养内部转岗&lt;/strong&gt;：参考 LinkedIn 数据，内部流动可将员工留存提升 40%&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="求职者"&gt;&lt;a href="#%e6%b1%82%e8%81%8c%e8%80%85" class="header-anchor"&gt;&lt;/a&gt;求职者
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;普通开发/测试应持续补齐 &lt;strong&gt;云原生 + 自动化测试 + 基础 AI&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;关注国央企“信创”“数据要素”等长期项目，以稳就业与培训机会为优势；&lt;/li&gt;
&lt;li&gt;AI &amp;amp; 架构方向建议组合 &lt;strong&gt;算法实践 + 高并发系统设计 + 行业领域知识&lt;/strong&gt;，扩大竞争壁垒。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;北京 2025 年 IT 技术岗位的主旋律是 &lt;strong&gt;“AI 驱动的高端岗位紧缺，传统岗位理性回调”&lt;/strong&gt;。掌握新技能、拥抱跨领域融合将是穿越周期的关键。&lt;/p&gt;

 &lt;/blockquote&gt;</description></item><item><title>Java老兵的十字路口：坚守还是突围？</title><link>https://xiaobox.github.io/p/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/</link><pubDate>Sat, 29 Mar 2025 05:33:55 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/cover.jpg" alt="Featured image of post Java老兵的十字路口：坚守还是突围？" /&gt;&lt;h2 id="java在技术江湖中的现状稳固基石还是夕阳西下"&gt;&lt;a href="#java%e5%9c%a8%e6%8a%80%e6%9c%af%e6%b1%9f%e6%b9%96%e4%b8%ad%e7%9a%84%e7%8e%b0%e7%8a%b6%e7%a8%b3%e5%9b%ba%e5%9f%ba%e7%9f%b3%e8%bf%98%e6%98%af%e5%a4%95%e9%98%b3%e8%a5%bf%e4%b8%8b" class="header-anchor"&gt;&lt;/a&gt;Java在技术江湖中的现状：稳固基石还是夕阳西下？
&lt;/h2&gt;&lt;p&gt;Java 作为企业级开发的常青树，至今在大量核心系统中扮演着中流砥柱的角色。然而，资深 Java 开发者也明显感受到技术环境的变化。一方面，在银行、政府、互联网巨头等复杂业务场景中，Java 的地位依然稳固；大量遗留系统和核心业务仍运行在 Java 上，短期内很难被完全替换。以优酷的版权管理系统为例，这套长达10年的老系统采用了过时的技术框架，积累了 81万行 Java 代码和大量“没人敢动”的if-else逻辑，可谓技术债累累。像这样的遗留系统，全面重构风险极高，只能在业务推动下逐步演进。因此，在许多传统领域，Java 作为“老码农”的看家本领，仍是不可或缺的基石。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/001-40dd5948.png"&gt;&lt;/p&gt;
&lt;p&gt;另一方面，新兴业务和初创项目对技术栈的选择更加多元。近年Go语言等后起之秀在性能、并发和开发效率上表现出色，成为云原生时代的“宠儿”。不少互联网大厂开始在核心服务中引入 Go：例如谷歌、滴滴、Uber、腾讯等都用 Go 开发高并发、高性能的服务。业界一度流传着“Java 老旧笨重、Go 崭新酷炫”的声音。面对这种冲击，不少资深 Java 工程师难免焦虑：Java 会不会像当年的 COBOL 一样淡出主流舞台？&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/002-28c85ce1.png"&gt;&lt;/p&gt;
&lt;p&gt;事实证明，这种担忧有些过度。Java 拥有数百万开发者和完整生态，并非轻易就能被取代的工具。正如有分析指出，Go 的崛起为行业提供了新选择，但并不是对 Java 的简单替代；两种语言各有优势，未来将长期共存。换言之，Java 依旧是技术江湖里的定海神针，只是江湖规矩变了——老兵们需要适应新玩法。&lt;/p&gt;
&lt;h2 id="java-面临的核心挑战笨重背后的突围"&gt;&lt;a href="#java-%e9%9d%a2%e4%b8%b4%e7%9a%84%e6%a0%b8%e5%bf%83%e6%8c%91%e6%88%98%e7%ac%a8%e9%87%8d%e8%83%8c%e5%90%8e%e7%9a%84%e7%aa%81%e5%9b%b4" class="header-anchor"&gt;&lt;/a&gt;Java 面临的核心挑战：笨重背后的突围
&lt;/h2&gt;&lt;p&gt;资深 Java 开发者在项目实践中遇到的挑战，往往并非语言本身跑不动，而是架构转型带来的“不适感”。近年来微服务、云原生风潮兴起，Java 传统的开发模式在新环境下面临诸多掣肘。&lt;/p&gt;
&lt;h3 id="微服务部署压力"&gt;&lt;a href="#%e5%be%ae%e6%9c%8d%e5%8a%a1%e9%83%a8%e7%bd%b2%e5%8e%8b%e5%8a%9b" class="header-anchor"&gt;&lt;/a&gt;微服务部署压力
&lt;/h3&gt;&lt;p&gt;将单体应用拆成数十上百的微服务后，每个服务都需要独立部署运行。Java 应用启动慢、内存占用高的问题被放大。在同样功能下，一个简单的 Go 容器镜像可能只有十几MB，而等价的 Java（如采用 Helidon 框架）镜像初始体积高达 1.4GB！即使使用模块化手段缩减JDK体积（JLink可降至150MB左右），Java应用的容器仍显得臃肿。如此高的基础开销让追求极致弹性的微服务架构如临大敌：部署50个 Java 微服务可能需要远超预期的硬件资源，这正是很多团队转向更轻量语言的原因之一。有开发者调侃：“即便Java性能再好，内存占用是别人的 2～10倍，成本账算下来也让人犹豫。”而且在无服务器（Serverless）场景下，Java 冷启动延迟更是令人头疼——函数实例首次启动可能耗时数秒到十几秒。这一问题长期无法回避，直到 AWS 推出 SnapStart 等黑科技，把 Java 函数冷启动时间缩短到毫秒级，才算勉强止血。但需要注意，这类优化是云厂商额外提供的特殊支持，侧面说明 Java 在边缘计算、FaaS 等领域的先天劣势依然存在。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/003-c6bc61f8.png"&gt;&lt;/p&gt;
&lt;h3 id="启动速度与样板代码"&gt;&lt;a href="#%e5%90%af%e5%8a%a8%e9%80%9f%e5%ba%a6%e4%b8%8e%e6%a0%b7%e6%9d%bf%e4%bb%a3%e7%a0%81" class="header-anchor"&gt;&lt;/a&gt;启动速度与样板代码
&lt;/h3&gt;&lt;p&gt;“万事开头难”在 Java 世界格外贴切。传统 Java Web 应用往往需要预热 JVM、加载大量类和配置，启动一个服务动辄数十秒甚至几分钟。这在强调弹性伸缩的云环境下难以接受。此外，Java 以模板代码多著称，同样的业务逻辑，用 Java 写可能需要冗长的类定义和 Getter/Setter，而用 Go/Kotlin 等语言则简洁得多。例如，Go 以极简的语法实现高并发，让开发者专注于业务；相比之下，过去的 Java 代码显得繁琐累赘，不少老兵自己也调侃天天在写“体力活”。虽然 Java 近年通过 Lambda、Streams、Records 等特性在不断精简，但是遗留项目中的大量样板代码依旧是维护负担。缺乏某些现代语言特性（如模式匹配、代数数据类型）也使Java在表达某些逻辑时不够优雅。这些痛点促使部分团队尝试用 Kotlin 等 JVM 语言替换 Java，以期获得更简洁的语法和更少的冗余。&lt;/p&gt;
&lt;h3 id="并发与性能困境"&gt;&lt;a href="#%e5%b9%b6%e5%8f%91%e4%b8%8e%e6%80%a7%e8%83%bd%e5%9b%b0%e5%a2%83" class="header-anchor"&gt;&lt;/a&gt;并发与性能困境
&lt;/h3&gt;&lt;p&gt;高并发一直是 Java 的强项，但实现方式却日益受到挑战。传统 Java 使用操作系统线程实现并发，每个线程都对应一定的内存和调度开销，在大规模场景下显得“沉重”。为绕过这个瓶颈，过去几年兴起了基于 Reactive 异步编程的微服务框架，通过单线程事件循环避免线程阻塞。然而异步风格代码复杂度高、调试困难，让许多工程师“叫苦不迭”。好消息是，JDK 19/20 引入了虚拟线程（Project Loom）并在 JDK 21 成为正式特性。虚拟线程是由 JVM 管理的超轻量线程，实现了 Go 协程式的并发模型。这意味着开发者可以用以往同步阻塞的简单代码，实现过去需要复杂回调/响应式才能处理的高并发任务。正如 Java 架构师 Brian Goetz 所言：Loom 的出现有望“一举终结Reactive编程的必要”——因为过去Reactive是为解决线程不足的权宜之计。虚拟线程让我们能够创建成千上万个并发任务而不必担心线程耗尽，大幅降低了编写和维护高并发代码的心智负担。然而，新事物也伴随不确定性：老项目若迁移到虚拟线程模型，需要评估线程本地变量、同步机制等是否还能正常工作；调优方式也与传统线程有所不同。目前虚拟线程虽强大，但毕竟是新特性，在大型生产环境中的考验还不充分。Java 老兵们既期待它带来性能飞跃，也需要保持一份观望和谨慎。&lt;/p&gt;
&lt;h3 id="graalvm-与原生执行"&gt;&lt;a href="#graalvm-%e4%b8%8e%e5%8e%9f%e7%94%9f%e6%89%a7%e8%a1%8c" class="header-anchor"&gt;&lt;/a&gt;GraalVM 与原生执行
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/004-3147eb4e.png"&gt;&lt;/p&gt;
&lt;p&gt;为了解决启动慢、内存高的问题，Java 社区近年另一“大招”是 GraalVM 原生镜像。通过提前编译(AOT)，可以将 Java 应用直接打包成本地可执行文件，启动时间和内存占用都有数量级的优化。这项技术被视为让 Java 重返边缘计算和 Serverless 舞台的希望：原生镜像下，一个 Spring Boot 微服务的“Hello World”容器镜像可小到 ~几十MB；运行时不需要JVM，冷启动延迟大幅降低。实际测试中，采用 GraalVM 原生镜像的 Java 服务在某些基准下性能甚至超越 Go：平均延迟仅0.25毫秒，每秒处理事务达到82426次，吞吐率是 Go 实现的两倍多！这种结果令人振奋，仿佛看到了 Java 打了一场漂亮的翻身仗。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/005-846f3af1.png"&gt;&lt;/p&gt;
&lt;p&gt;然而，理想很丰满，现实有时比较骨感。将复杂应用迁移到 GraalVM 原生镜像并非易事。例如，反射、动态代理等机制需要额外配置支持，许多成熟库在AOT编译下可能行为异常。构建原生镜像的过程也比较繁琐，往往需要调整代码、引入特定插件，并忍受较长的编译时间。调试诊断也更具挑战——原生应用无法使用 JVM 的丰富调试工具，需要新的手段排查问题。此外，引入 GraalVM 还意味着团队需要掌握一套新的知识体系。在的总结中作者就指出：“将 Spring Boot 应用打包为 Native 镜像并非没有挑战”，直接迁移复杂项目可能遇到种种坑，需要开发者充分评估和测试。因此，GraalVM 不是万能灵药，而是有门槛的新武器：用得好，Java 如虎添翼；用不好，反而可能引入新的不稳定因素。&lt;/p&gt;
&lt;p&gt;综上，资深 Java 开发者面对的不是“Java 不行了”，而是如何让 Java 行得更轻、更快、更优雅。JVM 社区显然没有躺在功劳簿上吃老本，而是在微服务、云原生时代积极求变。从 Spring Boot 3 对原生镜像的支持，到 JDK 连续的功能升级（如Records、Pattern Matching等），Java 正在努力破除“笨重”的刻板印象。老兵们需要做的，是与时俱进地拥抱这些变化，用新工具、新思路来武装自己的Java技能库。&lt;/p&gt;
&lt;h2 id="用舍之道哪些场景放弃-java哪些场景坚持-java"&gt;&lt;a href="#%e7%94%a8%e8%88%8d%e4%b9%8b%e9%81%93%e5%93%aa%e4%ba%9b%e5%9c%ba%e6%99%af%e6%94%be%e5%bc%83-java%e5%93%aa%e4%ba%9b%e5%9c%ba%e6%99%af%e5%9d%9a%e6%8c%81-java" class="header-anchor"&gt;&lt;/a&gt;用舍之道：哪些场景放弃 Java，哪些场景坚持 Java？
&lt;/h2&gt;&lt;p&gt;技术选型从来都不是非黑即白，对于 Java 的去留更是如此。究竟在哪些业务场景下应该考虑放弃 Java？哪些场景下 Java 仍是首选？结合真实案例和趋势，我们可以做出以下判断：&lt;/p&gt;
&lt;h3 id="场景一边缘计算与serverless--谨慎使用-java"&gt;&lt;a href="#%e5%9c%ba%e6%99%af%e4%b8%80%e8%be%b9%e7%bc%98%e8%ae%a1%e7%ae%97%e4%b8%8eserverless--%e8%b0%a8%e6%85%8e%e4%bd%bf%e7%94%a8-java" class="header-anchor"&gt;&lt;/a&gt;场景一：边缘计算与Serverless – 谨慎使用 Java。
&lt;/h3&gt;&lt;p&gt;对于运行环境受限、对启动延迟敏感的场景，选择 Java 需要非常慎重。典型如物联网设备、边缘网关、函数计算等，这些环境往往内存有限且要求冷启动极快。在这些场合，运行一个庞大的 JVM 显然不如直接使用原生语言（C/C++、Rust）或轻量脚本语言（JavaScript、Python）来得高效。过去不少团队在实现事件驱动的小型服务时，就倾向于用 Node.js 或 Python 编写——不是因为Java不能实现功能，而是因为Java在每次调用都要“热身”的开销让人难以忍受。虽然有 GraalVM Native Image 可以大幅优化，但对小型团队而言，引入它的复杂度可能得不偿失。因此，对于边缘和无服务函数等应用，除非有充足理由和相应优化手段，否则倾向于选择更轻便的技术栈。当然，规则也非绝对：如果业务逻辑需要调用大量现有的 Java 类库（例如进行某种算法运算，而相关库只有Java实现），那么即便在 Serverless 环境下通过原生镜像等方式使用 Java 也是可以考虑的。总的来说，在这些场景，“能不用Java就不用”是较为实际的指导原则。&lt;/p&gt;
&lt;h3 id="场景二高性能微服务--视情况取舍"&gt;&lt;a href="#%e5%9c%ba%e6%99%af%e4%ba%8c%e9%ab%98%e6%80%a7%e8%83%bd%e5%be%ae%e6%9c%8d%e5%8a%a1--%e8%a7%86%e6%83%85%e5%86%b5%e5%8f%96%e8%88%8d" class="header-anchor"&gt;&lt;/a&gt;场景二：高性能微服务 – 视情况取舍
&lt;/h3&gt;&lt;p&gt;在互联网分布式系统中，每种语言都有用武之地。如果团队主要目标是极致的性能和资源利用率，并且成员对 Go/Rust 等语言驾轻就熟，那么把部分微服务用新语言实现未尝不可。例如某些网关服务、实时通信服务，行业里确有用 Rust 或 Go 重写后延迟降低、内存减半的成功案例。特别是低延迟、高并发的基础设施组件（消息队列、代理服务器等），很多开源项目早就避开 Java 转投 Go/Rust 怀抱，这是技术基因所致（Java 更擅长业务逻辑，系统编程领域C系语言传统更强）。但是，对于业务逻辑复杂的微服务，Java 仍然具有难以替代的优势：强大的生态提供了各种中间件客户端、成熟的 ORM 和事务框架、安全完备的验证和监控工具等等。这些“全家桶”式的支持使Java在开发业务系统时如鱼得水，大大减少了造轮子的成本。如果纯粹为了追新把此类服务改用另一种语言，可能会发现需要重建许多Java自带的轮子，得不偿失。因此，我们的立场是：对性能极限有追求的核心组件，可以考虑非Java实现以挖掘潜力；但大多数微服务尤其是业务导向的微服务，Java 依然是稳妥且高效的选择。况且随着Quarkus、Micronaut等专为云环境优化的Java框架出现，以及JVM自身的持续优化，Java 微服务的“笨重”正在被削平。正如某次测试所示，在较大的机器上，Java 的吞吐甚至可与 Go 持平甚至略胜一筹——只要用对了方式，Java 完全能胜任高性能微服务。&lt;/p&gt;
&lt;h3 id="场景三大型核心系统--坚定拥抱-java"&gt;&lt;a href="#%e5%9c%ba%e6%99%af%e4%b8%89%e5%a4%a7%e5%9e%8b%e6%a0%b8%e5%bf%83%e7%b3%bb%e7%bb%9f--%e5%9d%9a%e5%ae%9a%e6%8b%a5%e6%8a%b1-java" class="header-anchor"&gt;&lt;/a&gt;场景三：大型核心系统 – 坚定拥抱 Java
&lt;/h3&gt;&lt;p&gt;对于那些 复杂度高、生命周期长、需要强一致性和可靠性的核心业务，Java 无疑仍是值得长期信赖的编程语言。例如银行的核心账务系统、航空公司的订票系统、阿里的电商交易中台等，这些系统往往经历多年演化，业务规则繁多且严谨，需要大量业内验证过的中间件支撑。Java 的严格类型体系和成熟框架在这里如鱼得水。特别是在金融、政府等对稳定性要求极高的领域，“Java + 大型商用中间件”的组合几乎是默认标配。从技术债的角度考虑，这类系统虽然也面临老旧架构的问题，但重构时通常还是在 Java 体系内升级（比如从 Struts 升级到 Spring Boot，或引入分布式事务框架等），而不会轻易迁移到一门全新的语言上。这不仅因为重写成本高，更因为 Java 多年沉淀的安全性和可靠性难以替代。可以说，在复杂业务长跑中，Java 是一匹稳健的“长途马”，跑得也许不算最快，但足够稳当，生态中现成的工具能够覆盖方方面面，让架构师和开发者更安心。基于这些原因，我们坚定认为：在复杂业务和核心系统场景下，坚持使用 Java 是明智之举。即便引入新的技术插件，也是作为补充而非颠覆，比如用 Python 做小部分AI预测，再把结果喂给Java主系统等等。Java 老兵在这些战场上大可发挥深厚经验，将系统设计得健壮且易于维护，为业务保驾护航。&lt;/p&gt;
&lt;p&gt;归纳来说，用舍有道，视需而定：Java 并非万能，同样也远未过时。关键在于根据项目需求选择最合适的工具。在前沿领域不妨多尝试新语言新架构，以保持竞争力；而在关系到企业命脉的长线工程上，Java 依然值得我们托付。&lt;/p&gt;
&lt;h2 id="java老兵的自我进化坚守阵地or华丽转型"&gt;&lt;a href="#java%e8%80%81%e5%85%b5%e7%9a%84%e8%87%aa%e6%88%91%e8%bf%9b%e5%8c%96%e5%9d%9a%e5%ae%88%e9%98%b5%e5%9c%b0or%e5%8d%8e%e4%b8%bd%e8%bd%ac%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;Java老兵的自我进化：坚守阵地or华丽转型？
&lt;/h2&gt;&lt;p&gt;面对风起云涌的技术浪潮，10年以上经验的 Java 老将们该何去何从？是固守舒适圈，还是勇敢拓展边界？以下几点建议或许对处在十字路口的你有所启发：&lt;/p&gt;
&lt;h3 id="拥抱java新特性跟上生态演进"&gt;&lt;a href="#%e6%8b%a5%e6%8a%b1java%e6%96%b0%e7%89%b9%e6%80%a7%e8%b7%9f%e4%b8%8a%e7%94%9f%e6%80%81%e6%bc%94%e8%bf%9b" class="header-anchor"&gt;&lt;/a&gt;拥抱Java新特性，跟上生态演进
&lt;/h3&gt;&lt;p&gt;不要认为“学了十几年Java就没有新东西可学”。相反，Java生态在飞速更新，每年两个版本迭代。老兵们应该主动学习 JDK近几版的新功能（如Records、Sealed Class、Pattern Matching、虚拟线程等），这些特性能显著改善代码质量和性能，使你的技能焕发新生。例如，试着用 Loom 虚拟线程改造一个老的并发模块，体会一下开发模式的简化；或者研究 GraalVM 如何将现有服务无缝打包为原生镜像，了解其中的限制和调优手段。拥抱新技术不仅能提升生产力，也向团队展示了你与时俱进的技术热情。作为Java老兵，切忌固步自封——持续学习是对抗职业倦怠和时代冲击的最好武器。&lt;/p&gt;
&lt;h3 id="拓展多元技能栈成为t型人才"&gt;&lt;a href="#%e6%8b%93%e5%b1%95%e5%a4%9a%e5%85%83%e6%8a%80%e8%83%bd%e6%a0%88%e6%88%90%e4%b8%bat%e5%9e%8b%e4%ba%ba%e6%89%8d" class="header-anchor"&gt;&lt;/a&gt;拓展多元技能栈，成为“T型”人才
&lt;/h3&gt;&lt;p&gt;在保持Java优势的同时，建议横向拓展一到两门其它语言或领域技能。比如，可以尝试学习 Go 或 Python，用它们做些小项目，体会不同语言在思维模型上的差异。再比如，深入了解一下前端技术或移动开发，哪怕不做前端，也能与前端同事更高效协作。这种“T”字型的技能结构（既有一门精深的主力技术，又对相关技术有所涉猎）将使你在团队中更具价值。很多架构师在成为架构师前，都曾是精通数门语言、熟悉多种数据库和中间件的全能型工程师。对Java老兵来说，学习一门新语言还能帮助跳出现有思维框架，把新理念反哺到Java日常开发中。例如，借鉴函数式编程思想优化Java代码，或者用脚本语言编写自动化工具提升开发效率。多元化的技能还为你提供了职业备胎：万一某天真的不想写Java了，你在其他领域的积累也足以支撑转型，不至于手足无措。&lt;/p&gt;
&lt;h3 id="深入业务和架构提升不可替代性"&gt;&lt;a href="#%e6%b7%b1%e5%85%a5%e4%b8%9a%e5%8a%a1%e5%92%8c%e6%9e%b6%e6%9e%84%e6%8f%90%e5%8d%87%e4%b8%8d%e5%8f%af%e6%9b%bf%e4%bb%a3%e6%80%a7" class="header-anchor"&gt;&lt;/a&gt;深入业务和架构，提升不可替代性
&lt;/h3&gt;&lt;p&gt;随着工作年限增长，“懂业务、能设计”往往比单纯的编码能力更重要。Java老兵应该充分利用在一个行业浸润多年的经验，去深入理解业务领域 的本质问题，把握业务发展方向。将业务洞察与技术方案相结合，主动参与系统架构设计和重大技术选型，这会让你成为团队中不可或缺的核心人物。很多时候，业务专家+技术专家的复合型人才，比仅仅精通某种语法的程序员更有竞争力。如果你已经是某核心系统的Owner，不妨尝试推进架构优化和性能提升项目，展示自己在宏观层面的掌控力。同时，培养自己的系统设计能力，多研究业界大型系统的架构案例，学习它们如何权衡取舍。当你能从容驾驭分布式事务、异地多活、CQRS 等架构模式时，你的价值早已超越“Java 工程师”的范畴，而成为真正的技术专家。这种升级，无论未来Java的热度如何，都能让你的职业生涯保持上升。&lt;/p&gt;
&lt;h3 id="考虑转型技术管理或其他新领域"&gt;&lt;a href="#%e8%80%83%e8%99%91%e8%bd%ac%e5%9e%8b%e6%8a%80%e6%9c%af%e7%ae%a1%e7%90%86%e6%88%96%e5%85%b6%e4%bb%96%e6%96%b0%e9%a2%86%e5%9f%9f" class="header-anchor"&gt;&lt;/a&gt;考虑转型技术管理或其他新领域
&lt;/h3&gt;&lt;p&gt;并非每个人都要永远写代码。工作十年以上后，你也可以根据兴趣转型，选择最适合自己的道路。如果你热衷带团队和项目把控，可以逐步走向 技术管理 岗位，担任Team Leader、技术经理甚至CTO，把多年经验用于培养新人和决策把关。很多Java老兵在这一阶段选择带领团队，既可传承自己的开发哲学，又能获得管理成就感。又或者，你对某些新兴领域情有独钟，例如 人工智能、大数据、安全 等，不妨利用业余时间学习相关知识，寻求内部调岗或外部机会。资深程序员转做产品经理、解决方案架构师的例子也屡见不鲜——只要有心，完全可以跳出演员阵容，转到幕后编剧或导演的位置上。当然，做出转型决定前需要评估清楚：你的核心竞争力是什么，新领域是否真心喜欢，从头开始是否有心理准备。转型不是逃避，而是为了更长远的发展。无论选择深耕Java栈还是开拓新跑道，持续的学习和热情都是关键驱动力。&lt;/p&gt;
&lt;h2 id="最后"&gt;&lt;a href="#%e6%9c%80%e5%90%8e" class="header-anchor"&gt;&lt;/a&gt;最后
&lt;/h2&gt;&lt;p&gt;想对每一位焦虑中的Java老兵说：技术江湖瞬息万变，但真正的资深工程师价值从不局限于某种语法。Java 之父 James Gosling 曾打比方说：“Java就像一辆可靠的卡车”，或许它没有跑车那样光鲜，但能载着重载货物稳稳前行。这辆卡车如今也在不断改装升级，动力和油耗都在改进。我们作为司机，要做的不是弃车而逃，而是练就更高超的驾驶技巧，并且学会在不同道路上换合适的交通工具。坚守初心并不代表故步自封，拥抱变化也不意味着全盘否定过去。当我们既掌握了Java这门老牌利器，又勇于学习新招式、新套路，在变化的浪潮中依然能找到自己的方向和节奏。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-03-29-java-lao-bing-de-shi-zi-lu-kou-jian-shou-hai-shi-tu-wei/006-0c6fa2fa.png"&gt;&lt;/p&gt;
&lt;p&gt;10+年开发生涯沉淀下来的经验与智慧，是宝贵的财富。无论Java的流行曲线如何波动，真正优秀的工程师都会不断进化，拓展自己的边界。在这个过程中，我们既要有克制冷静的思考，看清技术演进的本质；也要保持对编程的热爱，不忘初心地享受技术创造的乐趣。愿每一位Java老兵都能在时代洪流中找到属于自己的位置：该出手时果断出手，该坚守时稳如磐石，在新的十年里续写属于你的传奇。&lt;/p&gt;</description></item><item><title>云原生，你真的懂了吗？</title><link>https://xiaobox.github.io/p/2025-02-22-yun-yuan-sheng-ni-zhen-de-dong-le-ma/</link><pubDate>Sat, 22 Feb 2025 04:00:00 +0000</pubDate><guid>https://xiaobox.github.io/p/2025-02-22-yun-yuan-sheng-ni-zhen-de-dong-le-ma/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-02-22-yun-yuan-sheng-ni-zhen-de-dong-le-ma/cover.jpg" alt="Featured image of post 云原生，你真的懂了吗？" /&gt;&lt;h2 id="啥是云"&gt;&lt;a href="#%e5%95%a5%e6%98%af%e4%ba%91" class="header-anchor"&gt;&lt;/a&gt;啥是云？
&lt;/h2&gt;&lt;p&gt;说起云原生（cloud native），就不得不说明一下 “云” 是啥。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-02-22-yun-yuan-sheng-ni-zhen-de-dong-le-ma/001-79f74f23.png"&gt;&lt;/p&gt;
&lt;p&gt;简单理解，云就是 “云计算”，如果给它下个定义的话是这样的：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;云&amp;quot; 特指以云计算模型构建的现代化动态环境&lt;/p&gt;

 &lt;/blockquote&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;h3 id="云-可以有多种形态"&gt;&lt;a href="#%e4%ba%91-%e5%8f%af%e4%bb%a5%e6%9c%89%e5%a4%9a%e7%a7%8d%e5%bd%a2%e6%80%81" class="header-anchor"&gt;&lt;/a&gt;“云” 可以有多种形态
&lt;/h3&gt;&lt;p&gt;云还有多种形态，一般来说有以下三种：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;公有云（Public Cloud）： 由第三方云计算提供商（如 AWS、Azure、Google Cloud、阿里云、腾讯云等）拥有和运营，面向公众提供服务。&lt;/li&gt;
&lt;li&gt;私有云（Private Cloud）： 由企业或组织自己拥有和运营，仅供内部使用。私有云可以部署在企业自己的数据中心，也可以托管给第三方提供商。&lt;/li&gt;
&lt;li&gt;混合云（Hybrid Cloud）： 结合了公有云和私有云的优势，允许应用程序和数据在两者之间迁移和共享。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;还是用吃水比喻，公有云就像 “自来水”，打开水管就能喝。私有云就像自己找水源，自己挖井，自己舀水喝。混合云自然就是这两种的混合。&lt;/p&gt;
&lt;h3 id="资源有啥"&gt;&lt;a href="#%e8%b5%84%e6%ba%90%e6%9c%89%e5%95%a5" class="header-anchor"&gt;&lt;/a&gt;资源有啥？
&lt;/h3&gt;&lt;p&gt;说完了云，我们该说水了，云是提供资源的，那么具体有哪些资源呢？什么东西是云可以提供给我们的呢？你可能想到了：“嗨，不就是服务器嘛”。&lt;/p&gt;
&lt;p&gt;其实 “资源” 是一个&lt;strong&gt;多维度&lt;/strong&gt;的概念，远不止硬件设备。我们展开说说。&lt;/p&gt;
&lt;p&gt;首先是：基础资源，它包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;计算资源（CPU/GPU/FPGA）&lt;/li&gt;
&lt;li&gt;存储资源（磁盘 / SSD / 对象存储）&lt;/li&gt;
&lt;li&gt;网络资源（带宽 / IP / 负载均衡）&lt;/li&gt;
&lt;li&gt;内存资源（RAM）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;然后是抽象服务，比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;容器编排（Kubernetes（EKS/GKE/ACK）、Nomad）&lt;/li&gt;
&lt;li&gt;数据库服务（AWS RDS、阿里云 RDS）&lt;/li&gt;
&lt;li&gt;消息队列（Kafka 云托管、AWS SQS、RabbitMQ）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;接着是管理与安全，比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;身份权限（AWS IAM、阿里云 RAM、Azure AD）&lt;/li&gt;
&lt;li&gt;监控告警（Prometheus 云托管、Datadog、阿里云 ARMS）&lt;/li&gt;
&lt;li&gt;日志分析（ELK Stack 云服务、Splunk）&lt;/li&gt;
&lt;li&gt;安全防御（阿里云 WAF）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最后是高阶能力，比如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Serverless（AWS Lambda、阿里云 FC）&lt;/li&gt;
&lt;li&gt;服务网格（Istio、Linkerd）&lt;/li&gt;
&lt;li&gt;边缘计算（AWS Wavelength、阿里云 ENS）&lt;/li&gt;
&lt;li&gt;量子计算（AWS Braket、Azure Quantum）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我上面举的只是一些常见的例子，其实每一个分类下的资源条目是非常多的。所以你看，“资源” 可不止服务器那么简单，它是多维度的。现在几乎你能用的到的东西都上云了，都是资源。就算没有，经不住人家云厂商包装啊，只要你有需求，人家就有产品卖你，哈哈。&lt;/p&gt;
&lt;h2 id="云原生"&gt;&lt;a href="#%e4%ba%91%e5%8e%9f%e7%94%9f" class="header-anchor"&gt;&lt;/a&gt;云原生
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-02-22-yun-yuan-sheng-ni-zhen-de-dong-le-ma/002-7897a5f7.png"&gt;&lt;/p&gt;
&lt;p&gt;云其实还是比较好理解的，但是云原生（cloud native）就比较抽象了，在我刚接触这个概念的时候是一头雾水，无论别人给我讲，还是我给别人讲总是说不清楚，或者人家听不懂。&lt;/p&gt;
&lt;p&gt;我们还是先来说说定义吧，我找到 CNCF （https://github.com/cncf/toc/blob/main/DEFINITION.md）的一个定义，算比较权威了。&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中，构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。&lt;/p&gt;
&lt;p&gt;这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段，云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。&lt;/p&gt;

 &lt;/blockquote&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Cloud native practices empower organizations to develop, build, and deploy workloads in computing environments (public, private, hybrid cloud) to meet their organizational needs at scale in a programmatic and repeatable manner. It is characterized by loosely coupled systems that interoperate in a manner that is secure, resilient, manageable, sustainable, and observable.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;说实话，如果你没有在这个领域干过，光看定义是不容易理解的。甚至就算在云原生环境下从事开发的工程师，如果不认真思考、理解，也不能把什么是“云原生” 讲的很明白。&lt;/p&gt;
&lt;p&gt;原因是这个概念本来就比较抽象。所以我不用 CNCF 的定义，换一种说法来描述一下什么是 “云原生”&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;云原生是一种以云计算基础设施为基石，通过容器化封装、微服务拆分、声明式 API 和自动化运维，将应用的非功能需求（如弹性扩缩、故障自愈、安全策略）交由云平台管理的架构范式。其本质是通过技术手段让业务代码与底层资源解耦，使开发者只需关注业务逻辑，而由云平台自动处理部署、监控、容灾等复杂性。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;你看，我这样说是不是清晰一些了？ 更好理解一些了？还没有？接着往下看。&lt;/p&gt;
&lt;h3 id="本质"&gt;&lt;a href="#%e6%9c%ac%e8%b4%a8" class="header-anchor"&gt;&lt;/a&gt;本质
&lt;/h3&gt;&lt;p&gt;透过现象看本质，概念怎么说都行，重要的是要理解这个东西的本质。&lt;/p&gt;
&lt;p&gt;那我们就来看一看 “云原生” 的本质 ：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;云原生并非单纯的技术集合，而是一种 “以应用为中心” 的思维模式。它通过标准化技术栈（容器 / K8s / 微服务），将云计算从 “资源层” 提升到 “应用层”，让企业能像使用水电一样按需使用计算能力。它的目标是让技术复杂性对业务透明化。&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;说到这里，我们就不得不说一下为什么要使用或推崇“云原生”了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;云原生的出现源于传统应用架构在云计算时代的局限性。&lt;/strong&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;li&gt;环境不一致：开发、测试、生产环境差异导致 “在我机器上能跑” 的问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;采用 “云原生” 技术栈及应用架构可以有效的解决上面的所有问题。&lt;/p&gt;
&lt;h3 id="什么是不可替代的"&gt;&lt;a href="#%e4%bb%80%e4%b9%88%e6%98%af%e4%b8%8d%e5%8f%af%e6%9b%bf%e4%bb%a3%e7%9a%84" class="header-anchor"&gt;&lt;/a&gt;什么是不可替代的？
&lt;/h3&gt;&lt;p&gt;不得不说，Docker 和 Kubernetes 技术的出现给了 “云原生” 极大的助力。那如果没有 Docker 和 Kubernetes 呢？ 云原生这个概念还立得住吗？&lt;/p&gt;
&lt;p&gt;其实，云原生概念的出现（2010 年 Netflix 提出）比 Docker（2013）和 Kubernetes（2014）更早。核心思想在容器技术普及前就已萌芽。所以：&lt;strong&gt;云原生本质是一种架构哲学，而非特定技术捆绑&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;那么我们紧接着下一个问题就是：什么是云原生的核心内容，有什么是缺一不可的呢？或者说缺了什么就不能算是云原生了呢？&lt;/p&gt;
&lt;p&gt;总结来说，有四大支柱：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;弹性伸缩（Elasticity）&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;必须能力：根据负载自动扩缩资源&lt;/li&gt;
&lt;li&gt;替代方案：AWS Lambda（Serverless）、Nomad（非 K8s 编排器）&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="3"&gt;
&lt;li&gt;故障自愈（Resilience）&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;必须能力：服务熔断、重试、健康检查&lt;/li&gt;
&lt;li&gt;替代方案：Hystrix（微服务容错库）+ Consul（服务发现）&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="5"&gt;
&lt;li&gt;声明式管理（Declarative）&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;必须能力：通过 YAML/JSON 描述目标状态，而非手动操作&lt;/li&gt;
&lt;li&gt;替代方案：Terraform（基础设施即代码）+ Ansible（配置管理）&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="7"&gt;
&lt;li&gt;自动化交付（Automation）&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;必须能力：CI/CD 流水线、蓝绿部署&lt;/li&gt;
&lt;li&gt;替代方案：GitLab CI + Spinnaker（持续交付平台）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="云原生的-复杂性悖论"&gt;&lt;a href="#%e4%ba%91%e5%8e%9f%e7%94%9f%e7%9a%84-%e5%a4%8d%e6%9d%82%e6%80%a7%e6%82%96%e8%ae%ba" class="header-anchor"&gt;&lt;/a&gt;云原生的 “复杂性悖论”
&lt;/h3&gt;&lt;p&gt;云原生看起来真好呀，但事实是这样吗？对于软件开发，我们都知道一句著名的话：“没有银弹”，是的。云原生也不是哪儿哪儿都好，它也有它的问题。&lt;/p&gt;
&lt;p&gt;云原生存在一个看似矛盾的现象：&lt;strong&gt;它承诺降低业务复杂性，却引入了新的技术复杂性。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这种矛盾的核心在于技术栈的 “分层复杂性转移”：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;传统架构的复杂性集中在应用层（如单体重构困难、环境配置混乱）&lt;/li&gt;
&lt;li&gt;云原生的复杂性下沉到基础设施层（如 K8s 集群运维、Istio 配置）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对企业而言，这相当于用 “可控的工程复杂度” 替代 “不可控的业务阻塞风险”。但关键在于，这种转移是否真正带来净收益。&lt;/p&gt;
&lt;p&gt;说白了，你要会“算账”，在成本一定的情况下，要有所取舍，到底要不要上“云原生”，不是技术本身决定的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;云原生有它的显性与隐性成本&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;技术债务：K8s 版本升级兼容性问题、Helm Chart 维护&lt;/li&gt;
&lt;li&gt;人力成本：需要 DevOps 工程师（平均薪资比开发高 30%+）&lt;/li&gt;
&lt;li&gt;认知负担：团队需掌握容器、服务网格、声明式 API 等新范式&lt;/li&gt;
&lt;li&gt;工具链成本 ：监控（Prometheus+AlertManager）、日志（EFK）、追踪（Jaeger）的集成和维护&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;有成本当然也有收益&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;部署效率：从手动部署 1 小时 → 全自动 CI/CD 5 分钟（效率提升 12 倍）&lt;/li&gt;
&lt;li&gt;资源利用率 ：虚拟机静态分配 → 容器动态调度（CPU 利用率从 15% 提升至 60%+）&lt;/li&gt;
&lt;li&gt;故障恢复速度：人工排查 1 小时 → 自动熔断 + 滚动更新（MTTR 从 60 分钟降至 5 分钟）&lt;/li&gt;
&lt;li&gt;业务敏捷性：新功能上线周期从 1 个月 → 1 周（迭代速度提升 4 倍）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以，关键是要根据你的实际情况 “算账”，一般来说，当企业规模超过临界点（通常≥50 个微服务 / 日部署次数≥10 次），云原生的收益将显著超越成本。&lt;/p&gt;
&lt;h3 id="结论"&gt;&lt;a href="#%e7%bb%93%e8%ae%ba" class="header-anchor"&gt;&lt;/a&gt;结论
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-02-22-yun-yuan-sheng-ni-zhen-de-dong-le-ma/003-05d14457.png"&gt;&lt;/p&gt;
&lt;p&gt;所以说了半天云原生到底是什么？ 我不知道你明白了没有，我们上面林林总总写了那么多技术点，如果初次接触确实很头大。但这不重要。&lt;/p&gt;
&lt;p&gt;因为：&lt;strong&gt;云原生不是工具集，而是「工业化软件生产」的方法论升级&lt;/strong&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;strong&gt;我不希望给你一个中规中矩的回答模板，虽然它是正确的&lt;/strong&gt;，比如以下这样：&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“云原生是云计算时代的一种架构范式，旨在通过标准化技术栈（如容器、K8s）和自动化运维体系，将非业务功能（如弹性扩缩、故障自愈）从应用代码中剥离，由云平台接管。其核心驱动力是解决传统单体应用部署慢、环境不一致、扩展难的问题。&lt;/p&gt;
&lt;p&gt;从技术分层看，云原生包含：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;基础设施层：Docker 实现环境一致性，K8s 完成资源调度，比如我们通过 Deployment 的滚动更新实现零停机发布；&lt;/li&gt;
&lt;li&gt;应用架构层：微服务拆分业务能力，Istio 服务网格处理服务间通信的熔断、监控，例如在订单服务中配置超时自动重试；&lt;/li&gt;
&lt;li&gt;交付运维层：GitOps 工具链（如 Argo CD）确保声明式配置的版本可控，配合 Prometheus+Grafana 实现实时监控。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;关键设计原则包括不可变基础设施（容器镜像一次构建多次运行）、声明式 API（通过 YAML 描述目标状态而非手动操作）。但引入云原生也带来挑战，比如团队需要掌握复杂的 K8s 生态，我们通过建设内部开发者平台（IDP）封装底层细节，让开发者只需关注业务代码。”&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="云原生应用"&gt;&lt;a href="#%e4%ba%91%e5%8e%9f%e7%94%9f%e5%ba%94%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;云原生应用
&lt;/h2&gt;&lt;h3 id="什么样的应用是云原生的"&gt;&lt;a href="#%e4%bb%80%e4%b9%88%e6%a0%b7%e7%9a%84%e5%ba%94%e7%94%a8%e6%98%af%e4%ba%91%e5%8e%9f%e7%94%9f%e7%9a%84" class="header-anchor"&gt;&lt;/a&gt;什么样的应用是云原生的？
&lt;/h3&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2025-02-22-yun-yuan-sheng-ni-zhen-de-dong-le-ma/004-d345c5b7.png"&gt;&lt;/p&gt;
&lt;p&gt;一个应用是否云原生，而要看是否具备以下特征：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;容器化部署：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;应用打包为 Docker 镜像，在 Kubernetes 集群中运行。&lt;/li&gt;
&lt;li&gt;示例：电商大促时，通过 HPA（水平扩缩）自动增加订单处理服务的 Pod 数量。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="3"&gt;
&lt;li&gt;微服务架构：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;业务拆分为独立服务（如用户服务、支付服务），通过 API 通信。&lt;/li&gt;
&lt;li&gt;示例：视频网站将视频转码服务独立部署，利用 GPU 节点加速，不影响主站稳定性。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="5"&gt;
&lt;li&gt;DevOps 流水线：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;代码提交后自动触发 CI/CD，完成测试、镜像构建、灰度发布。&lt;/li&gt;
&lt;li&gt;示例：金融 App 通过蓝绿部署实现零停机更新，降低发布风险。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="7"&gt;
&lt;li&gt;依赖云原生中间件：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;使用云托管的数据库（如 AWS RDS）、消息队列（如 Kafka on K8s）、缓存（如 Redis Cluster）。&lt;/li&gt;
&lt;li&gt;示例：社交平台用云原生数据库 TiDB 处理海量关系数据，自动分片扩容。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="9"&gt;
&lt;li&gt;跨云与混合云兼容：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;应用设计不绑定特定云厂商，可在 AWS、Azure、私有云间迁移。&lt;/li&gt;
&lt;li&gt;示例：跨国企业采用 Anthos 实现跨公有云和本地数据中心的统一管理。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="最后"&gt;&lt;a href="#%e6%9c%80%e5%90%8e" class="header-anchor"&gt;&lt;/a&gt;最后
&lt;/h2&gt;&lt;p&gt;云原生不是终点，而是通往智能软件时代的必由之路。当我们将视角从工具本身移开，看到的是一场关于效率、可靠性与创新速度的认知革命。正如 Linux 之父 Linus Torvalds 所说：“技术终将老去，但优秀的架构思想永存。” 在这场变革中，比掌握某个工具更重要的，是建立持续进化的云原生思维体系。&lt;/p&gt;</description></item><item><title>三分钟解决 Java 进程 cpu 100% 问题</title><link>https://xiaobox.github.io/p/2024-08-22-san-fen-zhong-jie-jue-java-jin-cheng-cpu-100-wen-ti/</link><pubDate>Thu, 22 Aug 2024 08:04:00 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-08-22-san-fen-zhong-jie-jue-java-jin-cheng-cpu-100-wen-ti/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-22-san-fen-zhong-jie-jue-java-jin-cheng-cpu-100-wen-ti/cover.jpg" alt="Featured image of post 三分钟解决 Java 进程 cpu 100% 问题" /&gt;&lt;h2 id="起因"&gt;&lt;a href="#%e8%b5%b7%e5%9b%a0" class="header-anchor"&gt;&lt;/a&gt;起因
&lt;/h2&gt;&lt;p&gt;上午有小伙伴说某个 java 服务响应特别慢，看了一下监控，很多请求都超时了，服务是活着的，但响应非常慢。&lt;/p&gt;
&lt;p&gt;由于服务是多容器负载均衡调度部署的，又花了一点时间定位到具体的宿主机。仔细查下来发现，并不是部署该服务的所有容器都有问题，仅仅是某一个有问题。&lt;/p&gt;
&lt;p&gt;具体的问题是某 java 进程的 cpu 占用率 打满了，是 100% 。&lt;/p&gt;
&lt;p&gt;这里要跟大家说的是，如果某关键服务的所有副本全部出问题了，那么第一时间并不是揪着问题不放，跟那儿使劲查。而是先尝试恢复服务，如果系统在架构上的弹性和容错做的比较好，可能不会造成 “雪崩”，导致全系统异常，无法使用。但是注意，我说的是“关键服务”，就算你隔离、熔断做的再好，关键服务不能用了，整个系统还是不能用，对用户来说就是 “挂了” ，比如你出地铁想扫个共享单车，扫码没问题，但就是开不了锁（开锁服务出问题了）。&lt;/p&gt;
&lt;p&gt;对于我们今天遇到的问题来说，还好，没那么严重，观察下来只是某服务的某副本出了问题。这里我根据系统的具体情况和观察到的情况做了个决定：&lt;strong&gt;先不回滚服务，一边观察一边收集事故现场信息，同时让一位同事准备好，如果事故进一步恶化就立刻回滚。&lt;/strong&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;h2 id="问题解决过程"&gt;&lt;a href="#%e9%97%ae%e9%a2%98%e8%a7%a3%e5%86%b3%e8%bf%87%e7%a8%8b" class="header-anchor"&gt;&lt;/a&gt;问题解决过程
&lt;/h2&gt;&lt;p&gt;上文我说问题只要服务的某个副本上出了问题，你可能会觉得不对，代码都一样的，怎么可能就只有一个副本有问题呢？&lt;/p&gt;
&lt;p&gt;所以先解释下原因，最后事故处理完我们分析代码发现，原来是某个特殊的用户在某个特殊的条件下触下了某个 bug。那部分代码确实只会在这么特殊的条件下才会运行，而且这个动作的执行频率相当低。所以就是这么巧。&lt;/p&gt;
&lt;p&gt;我们进入正题，首先在宿主机上看到某 java 进程的 CPU 占用率是 100% 。由于我们所有的 java 进程全部是 docker 容器启动的，所以要找到具体是宿主机的哪个 docker 容器，这里我用了这个命令：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker ps -q | xargs docker inspect --format '{{.State.Pid}}, {{.Id}}' | grep 2880 &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;假设在宿主机上的这个 java 进程的 pid 为 2880。这行命令就是找出 pid 对应的具体是哪个 docker 容器。详解说明一下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker ps&lt;/code&gt; 是用来列出当前运行中的 Docker 容器的命令。-q 选项告诉 docker ps 仅输出每个容器的 ID，而不是完整的容器信息列表。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;|&lt;/code&gt;（管道操作符）：管道操作符用于将前一个命令的输出作为下一个命令的输入。这里，它将 &lt;code&gt;docker ps -q&lt;/code&gt; 命令输出的容器 ID 列表传递给下一个命令。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xargs docker inspect --format '{{.State.Pid}}, {{.Id}}'&lt;/code&gt;：xargs 是一个将输入数据转换为其他命令行参数的工具。在这里，它将 &lt;code&gt;docker ps -q&lt;/code&gt; 输出的容器 ID 列表转换为 &lt;code&gt;docker inspect&lt;/code&gt; 命令的参数。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker inspect&lt;/code&gt; 是用于获取有关 Docker 容器的详细信息的命令。&lt;code&gt;--format '{{.State.Pid}}, {{.Id}}'&lt;/code&gt; 是一个格式化选项，它指定了 &lt;code&gt;docker inspect&lt;/code&gt; 命令的输出格式。这里使用了 Go 模板语法来指定只输出每个容器的进程 ID（PID）和容器 ID。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;|&lt;/code&gt;（管道操作符）：再次使用管道操作符，将 &lt;code&gt;docker inspect&lt;/code&gt; 命令的输出传递给下一个命令。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;grep 2880&lt;/code&gt;：grep 是一个文本搜索工具，用于搜索包含特定模式的字符串。2880 是要搜索的字符串，代表一个进程 ID（PID）。这个命令会从输入中筛选出包含数字 2880 的行。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;将所有部分结合起来，这行命令的作用是：首先，列出所有运行中的 Docker 容器的 ID。然后，对每个容器 ID 执行 docker inspect，以获取每个容器的 PID 和 ID，并以特定格式输出。最后，从这些输出中筛选出 PID 为 2880 的容器，并显示其 PID 和 ID&lt;/p&gt;
&lt;p&gt;到这里我们知道了具体是哪个容器，然后进入到该容器中，查看了一下 cpu 的使用情况，确实很高，接着使用以下命令导出 java 进程的线程堆栈&lt;/p&gt;
&lt;p&gt;&lt;code&gt;jstack -l 1 &amp;gt; jstack.log &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;java 进程的 pid 为 1 ，所以上面命令中 1 就是 java 进程的进程 pid&lt;/p&gt;
&lt;h3 id="分析-threaddump"&gt;&lt;a href="#%e5%88%86%e6%9e%90-threaddump" class="header-anchor"&gt;&lt;/a&gt;分析 threadDump
&lt;/h3&gt;&lt;p&gt;用 jstack 命令导出 java 进程的线程堆栈快照后就可以进行分析了。&lt;/p&gt;
&lt;p&gt;这里我们使用在线的工具网站来分析：https://fastthread.io/&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-22-san-fen-zhong-jie-jue-java-jin-cheng-cpu-100-wen-ti/001-55d83854.png"&gt;&lt;/p&gt;
&lt;p&gt;我个人觉得是最好用的一个。你可能会问有没有本地的好用的工具。我找了一圈，有是有，但很一般，还不如人家这个在线网站呢。&lt;/p&gt;
&lt;p&gt;接着我们反 jstack.log 打个包上传上去。很快就会得到分析结果，会出一个关于这个 Thread Dump 的全方面分析报告，方便你定位相关问题。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-22-san-fen-zhong-jie-jue-java-jin-cheng-cpu-100-wen-ti/002-ca3860fe.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如果有异常会有红号感叹号提示。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;除了人家提示的明显异常，我一般重点会看有没有死锁，以及哪些线程占用的 CPU 较高：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-22-san-fen-zhong-jie-jue-java-jin-cheng-cpu-100-wen-ti/003-35de550a.png"&gt;&lt;/p&gt;
&lt;p&gt;剩下的就凭借你对系统的了解和经验作出判断了。&lt;/p&gt;
&lt;p&gt;具体到我们的情况，我们分析了占 CPU 最高的两个线程，全部跟我们自己写的代码有关。具体来说有一个线程的代码执行的是一个递归操作。出问题的就是这部分代码。&lt;/p&gt;
&lt;p&gt;找到原因后，很快我们就修复了 bug。&lt;/p&gt;
&lt;h2 id="最后"&gt;&lt;a href="#%e6%9c%80%e5%90%8e" class="header-anchor"&gt;&lt;/a&gt;最后
&lt;/h2&gt;&lt;p&gt;要说简单也简单，如果你的思路是对的，整个处理过程不超过 3 分钟。但如果你的思路有问题，找到问题的时间就可能会无限长。&lt;/p&gt;</description></item><item><title>容器编排工具的演进：从 Docker 到 Kubernetes</title><link>https://xiaobox.github.io/p/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/</link><pubDate>Sat, 10 Aug 2024 05:18:45 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/cover.jpg" alt="Featured image of post 容器编排工具的演进：从 Docker 到 Kubernetes" /&gt;&lt;p&gt;在现代应用部署中，Docker 和其他容器引擎为服务器端应用程序的部署提供了极大的便利。然而，随着应用和服务数量的增加，管理这些容器变得越来越困难。这催生了一类被称为容器编排器的工具，其中最为知名的莫过于 Kubernetes。容器编排的历史可以分为 Kubernetes 出现之前和之后两个阶段。&lt;/p&gt;
&lt;h4 id="容器的便利与妥协"&gt;&lt;a href="#%e5%ae%b9%e5%99%a8%e7%9a%84%e4%be%bf%e5%88%a9%e4%b8%8e%e5%a6%a5%e5%8d%8f" class="header-anchor"&gt;&lt;/a&gt;容器的便利与妥协
&lt;/h4&gt;&lt;p&gt;容器的使用虽然便利，但也带来了一些妥协。严格遵循 Docker 的理念，每个服务都应有其独立的容器，这将导致运行大量的容器。即使是一个简单的数据库网页界面，也可能需要分别运行数据库服务器、应用程序，以及可能包括用于处理静态文件的 Web 服务器、用于终止 SSL/TLS 连接的代理服务器、用作缓存的键值存储，甚至用于处理后台作业和计划任务的第二个应用程序容器。&lt;/p&gt;
&lt;p&gt;负责多个此类应用程序的管理员很快就会意识到，需要一个工具来简化管理任务，这时容器编排工具应运而生。容器编排器可以将多个容器作为一个单元来管理，并将多个服务器结合成一个集群，自动分配容器工作负载到集群节点中。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/001-b1b8ce49.png"&gt;&lt;/p&gt;
&lt;h4 id="docker-compose-与-swarm"&gt;&lt;a href="#docker-compose-%e4%b8%8e-swarm" class="header-anchor"&gt;&lt;/a&gt;Docker Compose 与 Swarm
&lt;/h4&gt;&lt;p&gt;Docker Compose 虽然不完全是一个编排器，但它是 Docker 首次尝试创建的工具，用于更轻松地管理由多个容器组成的应用程序。它使用 YAML 格式的文件，通常命名为&lt;code&gt;docker-compose.yml&lt;/code&gt;。Compose 读取该文件，并使用 Docker API 创建所需的资源，同时为所有资源添加标签，以便在创建后作为一组进行管理。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/002-eea10afc.png"&gt;&lt;/p&gt;
&lt;p&gt;Compose 文件中可以定义三种资源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;服务（services）：&lt;/strong&gt; 包含要启动的容器声明。每个条目相当于一个&lt;code&gt;docker run&lt;/code&gt;命令。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;网络（networks）：&lt;/strong&gt; 声明可以附加到容器的网络。每个条目相当于一个&lt;code&gt;docker network create&lt;/code&gt;命令。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;卷（volumes）：&lt;/strong&gt; 定义可以附加到容器的命名卷。每个条目相当于一个&lt;code&gt;docker volume create&lt;/code&gt;命令。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compose 提供了一种更方便的方式来管理由多个容器组成的应用程序，但在其最初版本中，它仅支持单个主机；所有创建的容器都在同一台机器上运行。为了扩展到多个主机，Docker 在 2016 年引入了 Swarm 模式。这是 Docker 的第二个名为“Swarm”的产品，前一个产品于 2014 年推出，采用了完全不同的方法在多个主机上运行容器，但现在已不再维护。&lt;/p&gt;
&lt;p&gt;Swarm 模式包含在 Docker 中，无需额外的软件即可使用。创建集群只需在初始节点上运行&lt;code&gt;docker swarm init&lt;/code&gt;，然后在每个其他节点上运行&lt;code&gt;docker swarm join&lt;/code&gt;。Swarm 集群包含两种类型的节点：管理节点和工作节点。管理节点提供 API 以在集群上启动容器，并使用基于 Raft 一致性算法的协议进行通信，以在所有管理节点之间同步集群状态。工作节点则负责运行容器。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/003-62b1f381.png"&gt;&lt;/p&gt;
&lt;p&gt;通过 Compose 文件在 Swarm 上部署服务。Swarm 通过为每个服务添加一个&lt;code&gt;deploy&lt;/code&gt;键扩展了 Compose 格式，该键指定服务应该运行的实例数量及其运行的节点。然而，这导致 Compose 和 Swarm 之间出现了一些分歧，某些选项如 CPU 和内存配额需要根据使用的工具以不同的方式指定。在此分歧期间，为 Swarm 准备的文件被称为“堆栈文件”而非 Compose 文件，幸好这些差异在当前版本的 Swarm 和 Compose 中已被平滑处理，Compose 格式现在有一个开放规范及其 GitHub 组织提供的参考实现。&lt;/p&gt;
&lt;p&gt;关于 Swarm 的未来存在一些不确定性。它曾经是名为 Docker Cloud 的服务的骨干，但该服务在 2018 年突然关闭。它还被宣传为 Docker 企业版的关键特性，但该产品已售予另一家公司，现以 Mirantis Kubernetes Engine 的名义进行市场推广。同时，最新版本的 Compose 已经获得了将容器部署到 Amazon 和 Microsoft 托管服务的能力。虽然没有宣布弃用，但最近也没有任何其他类型的公告；在 Docker 网站上搜索“Swarm”一词，仅能找到一些提及。&lt;/p&gt;
&lt;h4 id="kubernetes"&gt;&lt;a href="#kubernetes" class="header-anchor"&gt;&lt;/a&gt;Kubernetes
&lt;/h4&gt;&lt;p&gt;Kubernetes（有时称为 k8s）是受 Google 内部工具 Borg 启发的项目。Kubernetes 管理资源并协调在多达数千个节点的集群上运行工作负载；它在容器编排领域的统治地位如同 Google 在搜索领域的统治地位。Google 曾在 2014 年希望与 Docker 在 Kubernetes 开发上合作，但 Docker 决定走自己的路，发展 Swarm。相反，Kubernetes 在云原生计算基金会（CNCF）的支持下成长。到 2017 年，Kubernetes 的流行度已高到 Docker 宣布将其集成到 Docker 产品中。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/004-3033a01c.png"&gt;&lt;/p&gt;
&lt;p&gt;Kubernetes 以其复杂性而闻名。手动设置一个新集群是一项繁杂的任务，除了 Kubernetes 本身外，管理员还需选择和配置若干第三方组件。就像 Linux 内核需要结合其他软件以构成完整的操作系统一样，Kubernetes 仅是一个编排器，需结合其他软件以构成完整的集群。它需要容器引擎来运行其容器，还需要网络和持久化卷的插件。&lt;/p&gt;
&lt;p&gt;Kubernetes 发行版存在以填补这一空白。像 Linux 发行版一样，Kubernetes 发行版将 Kubernetes 与安装程序和精选的第三方组件捆绑在一起。不同的发行版存在以满足不同的需求；几乎每家规模一定的科技公司都有其自己的发行版和/或托管产品，以迎合企业需求。minikube 项目为开发者提供了一个更简便的本地实验环境。&lt;/p&gt;
&lt;h3 id="kubernetes-的组成结构"&gt;&lt;a href="#kubernetes-%e7%9a%84%e7%bb%84%e6%88%90%e7%bb%93%e6%9e%84" class="header-anchor"&gt;&lt;/a&gt;Kubernetes 的组成结构
&lt;/h3&gt;&lt;p&gt;一个 Kubernetes 集群包含多个软件组件。集群中的每个节点都会运行一个称为 kubelet 的代理，以保持集群成员资格并接受来自集群的工作，容器引擎，以及用于启用与其他节点上运行的容器进行网络通信的 kube-proxy。&lt;/p&gt;
&lt;p&gt;保持集群状态并对资源分配做出决策的组件被统称为控制平面，这包括一个分布式键值存储（etcd），一个将工作分配给集群节点的调度器，以及一个或多个控制器进程，这些进程对集群状态的变化做出反应，并触发任何必要的操作以使实际状态与所需状态相匹配。用户和集群节点通过 Kubernetes API 服务器与控制平面进行交互。为了实现变更，用户通过 API 服务器设置集群的期望状态，而 kubelet 将每个集群节点的实际状态报告给控制器进程。&lt;/p&gt;
&lt;p&gt;Kubernetes 在一个称为 Pod 的抽象中运行容器，Pod 可以包含一个或多个容器，尽管不建议在一个 Pod 中运行多个服务的容器。相反，通常一个 Pod 会有一个提供服务的主容器，可能还有一个或多个“sidecar”容器，用于从主容器中运行的服务收集指标或日志。Pod 中的所有容器都会一起调度在同一台机器上，并共享一个网络命名空间——在同一个 Pod 中运行的容器可以通过回环接口互相通信。每个 Pod 在集群内都会收到一个唯一的 IP 地址。在不同 Pod 中运行的容器可以使用它们的集群 IP 地址相互通信。&lt;/p&gt;
&lt;p&gt;一个 Pod 指定了一组要运行的容器，但 Pod 的定义并没有说明要在哪些地方运行这些容器，或运行多久——在没有这些信息的情况下，Kubernetes 会在集群中某处启动容器，但不会在它们退出时重新启动它们，并可能在控制平面决定其他工作负载需要它们使用的资源时突然终止它们。因此，Pod 很少单独使用；相反，Pod 的定义通常被封装在一个 Deployment 对象中，用于定义一个持久化服务。像 Compose 和 Swarm 一样，Kubernetes 管理的对象是在 YAML 中声明的；对于 Kubernetes，这些 YAML 声明通过 kubectl 工具提交到集群。&lt;/p&gt;
&lt;p&gt;除了 Pod 和 Deployment，Kubernetes 还可以管理许多其他类型的对象，例如负载均衡器和授权策略。支持的 API 列表在不断演变，且会因运行的 Kubernetes 版本和集群运行的发行版而有所不同。自定义资源可以用来向集群添加 API 以管理其他类型的对象。例如，KubeVirt 增加了 API 以使 Kubernetes 能够运行虚拟机。可以使用 kubectl api-versions 命令发现特定集群支持的 API 的完整列表。&lt;/p&gt;
&lt;p&gt;与 Compose 不同的是，每个对象是在一个单独的 YAML 文档中声明的，尽管可以通过在同一文件中用“&amp;mdash;”分隔它们内联多个 YAML 文档，如 Kubernetes 文档中所示。一个复杂的应用程序可能由多个对象组成，其定义分布在多个文件中；在维护此类应用程序时保持所有这些定义同步可能相当繁琐。为了使这项工作更容易，一些 Kubernetes 管理员转向了模板工具如 Jsonnet。&lt;/p&gt;
&lt;h4 id="helm-与应用部署"&gt;&lt;a href="#helm-%e4%b8%8e%e5%ba%94%e7%94%a8%e9%83%a8%e7%bd%b2" class="header-anchor"&gt;&lt;/a&gt;Helm 与应用部署
&lt;/h4&gt;&lt;p&gt;Helm 进一步推进了模板化的方法。与 Kubernetes 一样，Helm 的开发在 CNCF 的支持下进行；它被誉为“Kubernetes 的包管理器”。Helm 从一组称为 chart 的模板和变量声明集合中生成 Kubernetes 的 YAML 配置。其模板语言与 Ansible 的 Jinja 模板不同，但看起来非常相似；熟悉 Ansible 角色的人可能会对 Helm 图表感到得心应手。&lt;/p&gt;
&lt;p&gt;Helm 图表的集合可以在 Helm 存储库中发布；Artifact Hub 提供了一个公共 Helm 存储库的大型目录。管理员可以将这些存储库添加到他们的 Helm 配置中，并使用现成的 Helm 图表将预打包的流行应用程序版本部署到他们的集群。最近版本的 Helm 还支持将图表推送和拉取到容器注册表中，从而为管理员提供了将图表存储在与容器镜像相同位置的选项。&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/005-c4704500.png"&gt;&lt;/p&gt;
&lt;p&gt;Kubernetes 在短期内没有失去势头的迹象。它被设计为可以管理任何类型的资源；这种灵活性，如通过 KubeVirt 虚拟机控制器所示，即使容器化工作负载最终失宠，它也有可能保持相关性。开发进展迅速，定期发布新版本。版本支持为期一年；似乎没有长期支持版本。支持集群升级，但一些人更愿意建立一个新集群并迁移他们的服务。&lt;/p&gt;
&lt;h4 id="nomad-的简单替代方案"&gt;&lt;a href="#nomad-%e7%9a%84%e7%ae%80%e5%8d%95%e6%9b%bf%e4%bb%a3%e6%96%b9%e6%a1%88" class="header-anchor"&gt;&lt;/a&gt;Nomad 的简单替代方案
&lt;/h4&gt;&lt;p&gt;Nomad 是 HashiCorp 推出的编排器，作为 Kubernetes 的简单替代方案进行营销。Nomad 是一个开源项目，像 Docker 和 Kubernetes 一样。它由一个名为 nomad 的二进制文件组成，可用于启动一个称为代理的守护程序，并作为 CLI 与代理进行通信。根据其配置方式，代理进程可以以两种模式之一运行。在服务器模式下运行的代理接受作业并为它们分配集群资源。在客户端模式下运行的代理与服务器联系以接收作业、运行它们，并向服务器报告其状态。代理还可以在开发模式下运行，在这种模式下，它同时承担客户端和服务器的角色，形成一个可用于测试目的的单节点集群。&lt;/p&gt;
&lt;p&gt;创建一个 Nomad 集群可能相当简单。在 Nomad 的最基本操作模式下，必须启动初始服务器代理，然后可以使用 nomad server join 命令将其他节点添加到集群中。HashiCorp 还提供了 Consul，这是一种通用服务网格和发现工具。虽然可以单独使用，但 Nomad 与 Consul 结合使用时可能表现最佳。Nomad 代理可以使用 Consul 自动发现和加入集群，并且可以执行健康检查、提供 DNS 记录以及为集群上运行的服务提供 HTTPS 代理。&lt;/p&gt;
&lt;p&gt;Nomad 支持复杂的集群拓扑。每个集群分为一个或多个“数据中心”。与 Swarm 类似，单个数据中心内的服务器代理使用一种基于 Raft 的协议进行通信；该协议具有严格的延迟要求，但多个数据中心可以使用一种允许信息在集群中传播的流言协议链接在一起，而无需每个服务器都与每个其他服务器保持直接连接。从用户的角度来看，以这种方式链接在一起的数据中心可以作为一个集群运作。这种架构在扩展到巨大的集群时为 Nomad 带来优势。Kubernetes 官方支持最多 5000 个节点和 300000 个容器，而 Nomad 的文档引用了包含超过 10000 个节点和 200 万个容器的集群示例。&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-rong-qi-bian-pai-gong-ju-de-yan-jin-cong-docker-dao-kubernet/006-4f3abd38.png"&gt;&lt;/p&gt;
&lt;p&gt;与 Kubernetes 类似，Nomad 不包括容器引擎或运行时。它使用任务驱动程序来运行作业。使用 Docker 和 Podman 运行容器的任务驱动程序已包含在内；社区支持的驱动程序可用于其他容器引擎。同样与 Kubernetes 类似，Nomad 的野心不限于容器；还有其他类型工作负载的任务驱动程序，包括一个简单地在主机上运行命令的 fork/exec 驱动程序、用于运行虚拟机的 QEMU 驱动程序和用于启动 Java 应用程序的 Java 驱动程序。社区支持的任务驱动程序将 Nomad 连接到其他类型的工作负载。&lt;/p&gt;
&lt;p&gt;与 Docker 或 Kubernetes 不同，Nomad 避开了 YAML，而是采用 HashiCorp 配置语言（HCL），该语言最初是为另一个 HashiCorp 项目 Terraform 创建的，用于云资源的配置。HCL 在 HashiCorp 产品线中使用广泛，尽管在其他地方采用有限。用 HCL 编写的文档可以轻松转换为 JSON，但其目标是提供比 JSON 更便于手指输入且比 YAML 更不易出错的语法。&lt;/p&gt;
&lt;p&gt;HashiCorp 的 Helm 等效工具称为 Nomad Pack。像 Helm 一样，Nomad Pack 处理包含模板和变量声明的目录以生成作业配置。Nomad 还具有一个社区注册表，用于预打包应用程序，但可用选择远少于 Artifact Hub 的 Helm。&lt;/p&gt;
&lt;p&gt;Nomad 没有 Kubernetes 那样的受欢迎程度。像 Swarm 一样，其开发似乎主要由其创建者推动；虽然它已被许多大公司部署，但 HashiCorp 仍然是 Nomad 社区的中心。此时，项目似乎不太可能获得足够的动力以独立于其企业母公司存在。用户或许可以从 HashiCorp 更明确地致力于 Nomad 的开发和推广中找到一些保证，这与 Docker 对 Swarm 的承诺形成鲜明对比。&lt;/p&gt;
&lt;h4 id="结论"&gt;&lt;a href="#%e7%bb%93%e8%ae%ba" class="header-anchor"&gt;&lt;/a&gt;结论
&lt;/h4&gt;&lt;p&gt;Swarm、Kubernetes 和 Nomad 并不是唯一的容器编排器，但它们是三个最具生命力的工具。Apache Mesos 也可以用于运行容器，但在 2021 年几乎被搁置；基于 Mesos 的 DC/OS 也面临类似的情况，支持其发展的社区和商业实体正在寻找新的方向。尽管如此，Swarm、Kubernetes 和 Nomad 仍然是当前市场上最受欢迎和最活跃的容器编排解决方案，它们各自提供了不同的功能和优势，以满足不同规模和需求的企业。随着技术的不断进步和市场的变化，这些工具将继续演化，以适应未来的挑战和机遇。&lt;/p&gt;</description></item><item><title>HTML 中的 &lt;template&gt; 元素：提升动态网页的最佳工具</title><link>https://xiaobox.github.io/p/2024-08-10-html-zhong-de-template-yuan-su-ti-sheng-dong-tai-wang-ye-de/</link><pubDate>Sat, 10 Aug 2024 05:18:45 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-08-10-html-zhong-de-template-yuan-su-ti-sheng-dong-tai-wang-ye-de/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-html-zhong-de-template-yuan-su-ti-sheng-dong-tai-wang-ye-de-/cover.jpg" alt="Featured image of post HTML 中的 &lt;template&gt; 元素：提升动态网页的最佳工具" /&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-08-10-html-zhong-de-template-yuan-su-ti-sheng-dong-tai-wang-ye-de-/001-8c0b4ed5.png"&gt;&lt;/p&gt;
&lt;p&gt;在现代网页开发中，动态内容的生成和管理是一个重要的方面。为了简化这一过程，HTML5 引入了一个非常实用的元素——&lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt;。它为我们提供了一种灵活且高效的方式来管理和插入复杂的 HTML 结构。&lt;/p&gt;
&lt;h2 id="什么是-template-元素"&gt;&lt;a href="#%e4%bb%80%e4%b9%88%e6%98%af-template-%e5%85%83%e7%b4%a0" class="header-anchor"&gt;&lt;/a&gt;什么是 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素？
&lt;/h2&gt;&lt;p&gt;简单来说，&lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素是用来存储 HTML 片段的，这些片段在初始加载时并不呈现。它们仅在需要时才会被克隆并插入到 DOM 中。与普通隐藏元素不同，&lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素的内容是惰性的，这意味着其中的图片不会加载，脚本不会执行，样式也不会应用。&lt;/p&gt;
&lt;h3 id="为什么使用-template-元素"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e4%bd%bf%e7%94%a8-template-%e5%85%83%e7%b4%a0" class="header-anchor"&gt;&lt;/a&gt;为什么使用 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素？
&lt;/h3&gt;&lt;p&gt;在许多情况下，我们需要在网页加载后动态地添加复杂的 HTML 结构。如果完全依赖 JavaScript 来创建这些结构，可能会导致代码繁琐、复杂，尤其是当结构包含多个嵌套元素和属性时。&lt;/p&gt;
&lt;p&gt;以下是一个使用 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素的简单示例：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;burger-template&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;button&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;aria-expanded&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;false&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Menu&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;aria-controls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;mainnav&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;24&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;24&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;aria-hidden&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;4&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt; &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;5&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;6&lt;/span&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;7&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在这个例子中，我们定义了一个存储按钮的模板。这个按钮只有在 JavaScript 运行时才会被插入到页面中，从而保持页面的语义分离和代码的简洁性。&lt;/p&gt;
&lt;h2 id="如何使用-template-元素"&gt;&lt;a href="#%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8-template-%e5%85%83%e7%b4%a0" class="header-anchor"&gt;&lt;/a&gt;如何使用 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素？
&lt;/h2&gt;&lt;p&gt;使用 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素非常简单。首先，我们在 HTML 中定义一个模板元素，并赋予它一个唯一的 ID。然后，在 JavaScript 中，我们可以通过以下步骤来克隆和插入模板内容：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#burger-template&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cloneNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通过这种方式，我们可以将模板的内容克隆到指定的容器中。值得注意的是，这一过程不仅限于单次使用。您可以根据需要多次克隆和插入模板内容。&lt;/p&gt;
&lt;h3 id="实际应用中的例子"&gt;&lt;a href="#%e5%ae%9e%e9%99%85%e5%ba%94%e7%94%a8%e4%b8%ad%e7%9a%84%e4%be%8b%e5%ad%90" class="header-anchor"&gt;&lt;/a&gt;实际应用中的例子
&lt;/h3&gt;&lt;p&gt;在实际开发中，&lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素被广泛用于创建动态列表、表格行、交互式组件等。例如，在 Sass Guidelines 网站中，使用模板来动态注入 GitHub 链接，以便用户可以直接编辑视图或每个章节。这些链接原本应该始终存在，但由于该网站是由 Markdown 文件构建的，因此需要通过 JavaScript 动态生成。&lt;/p&gt;
&lt;h2 id="浏览器支持情况"&gt;&lt;a href="#%e6%b5%8f%e8%a7%88%e5%99%a8%e6%94%af%e6%8c%81%e6%83%85%e5%86%b5" class="header-anchor"&gt;&lt;/a&gt;浏览器支持情况
&lt;/h2&gt;&lt;p&gt;令人惊讶的是，几乎 98% 的现代浏览器都支持 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素。因此，在大多数情况下，您可以放心使用这一功能。如果您需要兼容旧版浏览器，可以通过以下方式检测支持情况：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;1&lt;/span&gt;&lt;span class="cl"&gt;if (&amp;#39;content&amp;#39; in document.createElement(&amp;#39;template&amp;#39;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;2&lt;/span&gt;&lt;span class="cl"&gt; // `&amp;lt;template&amp;gt;` 受支持。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="ln"&gt;3&lt;/span&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="为什么不使用隐藏元素"&gt;&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e4%b8%8d%e4%bd%bf%e7%94%a8%e9%9a%90%e8%97%8f%e5%85%83%e7%b4%a0" class="header-anchor"&gt;&lt;/a&gt;为什么不使用隐藏元素？
&lt;/h2&gt;&lt;p&gt;有读者可能会问，为什么不直接使用隐藏的 DOM 元素，例如 &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;，来存储模板内容呢？&lt;/p&gt;
&lt;p&gt;虽然这两者在某种程度上看似相似，但使用 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素有几个显著优势：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;惰性加载&lt;/strong&gt;：与隐藏的容器不同，&lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 的内容不会自动加载。这意味着其中的图片和脚本不会被执行，从而提高了页面性能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;灵活性&lt;/strong&gt;：&lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 可以包含任何 HTML 结构，而无需考虑 HTML 验证器的限制。例如，您可以在 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 中包含 &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; 或 &lt;code&gt;&amp;lt;dd&amp;gt;&lt;/code&gt; 等元素，而这些元素通常要求特定的父元素。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;语义性&lt;/strong&gt;：&lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 是专门为存储模板设计的，因此它在语义上更为清晰，尤其是对于第三方工具和扩展来说。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;安全性&lt;/strong&gt;：使用 CSS 隐藏元素并不可靠，因为 CSS 可能被禁用或覆盖。而 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素总是默认隐藏，即使在没有 CSS 的情况下也能保持其不可见性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SEO 考虑&lt;/strong&gt;：搜索引擎可能会索引通过 CSS 隐藏的内容，这可能导致不必要的模板数据被索引。而使用 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 则无需担心这一问题。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="总结"&gt;&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;&lt;/a&gt;总结
&lt;/h2&gt;&lt;p&gt;总的来说，HTML 的 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素为开发者提供了一种高效管理动态内容的方法。对于简单的节点操作，我们可以使用内置的 DOM 操作方法，但对于更复杂的结构，使用 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 无疑是更好的选择。&lt;/p&gt;
&lt;p&gt;希望本文能帮助您更好地理解和应用 &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; 元素。如果您有任何问题或建议，欢迎在评论区与我们分享！&lt;/p&gt;</description></item><item><title>RAG 实践- Ollama+MaxKB 部署本地知识库</title><link>https://xiaobox.github.io/p/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/</link><pubDate>Sat, 22 Jun 2024 09:55:14 +0000</pubDate><guid>https://xiaobox.github.io/p/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/</guid><description>&lt;img src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/cover.jpg" alt="Featured image of post RAG 实践- Ollama+MaxKB 部署本地知识库" /&gt;&lt;h2 id="前言"&gt;&lt;a href="#%e5%89%8d%e8%a8%80" class="header-anchor"&gt;&lt;/a&gt;前言
&lt;/h2&gt;&lt;p&gt;本文我们介绍另外一种部署本地知识库的方案：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Ollama + MaxKB&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;相对来说，容易安装且功能较完善，30 分钟内即可上线基于本地大模型的知识库问答系统，并嵌入到第三方业务系统中。&lt;/p&gt;
&lt;p&gt;缺点是如果你的电脑配置不高，问题回答响应时间较长。&lt;/p&gt;
&lt;p&gt;下图为 MaxKB 的产品架构：&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/001-08767b01.png"&gt;&lt;/p&gt;
&lt;p&gt;实现原理上，仍然是应用了 RAG 流程：&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/002-4f55ccfd.png"&gt;&lt;/p&gt;
&lt;h2 id="安装-maxkb"&gt;&lt;a href="#%e5%ae%89%e8%a3%85-maxkb" class="header-anchor"&gt;&lt;/a&gt;安装 MaxKB
&lt;/h2&gt;&lt;p&gt;首先我们通过 Docker 安装 MaxKB&lt;/p&gt;
&lt;p&gt;&lt;code&gt;docker run -d --name=maxkb -p 8080:8080 -v ~/.maxkb:/var/lib/postgresql/data cr2.fit2cloud.com/1panel/maxkb &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;注意这里镜像源是 china mainland，走代理的镜像会下载失败。&lt;/p&gt;
&lt;p&gt;安装成功后访问：http://localhost:8080/ 登录，初始账号为：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;用户名: admin 密码: MaxKB@123.. &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;进入系统后是这样的：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/003-01b4122a.png"&gt;&lt;/p&gt;
&lt;h2 id="配置模型"&gt;&lt;a href="#%e9%85%8d%e7%bd%ae%e6%a8%a1%e5%9e%8b" class="header-anchor"&gt;&lt;/a&gt;配置模型
&lt;/h2&gt;&lt;p&gt;接下来我们进行最重要的模型配置&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/004-5751bc9e.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到有许多模型的供应商，这里你可以通过 API key 在线去连接大模型&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/005-722d2069.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;API key 不同的模型厂商有不同的申请地址，这种方式不是本文采用的方式，本文我们将把通过 Ollama 本地部署的 Qwen2 大模型配置到 MaxKB&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;所以，第一步我们添加模型选择 Ollama&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/006-00646cce.png"&gt;&lt;/p&gt;
&lt;p&gt;第二步配置模型，在模型添加界面有几个点要注意（下图是修改界面，和添加界面差不多）&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/007-d7ed64f9.png"&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;模型名称和基础模型一定要和你在 &lt;code&gt;ollama list&lt;/code&gt; 中显示的一样，不然可能会导致没有必要的重复下载和连接失败&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/008-ca9df5eb.png"&gt;&lt;/li&gt;
&lt;li&gt;API 域名，因为 MaxKB 是 Docker 部署的，Ollama 是本机部署的，不在一个网络环境，所以要填 ：http://host.docker.internal:11434&lt;/li&gt;
&lt;li&gt;API Key 随便写什么都行&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="创建知识库"&gt;&lt;a href="#%e5%88%9b%e5%bb%ba%e7%9f%a5%e8%af%86%e5%ba%93" class="header-anchor"&gt;&lt;/a&gt;创建知识库
&lt;/h2&gt;&lt;p&gt;模型添加完成，就可以创建知识库了。&lt;/p&gt;
&lt;p&gt;这个比较简单，通过界面功能自己就能搞定，我就不多说了&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/009-c0e740af.png"&gt;&lt;/p&gt;
&lt;p&gt;这里比较好的是，MaxKB 支持选择文件夹，这一点 AnythingLLM 就不行，不过一次上传文件数量有限：&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/010-1298aa3c.png"&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;“&lt;/p&gt;
&lt;p&gt;支持格式：TXT、Markdown、PDF、DOCX、HTML 每次最多上传50个文件，每个文件不超过 100MB 若使用【高级分段】建议上传前规范文件的分段标识&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h2 id="创建应用"&gt;&lt;a href="#%e5%88%9b%e5%bb%ba%e5%ba%94%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;创建应用
&lt;/h2&gt;&lt;p&gt;知识库创建完，就可以创建应用进行问答了&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/011-c2fb9b46.png"&gt;&lt;/p&gt;
&lt;p&gt;这里注意除了要为应用添加知识库外，还要进行一下参数设置&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/012-3d44b352.png"&gt;&lt;/p&gt;
&lt;p&gt;我选择的是第二项，因为我的知识库数据量较小&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/013-61cbad40.png"&gt;&lt;/p&gt;
&lt;p&gt;设置完成后点击演示&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/014-76e6c2a8.png"&gt;&lt;/p&gt;
&lt;h2 id="问答效果展示"&gt;&lt;a href="#%e9%97%ae%e7%ad%94%e6%95%88%e6%9e%9c%e5%b1%95%e7%a4%ba" class="header-anchor"&gt;&lt;/a&gt;问答效果展示
&lt;/h2&gt;&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/015-caa129ab.png"&gt;&lt;/p&gt;
&lt;p&gt;这里不太好的是没有同时展示引文，更不用说引文的预览了，实际上这个功能基本上是企业应用上的 &lt;strong&gt;刚需&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="嵌入第三方应用"&gt;&lt;a href="#%e5%b5%8c%e5%85%a5%e7%ac%ac%e4%b8%89%e6%96%b9%e5%ba%94%e7%94%a8" class="header-anchor"&gt;&lt;/a&gt;嵌入第三方应用
&lt;/h2&gt;&lt;p&gt;嵌入三方应用的需求也是比较常见的，比如你可以通过 iframe 或者 js 代码的形式嵌入到你现有的系统中，我们经常看到一些网站右下角的浮窗就是这种形式，在 MaxKB 中支持嵌入三方应用，需要在应用的 “概览” 中点击 “嵌入第三方”&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/016-8c062a85.png"&gt;&lt;/p&gt;
&lt;p&gt;剩下的你只需要把代码集成到你的其他应用中就可以了&lt;/p&gt;
&lt;p&gt;&lt;img alt="Image" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://pub-f29bf2b53160470c9a85250116509a24.r2.dev/post/2024-06-22-rag-shi-jian-ollama-maxkb-bu-shu-ben-di-zhi-shi-ku/017-f904d255.png"&gt;&lt;/p&gt;
&lt;h2 id="思考"&gt;&lt;a href="#%e6%80%9d%e8%80%83" class="header-anchor"&gt;&lt;/a&gt;思考
&lt;/h2&gt;&lt;p&gt;学习新知识，最好的方式就是直接去应用它，你可能从来都不知道什么是 RAG，但对相关知识有个大概了解后，通过实践，亲自搭建几个可以 run 起来的应用，那些架构里的结构、名词，逐渐全部都能对应得上了。&lt;/p&gt;
&lt;p&gt;我笔记本的配置有限，如果所有的东西都部署在配置有性能强较的显卡的服务器上，那么就可以满足企业级应用的需求了，企业可以直接完成私有化部署并开始应用。&lt;/p&gt;
&lt;h2 id="参考"&gt;&lt;a href="#%e5%8f%82%e8%80%83" class="header-anchor"&gt;&lt;/a&gt;参考
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/1Panel-dev/MaxKB/wiki" target="_blank" rel="noopener"
 &gt;https://github.com/1Panel-dev/MaxKB/wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>