<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>黑光技术 - 完美之道，不在无可增加，而在无可删减。 – 博客</title>
    <link>https://www.helight.info/blog/</link>
    <description>Recent content in 博客 on 黑光技术 - 完美之道，不在无可增加，而在无可删减。</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-CN</language>
    
	  <atom:link href="https://www.helight.info/blog/index.xml" rel="self" type="application/rss+xml" />
    
    
      
        
      
    
    
    <item>
      <title>ESP32 WS2812 彩色 LED 驱动与动画演示实践</title>
      <link>https://www.helight.info/blog/2026/0701-esp32-ws2812-colorled/</link>
      <pubDate>Wed, 01 Jul 2026 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0701-esp32-ws2812-colorled/</guid>
      <description>
        
        
        &lt;h2&gt;一、背景与动机&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一背景与动机&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e8%83%8c%e6%99%af%e4%b8%8e%e5%8a%a8%e6%9c%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;最近在整理桌面时，翻出一块吃灰已久的 WS2812 灯环——16 颗 RGB LED 围成一圈，如果驱动起来做点氛围灯效果应该不错。WS2812（也叫 NeoPixel）是目前最常见的智能 LED 灯珠，每颗灯珠内置驱动 IC，仅需一根数据线就能独立控制 24 位颜色（GRB 各 8 位），级联起来可以做出各种酷炫的动态效果。&lt;/p&gt;
&lt;p&gt;但 WS2812 有一个让人头疼的地方：&lt;strong&gt;信号时序要求非常严格&lt;/strong&gt;。0 码需要高电平约 0.4 µs + 低电平约 0.8 µs，1 码则是高电平 0.8 µs + 低电平 0.4 µs，误差容忍度通常在 ±150 ns 以内。普通 GPIO 软件翻转很难同时满足 ns 级精度和多任务实时性。&lt;/p&gt;
&lt;p&gt;恰好之前做过一个 ESP32 WiFi 时钟项目（&lt;a href=&#34;https://www.helight.info/blog/2026/0614-esp32-wifi-clock/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;基于 ESP32 的 WiFi 智能时钟&lt;/a&gt;），对 ESP32 的 RMT（Remote Control）外设比较熟悉。RMT 原本是为红外遥控设计的，能硬件生成精确到 100 ns 粒度的脉冲序列，天然适配 WS2812 的时序需求。于是决定在 &lt;a href=&#34;https://github.com/helight/esp32projects&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;esp32projects&lt;/a&gt; 仓库中新增一个 &lt;code&gt;colorled&lt;/code&gt; 子项目，把完整的 WS2812 驱动和几种常见动画效果实现出来。&lt;/p&gt;
&lt;h2&gt;二、核心原理&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二核心原理&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e6%a0%b8%e5%bf%83%e5%8e%9f%e7%90%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. WS2812 的时序挑战&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-ws2812-的时序挑战&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-ws2812-%e7%9a%84%e6%97%b6%e5%ba%8f%e6%8c%91%e6%88%98&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;WS2812 使用单总线协议，每个 bit 通过不同的高低电平比例来编码：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;信号&lt;/th&gt;
					&lt;th&gt;高电平持续时间&lt;/th&gt;
					&lt;th&gt;低电平持续时间&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;0 码&lt;/td&gt;
					&lt;td&gt;~0.4 µs&lt;/td&gt;
					&lt;td&gt;~0.8 µs&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;1 码&lt;/td&gt;
					&lt;td&gt;~0.8 µs&lt;/td&gt;
					&lt;td&gt;~0.4 µs&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;复位&lt;/td&gt;
					&lt;td&gt;&amp;gt;50 µs 低电平&lt;/td&gt;
					&lt;td&gt;—&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;发送完所有灯珠的数据后，还需要一个超过 50 µs 的低电平复位信号，灯珠才会把收到的数据锁存到输出。每个灯珠需要 24 个 bit（GRB × 8），所以 16 颗灯珠就是 384 bit，总传输时间大约 300 µs。&lt;/p&gt;
&lt;h3&gt;2. RMT 外设方案&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-rmt-外设方案&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-rmt-%e5%a4%96%e8%ae%be%e6%96%b9%e6%a1%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;RMT 的全称是 &lt;strong&gt;Remote Control（遥控信号发送）&lt;/strong&gt;，是 ESP32 上专门为红外/射频遥控信号设计的硬件外设。它最早是为了驱动红外 LED 发送 NEC、Sony SIRC 等遥控协议而生的，但由于其灵活的可编程能力，在嵌入式社区中被广泛用于驱动各类单总线设备——WS2812 就是其中最典型的应用。&lt;/p&gt;
&lt;h4&gt;RMT 基本工作原理&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;rmt-基本工作原理&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#rmt-%e5%9f%ba%e6%9c%ac%e5%b7%a5%e4%bd%9c%e5%8e%9f%e7%90%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;RMT 的核心是一个&lt;strong&gt;硬件状态机驱动的可编程脉冲发生器&lt;/strong&gt;，它的工作模型非常直观：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;① 时钟与 tick&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;RMT 模块使用 APB 时钟（通常 80 MHz）作为源时钟，通过分频器产生工作时钟。每个 tick 的时长由分频系数决定：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;RMT 时钟频率 = APB 时钟 / (分频系数 &amp;#43; 1)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;例如分频系数设为 7，则 RMT 时钟 = 80 MHz / 8 = 10 MHz，每个 tick = 0.1 µs。tick 是 RMT 所有时序操作的基本时间单位。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;② 内存指令槽（Item/Slot）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;每个 RMT 通道内部有一段专用的 RAM（通常 64 × 32 bit），按&amp;quot;指令槽&amp;quot;组织。每个指令槽是一个 32 位的结构：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;31      15 14      0
┌────────┬────────┐
│ level0 │ duration0 │  ← 第一段电平：先输出 level0，保持 duration0 个 tick
├────────┼────────┤
│ level1 │ duration1 │  ← 第二段电平：再输出 level1，保持 duration1 个 tick
└────────┴────────┘&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;level&lt;/code&gt;（1 bit）：0 表示低电平，1 表示高电平&lt;/li&gt;
&lt;li&gt;&lt;code&gt;duration&lt;/code&gt;（15 bit）：持续 tick 数，范围 1–32767&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以&lt;strong&gt;一个指令槽可以描述一段&amp;quot;高低电平对&amp;quot;&lt;/strong&gt;，这正是脉冲信号的基本单元。对于一个 NEC 红外遥控的&amp;quot;引导码&amp;quot;（9 ms 高电平 + 4.5 ms 低电平），只需要一个指令槽：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;level0=1, duration0=90000  (9 ms @ 10 MHz)
level1=0, duration1=45000  (4.5 ms @ 10 MHz)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;③ 硬件自动遍历&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;配置好指令槽序列后，只需要触发通道启动，RMT 硬件就会从指令槽 0 开始，按顺序逐个输出每个槽位定义的电平波形，直到遇到&lt;strong&gt;结束标记&lt;/strong&gt;（高 15 bit 全 1 的特殊槽位）或达到预设的发送数量。整个过程&lt;strong&gt;完全由硬件状态机驱动，CPU 零干预&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;当发送完成时，RMT 可以产生中断或触发 DMA，通知 CPU 进行下一轮数据处理。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;④ 与 WS2812 的映射关系&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;WS2812 需要为每个 bit 输出一个特定的高低电平对（0 码 = 0.4 µs 高 + 0.8 µs 低，1 码 = 0.8 µs 高 + 0.4 µs 低），正好对应 RMT 的一个指令槽。24 个 bit（3 字节）就对应 24 个指令槽，再加上末尾的复位低电平。所以用 RMT 驱动 WS2812 在概念上非常自然——&lt;strong&gt;把颜色字节翻译成一串指令槽序列，然后交给硬件去&amp;quot;播放&amp;quot;&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;⑤ 从旧 API 到新 API&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在 ESP-IDF v4.x 及更早版本中，需要手动填充指令槽数组：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 旧 API：手动构建 RMT items
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;rmt_item32_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;24&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;24&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;level0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x800000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;T1H&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;T0H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;level1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x800000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;T1L&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;T0L&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;bit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;rmt_write_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RMT_CHANNEL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;24&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这种方式的缺点是：每次发送都需要手动拼装 24 个指令槽，代码冗长且容易出错。ESP-IDF v5.x 引入的 &lt;code&gt;rmt_bytes_encoder&lt;/code&gt; 封装了这一过程，只需要配置 0 码和 1 码的模板，驱动自动完成字节到指令槽的转换——这正是本项目中使用的方案。&lt;/p&gt;
&lt;h4&gt;RMT 配置与优势&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;rmt-配置与优势&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#rmt-%e9%85%8d%e7%bd%ae%e4%b8%8e%e4%bc%98%e5%8a%bf&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;对于 WS2812 来说，RMT 的优势非常明显：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;高精度时序&lt;/strong&gt;：tick 精度可达 100 ns（12.5 MHz 时钟），而 WS2812 的时序容忍度约 ±150 ns，完全满足要求&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;硬件自动发送&lt;/strong&gt;：发送过程中 CPU 可以去做其他事情（比如计算下一帧的动画数据），适合多任务场景&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多通道独立&lt;/strong&gt;：ESP32 有 8 个 RMT 通道（部分型号 4 个），可以同时驱动多路 WS2812 灯带&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;具体到本项目，使用新版 API 的 &lt;code&gt;rmt_bytes_encoder&lt;/code&gt; 配置如下：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;rmt_bytes_encoder_config_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bytes_encoder_cfg&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bit0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;level0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;T0H_TICKS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;// 0 码高电平：4 ticks → 0.4 µs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;level1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;T0L_TICKS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;// 0 码低电平：8 ticks → 0.8 µs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bit1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;level0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;T1H_TICKS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;// 1 码高电平：8 ticks → 0.8 µs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;level1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;T1L_TICKS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;// 1 码低电平：4 ticks → 0.4 µs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;flags&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;msb_first&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;         &lt;span class=&#34;c1&#34;&gt;// 高位先行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;RMT 时钟配置为 10 MHz（0.1 µs/tick），这样时序参数刚好是整数——4 ticks 对应 0.4 µs，8 ticks 对应 0.8 µs，非常简洁。&lt;/p&gt;
&lt;h2&gt;三、实战步骤&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三实战步骤&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e5%ae%9e%e6%88%98%e6%ad%a5%e9%aa%a4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 硬件接线&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-硬件接线&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e7%a1%ac%e4%bb%b6%e6%8e%a5%e7%ba%bf&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这里我用了一块 ESP32 DOIT DevKit V1 开发板和一个 16 颗灯珠的 WS2812 环形灯板，接线非常简单：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;WS2812 引脚&lt;/th&gt;
					&lt;th&gt;连接&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;VCC (5V)&lt;/td&gt;
					&lt;td&gt;5V 电源（16 颗灯珠峰值电流约 1A，电脑 USB 勉强够用，更多灯珠需外接电源）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;GND&lt;/td&gt;
					&lt;td&gt;共地&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;DIN (数据输入)&lt;/td&gt;
					&lt;td&gt;ESP32 GPIO15（代码中由 &lt;code&gt;WS2812_GPIO&lt;/code&gt; 宏定义，可改）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
  &lt;p&gt;如果灯珠数量较多（超过 30 颗），强烈建议外接 5V 电源，否则 USB 供电可能不稳导致颜色异常。&lt;/p&gt;

&lt;/blockquote&gt;
&lt;h3&gt;2. 项目结构&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-项目结构&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e9%a1%b9%e7%9b%ae%e7%bb%93%e6%9e%84&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;整个 &lt;code&gt;colorled&lt;/code&gt; 项目是 &lt;a href=&#34;https://github.com/helight/esp32projects&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;esp32projects&lt;/a&gt; 多项目仓库中的一个子项目，目录结构如下：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;colorled/
├── CMakeLists.txt
├── main/
│   ├── CMakeLists.txt
│   ├── main.c          # 主程序：动画逻辑 &amp;#43; 帧循环
│   └── ws2812.h        # WS2812 驱动头文件
└── platformio.ini      # PlatformIO 构建配置&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;3. 驱动层实现&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-驱动层实现&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-%e9%a9%b1%e5%8a%a8%e5%b1%82%e5%ae%9e%e7%8e%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;驱动层主要处理两件事情：&lt;strong&gt;RGB→GRB 色彩转换&lt;/strong&gt;和&lt;strong&gt;通过 RMT 发送数据&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;WS2812 的内部颜色顺序是 &lt;strong&gt;GRB&lt;/strong&gt;（Green-Red-Blue），而非常见的 RGB。为了让上层动画算法不受硬件差异困扰，代码维护了一个 &lt;code&gt;led_rgb[]&lt;/code&gt; 数组作为&lt;strong&gt;逻辑渲染缓冲&lt;/strong&gt;（RGB 顺序），在发送之前才转换为 GRB：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 渲染算法写 led_rgb（R、G、B 分别存储在相邻字节）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;led_rgb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;red&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;// R
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;led_rgb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;green&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// G
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;led_rgb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;blue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// B
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 发送时重新排列为 GRB
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ws2812_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;led_rgb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// G
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ws2812_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;led_rgb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// R
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ws2812_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;led_rgb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;// B
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这种设计让上层动画代码只需使用常规的 RGB 思维，底层自动处理硬件差异。&lt;/p&gt;
&lt;h3&gt;4. HSV 色彩空间实现&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;4-hsv-色彩空间实现&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#4-hsv-%e8%89%b2%e5%bd%a9%e7%a9%ba%e9%97%b4%e5%ae%9e%e7%8e%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;彩虹类动画的关键是 &lt;strong&gt;HSV 色彩空间&lt;/strong&gt;。代码实现了 8 位精度的 &lt;code&gt;hsv_to_rgb&lt;/code&gt; 转换函数：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hue（色相）&lt;/strong&gt;：0–255 映射到 0°–360° 色环&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Saturation（饱和度）&lt;/strong&gt;：0–255，0 为灰色，255 为纯色&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Value（明度）&lt;/strong&gt;：0–255，决定颜色亮度&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;转换算法将色环 0–255 均匀分成 6 个区域（每区约 43 个单位），每个区域对应 R/G/B 其中两个分量的线性插值。这种方式比直接操作 RGB 三通道更自然——想做彩虹效果时，只需要递增 Hue 值，不需要分别协调 R/G/B 的变化。&lt;/p&gt;
&lt;h3&gt;5. 三种动画场景&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;5-三种动画场景&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#5-%e4%b8%89%e7%a7%8d%e5%8a%a8%e7%94%bb%e5%9c%ba%e6%99%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在 &lt;code&gt;app_main()&lt;/code&gt; 的主循环中，通过帧计数 &lt;code&gt;frame&lt;/code&gt; 每 320 帧轮换一次场景。帧率由 &lt;code&gt;FRAME_DELAY_MS&lt;/code&gt;（25 ms → 约 40 FPS）控制。&lt;/p&gt;
&lt;h4&gt;场景 0：彩虹（Rainbow）&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;场景-0彩虹rainbow&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9c%ba%e6%99%af-0%e5%bd%a9%e8%99%b9rainbow&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;彩虹场景利用了 HSV 的最大优势：&lt;strong&gt;仅改变 Hue 即可实现平滑的彩色过渡&lt;/strong&gt;。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;WS2812_LED_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hue&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;base_hue&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;256&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;WS2812_LED_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;hsv_to_rgb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;160&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;set_pixel_rgb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;256 / WS2812_LED_COUNT&lt;/code&gt; 计算出相邻灯珠之间的色相步长。对于 16 颗灯珠，步长为 16，即每颗灯珠跨越约 22.5°，覆盖完整彩虹。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;base_hue&lt;/code&gt; 是全局色相偏移量，&lt;strong&gt;每帧递增 2&lt;/strong&gt;（相当于约 2.8°/帧），使整条彩虹连续旋转。&lt;/li&gt;
&lt;li&gt;每个像素的色相取 &lt;code&gt;(uint8_t)&lt;/code&gt; 自动溢出 256，天然实现色相环绕，无需额外取模。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;场景 1：彗星拖尾（Comet Tail）&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;场景-1彗星拖尾comet-tail&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9c%ba%e6%99%af-1%e5%bd%97%e6%98%9f%e6%8b%96%e5%b0%becomet-tail&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;彗星拖尾模拟一颗&amp;quot;流星&amp;quot;在环形灯带上飞过的视觉效果——头部高亮，尾迹渐暗渐远：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;head&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;frame&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;WS2812_LED_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pos&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;head&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pos&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pos&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;WS2812_LED_COUNT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;hsv_to_rgb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;base_hue&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;        &lt;span class=&#34;c1&#34;&gt;// 越远的尾巴色相偏移越大
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;mi&#34;&gt;220&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;                      &lt;span class=&#34;c1&#34;&gt;// 轻微去饱和
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;mi&#34;&gt;220&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;             &lt;span class=&#34;c1&#34;&gt;// 亮度逐级递减
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;set_pixel_rgb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;g&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style=&#34;text-align: center&#34;&gt;尾部索引 &lt;code&gt;t&lt;/code&gt;&lt;/th&gt;
					&lt;th style=&#34;text-align: center&#34;&gt;色相偏移&lt;/th&gt;
					&lt;th style=&#34;text-align: center&#34;&gt;亮度 &lt;code&gt;val&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;视觉效果&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;0（头部）&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;+0&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;220&lt;/td&gt;
					&lt;td&gt;高亮，主色&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;1&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;+8&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;188&lt;/td&gt;
					&lt;td&gt;稍暗&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;2&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;+16&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;156&lt;/td&gt;
					&lt;td&gt;继续衰减&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;3&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;+24&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;124&lt;/td&gt;
					&lt;td&gt;较暗&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;4&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;+32&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;92&lt;/td&gt;
					&lt;td&gt;暗淡&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;5（最远）&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;+40&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;60&lt;/td&gt;
					&lt;td&gt;微弱余晖&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;尾部由 6 颗灯珠组成，约占 16 颗灯带的 1/3，既能看清拖尾效果，又不会覆盖整个灯带导致头部不突出。色相每步偏移 +8，使尾巴带有细微的色相渐变，增强层次感。&lt;/p&gt;
&lt;h4&gt;场景 2：呼吸灯（Breathing）&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;场景-2呼吸灯breathing&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9c%ba%e6%99%af-2%e5%91%bc%e5%90%b8%e7%81%afbreathing&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;呼吸灯模拟生物呼吸的节奏——所有灯珠同步从暗到亮、再从亮到暗：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wave&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;frame&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;120&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;frame&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;         &lt;span class=&#34;c1&#34;&gt;// 上升段：0 → 236
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)((&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;59&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;frame&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// 下降段：236 → 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这是一个&lt;strong&gt;三角波（锯齿波）发生器&lt;/strong&gt;，周期为 120 帧（约 3 秒一次呼吸）：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th style=&#34;text-align: center&#34;&gt;帧区间&lt;/th&gt;
					&lt;th style=&#34;text-align: center&#34;&gt;波形阶段&lt;/th&gt;
					&lt;th style=&#34;text-align: center&#34;&gt;&lt;code&gt;wave&lt;/code&gt; 值范围&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;0–59&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;上升（吸气）&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;0 → 236&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;60–119&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;下降（呼气）&lt;/td&gt;
					&lt;td style=&#34;text-align: center&#34;&gt;236 → 0&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;然后通过 &lt;code&gt;scale8&lt;/code&gt; 函数对每个像素的 R/G/B 分量独立缩放，保持色调不变、仅改变亮度：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;inline&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;scale8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scale&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint8_t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(((&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint16_t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;uint16_t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;scale&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;255U&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;每颗灯珠的色相略有差异（步长 5），在呼吸的同时呈现微弱的渐变色彩，避免单调。&lt;/p&gt;
&lt;h3&gt;6. 帧刷新流程&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;6-帧刷新流程&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#6-%e5%b8%a7%e5%88%b7%e6%96%b0%e6%b5%81%e7%a8%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;每一帧的完整流程如下：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;app_main 主循环
  ├── 根据 scene 类型更新 led_rgb[] 缓冲
  ├── 调用 ws2812_show_buffer()
  │     ├── RGB → GRB 转存到 ws2812_data[]
  │     ├── rmt_transmit() 通过 bytes_encoder 自动编码并发送
  │     └── rmt_tx_wait_all_done() 等待发送完成
  ├── base_hue &amp;#43;= 2（色相推进）
  ├── frame&amp;#43;&amp;#43;（帧计数）
  └── vTaskDelay(25 ms) → 约 40 FPS&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;7. 构建与烧录&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;7-构建与烧录&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#7-%e6%9e%84%e5%bb%ba%e4%b8%8e%e7%83%a7%e5%bd%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;项目使用 &lt;strong&gt;PlatformIO&lt;/strong&gt; 构建，目标板为 &lt;code&gt;rymcu-esp32-devkitc&lt;/code&gt;，框架为 &lt;code&gt;espidf&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 进入子项目目录&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; colorled
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 安装依赖（PlatformIO 会自动下载 ESP-IDF 工具链）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pio run
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 烧录到目标板&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pio run --target upload
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 监视串口日志&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pio device monitor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;也可直接使用 ESP-IDF 原生工具链：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;idf.py build
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;idf.py -p /dev/cu.usbserial-xxxx flash monitor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;四、效果与踩坑&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四效果与踩坑&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e6%95%88%e6%9e%9c%e4%b8%8e%e8%b8%a9%e5%9d%91&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;效果体验&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;效果体验&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%95%88%e6%9e%9c%e4%bd%93%e9%aa%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;通电之后，三种动画每 320 帧（约 8 秒）自动切换：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;彩虹模式&lt;/strong&gt;：灯环像色轮一样缓慢旋转，色彩过渡非常平滑&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;彗星拖尾&lt;/strong&gt;：一颗亮色&amp;quot;流星&amp;quot;在环形灯带上飞驰，后面拖着渐变的余晖&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;呼吸灯&lt;/strong&gt;：所有灯珠同步明暗交替，带微弱的彩色渐变，效果最柔和&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;踩坑记录&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;踩坑记录&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%b8%a9%e5%9d%91%e8%ae%b0%e5%bd%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;① 时序参数需要实测调整&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;虽然 WS2812 数据手册给出了标准的 0.4 µs / 0.8 µs 时序，但在我的实际灯板上，0 码高电平需要略低到 0.35 µs（3 ticks）才能稳定显示。不同厂家的 WS2812 灯珠存在差异，建议先用逻辑分析仪实测调整。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;② 复位时序不能忽略&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rmt_bytes_encoder&lt;/code&gt; 会自动在每帧数据末尾插入低电平复位信号，但如果手动配置则需要确保复位低电平 &amp;gt; 50 µs，否则灯珠不会锁存新的颜色数据。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;③ 供电不足导致颜色偏移&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;16 颗灯珠全部设为白色（RGB 全亮）时，峰值电流接近 1A。直接用开发板的 USB 供电会导致电压跌落，表现为：靠近数据源的灯珠颜色正常，远处的颜色偏黄偏暗。接上外置 5V 电源后就正常了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;④ 帧率与实时性的平衡&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;40 FPS（25 ms/帧）对于 LED 动画来说已经非常流畅。如果把 &lt;code&gt;FRAME_DELAY_MS&lt;/code&gt; 降到 10 ms 以下，RMT 发送占用的时间会开始挤占主循环，可能导致 WiFi/蓝牙等其他任务响应延迟。&lt;/p&gt;
&lt;h2&gt;五、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这次实践完整走通了一条从&lt;strong&gt;底层硬件时序 → 驱动封装 → 色彩空间管理 → 上层动画效果&lt;/strong&gt;的技术链路。几个核心收获：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;RMT 外设是 ESP32 驱动 WS2812 的最佳方案&lt;/strong&gt;——硬件生成精确脉冲，无需 CPU 干预，代码量很少&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HSV 色彩模型是写动画的利器&lt;/strong&gt;——彩虹、渐变这类效果用色相递进比直接操作 RGB 简单得多&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分层设计让代码更清晰&lt;/strong&gt;——RGB 逻辑缓冲 + GRB 硬件映射的分离，让动画算法不受硬件差异影响&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;代码已开源在 &lt;a href=&#34;https://github.com/helight/esp32projects/tree/main/colorled&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;github.com/helight/esp32projects/tree/main/colorled&lt;/a&gt;，感兴趣的读者可以直接拿去用，改成自己的灯带数量、引脚和动画场景都很方便。&lt;/p&gt;
&lt;p&gt;下一步我打算在这个项目基础上增加一个 WiFi 控制功能，通过 Web 页面或手机 App 实时切换动画模式和调整颜色参数，让它变成一个真正可交互的桌面氛围灯。&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>从 tmux 到 cmux：终端效率工具的一次重大升级</title>
      <link>https://www.helight.info/blog/2026/0617-cmux-vs-tmux/</link>
      <pubDate>Wed, 17 Jun 2026 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0617-cmux-vs-tmux/</guid>
      <description>
        
        
        &lt;p&gt;最近重新审视了自己的终端工作流，做了一个重大决定：&lt;strong&gt;从 tmux 迁移到 cmux&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;用 tmux 很多年了，说实话，它的功能已经很强大——窗口、窗格、会话管理、持久化等等。但用得越久，我越觉得某些地方不够自然。&lt;strong&gt;命令的繁琐程度和切换的割裂感&lt;/strong&gt;一直是我的心病。cmux 的出现恰好击中了这些痛点，而且它的理念让整个终端体验上了一个全新的维度。&lt;/p&gt;
&lt;p&gt;这篇文章不写枯燥的参数对比，而是从实际使用场景出发，聊聊 cmux 到底好在哪里。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;一、tmux 的优点与痛点&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一tmux-的优点与痛点&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80tmux-%e7%9a%84%e4%bc%98%e7%82%b9%e4%b8%8e%e7%97%9b%e7%82%b9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;✅ tmux 做对的事情&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-tmux-做对的事情&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-tmux-%e5%81%9a%e5%af%b9%e7%9a%84%e4%ba%8b%e6%83%85&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&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;h3&gt;❌ 那些让我越来越不舒服的地方&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-那些让我越来越不舒服的地方&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e9%82%a3%e4%ba%9b%e8%ae%a9%e6%88%91%e8%b6%8a%e6%9d%a5%e8%b6%8a%e4%b8%8d%e8%88%92%e6%9c%8d%e7%9a%84%e5%9c%b0%e6%96%b9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;h4&gt;1. Session 管理靠记忆&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-session-管理靠记忆&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-session-%e7%ae%a1%e7%90%86%e9%9d%a0%e8%ae%b0%e5%bf%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 我需要记住所有这些命令...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tmux new -s dev     &lt;span class=&#34;c1&#34;&gt;# 新建会话&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tmux ls             &lt;span class=&#34;c1&#34;&gt;# 列出所有会话&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tmux a              &lt;span class=&#34;c1&#34;&gt;# 重新连接&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tmux kill-session   &lt;span class=&#34;c1&#34;&gt;# 杀掉会话&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tmux rename-session -t old new  &lt;span class=&#34;c1&#34;&gt;# 重命名&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;随着项目增多，会话名越来越多。每次打开终端都要想：&lt;em&gt;我该连哪个？新开的叫什么名字？&lt;/em&gt; 这种上下文切换非常打断思路。&lt;/p&gt;
&lt;h4&gt;2. 快捷键不直观&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-快捷键不直观&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e5%bf%ab%e6%8d%b7%e9%94%ae%e4%b8%8d%e7%9b%b4%e8%a7%82&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;tmux 的默认前缀键是 &lt;code&gt;Ctrl+b&lt;/code&gt;，切分窗格要用 &lt;code&gt;Ctrl+b %&lt;/code&gt;（垂直）或 &lt;code&gt;Ctrl+b &amp;quot;&lt;/code&gt;（水平）。&lt;strong&gt;为什么是 &lt;code&gt;%&lt;/code&gt; 和 &lt;code&gt;&amp;quot;&lt;/code&gt;？&lt;/strong&gt; 这些符号的来源对新手没有任何语义帮助。更不用说各种配置方案里密密麻麻的自定义快捷键，记都记不住。&lt;/p&gt;
&lt;h4&gt;3. 切换不够&amp;quot;丝滑&amp;quot;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-切换不够丝滑&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-%e5%88%87%e6%8d%a2%e4%b8%8d%e5%a4%9f%e4%b8%9d%e6%bb%91&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;tmux 的设计哲学是&lt;strong&gt;命令式操作&lt;/strong&gt;：你想做某件事，就要输入对应的命令或快捷键。但很多时候我其实不知道自己想要什么——我只是想&amp;quot;随便看看别的会话/窗格&amp;quot;。&lt;strong&gt;等待我去决策的命令模式 vs 按需呈现的自然状态&lt;/strong&gt;，后者显然更符合直觉。&lt;/p&gt;
&lt;h4&gt;4. 屏幕复制模式——tmux 的老毛病了&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;4-屏幕复制模式tmux-的老毛病了&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#4-%e5%b1%8f%e5%b9%95%e5%a4%8d%e5%88%b6%e6%a8%a1%e5%bc%8ftmux-%e7%9a%84%e8%80%81%e6%af%9b%e7%97%85%e4%ba%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;tmux 的 &lt;code&gt;copy-mode&lt;/code&gt;（用于滚动浏览和复制输出）是我最头疼的功能之一。每次都要先激活复制模式（复杂的组合键），通过非文本交互方式（如滚轮或方向键移动选择）选取区域，最后再按特定组合键结束选择、复制代码块。这是一个流程不自然、步骤繁琐到让人放弃使用的过程，且它对整个终端环境都有极高的要求——&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;macOS Terminal / iTerm2 上的鼠标支持经常抽风&lt;/li&gt;
&lt;li&gt;&lt;code&gt;set -g mouse on&lt;/code&gt; 开了之后滚动和选区冲突&lt;/li&gt;
&lt;li&gt;在不同的 TTY 和本地/远程之间表现不一致&lt;/li&gt;
&lt;li&gt;复制的文字粘到别处经常丢失格式、甚至乱码&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个功能是我在 tmux copy-mode 中&lt;strong&gt;用鼠标滚轮切换到浏览器去复制&lt;/strong&gt;的高频场景，本质上是因为 tmux 的 copy-mode 体验始终没有做到&amp;quot;自然滚动、直接选中&amp;quot;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;二、cmux 的核心优势&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二cmux-的核心优势&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8ccmux-%e7%9a%84%e6%a0%b8%e5%bf%83%e4%bc%98%e5%8a%bf&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;🔥 Session 管理：基于光标位置&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-session-管理基于光标位置&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-session-%e7%ae%a1%e7%90%86%e5%9f%ba%e4%ba%8e%e5%85%89%e6%a0%87%e4%bd%8d%e7%bd%ae&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是 cmux 让我眼前一亮的第一个功能。&lt;/p&gt;
&lt;p&gt;tmux 的会话切换是&lt;strong&gt;显式的&lt;/strong&gt;——你要知道有 A、B、C 三个会话，然后决定连哪个。而 cmux 通过监听你的光标/窗口位置，&lt;strong&gt;动态判断你当前在做什么工作上下文&lt;/strong&gt;，然后按需展示可用的操作选项。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;┌─────────────────────────────────────┐
│  你在编辑 Go 代码                     │
│                                     │
│  → 可用操作：                        │
│     • 运行测试      (Ctrl&amp;#43;T)        │
│     • 运行应用      (Ctrl&amp;#43;R)        │
│     • 打开 git log   Ctrl&amp;#43;G)         │
│     • 查看终端日志 (Ctrl&amp;#43;L)          │
│                                     │
│  你在 git status 输出上                │
│                                     │
│  → 可用操作：                        │
│     • 提交修改      (Ctrl&amp;#43;S)        │
│     • 暂存文件      (Ctrl&amp;#43;A)        │
│     • 打开 yazi    (Ctrl&amp;#43;Y)         │
└─────────────────────────────────────┘&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;无需记住会话名，无需在多个窗口间来回切换。&lt;/strong&gt; cmux 根据你的上下文动态展示可用操作，这个体验差异是翻天覆地的。&lt;/p&gt;
&lt;h3&gt;⌨️ 不再需要死记硬背快捷键&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-不再需要死记硬背快捷键&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e4%b8%8d%e5%86%8d%e9%9c%80%e8%a6%81%e6%ad%bb%e8%ae%b0%e7%a1%ac%e8%83%8c%e5%bf%ab%e6%8d%b7%e9%94%ae&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;cmux 的一个核心理念是：&lt;strong&gt;快捷键应该被&amp;quot;发现&amp;quot;，而不是被&amp;quot;记忆&amp;quot;&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;它通过智能提示和 AI 辅助，在你需要的时候实时推荐可用的按键映射。比如当你打开一个 Go 项目目录时，它会提示 &lt;code&gt;Ctrl+G&lt;/code&gt; 可以运行测试、&lt;code&gt;Ctrl+L&lt;/code&gt; 可以执行 lint、&lt;code&gt;Ctrl+B&lt;/code&gt; 可以构建。这些快捷键的语义性更强，而且有可视化提示帮你记住。&lt;/p&gt;
&lt;h3&gt;🧩 插件生态：lazygit · yazi · 更多&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-插件生态lazygit--yazi--更多&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e6%8f%92%e4%bb%b6%e7%94%9f%e6%80%81lazygit--yazi--%e6%9b%b4%e5%a4%9a&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;cmux 的插件系统设计使得集成常用工具变得极其简单。以 lazygit 和 yazi 为例：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;lazygit 集成：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# cmux 配置示例&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;plugins&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;lazygit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;enable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;shortcut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Ctrl+G&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;auto-detect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# 在 git 仓库中自动可用&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;只需要几行配置，cmux 就能做到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;检测到当前是 Git 仓库时&lt;strong&gt;自动启用&lt;/strong&gt; lazygit 入口&lt;/li&gt;
&lt;li&gt;将 &lt;code&gt;Ctrl+G&lt;/code&gt; 映射到一键唤起 lazygit（无需手动编辑 tmux.conf）&lt;/li&gt;
&lt;li&gt;在正确的工作目录下启动，路径无需关心&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;yazi 集成：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;plugins&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;yazi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;enable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;shortcut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Ctrl+Y&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;enter-cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# 支持 cd 回写：退出 yazi 自动 cd 到所选目录&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这个功能简直是革命性的。tmux+neovim 的用户需要配合 &lt;code&gt;vifm&lt;/code&gt; 或手动路径输入，而 cmux + yazi 的组合让&lt;strong&gt;整个文件浏览流程变得像用 GUI 一样自然&lt;/strong&gt;。更妙的是它可以和编辑器的 cwd 联动——在编辑器里右键&amp;quot;在 yazi 中打开当前目录&amp;quot;，完全无缝。&lt;/p&gt;
&lt;h3&gt;⚡️ 内嵌浏览器开发环境（真正的杀手锏）&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-内嵌浏览器开发环境真正的杀手锏&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%86%85%e5%b5%8c%e6%b5%8f%e8%a7%88%e5%99%a8%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e7%9c%9f%e6%ad%a3%e7%9a%84%e6%9d%80%e6%89%8b%e9%94%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是 cmux 对所有&lt;strong&gt;现代前端开发者&lt;/strong&gt;来说，最颠覆性的体验。很多用户没有意识到，cmux 不仅是一个终端管理器，它还内置了对 Chromium 的支持和渲染引擎。这意味着你可以实现一个“全栈式”的 Dev Environment：在一个几乎不占用额外资源的终端窗口中，同时运行你的代码编辑器、后端日志输出、前端服务（Dev Server），以及最关键的——&lt;strong&gt;带完整互动的浏览器实例&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;在传统工作流中，如果你想调试一个前端组件需要查看网络请求或检查DOM结构，你必须切出终端，手动切换到 Chrome/Firefox。而在使用 cmux 后，这一切都嵌在了你的终端会话内：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它直接渲染了一个完整的 Chromium 实例。&lt;/li&gt;
&lt;li&gt;你可以在里面激活 DevTools、进行元素检测和网络请求监听（甚至包含 MutationObserver）。&lt;/li&gt;
&lt;li&gt;当你修改代码并触发热更新时，这个嵌入式的浏览器能实时感知到变化，提供与本地开发体验无异的流畅性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这使得前后端分离的开发工作流达到了一个**“一屏搞定”的最佳状态**，从概念上彻底打破了终端工具只能处理纯文本信息的限制。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;三、实际使用场景对比&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三实际使用场景对比&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e5%ae%9e%e9%99%85%e4%bd%bf%e7%94%a8%e5%9c%ba%e6%99%af%e5%af%b9%e6%af%94&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;场景 1：打开新项目&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;场景-1打开新项目&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9c%ba%e6%99%af-1%e6%89%93%e5%bc%80%e6%96%b0%e9%a1%b9%e7%9b%ae&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&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;tmux&lt;/th&gt;
					&lt;th&gt;cmux&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;新建会话&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;tmux new -s proj-name&lt;/code&gt; &amp;lt;0xF0&amp;gt;&amp;lt;0x9F&amp;gt;&amp;lt;0x94&amp;gt;&amp;lt;0xA4&amp;gt; 手动键入&lt;/td&gt;
					&lt;td&gt;自动检测到新工作区并创建上下文 ✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;连接会话&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;tmux a -t proj-name&lt;/code&gt; &amp;lt;0xF0&amp;gt;&amp;lt;0x9F&amp;gt;&amp;lt;0x94&amp;gt;&amp;lt;0xA4&amp;gt; 需要记住名字&lt;/td&gt;
					&lt;td&gt;光标指向该窗格即自动关联 ✅&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;切分窗格&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;Ctrl+b %&lt;/code&gt; ❓ 记不住&lt;/td&gt;
					&lt;td&gt;直接拖动分割线 🖱️&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;打开终端工具&lt;/td&gt;
					&lt;td&gt;手动输入命令或提前绑定快捷键&lt;/td&gt;
					&lt;td&gt;按需提示可用操作 💡&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;场景 2：日常开发循环&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;场景-2日常开发循环&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9c%ba%e6%99%af-2%e6%97%a5%e5%b8%b8%e5%bc%80%e5%8f%91%e5%be%aa%e7%8e%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;tmux 路径：
1. Ctrl&amp;#43;b [进入复制模式] → 鼠标选择/滚轮滚动
2. Ctrl&amp;#43;b o → 切换窗格（顺序不可控）
3. tmux ls → 列出会话
4. tmux a -t dev → 回到开发会话

cmux 路径：
1. 滚轮滚动 / 直接点击查看历史
2. 鼠标/方向键导航到目标窗格
3. 无&amp;#34;列出会话&amp;#34;需求（自动发现）
4. 已在正确的会话中 ✅&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;场景 3：Git 操作&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;场景-3git-操作&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9c%ba%e6%99%af-3git-%e6%93%8d%e4%bd%9c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;tmux 用户通常需要在不同窗格间手动切换：一个跑 git status，一个跑 vim。cmux 下可以直接调用 lazygit，然后 yazi 浏览修改的文件列表。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;四、个人迁移体验&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四个人迁移体验&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e4%b8%aa%e4%ba%ba%e8%bf%81%e7%a7%bb%e4%bd%93%e9%aa%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;说实话，用 tmux 的时候我觉得&amp;quot;还不错了&amp;quot;。毕竟终端复用器的功能它都有了，社区也足够成熟。但用得越久，那种&lt;strong&gt;微妙的摩擦感&lt;/strong&gt;越来越明显——不是功能缺失，而是交互方式不够自然。&lt;/p&gt;
&lt;p&gt;迁移到 cmux 后的几个真实感受：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;学习成本出乎意料地低&lt;/strong&gt;。没有 tmux 那一大套命令体系，取而代之的是&amp;quot;所见即所得&amp;quot;的操作模式。快捷键不再是负担而是辅助发现的手段。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;上下文切换的损耗大幅降低&lt;/strong&gt;。以前打开终端的第一件事是 &lt;code&gt;tmux ls&lt;/code&gt; → 找到目标 session → 连接。现在几乎无感——我打开编辑器/终端，cmux 已经准备好了我的工作区。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;插件配置复杂度下降了一个数量级&lt;/strong&gt;。之前的 tmux 配置文件长达数百行，各种 &lt;code&gt;bind-key&lt;/code&gt;、&lt;code&gt;source-file&lt;/code&gt;、&lt;code&gt;if-shell&lt;/code&gt; 逻辑。cmux 的配置更像是在声明&amp;quot;我要什么&amp;quot;而非&amp;quot;我怎么实现&amp;quot;。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;五、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;tmux 是一个优秀的工具，它解决了终端复用器领域的经典问题。但 cmux 代表的是&lt;strong&gt;下一代终端体验的方向&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;从命令驱动到上下文驱动&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;从记忆快捷键到发现式操作&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;从手动集成 tools 到插件原生联动&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;从静态配置到 AI Agent 感知&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你也在用 tmux（或 screen），不妨试试 cmux。至少它让我重新感受到了——终端工具也可以是优雅、智能且自然的。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;本文提到的工具配置细节可能会随版本更新而变化，建议查阅各项目的最新文档。&lt;/em&gt;&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>基于ESP32的WiFi智能时钟 - 从硬件连接到全栈UI渲染的实践</title>
      <link>https://www.helight.info/blog/2026/0614-esp32-wifi-clock/</link>
      <pubDate>Sun, 14 Jun 2026 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0614-esp32-wifi-clock/</guid>
      <description>
        
        
        &lt;h2&gt;一、背景与动机&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一背景与动机&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e8%83%8c%e6%99%af%e4%b8%8e%e5%8a%a8%e6%9c%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;前段时间在整理桌面时，发现缺一个既能看时间又能看天气的小屏幕。市面上的桌面时钟要么功能简单、要么价格不菲，而且都不太&amp;quot;个人化&amp;quot;——我想要的是能显示农历日期、能看到夜空背景、还能根据网络自动校时的设备。&lt;/p&gt;
&lt;p&gt;手上正好有一块吃灰已久的 ESP32 开发板和一个 1.8 寸 ST7735S TFT 屏幕，于是决定自己动手做一个 WiFi 智能时钟。其实类似的教程网上也不少，但大部分只做到&amp;quot;显示时间&amp;quot;就停了。我想把这个项目做得更完整一些：网络校时、天气信息、农历日期、甚至是全屏程序化渲染的夜空场景。这篇文章把整个实践过程记录下来，希望对也想做个桌面时钟的朋友有用。&lt;/p&gt;
&lt;h2&gt;二、核心设计思路&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二核心设计思路&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e6%a0%b8%e5%bf%83%e8%ae%be%e8%ae%a1%e6%80%9d%e8%b7%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 硬件选型与连接&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-硬件选型与连接&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e7%a1%ac%e4%bb%b6%e9%80%89%e5%9e%8b%e4%b8%8e%e8%bf%9e%e6%8e%a5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;硬件组合很简单：ESP32 DOIT DevKit V1 做主控，搭配 1.8 寸 ST7735S TFT 屏幕（128×160 像素，SPI 接口，RGB565 色彩）。ST7735S 是这类小尺寸屏幕里非常常见的驱动芯片，价格便宜、文档齐全。&lt;/p&gt;
&lt;p&gt;SPI 接线方式如下，我这里用了几根杜邦线直连：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;信号&lt;/th&gt;
					&lt;th&gt;GPIO&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;MOSI&lt;/td&gt;
					&lt;td&gt;23&lt;/td&gt;
					&lt;td&gt;SPI 主出从入&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;CLK&lt;/td&gt;
					&lt;td&gt;18&lt;/td&gt;
					&lt;td&gt;SPI 时钟&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;CS&lt;/td&gt;
					&lt;td&gt;5&lt;/td&gt;
					&lt;td&gt;片选&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;DC&lt;/td&gt;
					&lt;td&gt;21&lt;/td&gt;
					&lt;td&gt;数据/命令选择&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;RST&lt;/td&gt;
					&lt;td&gt;2&lt;/td&gt;
					&lt;td&gt;复位&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;BCKL&lt;/td&gt;
					&lt;td&gt;4&lt;/td&gt;
					&lt;td&gt;背光控制&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;2. 软件架构&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-软件架构&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e8%bd%af%e4%bb%b6%e6%9e%b6%e6%9e%84&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;整体采用 ESP-IDF 框架，通过 PlatformIO 管理。图形引擎选择了 &lt;a href=&#34;https://github.com/olikraus/u8g2&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;U8g2&lt;/a&gt; v2.35.19——这是一款非常成熟单色图形库，支持丰富的字体。虽然 ST7735S 是彩色屏，但我采用了一个巧妙的方案：U8g2 按位图模式驱动，然后逐行混合到程序化生成的夜空背景之上，实现白色 UI 叠加的效果。&lt;/p&gt;
&lt;p&gt;项目按功能拆分为以下模块：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lcd_st7735&lt;/code&gt; — 屏幕底层驱动：SPI 通信、初始化序列、场景渲染（渐变天空 + 星星 + 月亮 + 山脉）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wifi_service&lt;/code&gt; — WiFi 连接管理 + SNTP 网络授时&lt;/li&gt;
&lt;li&gt;&lt;code&gt;weather_client&lt;/code&gt; — 天气 HTTP 客户端（心知天气 API）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main.c&lt;/code&gt; — 主循环：UI 布局绘制、农历转换（查表法覆盖 1900-2100 年）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;三、实战步骤&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三实战步骤&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e5%ae%9e%e6%88%98%e6%ad%a5%e9%aa%a4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 搭建开发环境&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-搭建开发环境&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e6%90%ad%e5%bb%ba%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;项目使用 PlatformIO，在 VS Code 中安装 PlatformIO 插件后即可。&lt;code&gt;platformio.ini&lt;/code&gt; 配置如下：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[env:esp32dev]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;platform&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;espressif32&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;board&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;esp32dev&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;framework&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;espidf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;monitor_speed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;115200&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;添加 U8g2 库依赖：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;lib_deps&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s&#34;&gt;    olikraus/U8g2@^2.35.19&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;2. WiFi 连接与网络授时&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-wifi-连接与网络授时&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-wifi-%e8%bf%9e%e6%8e%a5%e4%b8%8e%e7%bd%91%e7%bb%9c%e6%8e%88%e6%97%b6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;时钟的核心需求之一是时间准确。我用了 SNTP（Simple Network Time Protocol）从 &lt;code&gt;pool.ntp.org&lt;/code&gt; 获取 UTC 时间，再转换为北京时间（CST-8）。&lt;/p&gt;
&lt;p&gt;WiFi 连接这块我做了一些工程化的处理：支持自动重连（最多 10 次）、断开原因诊断（通过 &lt;code&gt;wifi_err_reason&lt;/code&gt; 判断是密码错误还是信号丢失），未联网时屏幕底部显示连接状态提示，方便调试。&lt;/p&gt;
&lt;p&gt;配置集中在 &lt;code&gt;wifi_config.h&lt;/code&gt; 中：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define APP_WIFI_ENABLE     1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define APP_WIFI_SSID       &amp;#34;your_ssid&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define APP_WIFI_PASSWORD   &amp;#34;your_password&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define APP_WIFI_MAXIMUM_RETRY 10
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define APP_SNTP_SERVER     &amp;#34;pool.ntp.org&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define APP_TIMEZONE        &amp;#34;CST-8&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;3. 天气数据获取&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-天气数据获取&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-%e5%a4%a9%e6%b0%94%e6%95%b0%e6%8d%ae%e8%8e%b7%e5%8f%96&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;天气信息来自心知天气 API。这块的设计要点是&lt;strong&gt;容错&lt;/strong&gt;：成功获取后 10 分钟轮询一次，如果请求失败则 30 秒快速重试，避免长时间无天气显示。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define APP_WEATHER_API_KEY &amp;#34;your_api_key&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define APP_WEATHER_LANGUAGE &amp;#34;zh-Hans&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define APP_WEATHER_LOCATION &amp;#34;shenzhen&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define APP_WEATHER_UNIT &amp;#34;c&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;免费 API Key 在心知天气官网注册即可获取，对个人项目来说完全够用。&lt;/p&gt;
&lt;h3&gt;4. 农历日期转换&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;4-农历日期转换&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#4-%e5%86%9c%e5%8e%86%e6%97%a5%e6%9c%9f%e8%bd%ac%e6%8d%a2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这个功能是我个人比较坚持的——作为中国人，看农历日期比纯粹的公历更有生活感。农历转换采用查表法，一张预计算的农历数据表覆盖了 1900 到 2100 年，支持干支纪年、闰月识别。&lt;/p&gt;
&lt;h3&gt;5. 程序化夜空场景渲染&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;5-程序化夜空场景渲染&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#5-%e7%a8%8b%e5%ba%8f%e5%8c%96%e5%a4%9c%e7%a9%ba%e5%9c%ba%e6%99%af%e6%b8%b2%e6%9f%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是最有意思的一部分。我没有用外部图片，而是用代码在屏幕上一笔一笔绘制夜空背景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;三段渐变天空&lt;/strong&gt;：从顶部藏青色过渡到暗紫色、再到底部的暖褐色&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;星星点&lt;/strong&gt;：用确定性哈希算法散布，确保每次开机星星位置固定&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;暖色月亮&lt;/strong&gt;：绘制在右上角，给画面一个视觉焦点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;山脉剪影&lt;/strong&gt;：底部三重山峰，白色文字和图标叠加在场景之上&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;U8g2 本身是单色库，但通过像素级位图混合到 RGB 背景上，实现了&amp;quot;白色 UI + 彩色背景&amp;quot;的效果。这套渲染逻辑都封装在 &lt;code&gt;lcd_st7735.c&lt;/code&gt; 中，屏幕布局大致如下：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;┌──────────────────────────────────┐
│  ⭐ 月                          │ ← 夜空渐变背景
│            ShenZhen             │
│       [🌡] 26°C   [☁️]          │ ← 天气面板（白框透明底）
│  ─────────────────────────────  │
│           正月十五               │ ← 农历日期
│      2025-06-14  Sun            │ ← 公历日期&amp;#43;星期
│  ─────────────────────────────  │
│          12:34:56               │ ← 时间（粗体大字）
│      ⛰️    ⛰️    ⛰️             │ ← 山脉剪影
└──────────────────────────────────┘&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;6. 编译与烧录&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;6-编译与烧录&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#6-%e7%bc%96%e8%af%91%e4%b8%8e%e7%83%a7%e5%bd%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一切就绪后，一条命令即可编译烧录：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 编译&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pio run
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 烧录到开发板&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pio run --target upload
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 查看串口日志&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pio device monitor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;首次上电后，ESP32 会自动连接 WiFi，同步 NTP 时间，获取天气数据，然后进入时钟主循环。&lt;/p&gt;
&lt;h2&gt;四、踩坑记录&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四踩坑记录&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e8%b8%a9%e5%9d%91%e8%ae%b0%e5%bd%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这个项目虽然看起来不复杂，但实际调试过程中还是踩了几个坑：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. ST7735S 初始化序列&lt;/strong&gt;：市面上 ST7735S 的初始化命令序列五花八门，不同厂商的屏幕参数有细微差异。我试了好几个版本的初始化序列才找到当前这块屏幕能正确显示色彩的配置。建议到手后先跑一个纯色填充测试，确认 RGB 顺序和偏移参数。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. U8g2 与彩色背景的混合&lt;/strong&gt;：U8g2 本质是单色库，要叠加到渐变天空背景上需要逐像素处理。最初我直接在背景上画白色文字，发现部分像素被背景色覆盖导致文字不清晰。后来改用先截取 U8g2 缓冲区，再逐行混合到场景缓冲区的方案，文字边缘才干净起来。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 农历数据表精度&lt;/strong&gt;：农历查表法虽然速度快，但闰月判断的逻辑需要仔细核对。我对照了几年的在线农历数据人工验证，发现有一条闰月标志位的判断写反了，修正后才通过验证。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. 心知天气 API 免费额度&lt;/strong&gt;：免费版 API 有调用次数限制，如果刷新太频繁会超出配额。最终采用成功 10 分钟刷新、失败 30 秒重试的策略，既保证了数据及时性又不会浪费配额。&lt;/p&gt;
&lt;h2&gt;五、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这个项目从构思到跑通，前前后后大概花了两个周末的时间。最大的收获是重新熟悉了 ESP-IDF 的底层开发流程——从 SPI 驱动到 WiFi 管理，从 HTTP 客户端到 SNTP 校时，几乎是嵌入式开发的全栈体验。&lt;/p&gt;
&lt;p&gt;程序化生成夜空背景是我最满意的一环。虽然用代码画出来的场景不如真实照片或外部图片精细，但这种&amp;quot;零依赖&amp;quot;的方式让整个项目干净利落——不需要 SD 卡、不需要文件系统，编译烧录就能跑。如果你也想做一个桌面时钟，又不想局限于&amp;quot;数字+纯色背景&amp;quot;的 boring 方案，可以试试这种思路。&lt;/p&gt;
&lt;p&gt;效果在这里展示：&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2026/0614-esp32-wifi-clock/imgs/esp32.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>小说阅读的三重境界：从人物性格到价值观的深度洞察</title>
      <link>https://www.helight.info/blog/2026/0529-reading-insight/</link>
      <pubDate>Fri, 29 May 2026 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0529-reading-insight/</guid>
      <description>
        
        
        &lt;p&gt;最近在整理自己的读书笔记时，发现自己过去读小说有一个习惯——看完就忘，只留下&amp;quot;好看&amp;quot;或&amp;quot;不好看&amp;quot;这么一句评价。后来我开始刻意地做一种练习：在读小说的时候，不只是追情节，而是停下来观察人物、思考命运、提炼价值。慢慢地，我总结出了一套自己的阅读方法，这篇文章就是把这些思考记录下来。&lt;/p&gt;
&lt;p&gt;文中一些例子的整理和表述细节借助了 AI 做了补充和润色，但整体框架和方法论是我自己在读书过程中的真实体会。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;一、为什么要重新思考&amp;quot;读小说&amp;quot;这件事&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一为什么要重新思考读小说这件事&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e9%87%8d%e6%96%b0%e6%80%9d%e8%80%83%e8%af%bb%e5%b0%8f%e8%af%b4%e8%bf%99%e4%bb%b6%e4%ba%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;作为一个技术背景的人，我以前总觉得读小说是一种消遣——放松的时候翻翻，看过就算。但后来我发现，同样一本书，有的人读完了能滔滔不绝地讲出很多洞见，而我读完了只能说&amp;quot;挺好看的，推荐&amp;quot;。这种差距不是因为智力，而是因为&lt;strong&gt;阅读的方法&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;小说其实是一座巨大的认知富矿。它不是简单的故事堆砌，而是作者用人物和情节搭建出来的一套复杂系统。在这套系统里，人物有他的性格、他的欲望、他的恐惧、他的行为模式，这些要素相互作用，最终形成了人物的命运。而不同的命运背后，折射的是不同的世界观、人生观和价值观。&lt;/p&gt;
&lt;p&gt;如果我们能有一套方法，在读小说的时候有意识地进行拆解和分析，那么每一次阅读就不只是消遣，而是一次对人性和价值观的深度观察。&lt;/p&gt;
&lt;p&gt;这套方法我称之为&amp;quot;小说阅读的三重境界&amp;quot;：&lt;strong&gt;看见人物 → 理解命运 → 提炼价值&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;二、第一重境界：看见人物——性格决定命运&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二第一重境界看见人物性格决定命运&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e7%ac%ac%e4%b8%80%e9%87%8d%e5%a2%83%e7%95%8c%e7%9c%8b%e8%a7%81%e4%ba%ba%e7%89%a9%e6%80%a7%e6%a0%bc%e5%86%b3%e5%ae%9a%e5%91%bd%e8%bf%90&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 每个人物都是一个完整的世界&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-每个人物都是一个完整的世界&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e6%af%8f%e4%b8%aa%e4%ba%ba%e7%89%a9%e9%83%bd%e6%98%af%e4%b8%80%e4%b8%aa%e5%ae%8c%e6%95%b4%e7%9a%84%e4%b8%96%e7%95%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;读小说的第一步，不是追逐情节如何发展，而是先认识人物。每个人物都像我们身边的一个人，有他独特的性格底色和行为逻辑。&lt;/p&gt;
&lt;p&gt;我一般会从四个维度去观察一个人物：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;维度&lt;/th&gt;
					&lt;th&gt;核心问题&lt;/th&gt;
					&lt;th&gt;观察点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;气质底色&lt;/td&gt;
					&lt;td&gt;这个人是怎样的人？&lt;/td&gt;
					&lt;td&gt;外向/内向、理性/感性、果决/犹豫&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;核心欲望&lt;/td&gt;
					&lt;td&gt;他最想要什么？&lt;/td&gt;
					&lt;td&gt;权力、爱情、自由、认同、复仇、救赎&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;恐惧来源&lt;/td&gt;
					&lt;td&gt;他最害怕什么？&lt;/td&gt;
					&lt;td&gt;失去、背叛、平庸、被遗忘、不确定性&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;行为模式&lt;/td&gt;
					&lt;td&gt;他如何行动？&lt;/td&gt;
					&lt;td&gt;主动进取/被动承受、深思熟虑/冲动行事&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;举个例子，读《水浒传》的时候我特别注意过林冲和鲁智深这两个人物。林冲的底色是&amp;quot;隐忍&amp;quot;，不管受到多大的委屈，他首先想的是&amp;quot;忍一忍就过去了&amp;quot;；而鲁智深是&amp;quot;直率&amp;quot;，拳头比脑子快，遇到不平事直接开打。两人面对相似的压迫，走向了完全不同的命运——这不是情节的偶然，而是性格的必然。&lt;/p&gt;
&lt;h3&gt;2. 人物关系：命运暗藏其中&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-人物关系命运暗藏其中&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e4%ba%ba%e7%89%a9%e5%85%b3%e7%b3%bb%e5%91%bd%e8%bf%90%e6%9a%97%e8%97%8f%e5%85%b6%e4%b8%ad&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一个人物的命运从来不是孤立的。每个角色都活在一张复杂的关系网里，这张网在很大程度上定义了他的走向。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;主角与对手&lt;/strong&gt;：价值观的直接碰撞&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;导师与追随者&lt;/strong&gt;：理念的传承或背叛&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;朋友与敌人&lt;/strong&gt;：信任与怀疑的博弈&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;爱人与仇人&lt;/strong&gt;：情感与理性的撕扯&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我自己的体会是，读小说的时候不光要关注主角，还要留心那些配角。很多时候，配角的存在并不是为了推动剧情，而是&lt;strong&gt;为了映衬主角的价值观&lt;/strong&gt;。如果没有薛宝钗，林黛玉的孤傲不会被衬托得那么鲜明；没有鲁智深，林冲的隐忍也不会显得那么沉重。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;三、第二重境界：理解命运——行为的必然性&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三第二重境界理解命运行为的必然性&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e7%ac%ac%e4%ba%8c%e9%87%8d%e5%a2%83%e7%95%8c%e7%90%86%e8%a7%a3%e5%91%bd%e8%bf%90%e8%a1%8c%e4%b8%ba%e7%9a%84%e5%bf%85%e7%84%b6%e6%80%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 性格 → 行为 → 命运的链条&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-性格--行为--命运的链条&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e6%80%a7%e6%a0%bc--%e8%a1%8c%e4%b8%ba--%e5%91%bd%e8%bf%90%e7%9a%84%e9%93%be%e6%9d%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是我这套方法的一个核心观察：&lt;strong&gt;一个人的命运，是他性格的延伸&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;我把它总结成一条链：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;性格 → 选择 → 行动 → 后果 → 命运&lt;/strong&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;p&gt;每次在小说中看到一个重大转折，我都会停下来追问：这个人为什么在这个时候做这个选择？如果他换一种性格，会怎么选？&lt;/p&gt;
&lt;p&gt;用这个链条去看《红楼梦》，会非常有意思：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;人物&lt;/th&gt;
					&lt;th&gt;性格特质&lt;/th&gt;
					&lt;th&gt;关键选择&lt;/th&gt;
					&lt;th&gt;命运走向&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;林黛玉&lt;/td&gt;
					&lt;td&gt;敏感、孤傲、至情至性&lt;/td&gt;
					&lt;td&gt;以诗自守，不迎合世俗&lt;/td&gt;
					&lt;td&gt;泪尽而亡&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;薛宝钗&lt;/td&gt;
					&lt;td&gt;理性、圆融、入世务实&lt;/td&gt;
					&lt;td&gt;处处周全，顺应时势&lt;/td&gt;
					&lt;td&gt;嫁为人妇但心有所失&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;贾宝玉&lt;/td&gt;
					&lt;td&gt;叛逆、痴情、厌恶仕途&lt;/td&gt;
					&lt;td&gt;抗拒家族安排，追求至情&lt;/td&gt;
					&lt;td&gt;出家遁世&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这不是命运在捉弄人，而是每个人按照自己的本性，走完了自己选择的道路。林黛玉不可能像薛宝钗那样去讨好长辈，薛宝钗也不可能像林黛玉那样纵情任性。&lt;strong&gt;性格决定了她们会看到什么路、会选什么路、会走到哪里。&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;2. 命运的转折点：矛盾的总爆发&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-命运的转折点矛盾的总爆发&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e5%91%bd%e8%bf%90%e7%9a%84%e8%bd%ac%e6%8a%98%e7%82%b9%e7%9f%9b%e7%9b%be%e7%9a%84%e6%80%bb%e7%88%86%e5%8f%91&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;小说里最精彩的部分，往往是那些命运的转折点——所有矛盾积累到不可回避的时候，人物被迫做出重大选择。这些转折点是&lt;strong&gt;最佳的分析窗口&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;我一般会问自己四个问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;这是什么矛盾？（理想与现实？个人与集体？道德与欲望？）&lt;/li&gt;
&lt;li&gt;人物面前有哪些选择？&lt;/li&gt;
&lt;li&gt;他为什么选择了这一条路？&lt;/li&gt;
&lt;li&gt;如果换一种性格的人在这里，会怎么选？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;每一个转折点，都是一次人物性格和价值观的&amp;quot;公开告白&amp;quot;。读到这里停下来想一想，往往比一口气读完整个章节收获更大。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;四、第三重境界：提炼价值——三观的升维&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四第三重境界提炼价值三观的升维&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e7%ac%ac%e4%b8%89%e9%87%8d%e5%a2%83%e7%95%8c%e6%8f%90%e7%82%bc%e4%bb%b7%e5%80%bc%e4%b8%89%e8%a7%82%e7%9a%84%e5%8d%87%e7%bb%b4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 从人物命运中提炼三观&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-从人物命运中提炼三观&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e4%bb%8e%e4%ba%ba%e7%89%a9%e5%91%bd%e8%bf%90%e4%b8%ad%e6%8f%90%e7%82%bc%e4%b8%89%e8%a7%82&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;当我们对足够多的人物做了深入分析之后，最有趣的部分就来了——&lt;strong&gt;超越具体的角色，抽象出他们背后的世界观、人生观和价值观&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;我把这三观拆解成了三个问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;世界观&lt;/strong&gt;：这个人物认为世界的本质是怎样的？世界是公正的还是荒诞的？努力就会有回报吗？&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;人生观&lt;/strong&gt;：他如何理解生命的意义？生命是用来体验的还是用来成就的？应该追求快乐还是承担责任？&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;价值观&lt;/strong&gt;：他如何判断是非对错？目的能否证明手段合理？个人自由与集体利益哪个更重要？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;同一个故事里，不同人物面对同一件事，会给出完全不同的回答。这些不同的回答背后，就是他们各自的三观。&lt;/p&gt;
&lt;h3&gt;2. 多人物对照：看到价值观的坐标系&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-多人物对照看到价值观的坐标系&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e5%a4%9a%e4%ba%ba%e7%89%a9%e5%af%b9%e7%85%a7%e7%9c%8b%e5%88%b0%e4%bb%b7%e5%80%bc%e8%a7%82%e7%9a%84%e5%9d%90%e6%a0%87%e7%b3%bb&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一部优秀的小说，从来不只呈现一种单一的价值观。作者会把不同的人物放在同一片舞台上，让他们各自的信念相互碰撞。我们要做的，就是在这场碰撞中去抽象出&lt;strong&gt;一幅价值观的坐标系&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;拿《三体》来说，书中的几个关键人物几乎覆盖了所有典型的价值取向：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;章北海&lt;/strong&gt;：极度理性的集体主义者，&amp;ldquo;为了人类文明的延续，一切牺牲都是必要的&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;维德&lt;/strong&gt;：极端的实用主义者，&amp;ldquo;前进，不择手段地前进&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;罗辑&lt;/strong&gt;：从个人主义走向责任担当，最终扛起执剑人的重担&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;程心&lt;/strong&gt;：怀揣着爱与善良，却在极端情境下做出了让文明陷落的抉择&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;罗辑和程心之间的对照尤其深刻。罗辑在接过执剑人的那一刻，选择了理性与牺牲；程心在同样的位置上，选择了爱与不忍。&lt;strong&gt;这不是他们的能力差距，而是价值观的差异&lt;/strong&gt;。罗辑相信&amp;quot;责任高于一切&amp;quot;，程心相信&amp;quot;爱高于一切&amp;quot;。两种信念都有各自的崇高，也都有各自的悲剧。&lt;/p&gt;
&lt;p&gt;读到这里，我最大的体会是：&lt;strong&gt;好的小说不是要做道德审判，而是让人看到每一种价值观的边界和代价。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;五、我的实操方法和总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五我的实操方法和总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e6%88%91%e7%9a%84%e5%ae%9e%e6%93%8d%e6%96%b9%e6%b3%95%e5%92%8c%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 三步阅读法&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-三步阅读法&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e4%b8%89%e6%ad%a5%e9%98%85%e8%af%bb%e6%b3%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&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;人物之间有没有新的关系变动？&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;p&gt;用&amp;quot;性格→行为→命运&amp;quot;的链条，为每个主要人物画一个图谱：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;找出3到5个改变人物命运的关键时刻&lt;/li&gt;
&lt;li&gt;分析每个时刻的性格驱动&lt;/li&gt;
&lt;li&gt;标注性格与命运之间的因果关系&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;🔴 第三步：价值观矩阵（整本书读完）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;站在全局视角回答这几个问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;这本书里对立的核心价值观是什么？&lt;/li&gt;
&lt;li&gt;作者更倾向于哪一种？（或者故意不做评判？）&lt;/li&gt;
&lt;li&gt;这种价值观在今天的社会中处于什么位置？&lt;/li&gt;
&lt;li&gt;我自己的立场是什么？为什么？&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;2. 读到最后，读的是自己&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-读到最后读的是自己&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e8%af%bb%e5%88%b0%e6%9c%80%e5%90%8e%e8%af%bb%e7%9a%84%e6%98%af%e8%87%aa%e5%b7%b1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;把这套方法用久了之后，我慢慢发现一件事——&lt;strong&gt;你对人物的好恶，你对命运的评判，你对结局的满意或不满，其实都在暴露你自己的价值观。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你喜欢林黛玉还是薛宝钗？你认同罗辑还是程心？你对福贵的命运感到同情还是无能为力？每一个答案背后，都是你自己。&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;每一本小说，都是一个灵魂实验室。
我们在其中与一百种人生相遇，
最终，只是为了更清楚地看到自己。&lt;/p&gt;

&lt;/blockquote&gt;
&lt;p&gt;这大概就是我觉得读书最有意思的地方——你以为你在读别人的故事，其实你一直在读你自己。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;后记：这篇文章是我近期在读书过程中的一些思考整理。文中涉及的经典小说例证比较宽泛，部分例子的具体表述是我借助 AI 做了补充和润色，核心的方法论和阅读体会来自我自己的实践。希望对同样喜欢读书的朋友有所启发。&lt;/em&gt;&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>Skill 开发实践：skill 配置化以适配更多的环境</title>
      <link>https://www.helight.info/blog/2026/0416-ai-agent-skill-dev/</link>
      <pubDate>Thu, 16 Apr 2026 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0416-ai-agent-skill-dev/</guid>
      <description>
        
        
        &lt;h2&gt;一、背景与动机&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一背景与动机&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e8%83%8c%e6%99%af%e4%b8%8e%e5%8a%a8%e6%9c%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;最近我一直在用 AI Agent（CodeBuddy）辅助写博客。之前在 OpenClaw 平台上搭建了一个 blog-writer Skill，可以自动完成从文章生成、Banner 制作到 PR 提交的完整流程。但当我把这个 Skill 迁移到本地 CodeBuddy IDE 时，立刻遇到了一个棘手的问题——&lt;strong&gt;所有 Python 脚本里都写死了绝对路径&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;其实这里我有一个思考就是现在所谓的skill到底是一个什么？他和大模型、和程序、和具体的业务场景之间的关系是什么？这个是我在这次实践当中得到的一点思考。我认为首先他应该是解决一个具体场景一系列操作的一个个操作的集合，他能够解决一个具体的问题，这有点些像我们以前在写代码的时候，我们要把多个操作能够有序的串联起来去解决拒绝具体的问题，比如说我们可能会写一个crontab 定时任务，然后去解决这个一个具体的问题。&lt;/p&gt;
&lt;p&gt;那么这种情况下我们就是要把 skill 当作一个软件体看，但是这个软件他有他的特点，就是除了他有对于问题的描述过程，还有解决的这个程序，另外他还可以调用大模型去对解决问题过程中的情况进行反思会，更加的自动或智能，而对于解决具体的场景的问题是没有问题的，但是很多时候我们就会想到那同样的场景，这个问题能解决，能不能解决其他的问题？那问题和问题是不同的，但是解决多而步骤和过程是一样的，这种情况下是不是可以抽象成为一种配置，让这个 skill 更加通用化。&lt;/p&gt;
&lt;p&gt;比如：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;BLOG_ROOT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/projects/hxblog/content/blog&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SSH_KEY&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/root/.ssh/id_ed25519&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;BLOG_ROOT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/projects/hxblog&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这些路径在 OpenClaw 的容器环境里能跑，换到我的 macOS 本地环境就全部失效了。这让我意识到：&lt;strong&gt;一个好的 Agent Skill 必须像一个好的软件库一样，消除对特定运行环境的硬依赖&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;于是我花了一个下午，把整个 blog-writer Skill 从&amp;quot;能跑就行&amp;quot;重构成了&amp;quot;哪都能跑&amp;quot;。这篇文章记录完整的重构过程和思路。&lt;/p&gt;
&lt;h2&gt;二、问题分析：硬编码依赖清单&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二问题分析硬编码依赖清单&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90%e7%a1%ac%e7%bc%96%e7%a0%81%e4%be%9d%e8%b5%96%e6%b8%85%e5%8d%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在动手之前，我先做了一次全面的依赖审计。用 &lt;code&gt;grep&lt;/code&gt; 扫描所有脚本，梳理出以下硬编码问题：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;脚本文件&lt;/th&gt;
					&lt;th&gt;硬编码内容&lt;/th&gt;
					&lt;th&gt;影响范围&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;gen_article.py&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BLOG_ROOT = Path(&amp;quot;/projects/hxblog/content/blog&amp;quot;)&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;文章生成路径错误&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;submit_pr.py&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BLOG_ROOT = &amp;quot;/projects/hxblog&amp;quot;&lt;/code&gt;、&lt;code&gt;git config user.name helight&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Git 操作失败&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;deploy.py&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;SSH 主机/端口/用户/密钥 4 个常量&lt;/td&gt;
					&lt;td&gt;部署完全不可用&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;init_post.py&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BLOG_ROOT = &amp;quot;/projects/hxblog/content/blog&amp;quot;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;初始化失败&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;gen_banner.py&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Linux-only 字体路径&lt;/td&gt;
					&lt;td&gt;macOS 上字体加载失败&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;sync_to_wechat.py&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;--blog-root&lt;/code&gt; 默认值硬编码&lt;/td&gt;
					&lt;td&gt;微信同步失败&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;SKILL.md&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;所有命令用 &lt;code&gt;/projects/.openclaw/skills/...&lt;/code&gt; 绝对路径&lt;/td&gt;
					&lt;td&gt;Agent 无法执行&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;一共 &lt;strong&gt;7 个脚本 + 1 个 SKILL.md&lt;/strong&gt;，涉及 &lt;strong&gt;十几处&lt;/strong&gt;硬编码。问题的本质是：&lt;strong&gt;配置散落在代码各处，没有统一的配置管理层&lt;/strong&gt;。&lt;/p&gt;
&lt;h2&gt;三、实战步骤&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三实战步骤&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e5%ae%9e%e6%88%98%e6%ad%a5%e9%aa%a4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 第一步：SKILL.md 路径通用化&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-第一步skillmd-路径通用化&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e7%ac%ac%e4%b8%80%e6%ad%a5skillmd-%e8%b7%af%e5%be%84%e9%80%9a%e7%94%a8%e5%8c%96&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;SKILL.md 是 Agent 的&amp;quot;操作手册&amp;quot;，里面的命令路径必须先改对。&lt;/p&gt;
&lt;p&gt;我引入了 &lt;code&gt;SCRIPTS_DIR&lt;/code&gt; 变量约定，所有脚本调用统一使用 &lt;code&gt;${SCRIPTS_DIR}/xx.py&lt;/code&gt;：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## 环境约定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;以下用 &lt;span class=&#34;sb&#34;&gt;`SCRIPTS_DIR`&lt;/span&gt; 代表脚本目录的实际路径：
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SCRIPTS_DIR=&amp;#34;.codebuddy/skills/blog-writer/scripts&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&amp;gt; Agent 在执行时应根据实际 Skill 安装位置替换 &lt;span class=&#34;sb&#34;&gt;`SCRIPTS_DIR`&lt;/span&gt;。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这里我考虑过直接用 &lt;code&gt;scripts/xx.py&lt;/code&gt; 短路径，但分析后发现 Agent 默认在&lt;strong&gt;项目根目录&lt;/strong&gt;执行命令，如果用短路径需要先 &lt;code&gt;cd&lt;/code&gt; 到 Skill 目录，反而增加出错风险。最终选择了从项目根目录出发的相对路径。&lt;/p&gt;
&lt;h3&gt;2. 第二步：脚本内路径改为自动探测 + 参数注入&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-第二步脚本内路径改为自动探测--参数注入&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e7%ac%ac%e4%ba%8c%e6%ad%a5%e8%84%9a%e6%9c%ac%e5%86%85%e8%b7%af%e5%be%84%e6%94%b9%e4%b8%ba%e8%87%aa%e5%8a%a8%e6%8e%a2%e6%b5%8b--%e5%8f%82%e6%95%b0%e6%b3%a8%e5%85%a5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;核心改造思路是&lt;strong&gt;三级优先级&lt;/strong&gt;：命令行参数 &amp;gt; 环境变量 &amp;gt; 自动探测。&lt;/p&gt;
&lt;p&gt;以 &lt;code&gt;gen_article.py&lt;/code&gt; 为例，原来的硬编码：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;BLOG_ROOT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/projects/hxblog/content/blog&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;改为自动探测函数 + &lt;code&gt;--blog-root&lt;/code&gt; 参数：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;_detect_blog_root&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;自动探测博客内容根目录&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;cwd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cwd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;candidate&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cwd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;content&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;blog&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;candidate&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is_dir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;candidate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cwd&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;自动探测的逻辑很简单：如果当前目录下有 &lt;code&gt;content/blog&lt;/code&gt; 子目录，就认为是 Hugo 博客仓库。这个启发式规则在绝大多数情况下都能正确工作。&lt;/p&gt;
&lt;h3&gt;3. 第三步：设计统一配置文件&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-第三步设计统一配置文件&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-%e7%ac%ac%e4%b8%89%e6%ad%a5%e8%ae%be%e8%ae%a1%e7%bb%9f%e4%b8%80%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;脚本改完后发现一个新问题：每个脚本都有自己的参数，用户需要在多个地方重复配置同样的信息（比如微信凭证、SSH 信息）。于是我设计了一个 &lt;strong&gt;TOML 格式的统一配置文件&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c&#34;&gt;# config.toml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;blog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;site_url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://helight.cn&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;repo&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;helight/hxblog&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;author&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;helight&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;link&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://helight.cn&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;git&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;user_name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;helight&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;user_email&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;helight@qq.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;github_token&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;deploy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;host&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;port&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;22&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;user&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;~/.ssh/id_ed25519&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;blog_dir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;wechat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;app_id&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;app_secret&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;选择 TOML 而不是 YAML/JSON 的原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python 3.11+ 内置 &lt;code&gt;tomllib&lt;/code&gt;，&lt;strong&gt;零依赖&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;语法比 YAML 更严格，不容易犯缩进错误&lt;/li&gt;
&lt;li&gt;注释友好，适合配置文件场景&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 第四步：实现配置解析模块&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;4-第四步实现配置解析模块&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#4-%e7%ac%ac%e5%9b%9b%e6%ad%a5%e5%ae%9e%e7%8e%b0%e9%85%8d%e7%bd%ae%e8%a7%a3%e6%9e%90%e6%a8%a1%e5%9d%97&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;config.py&lt;/code&gt; 是整个配置系统的核心，它实现了：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 三级优先级覆盖&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;load_config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;overrides&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 1. 加载 config.toml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;config_path&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_find_config_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_parse_toml&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;config_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;config_path&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 2. 环境变量覆盖&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_apply_env_overrides&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 3. 命令行参数覆盖&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;overrides&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;section&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;field&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;section&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;field&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_build_config&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;关键设计决策：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;配置文件查找顺序&lt;/strong&gt;：环境变量 &lt;code&gt;BLOG_WRITER_CONFIG&lt;/code&gt; &amp;gt; Skill 目录 &lt;code&gt;config.toml&lt;/code&gt; &amp;gt; 项目根目录 &lt;code&gt;.blog-writer.toml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;环境变量映射&lt;/strong&gt;：&lt;code&gt;DEPLOY_SSH_HOST&lt;/code&gt; → &lt;code&gt;deploy.host&lt;/code&gt;，兼容已有的环境变量使用方式&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;类型安全&lt;/strong&gt;：用 &lt;code&gt;dataclass&lt;/code&gt; 定义配置结构，IDE 有自动补全&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;向后兼容&lt;/strong&gt;：没有 &lt;code&gt;config.toml&lt;/code&gt; 也能运行，回退到环境变量和默认值&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我还为 Python 3.10 及以下版本写了一个简易 TOML 解析器（不依赖第三方库 &lt;code&gt;tomli&lt;/code&gt;），确保在各种环境下都能使用。&lt;/p&gt;
&lt;h3&gt;5. 第五步：跨平台字体探测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;5-第五步跨平台字体探测&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#5-%e7%ac%ac%e4%ba%94%e6%ad%a5%e8%b7%a8%e5%b9%b3%e5%8f%b0%e5%ad%97%e4%bd%93%e6%8e%a2%e6%b5%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;gen_banner.py&lt;/code&gt; 原来只有 Linux 字体路径：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;candidates&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;/usr/share/fonts/wqy-microhei/wqy-microhei.ttc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;改为全平台覆盖：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;candidates&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;cfg_font&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# 用户配置优先&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;/System/Library/Fonts/PingFang.ttc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;/System/Library/Fonts/STHeiti Medium.ttc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:/Windows/Fonts/msyh.ttc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;6. 第六步：敏感信息保护&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;6-第六步敏感信息保护&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#6-%e7%ac%ac%e5%85%ad%e6%ad%a5%e6%95%8f%e6%84%9f%e4%bf%a1%e6%81%af%e4%bf%9d%e6%8a%a4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;config.toml&lt;/code&gt; 包含 SSH 密钥路径、微信 AppSecret、GitHub Token 等敏感信息，必须确保不会被意外提交：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;# .gitignore
config.toml
__pycache__/
*.pyc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;同时提供 &lt;code&gt;config.example.toml&lt;/code&gt; 作为模板，用户复制后填写自己的值。&lt;/p&gt;
&lt;h2&gt;四、踩坑记录&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四踩坑记录&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e8%b8%a9%e5%9d%91%e8%ae%b0%e5%bd%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;踩坑 1：相对路径 vs 绝对路径的抉择&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;踩坑-1相对路径-vs-绝对路径的抉择&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%b8%a9%e5%9d%91-1%e7%9b%b8%e5%af%b9%e8%b7%af%e5%be%84-vs-%e7%bb%9d%e5%af%b9%e8%b7%af%e5%be%84%e7%9a%84%e6%8a%89%e6%8b%a9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;最初我想把 SKILL.md 中的脚本路径写成 &lt;code&gt;scripts/xx.py&lt;/code&gt;，看起来更简洁。但分析后发现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Agent 默认 cwd 是&lt;strong&gt;项目根目录&lt;/strong&gt;，不是 Skill 目录&lt;/li&gt;
&lt;li&gt;脚本内部用 &lt;code&gt;Path(__file__).parent.parent&lt;/code&gt; 定位 Skill 资源，&lt;strong&gt;不依赖 cwd&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;如果要用短路径，就得先 &lt;code&gt;cd&lt;/code&gt; 到 Skill 目录，增加了一步容易遗漏的操作&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;结论：&lt;strong&gt;从项目根目录出发的完整相对路径是最稳妥的方案&lt;/strong&gt;。&lt;/p&gt;
&lt;h3&gt;踩坑 2：环境变量和配置文件的优先级&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;踩坑-2环境变量和配置文件的优先级&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%b8%a9%e5%9d%91-2%e7%8e%af%e5%a2%83%e5%8f%98%e9%87%8f%e5%92%8c%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6%e7%9a%84%e4%bc%98%e5%85%88%e7%ba%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一开始我把环境变量的优先级设为最高，后来发现问题：用户在 shell 里 &lt;code&gt;export&lt;/code&gt; 过一个临时变量，忘了 &lt;code&gt;unset&lt;/code&gt;，导致配置文件里的值永远不生效。&lt;/p&gt;
&lt;p&gt;最终确定的优先级：&lt;strong&gt;命令行参数 &amp;gt; 环境变量 &amp;gt; config.toml &amp;gt; 默认值&lt;/strong&gt;。命令行参数优先级最高，因为它是最&amp;quot;显式&amp;quot;的操作。&lt;/p&gt;
&lt;h3&gt;踩坑 3：TOML 解析的兼容性&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;踩坑-3toml-解析的兼容性&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%b8%a9%e5%9d%91-3toml-%e8%a7%a3%e6%9e%90%e7%9a%84%e5%85%bc%e5%ae%b9%e6%80%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Python 3.11 才内置 &lt;code&gt;tomllib&lt;/code&gt;，很多环境还在用 3.10 甚至 3.9。我的方案是&lt;strong&gt;三级回退&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;tomllib&lt;/span&gt;          &lt;span class=&#34;c1&#34;&gt;# Python 3.11+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ModuleNotFoundError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;tomli&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;tomllib&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# pip install tomli&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ModuleNotFoundError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;tomllib&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;       &lt;span class=&#34;c1&#34;&gt;# 使用内置简易解析器&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;简易解析器只支持 &lt;code&gt;[section]&lt;/code&gt; + &lt;code&gt;key = &amp;quot;value&amp;quot;&lt;/code&gt; 基本语法，但对配置文件已经完全够用了。&lt;/p&gt;
&lt;h2&gt;五、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这次重构的核心收获：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Skill 就是软件库&lt;/strong&gt;：Agent Skill 虽然是给 AI 用的，但本质上和写一个开源库没区别——要考虑可移植性、配置管理、文档完整性。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;配置集中管理是关键&lt;/strong&gt;：从散落在 7 个文件里的十几处硬编码，收敛到一个 &lt;code&gt;config.toml&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;gt; 环境变量 &amp;gt; 配置文件 &amp;gt; 默认值&lt;/code&gt; 这个模式在 CLI 工具中非常常见（Docker、kubectl 都是这么做的），用在 Agent Skill 上同样合适。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;自动探测 + 显式覆盖&lt;/strong&gt;的组合：大多数情况下自动探测就能工作，少数特殊场景用户可以显式指定，兼顾了易用性和灵活性。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;重构后的 blog-writer Skill 已经可以在 OpenClaw 容器、本地 macOS、甚至 Windows 上无缝运行——这篇文章本身就是用重构后的 Skill 写的。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>零代码搭建SSL证书监控：用元宝Bot10分钟完成以前做不好的事</title>
      <link>https://www.helight.info/blog/2026/0416-ssl-cert-monitor-with-ai-bot/</link>
      <pubDate>Thu, 16 Apr 2026 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0416-ssl-cert-monitor-with-ai-bot/</guid>
      <description>
        
        
        &lt;h2&gt;一、背景：这件事我折腾了好几个版本&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一背景这件事我折腾了好几个版本&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e8%83%8c%e6%99%af%e8%bf%99%e4%bb%b6%e4%ba%8b%e6%88%91%e6%8a%98%e8%85%be%e4%ba%86%e5%a5%bd%e5%87%a0%e4%b8%aa%e7%89%88%e6%9c%ac&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我手上有几个个人站点，域名和SSL证书都是自己维护的。因为是个人站点所以都是用的免费证书，但是免费证书目前只有3个月的期限，所以要定期的续期证书。证书忘记续期这种事，我相信每个维护过个人站点的同学都遇到过——网站突然https报红，一看才发现证书过期了好几天。&lt;/p&gt;
&lt;p&gt;为了解决这个问题，我之前做过好几个版本的监控：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;版本一：Python脚本 / Golang 自写&lt;/strong&gt;：逻辑不难，检测证书到期时间几十行代码就搞定，但问题卡在&lt;strong&gt;告警通知&lt;/strong&gt;上。邮件免费，但实时性差，经常漏看；短信实时，但要钱，而且申请短信服务的审批流程极度繁琐，个人开发者很难快速搞定。折腾了很久，效果始终不理想。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;版本二：小龙虾（Crawlab）&lt;/strong&gt;：试用了一段时间，告警只支持邮件，短信接口也需要自己对接调试，绕了一圈还是没解决微信通知的问题。而且小龙虾本身就需要单独找台机器部署，或者用云端版本，还要配置大模型——大模型调用也是要收费的，成本叠在一起，对个人开发者来说性价比并不高。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;折腾了这几轮，核心矛盾只有一个：&lt;strong&gt;一直想用微信告警通知，但始终搞不定&lt;/strong&gt;。微信的接口对个人开发者不友好，公众号需要认证，企业微信机器人又不是人人都有，测试号模板消息的配置流程也需要一定时间摸索。&lt;/p&gt;
&lt;p&gt;这次我换了一个思路——用AI Bot来做这件事，结果10分钟就完成了，而且一行代码都没写。&lt;/p&gt;
&lt;h2&gt;二、工具介绍：元宝Bot&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二工具介绍元宝bot&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e5%b7%a5%e5%85%b7%e4%bb%8b%e7%bb%8d%e5%85%83%e5%ae%9dbot&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这次用到的工具是腾讯的&lt;strong&gt;元宝Bot&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;简单说，它是一个能访问工具和执行任务的AI助手，核心能力是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;理解自然语言需求，自动生成并执行代码&lt;/li&gt;
&lt;li&gt;内置「Skill」（技能）扩展机制，可以调用各种工具&lt;/li&gt;
&lt;li&gt;支持定时任务（Cron），配置后自动周期性执行&lt;/li&gt;
&lt;li&gt;可以通过企业微信/微信发送通知&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我之所以选它，有两个核心原因：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;模型不用自己配，直接免费用&lt;/strong&gt;。这和小龙虾最大的区别在于——小龙虾是一个执行框架，你还得自己去接大模型、付大模型的费用；而元宝Bot本身就内置了大模型能力，申请开通之后直接用，不需要额外配置，也不额外收费。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;可以直接发微信通知&lt;/strong&gt;。这是我之前所有方案都没解决的痛点，元宝的通知链路天然打通了微信，配置起来也比想象中简单。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;三、全程对话实录：10分钟完成监控&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三全程对话实录10分钟完成监控&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e5%85%a8%e7%a8%8b%e5%af%b9%e8%af%9d%e5%ae%9e%e5%bd%9510%e5%88%86%e9%92%9f%e5%ae%8c%e6%88%90%e7%9b%91%e6%8e%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 告诉Bot我要做什么&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-告诉bot我要做什么&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e5%91%8a%e8%af%89bot%e6%88%91%e8%a6%81%e5%81%9a%e4%bb%80%e4%b9%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;我直接在对话框里说：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;我要对一个指定列表的域名的ssl证书进行监控，请创建一个skill来支持这个事情，列出每个域名的证书到期时间，到期时间小于10天的请单独列出来给我。&lt;/p&gt;

&lt;/blockquote&gt;
&lt;p&gt;Bot理解后，&lt;strong&gt;自动生成了一个Python脚本&lt;/strong&gt;，核心逻辑是通过TLS握手获取证书信息，计算剩余天数：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;ssl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;socket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;datetime&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;check_cert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;domain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ssl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;create_default_context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wrap_socket&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;socket&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;socket&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server_hostname&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;domain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;domain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;443&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;cert&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getpeercert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;expire_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cert&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;notAfter&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# e.g. &amp;#39;Jun 15 12:00:00 2025 GMT&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;expire_dt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;strptime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;expire_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;%b &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%d&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt; %H:%M:%S %Y %Z&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;days_left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;expire_dt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;utcnow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;days&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;domain&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;domain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;expire&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expire_dt&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;strftime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;%Y-%m-&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%d&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;days_left&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days_left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;warning&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days_left&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;脚本会把所有域名的证书状态汇总输出，≤10天的单独高亮标出。&lt;/p&gt;
&lt;h3&gt;2. 配置域名列表和定时任务&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-配置域名列表和定时任务&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e9%85%8d%e7%bd%ae%e5%9f%9f%e5%90%8d%e5%88%97%e8%a1%a8%e5%92%8c%e5%ae%9a%e6%97%b6%e4%bb%bb%e5%8a%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;我给了Bot要监控的6个域名，并说明每天9:30检测一次：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;https://www.helight.info
https://www.helight.cn
https://www.kerneltravel.net&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Bot自动创建了一个Cron任务，每天 &lt;code&gt;9:30 Asia/Shanghai&lt;/code&gt; 执行检测。这步我完全没有写任何配置文件，纯对话完成。&lt;/p&gt;
&lt;h3&gt;3. 配置微信通知&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-配置微信通知&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-%e9%85%8d%e7%bd%ae%e5%be%ae%e4%bf%a1%e9%80%9a%e7%9f%a5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是以前最麻烦的一步，这次出乎意料的顺畅。&lt;/p&gt;
&lt;p&gt;我问Bot怎么配置微信通知，它提供了几种方案，我选了&lt;strong&gt;微信测试号&lt;/strong&gt;（免费，个人就够用）：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;① 申请测试号&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;访问 &lt;code&gt;https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo&lt;/code&gt;，扫码登录即可获得 AppID 和 AppSecret，整个过程不超过2分钟。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;② 配置模板消息&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在测试号管理页面添加一个消息模板，内容大概是：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;证书到期提醒
域名：{{keyword1.DATA}}
到期时间：{{keyword2.DATA}}
剩余天数：{{keyword3.DATA}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;③ 把信息告诉Bot&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我直接把 AppID、AppSecret、模板ID、自己的 OpenID 告诉了Bot（注意：这些信息属于个人配置，不要公开分享），Bot自动把微信通知逻辑写进了检测脚本，并更新了Cron任务参数。&lt;/p&gt;
&lt;p&gt;整个配置过程就是纯聊天，Bot帮我完成了所有代码修改。&lt;/p&gt;
&lt;h3&gt;4. 验证效果&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;4-验证效果&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#4-%e9%aa%8c%e8%af%81%e6%95%88%e6%9e%9c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;配置完成后，Bot主动发起了一次测试检测，我的微信立刻收到了一条模板消息——域名名称、证书到期日期、剩余天数，格式清晰，一目了然。&lt;/p&gt;
&lt;p&gt;Bot最后给了一个状态汇总：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;当前监控的几个域名证书状态：
- www.helight.info      到期：2025-07-20  剩余：69天  ✅
- www.helight.cn        到期：2025-06-30  剩余：49天  ✅
- www.kerneltravel.net  到期：2025-06-05  剩余：24天  ✅

⚠️ 无即将过期证书（≤10天）&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;四、这次体验的几点感受&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四这次体验的几点感受&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e8%bf%99%e6%ac%a1%e4%bd%93%e9%aa%8c%e7%9a%84%e5%87%a0%e7%82%b9%e6%84%9f%e5%8f%97&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;最大的惊喜是微信通知&lt;/strong&gt;。以前我用各种监控工具，微信通知要么不支持、要么配置极度繁琐，这次通过测试号模板消息，整个配置过程就是聊天，Bot帮我写好了所有调用代码。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;一行代码没写&lt;/strong&gt;。从提需求到收到微信测试通知，只是在对话框里描述需求、回答Bot的问题（比如测试号信息），所有代码都是Bot生成的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;定时任务也是对话配置的&lt;/strong&gt;。&amp;ldquo;每天早上9点半检测一次&amp;rdquo;——就这一句话，Bot帮我创建好了Cron任务，配好了通知投递渠道，我连crontab文件都没碰。&lt;/p&gt;
&lt;p&gt;当然也有一点小插曲：Bot第一次问我模板ID时，我填了个数字&amp;quot;1&amp;quot;，它发现格式不对，主动提示我去确认真实的模板ID。这个细节挺好的，没有默默失败，而是主动说明问题。&lt;/p&gt;
&lt;h2&gt;五、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这件事让我重新思考了&amp;quot;做一个工具&amp;quot;的边界。&lt;/p&gt;
&lt;p&gt;过去我做监控，默认思路是：找方案 → 写代码 → 调试 → 配环境 → 上线维护。每一步都有成本，所以个人项目往往凑合就过去了，或者花了大量时间搞出一个&amp;quot;差不多能用&amp;quot;的版本。&lt;/p&gt;
&lt;p&gt;这次完全不一样。&lt;strong&gt;我只需要描述清楚我要什么，剩下的Bot来做&lt;/strong&gt;。关键是，它做的东西是真实可用的——代码是真实运行的Python脚本，Cron是系统级定时任务，微信通知是真实触达我手机的消息。&lt;/p&gt;
&lt;p&gt;我之前折腾了好几个版本SSL监控都没满意的，这次10分钟搞定，而且通知链路是我最想要的微信。&lt;/p&gt;
&lt;p&gt;AI Bot的价值不在于&amp;quot;它能写代码&amp;quot;，而在于&lt;strong&gt;它把「描述需求」和「交付可用工具」之间的距离，从小时/天级别压缩到了分钟级别&lt;/strong&gt;。对于个人开发者来说，这个变化是实质性的。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>Skill 异常处理实践：让 AI Agent 告别静默失败</title>
      <link>https://www.helight.info/blog/2026/0411-skill-exception-handling/</link>
      <pubDate>Sat, 11 Apr 2026 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0411-skill-exception-handling/</guid>
      <description>
        
        
        &lt;p&gt;最近在做一件事：让我的 AI Agent 系统更可靠。&lt;/p&gt;
&lt;p&gt;我用 OpenClaw 搭了一套自动化工作流，其中有个 Skill 负责每天早上拉取 TAPD 数据、生成站会摘要报告。跑了一段时间后，某天报告里出现了一条惊悚的风险告警——&amp;ldquo;全部 28 个需求均未设置计划开始时间和计划完成时间&amp;rdquo;。&lt;/p&gt;
&lt;p&gt;实际情况是大部分需求都有排期。&lt;/p&gt;
&lt;p&gt;这次误报让我认真思考了一个问题：AI Agent 的可靠性，光靠框架层面的保障是不够的，&lt;strong&gt;Skill 自身必须有完善的异常处理机制&lt;/strong&gt;，并且要能把异常清晰地透传到上层，让 LLM 做出正确判断。&lt;/p&gt;
&lt;h2&gt;一、一次真实的线上误报&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一一次真实的线上误报&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e4%b8%80%e6%ac%a1%e7%9c%9f%e5%ae%9e%e7%9a%84%e7%ba%bf%e4%b8%8a%e8%af%af%e6%8a%a5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;排查下来，这次误报由两个技术问题叠加导致：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题一：JSON 截断&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;内部 MCP 工具（mcporter-internal）有约 7KB 的输出大小限制。当我用 &lt;code&gt;limit=200&lt;/code&gt; 拉取需求列表时，返回的 JSON 数据被截断，解析失败，于是返回了一个空列表。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题二：脚本静默失败&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;脚本拿到空列表之后，没有报错，而是&amp;quot;正常&amp;quot;地往下执行——把 0 条需求当作&amp;quot;这个迭代没有需求&amp;quot;处理，然后生成了一份全是误报的风险分析。&lt;/p&gt;
&lt;p&gt;LLM 收到这份输出后，无法区分&amp;quot;API 调用失败&amp;quot;和&amp;quot;真的没有数据&amp;quot;，于是老老实实地生成了一份错误报告发给了我。&lt;/p&gt;
&lt;p&gt;顺带在排查过程中还发现了一个隐藏 Bug：&lt;code&gt;scan_risks.py&lt;/code&gt; 里有一个 &lt;code&gt;continue&lt;/code&gt; 语句，后面紧跟着一段永远不会被执行的死代码。这类逻辑错误在 Code Review 中很容易被忽略。&lt;/p&gt;
&lt;p&gt;这次事故的根因，一句话总结：&lt;strong&gt;Skill 脚本出错了，但 LLM 不知道&lt;/strong&gt;。&lt;/p&gt;
&lt;h2&gt;二、核心设计原则&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二核心设计原则&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e6%a0%b8%e5%bf%83%e8%ae%be%e8%ae%a1%e5%8e%9f%e5%88%99&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;基于这次事故，我重新设计了 Skill 的异常处理体系，确立了四条原则。&lt;/p&gt;
&lt;h3&gt;原则一：永不静默失败&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;原则一永不静默失败&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8e%9f%e5%88%99%e4%b8%80%e6%b0%b8%e4%b8%8d%e9%9d%99%e9%bb%98%e5%a4%b1%e8%b4%a5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;最危险的错误不是程序崩溃，而是程序&amp;quot;静悄悄地&amp;quot;返回了错误数据。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ❌ 危险：失败时返回空列表，LLM 会误以为「没有需求」&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_stories&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;workspace_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iteration_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call_safe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;stories_get&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;ok&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;extract_list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# ✅ 正确：失败时抛出异常，携带错误类型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_stories&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;workspace_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iteration_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call_safe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;stories_get&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;ok&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TapdApiError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;获取需求列表失败: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;error_type&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TapdApiError&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UNKNOWN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;extract_list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;区别在于：前者让错误消失了，后者让错误浮出水面，交由调用方决定如何处理。&lt;/p&gt;
&lt;h3&gt;原则二：区分错误类型，给出针对性提示&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;原则二区分错误类型给出针对性提示&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8e%9f%e5%88%99%e4%ba%8c%e5%8c%ba%e5%88%86%e9%94%99%e8%af%af%e7%b1%bb%e5%9e%8b%e7%bb%99%e5%87%ba%e9%92%88%e5%af%b9%e6%80%a7%e6%8f%90%e7%a4%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&amp;ldquo;出错了&amp;quot;对用户没有帮助，&amp;ldquo;鉴权失败，请重新登录&amp;quot;才有帮助。我为 TAPD API 调用定义了 8 种错误类型：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;错误类型&lt;/th&gt;
					&lt;th&gt;触发场景&lt;/th&gt;
					&lt;th&gt;用户可采取的行动&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;timeout&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;调用超时&lt;/td&gt;
					&lt;td&gt;检查内网连通性，稍后重试&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;command_not_found&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;工具未安装&lt;/td&gt;
					&lt;td&gt;运行 npm install 安装&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;auth_failed&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;鉴权失败（401/403）&lt;/td&gt;
					&lt;td&gt;确认已完成 tapd 授权&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;empty_response&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;返回空响应&lt;/td&gt;
					&lt;td&gt;检查内网服务是否可达&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;json_truncated&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;JSON 被截断&lt;/td&gt;
					&lt;td&gt;减少 limit 参数，使用分页&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;json_parse&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;JSON 解析失败&lt;/td&gt;
					&lt;td&gt;检查接口返回格式&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;api_error&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;接口返回业务错误&lt;/td&gt;
					&lt;td&gt;确认 workspace_id 和账号权限&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;process_error&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;进程返回非零退出码&lt;/td&gt;
					&lt;td&gt;查看 stderr 获取详细原因&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;结构化的错误类型让调用方可以精确区分原因，而不是猜测。&lt;/p&gt;
&lt;h3&gt;原则三：致命错误 vs 非致命错误，分级处理&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;原则三致命错误-vs-非致命错误分级处理&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8e%9f%e5%88%99%e4%b8%89%e8%87%b4%e5%91%bd%e9%94%99%e8%af%af-vs-%e9%9d%9e%e8%87%b4%e5%91%bd%e9%94%99%e8%af%af%e5%88%86%e7%ba%a7%e5%a4%84%e7%90%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;并非所有错误都需要终止执行：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;致命错误&lt;/strong&gt;：核心数据获取失败（需求列表），无法继续生成报告，直接退出&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;非致命错误&lt;/strong&gt;：辅助数据获取失败（任务列表、迭代信息），影响部分功能，但可以降级继续&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;降级处理时，脚本会：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;向 &lt;code&gt;stderr&lt;/code&gt; 输出警告（供调试查看）&lt;/li&gt;
&lt;li&gt;在输出 JSON 的 &lt;code&gt;warnings&lt;/code&gt; 字段记录降级信息（供 LLM 感知）&lt;/li&gt;
&lt;li&gt;继续执行，生成带有数据完整性声明的报告&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;原则四：输出 LLM 友好的错误 JSON&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;原则四输出-llm-友好的错误-json&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8e%9f%e5%88%99%e5%9b%9b%e8%be%93%e5%87%ba-llm-%e5%8f%8b%e5%a5%bd%e7%9a%84%e9%94%99%e8%af%af-json&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Skill 脚本的输出会被 LLM 直接读取。如果脚本只是 &lt;code&gt;sys.exit(1)&lt;/code&gt; 而不输出任何内容，LLM 完全不知道发生了什么。&lt;/p&gt;
&lt;p&gt;我设计了统一的错误输出格式，包含 &lt;code&gt;llm_hint&lt;/code&gt; 字段作为专门给 LLM 的决策提示：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;error_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;auth_failed&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;TAPD 鉴权失败，请确认 mcporter-internal 已完成 tapd 授权配置&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;workspace_id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;70132312&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;llm_hint&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;🔴 TAPD 鉴权失败，请确认 mcporter-internal 已完成 tapd 授权配置。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;LLM 读取 &lt;code&gt;llm_hint&lt;/code&gt; 后可以直接向用户输出友好的错误说明，而不是一段技术性的堆栈信息。&lt;/p&gt;
&lt;h2&gt;三、工程实现&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三工程实现&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e5%b7%a5%e7%a8%8b%e5%ae%9e%e7%8e%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;TapdApiError：结构化异常类&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;tapdapierror结构化异常类&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#tapdapierror%e7%bb%93%e6%9e%84%e5%8c%96%e5%bc%82%e5%b8%b8%e7%b1%bb&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;TapdApiError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;Exception&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 错误类型常量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;TIMEOUT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;timeout&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;NOT_FOUND&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;command_not_found&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;AUTH_FAILED&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;auth_failed&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;EMPTY_RESPONSE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;empty_response&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;JSON_TRUNCATED&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;json_truncated&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;JSON_PARSE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;json_parse&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;API_ERROR&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;api_error&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;PROCESS_ERROR&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;process_error&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;UNKNOWN&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;unknown&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;fm&#34;&gt;__init__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;unknown&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;raw&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;super&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;fm&#34;&gt;__init__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;raw&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# 原始输出，用于调试&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;error_type&lt;/code&gt; 使用字符串常量，调用方可以用 &lt;code&gt;e.error_type == TapdApiError.AUTH_FAILED&lt;/code&gt; 精确判断；&lt;code&gt;raw&lt;/code&gt; 字段保留原始输出，便于调试。&lt;/p&gt;
&lt;h3&gt;call() 与 call_safe()：双接口设计&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;call-与-call_safe双接口设计&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#call-%e4%b8%8e-call_safe%e5%8f%8c%e6%8e%a5%e5%8f%a3%e8%ae%be%e8%ae%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# call_safe() 返回结构化结果，不抛出异常&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;call_safe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tool_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tool_args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timeout&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tool_name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tool_args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;ok&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TapdApiError&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;ok&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;error&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;error_type&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;Exception&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;ok&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;error&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;未预期的异常: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;error_type&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TapdApiError&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UNKNOWN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;call()&lt;/code&gt;：抛出 &lt;code&gt;TapdApiError&lt;/code&gt;，适用于需要精确控制异常处理的场景&lt;/li&gt;
&lt;li&gt;&lt;code&gt;call_safe()&lt;/code&gt;：返回 &lt;code&gt;{ok, error_type, ...}&lt;/code&gt;，适用于主流程，避免未捕获异常导致输出混乱&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;exit_with_error()：标准化错误退出&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;exit_with_error标准化错误退出&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#exit_with_error%e6%a0%87%e5%87%86%e5%8c%96%e9%94%99%e8%af%af%e9%80%80%e5%87%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;exit_with_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;workspace_id&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;output&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;ok&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;error_type&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;error&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;workspace_id&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;workspace_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s1&#34;&gt;&amp;#39;llm_hint&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hint&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;🔴 脚本执行失败（&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;）：&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dumps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;output&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ensure_ascii&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;indent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 在 main() 中使用&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;stories&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tapd_api&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_stories&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;workspace_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iteration_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tapd_api&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TapdApiError&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;exit_with_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;hint&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_error_hint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# 根据 error_type 生成针对性提示&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;四、JSON 截断问题的根治：分页拉取&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四json-截断问题的根治分页拉取&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9bjson-%e6%88%aa%e6%96%ad%e9%97%ae%e9%a2%98%e7%9a%84%e6%a0%b9%e6%b2%bb%e5%88%86%e9%a1%b5%e6%8b%89%e5%8f%96&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这次事故的直接触发点是 JSON 截断。解决思路很简单：分页拉取，每页数据量控制在安全范围内。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_stories&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;workspace_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iteration_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;limit&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;PAGE_SIZE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# 经验值，10 条约 2-3KB，安全边际充足&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;all_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;page&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;first_page&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[],&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call_safe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;stories_get&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;base_args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;page&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;page&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;ok&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;first_page&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TapdApiError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# 第一页失败：致命错误&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;⚠️ 第&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;page&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;页失败，停止分页&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;                      &lt;span class=&#34;c1&#34;&gt;# 后续页失败：降级处理&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;first_page&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;page_items&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;extract_list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;page_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;all_items&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;extend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;page_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;page&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;page_items&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PAGE_SIZE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# 最后一页&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;all_items&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;关键决策：&lt;strong&gt;第一页失败 = 致命错误&lt;/strong&gt;（无法获取任何数据，必须终止）；&lt;strong&gt;后续页失败 = 降级处理&lt;/strong&gt;（已有部分数据，停止分页但返回已有数据，输出警告）。&lt;/p&gt;
&lt;p&gt;截断检测：通过检查输出是否以 &lt;code&gt;...&lt;/code&gt; 或 &lt;code&gt;…&lt;/code&gt; 结尾，以及长度超过 1000 且不以 &lt;code&gt;}&lt;/code&gt; 或 &lt;code&gt;]&lt;/code&gt; 结尾，来识别截断情况。&lt;/p&gt;
&lt;h2&gt;五、完整架构&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五完整架构&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e5%ae%8c%e6%95%b4%e6%9e%b6%e6%9e%84&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;经过改造后，整个异常处理体系的分层如下：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;┌────────────────────────────────────────────────────────┐
│ LLM（读取输出 JSON）                                    │
│   ok=true  → 正常处理                                  │
│   ok=false → 读取 llm_hint，向用户输出友好错误提示     │
└───────────────────────┬────────────────────────────────┘
                        │ stdout（JSON）
┌───────────────────────▼────────────────────────────────┐
│ 脚本层（fetch_standup / scan_risks 等）                 │
│   致命错误 → exit_with_error() → ok=false JSON &amp;#43; 退出 │
│   降级错误 → 记录 warnings，继续执行                   │
└───────────────────────┬────────────────────────────────┘
                        │ 抛出 TapdApiError
┌───────────────────────▼────────────────────────────────┐
│ tapd_api.py（公共 API 模块）                            │
│   call()      → 识别 8 种错误类型，抛出 TapdApiError   │
│   call_safe() → 捕获异常，返回 {ok, error_type, data} │
│   get_*()    → 分页拉取，首页失败抛出，后续页降级      │
└───────────────────────┬────────────────────────────────┘
                        │ subprocess
┌───────────────────────▼────────────────────────────────┐
│ mcporter-internal（内网 MCP 工具）                      │
│   timeout / not_found / auth_failed / json_truncated…  │
└────────────────────────────────────────────────────────┘&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这个分层设计的核心思想是：&lt;strong&gt;每一层都对上层负责&lt;/strong&gt;，把自己能识别的错误翻译成结构化信息，传递给上层，而不是让问题在本层消失。&lt;/p&gt;
&lt;h2&gt;六、第二个案例：blog-writer Skill 的改造&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;六第二个案例blog-writer-skill-的改造&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%ad%e7%ac%ac%e4%ba%8c%e4%b8%aa%e6%a1%88%e4%be%8bblog-writer-skill-%e7%9a%84%e6%94%b9%e9%80%a0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;TAPD Skill 改造完之后，我顺手把自己另一个常用 Skill——&lt;strong&gt;blog-writer&lt;/strong&gt;——也过了一遍。它负责生成博客文章并自动提交 PR、部署到远程服务器。一看之下，同样的毛病：三个核心脚本，失败时要么裸抛异常，要么只是 &lt;code&gt;sys.exit(1)&lt;/code&gt; 什么都不输出。&lt;/p&gt;
&lt;h3&gt;6.1 改造前的问题&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;61-改造前的问题&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#61-%e6%94%b9%e9%80%a0%e5%89%8d%e7%9a%84%e9%97%ae%e9%a2%98&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;submit_pr.py（提交 PR）&lt;/strong&gt;：&lt;code&gt;create_pr()&lt;/code&gt; 函数里调用 GitHub API，失败时直接抛出 &lt;code&gt;urllib.error.HTTPError&lt;/code&gt;，调用方没有捕获，LLM 看到的是一段 Python traceback，完全无法判断是网络问题还是 Token 过期。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 改造前：裸抛，LLM 拿到的是 traceback&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;urllib&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;urlopen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;req&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timeout&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;loads&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;html_url&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# HTTPError 直接往上飞，main() 没有 try/except&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;deploy.py（远程部署）&lt;/strong&gt;：SSH 连接失败、make 命令失败，都只是 &lt;code&gt;logging.error()&lt;/code&gt; 打日志然后 &lt;code&gt;sys.exit(1)&lt;/code&gt;。LLM 不知道是连不上服务器、密钥问题还是 make 本身报错。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;gen_banner.py（生成 Banner）&lt;/strong&gt;：找不到 CJK 字体时，&lt;strong&gt;静默 fallback&lt;/strong&gt; 到系统默认点阵字体——中文标题直接变成方块，但脚本正常退出，LLM 和用户都不会收到任何警告。这是个典型的&amp;quot;成功了，但结果是错的&amp;rdquo;。&lt;/p&gt;
&lt;h3&gt;6.2 改造后：统一接入 exit_with_error()&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;62-改造后统一接入-exit_with_error&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#62-%e6%94%b9%e9%80%a0%e5%90%8e%e7%bb%9f%e4%b8%80%e6%8e%a5%e5%85%a5-exit_with_error&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;三个脚本都引入了同样的模式，以 &lt;code&gt;submit_pr.py&lt;/code&gt; 为例：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 错误类型常量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ERR_GIT&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;git_error&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ERR_AUTH&lt;/span&gt;      &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;auth_failed&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ERR_NETWORK&lt;/span&gt;   &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;network_error&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ERR_EXISTS&lt;/span&gt;    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;already_exists&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ERR_NOT_FOUND&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;not_found&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;_HINT_MAP&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;ERR_AUTH&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;🔴 GitHub 鉴权失败（401/403），请确认 git remote URL 中的 PAT 有效。&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;ERR_NETWORK&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;🔴 网络请求失败，请检查内网/外网连通性，稍后重试。&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;ERR_EXISTS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;  &lt;span class=&#34;s2&#34;&gt;&amp;#34;🟡 PR 分支已存在，请检查 GitHub 上是否已有对应 PR。&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;exit_with_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;detail&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;output&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;error_type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;detail&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;detail&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;llm_hint&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_HINT_MAP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;🔴 未知错误&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dumps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;output&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ensure_ascii&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;indent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;GitHub API 调用现在按 HTTP 状态码细化：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;urllib&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;HTTPError&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;code&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;401&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;403&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;exit_with_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ERR_AUTH&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;GitHub 鉴权失败（HTTP &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;code&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;）&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;elif&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;code&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;422&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;pull request already exists&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;detail&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lower&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;exit_with_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ERR_EXISTS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;该分支已存在对应的 PR，请勿重复创建&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;exit_with_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ERR_PR_CREATE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;PR 创建失败（HTTP &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;code&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;）：参数错误&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;exit_with_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ERR_PR_CREATE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;PR 创建失败（HTTP &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;code&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;）&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;deploy.py&lt;/strong&gt; 加了前置校验和 SSH 错误分类：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 前置校验：私钥文件存在（不等 SSH 进程崩溃再报错）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exists&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SSH_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;exit_with_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ERR_SSH_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;SSH 私钥文件不存在：&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SSH_KEY&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 超时单独捕获&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;subprocess&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TimeoutExpired&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;exit_with_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ERR_TIMEOUT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;SSH 命令超时（120s）&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 根据退出码和 stderr 推断 SSH 错误类型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;_classify_ssh_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;255&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;connection refused&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;no route to host&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ERR_SSH_CONNECT&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;# 连不上&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;permission denied&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;publickey&amp;#34;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ERR_SSH_AUTH&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;# 密钥问题&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ERR_MAKE_FAILED&lt;/span&gt;           &lt;span class=&#34;c1&#34;&gt;# make 本身失败&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;gen_banner.py&lt;/strong&gt; 的字体静默失败改为降级警告透传：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 改造前：静默 fallback，用户不知道中文会乱码&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ImageFont&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;load_default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 改造后：输出 WARNING，降级继续（非致命），LLM/用户可感知&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_font_missing_warned&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;WARNING: 未找到 CJK 字体，中文标题将显示为方块。&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34; 请运行：dnf install google-noto-cjk-fonts&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;_font_missing_warned&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ImageFont&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;load_default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;正常输出时也带上 &lt;code&gt;warnings&lt;/code&gt; 字段：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;ok&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/projects/hxblog/.../banner.jpg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;warnings&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;CJK 字体缺失，中文标题可能显示为方块，请安装 google-noto-cjk-fonts&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;llm_hint&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;✅ Banner 生成成功  ⚠️ 注意：CJK 字体缺失...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;6.3 两个案例的共同模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;63-两个案例的共同模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#63-%e4%b8%a4%e4%b8%aa%e6%a1%88%e4%be%8b%e7%9a%84%e5%85%b1%e5%90%8c%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;把两次改造对比一下，会发现问题是同构的：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;问题类型&lt;/th&gt;
					&lt;th&gt;TAPD Skill&lt;/th&gt;
					&lt;th&gt;blog-writer Skill&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;静默返回错误数据&lt;/td&gt;
					&lt;td&gt;API 失败返回空列表&lt;/td&gt;
					&lt;td&gt;字体缺失静默生成乱码 Banner&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;裸抛异常&lt;/td&gt;
					&lt;td&gt;subprocess 异常未捕获&lt;/td&gt;
					&lt;td&gt;HTTPError 未捕获&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;退出无输出&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;sys.exit(1)&lt;/code&gt; 无 JSON&lt;/td&gt;
					&lt;td&gt;同左&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;错误类型不细分&lt;/td&gt;
					&lt;td&gt;统一 Exception&lt;/td&gt;
					&lt;td&gt;HTTP 状态码未细化&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;解法也是同构的：&lt;code&gt;exit_with_error()&lt;/code&gt; + &lt;code&gt;error_type&lt;/code&gt; 常量 + &lt;code&gt;llm_hint&lt;/code&gt; + &lt;code&gt;warnings&lt;/code&gt; 降级字段。&lt;strong&gt;这套模式可以直接复用到任何 Skill 脚本里，不需要每次重新设计。&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;七、Skill 开发 Checklist&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;七skill-开发-checklist&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%83skill-%e5%bc%80%e5%8f%91-checklist&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;改造完成后，我整理了一份 Skill 开发的异常处理 Checklist，供后续开发参考：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;strong&gt;异常类&lt;/strong&gt;：定义结构化异常类，包含 &lt;code&gt;error_type&lt;/code&gt; 字段&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;strong&gt;exit_with_error&lt;/strong&gt;：实现标准化错误退出函数，输出 &lt;code&gt;ok=false&lt;/code&gt; JSON&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;strong&gt;llm_hint&lt;/strong&gt;：每个输出 JSON 都包含 &lt;code&gt;llm_hint&lt;/code&gt;，指导 LLM 决策&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;strong&gt;warnings&lt;/strong&gt;：降级处理时记录 &lt;code&gt;warnings&lt;/code&gt;，声明数据局限性&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;strong&gt;分页拉取&lt;/strong&gt;：对可能超出大小限制的 API 调用使用分页&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;strong&gt;致命/降级分级&lt;/strong&gt;：区分核心数据和辅助数据，制定不同失败策略&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;strong&gt;语法检查&lt;/strong&gt;：提交前运行 &lt;code&gt;python3 -m py_compile&lt;/code&gt; 验证语法&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;strong&gt;死代码检查&lt;/strong&gt;：检查 &lt;code&gt;continue&lt;/code&gt;/&lt;code&gt;return&lt;/code&gt;/&lt;code&gt;break&lt;/code&gt; 后是否有永远不执行的代码&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;八、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;八总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%ab%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这次事故给我的核心启示：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI Agent 的可靠性是分层的。&lt;/strong&gt; 框架层（OpenClaw）负责 Skill 的调度和执行保障，但 Skill 自身必须有完善的异常处理——异常要向上透传，而不是被内部消化成错误数据悄悄返回。&lt;/p&gt;
&lt;p&gt;一个 Skill 如果对 LLM 说&amp;quot;我执行完了，没有数据&amp;rdquo;，和说&amp;quot;我执行失败了，原因是鉴权失败，请检查配置&amp;quot;，对 LLM 最终生成的输出影响是天壤之别。&lt;/p&gt;
&lt;p&gt;静默失败是 AI Agent 系统中最危险的模式，因为 LLM 不会主动质疑数据的来源是否可靠，它只会&amp;quot;诚实地&amp;quot;基于你给的数据输出结果。所以数据源（Skill 脚本）的防御性设计，是整个系统可靠性的基础。&lt;/p&gt;
&lt;p&gt;这套异常处理模式不只适用于 TAPD Skill，对所有通过 subprocess 调用外部命令、结果会被 LLM 解析的 Skill 都适用。如果你也在构建类似的 AI Agent 工作流，希望这篇文章能提供一些参考。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>AI时代程序员的转身：研发范式的变化与能力重塑</title>
      <link>https://www.helight.info/blog/2026/0403-ai-era-programmer-transformation/</link>
      <pubDate>Fri, 03 Apr 2026 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0403-ai-era-programmer-transformation/</guid>
      <description>
        
        
        &lt;p&gt;最近在团队内部做了一次关于 AI 时代研发范式变化的分享，把 PPT 内容整理出来，并附上自己的一些思考和总结。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Slide 1：主题&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;slide-1主题&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#slide-1%e4%b8%bb%e9%a2%98&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;AI时代程序员的转身&lt;/strong&gt;
研发范式的变化与能力重塑&lt;/p&gt;
&lt;p&gt;&lt;em&gt;2026-03-27&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Slide 2：为什么要&amp;quot;转身&amp;quot;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;slide-2为什么要转身&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#slide-2%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e8%bd%ac%e8%ba%ab&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;blockquote&gt;
  &lt;p&gt;编码本身正在从&amp;quot;核心产出&amp;quot;变为&amp;quot;基础设施&amp;quot;——这不是威胁，而是解放。&lt;/p&gt;

&lt;/blockquote&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;/td&gt;
					&lt;td&gt;手写碰撞检测逻辑，数百行代码反复调试&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;现在&lt;/td&gt;
					&lt;td&gt;自然语言描述碰撞规则，AI生成代码，人做审查&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;未来&lt;/td&gt;
					&lt;td&gt;Agent自主完成开发测试，工程师专注玩法创新&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;转身的本质：从&amp;quot;手写代码&amp;quot;到&amp;quot;驾驭AI写代码&amp;quot;，从&amp;quot;执行者&amp;quot;到&amp;quot;决策者&amp;quot;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;小结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;小结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b0%8f%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这张PPT用碰撞检测这个具体的工程例子，把&amp;quot;AI替代&amp;quot;这件事讲得很清晰：不是工程师消失，而是工程师的重心在上移。以前我们花大量时间在&amp;quot;怎么实现&amp;quot;上，今后越来越多的精力应该放在&amp;quot;实现什么&amp;quot;和&amp;quot;为什么这么实现&amp;quot;上。这个转变不是突然发生的，而是随着 AI 工具能力的提升在持续加速。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Slide 3：研发范式的四个新维度&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;slide-3研发范式的四个新维度&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#slide-3%e7%a0%94%e5%8f%91%e8%8c%83%e5%bc%8f%e7%9a%84%e5%9b%9b%e4%b8%aa%e6%96%b0%e7%bb%b4%e5%ba%a6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;blockquote&gt;
  &lt;p&gt;研发范式的变化与能力重塑&lt;/p&gt;

&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Spec 规格描述&lt;/strong&gt;
程序员的新&amp;quot;代码&amp;quot;——用结构化自然语言精确描述需求、约束和验收标准&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;案例：为系统编写Spec，定义系统能力、交互逻辑&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Skill 技能封装&lt;/strong&gt;
将领域知识、编码规范封装为AI可调用的&amp;quot;技能包&amp;quot;，实现组织级知识复用&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;案例：封装&amp;quot;UE5网络同步Skill&amp;quot;，含帧同步/状态同步最佳实践&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Agent Engineering&lt;/strong&gt;
设计、构建、编排AI Agent完成复杂研发任务的工程能力&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;案例：构建&amp;quot;H5测试Agent&amp;quot;，自动生成测试用例并输出Bug清单&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Harness Engineering&lt;/strong&gt;
AI研发链路的端到端工程治理：质量、成本、安全、可观测性&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;案例：生产任务自动化，设置目标，H5活动全流程开发、测试、检测、上线&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;小结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;小结-1&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b0%8f%e7%bb%93-1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这四个维度是我认为 AI 时代最重要的新能力框架。Spec 是输入质量的保障，Skill 是团队知识的沉淀，Agent Engineering 是复杂任务的编排能力，Harness Engineering 是整个 AI 研发链路的工程治理。这四件事以前要么不存在，要么是&amp;quot;软技能&amp;quot;，现在都变成了硬核的工程能力，需要系统性地去建设。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Slide 4：以大模型的方式思考&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;slide-4以大模型的方式思考&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#slide-4%e4%bb%a5%e5%a4%a7%e6%a8%a1%e5%9e%8b%e7%9a%84%e6%96%b9%e5%bc%8f%e6%80%9d%e8%80%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;blockquote&gt;
  &lt;p&gt;不换思维模式，就无法有效驾驭AI工具&lt;/p&gt;

&lt;/blockquote&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;传统思维&lt;/th&gt;
					&lt;th&gt;大模型思维&lt;/th&gt;
					&lt;th&gt;实操示例&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&amp;ldquo;怎么实现这个算法？&amp;rdquo;&lt;/td&gt;
					&lt;td&gt;&amp;ldquo;怎么描述问题让AI给最优解？&amp;rdquo;&lt;/td&gt;
					&lt;td&gt;A*寻路：描述约束和性能要求&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&amp;ldquo;代码必须100%正确&amp;rdquo;&lt;/td&gt;
					&lt;td&gt;&amp;ldquo;快速生成→审查→迭代修正&amp;rdquo;&lt;/td&gt;
					&lt;td&gt;AI出80分代码，人补到100分&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&amp;ldquo;我要掌控每一行代码&amp;rdquo;&lt;/td&gt;
					&lt;td&gt;&amp;ldquo;我要掌控架构和关键决策&amp;rdquo;&lt;/td&gt;
					&lt;td&gt;人定义伤害公式，AI填充实现&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&amp;ldquo;文档是副产物&amp;rdquo;&lt;/td&gt;
					&lt;td&gt;&amp;ldquo;Spec/Prompt是核心产出&amp;rdquo;&lt;/td&gt;
					&lt;td&gt;写好文档 = 写好代码&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&amp;ldquo;工具是辅助&amp;rdquo;&lt;/td&gt;
					&lt;td&gt;&amp;ldquo;工具链是生产力核心&amp;rdquo;&lt;/td&gt;
					&lt;td&gt;Agent+Skill组合 &amp;gt; 编码能力&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;小结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;小结-2&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b0%8f%e7%bb%93-2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;思维转换这张 PPT 是我觉得最难落地的部分。道理大家都懂，但真正让一个有十年经验的工程师放弃&amp;quot;掌控每一行代码&amp;quot;的执念，是很难的。从我自己的实践来看，转变的关键是&lt;strong&gt;先从小任务开始信任 AI&lt;/strong&gt;——让 AI 写一个自己熟悉领域的模块，然后认真做 Review，慢慢建立起&amp;quot;AI 能干这个&amp;quot;的信心。一旦信任建立了，思维自然跟着变。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Slide 5：AI时代程序员的能力模型&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;slide-5ai时代程序员的能力模型&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#slide-5ai%e6%97%b6%e4%bb%a3%e7%a8%8b%e5%ba%8f%e5%91%98%e7%9a%84%e8%83%bd%e5%8a%9b%e6%a8%a1%e5%9e%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;blockquote&gt;
  &lt;p&gt;核心变化：▲ 价值上升 - 战略与架构 ｜ ▼ 价值下降 - 机械化执行 ｜ ★ 全新要求 - AI协同与治理&lt;/p&gt;

&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;价值上升的能力（▲）&lt;/strong&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;strong&gt;全新要求的能力（★）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prompt工程：高效引导AI模型输出精准代码&lt;/li&gt;
&lt;li&gt;Agent编排：设计并管理自动化智能体工作流&lt;/li&gt;
&lt;li&gt;AI输出审查：鉴别并修复AI生成代码的安全与逻辑漏洞&lt;/li&gt;
&lt;li&gt;Harness治理：建立AI工具链的规范与效能评估体系&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;价值下降的能力（▼）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;语法记忆：对特定编程语言语法的死记硬背&lt;/li&gt;
&lt;li&gt;API背诵：强依赖人工查阅和记忆标准库接口&lt;/li&gt;
&lt;li&gt;模板化编码：编写CRUD等高度重复的样板代码&lt;/li&gt;
&lt;li&gt;重复性测试：手动执行基础的单元测试与回归测试&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;小结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;小结-3&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b0%8f%e7%bb%93-3&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这个能力模型给出了一个很直接的判断框架：&lt;strong&gt;越靠近&amp;quot;决策&amp;quot;的能力越值钱，越靠近&amp;quot;执行&amp;quot;的能力越快被替代&lt;/strong&gt;。对个人来说，现在需要认真思考自己的时间分配——有多少精力在做&amp;quot;背语法&amp;quot;和&amp;quot;写CRUD&amp;quot;，有多少在做&amp;quot;架构设计&amp;quot;和&amp;quot;业务洞察&amp;quot;？如果前者比例很高，那就是一个需要调整的信号。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Slide 6：AI Agent vs 人类开发者&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;slide-6ai-agent-vs-人类开发者&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#slide-6ai-agent-vs-%e4%ba%ba%e7%b1%bb%e5%bc%80%e5%8f%91%e8%80%85&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;blockquote&gt;
  &lt;p&gt;协同原则：AI是你的10x工程师搭档，不是你的替代者
人类负责 What &amp;amp; Why，AI负责 How，共同负责质量&lt;/p&gt;

&lt;/blockquote&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;维度&lt;/th&gt;
					&lt;th&gt;人类开发者&lt;/th&gt;
					&lt;th&gt;AI Agent&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;/td&gt;
					&lt;td&gt;深（业务+玩家心理）&lt;/td&gt;
					&lt;td&gt;浅（依赖Spec质量）&lt;/td&gt;
					&lt;td&gt;人写Spec，AI执行&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;编码速度&lt;/td&gt;
					&lt;td&gt;中（百行/时）&lt;/td&gt;
					&lt;td&gt;极高（千行/分）&lt;/td&gt;
					&lt;td&gt;AI初稿，人精修&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;创造力&lt;/td&gt;
					&lt;td&gt;高（原创玩法设计）&lt;/td&gt;
					&lt;td&gt;中（组合式创新）&lt;/td&gt;
					&lt;td&gt;人定方向，AI扩展&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;质量意识&lt;/td&gt;
					&lt;td&gt;高（责任心驱动）&lt;/td&gt;
					&lt;td&gt;中（规则驱动）&lt;/td&gt;
					&lt;td&gt;AI自测，人验收&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;持续性&lt;/td&gt;
					&lt;td&gt;低（8h/天）&lt;/td&gt;
					&lt;td&gt;高（24×7）&lt;/td&gt;
					&lt;td&gt;人规划，AI持续执行&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;知识广度&lt;/td&gt;
					&lt;td&gt;窄（专精领域）&lt;/td&gt;
					&lt;td&gt;广（跨领域）&lt;/td&gt;
					&lt;td&gt;AI调研，人决策&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;小结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;小结-4&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b0%8f%e7%bb%93-4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这张对比表的价值在于&lt;strong&gt;找到人机协同的最优分工&lt;/strong&gt;，而不是非此即彼地讨论&amp;quot;AI能不能替代人&amp;quot;。每个维度都有各自的优势区间，最聪明的做法是把任务拆解到合适的粒度，让人和 AI 各司其职。比如&amp;quot;持续性&amp;quot;这一条很关键——AI 可以 24×7 跑，而人不行；利用好这一点，很多测试、监控、自动化流程都可以交给 Agent 在后台持续执行，人只需要做规划和最终验收。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Slide 7：行动路线图&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;slide-7行动路线图&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#slide-7%e8%a1%8c%e5%8a%a8%e8%b7%af%e7%ba%bf%e5%9b%be&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Phase 1 — 工具普及期&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;熟练掌握AI编码工具 CodeBuddy&lt;/li&gt;
&lt;li&gt;建立团队Prompt模板库&lt;/li&gt;
&lt;li&gt;选定试点项目验证效率&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Phase 2 — 能力构建期&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;封装3~5个团队专属Skill&lt;/li&gt;
&lt;li&gt;落地首个Agent场景&lt;/li&gt;
&lt;li&gt;建立AI代码质量门禁&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Phase 3 — 体系成熟期&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;构建团队Agent&lt;/li&gt;
&lt;li&gt;AI-Native开发文化&lt;/li&gt;
&lt;li&gt;实现全链路智能化研发&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;四大行动号召（Calls to Action）&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;立刻开始&lt;/strong&gt; — 打破观望态度，将AI工具无缝引入日常工作流，建立对AI能力的初步认知与信任。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;刻意练习&lt;/strong&gt; — 系统性掌握 Prompt Engineering（提示词工程），通过反复实践提升人机交互的精准度。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;向上跃迁&lt;/strong&gt; — 将精力从底层代码实现转移到系统架构、业务逻辑与创新设计上，实现个人价值升维。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;分享共建&lt;/strong&gt; — 在团队内部分享最佳实践与优质 Prompt，沉淀组织级AI资产，推动整体效能提升。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;小结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;小结-5&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b0%8f%e7%bb%93-5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;路线图的价值在于把&amp;quot;转身&amp;quot;这件抽象的事情拆成了可执行的步骤。从我的观察来看，很多团队卡在 Phase 1 出不来，原因是&amp;quot;用了工具但没有沉淀&amp;quot;——Prompt 写过就忘、案例做过没复盘。Phase 2 的核心动作&amp;quot;封装 Skill&amp;quot;是关键转折点，它把个人经验变成团队资产，把&amp;quot;我会用AI&amp;quot;变成&amp;quot;团队会用AI&amp;quot;。这一步做好了，后面的 Phase 3 才有根基。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Slide 8：结语&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;slide-8结语&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#slide-8%e7%bb%93%e8%af%ad&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;blockquote&gt;
  &lt;p&gt;我们不是在跟AI赛跑，而是在学会骑上AI这匹快马&lt;/p&gt;

&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;人机协同原则（HUMAN-MACHINE COLLABORATION）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;人类（Human）负责 What &amp;amp; Why：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;战略思考与业务洞察&lt;/li&gt;
&lt;li&gt;核心需求定义与架构设计&lt;/li&gt;
&lt;li&gt;最终决策与质量把控&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;人工智能（AI）负责 How：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;基础代码生成与补全&lt;/li&gt;
&lt;li&gt;重复性劳动与模板化工作&lt;/li&gt;
&lt;li&gt;细节实现与执行效率提升&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;CORE PARADIGM SHIFT&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;从『手写代码』到『驾驭AI写代码』&lt;/p&gt;

&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;转身不是转行，是升级。让我们一起，成为AI时代的顶尖游戏技术团队！&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;小结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;小结-6&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b0%8f%e7%bb%93-6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;结尾这句&amp;quot;转身不是转行，是升级&amp;quot;是整个分享的核心立意。我想强调的是：工程师的核心价值从来不只是写代码，而是&lt;strong&gt;理解问题、做出决策、保障质量&lt;/strong&gt;。AI 把我们从大量机械劳动中解放出来，让我们可以把更多时间花在真正需要人类判断的地方。这是一次升级的机会，抓住它的人会走得更远。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>用 AI 给故障复盘打分：质量审核自动化实践</title>
      <link>https://www.helight.info/blog/2026/0328-ai-postmortem-quality-review/</link>
      <pubDate>Sat, 28 Mar 2026 09:00:00 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0328-ai-postmortem-quality-review/</guid>
      <description>
        
        
        &lt;h2&gt;一、为什么复盘质量普遍不高&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一为什么复盘质量普遍不高&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e4%b8%ba%e4%bb%80%e4%b9%88%e5%a4%8d%e7%9b%98%e8%b4%a8%e9%87%8f%e6%99%ae%e9%81%8d%e4%b8%8d%e9%ab%98&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;每次线上故障之后，团队都会写复盘报告，列出&amp;quot;优化措施&amp;quot;。形式上看起来很完整，但仔细读下去，会发现大量这样的内容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;加强研发规范意识，避免类似问题再次发生&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;相关同学注意配置变更前做好充分测试&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;后续优化监控告警策略，提升感知能力&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些措施写了和没写没有区别。没有 Owner，没有截止时间，没有可验证的完成标准，更关键的是——&lt;strong&gt;和故障的根因没有直接关系&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;为什么会这样？根本原因是：&lt;strong&gt;评审标准不显式，执行靠经验和感觉&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;审核者知道这条措施&amp;quot;不够好&amp;quot;，但很难说清楚哪里不好、应该怎么改。被审核者不知道标准在哪，只能凭感觉写。久而久之，复盘变成了走流程，优化措施成了&amp;quot;填空题&amp;quot;。&lt;/p&gt;
&lt;h2&gt;二、9 条评审原则：让标准显式化&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二9-条评审原则让标准显式化&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c9-%e6%9d%a1%e8%af%84%e5%ae%a1%e5%8e%9f%e5%88%99%e8%ae%a9%e6%a0%87%e5%87%86%e6%98%be%e5%bc%8f%e5%8c%96&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;要解决这个问题，第一步是把评审标准显式化——用具体、可操作的规则替代模糊的&amp;quot;写得好不好&amp;quot;判断。&lt;/p&gt;
&lt;p&gt;我把复盘优化措施的质量评审拆成 9 条原则（P1～P9）：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;代码&lt;/th&gt;
					&lt;th&gt;原则&lt;/th&gt;
					&lt;th&gt;核心问题&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;P1&lt;/td&gt;
					&lt;td&gt;具体明确&lt;/td&gt;
					&lt;td&gt;有没有&amp;quot;加强/注意/优化/完善&amp;quot;等模糊词？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;P2&lt;/td&gt;
					&lt;td&gt;可执行&lt;/td&gt;
					&lt;td&gt;有没有明确动作 + 单一责任人 + 可判断完成的标准？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;P3&lt;/td&gt;
					&lt;td&gt;可验证&lt;/td&gt;
					&lt;td&gt;验收方式是否客观可查（文档/截图/CI结果）？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;P4&lt;/td&gt;
					&lt;td&gt;分类清晰&lt;/td&gt;
					&lt;td&gt;多条子措施是否按流程/技术/人员/监控归类？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;P5&lt;/td&gt;
					&lt;td&gt;时效性&lt;/td&gt;
					&lt;td&gt;是否有精确截止日期（精确到天）？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;P6&lt;/td&gt;
					&lt;td&gt;根因对应&lt;/td&gt;
					&lt;td&gt;整改措施能否直接切断根因链？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;P7&lt;/td&gt;
					&lt;td&gt;覆盖面&lt;/td&gt;
					&lt;td&gt;是否形成通用机制，而非只修了本次？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;P8&lt;/td&gt;
					&lt;td&gt;防复发机制&lt;/td&gt;
					&lt;td&gt;有没有卡点/门禁/自动化检测？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;P9&lt;/td&gt;
					&lt;td&gt;Owner 唯一&lt;/td&gt;
					&lt;td&gt;每条子措施只能有一个 Owner&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这 9 条原则中，最核心的是&lt;strong&gt;三角关系&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;根因对应（P6）× 可执行（P2）× 可验证（P3）&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;一条合格的优化措施，必须同时满足这三个条件：针对根因、有人负责能执行、完成后能验证。任何一条缺失，这个措施的实际价值就大打折扣。&lt;/p&gt;
&lt;h2&gt;三、自动化审核流程&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三自动化审核流程&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e8%87%aa%e5%8a%a8%e5%8c%96%e5%ae%a1%e6%a0%b8%e6%b5%81%e7%a8%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;有了显式的标准，下一步是自动化执行。整个流程分四个阶段：&lt;/p&gt;
&lt;h3&gt;3.1 数据提取&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;31-数据提取&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#31-%e6%95%b0%e6%8d%ae%e6%8f%90%e5%8f%96&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;从故障复盘 Excel 中提取结构化数据。每条故障记录包含四个关键字段：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;问题描述&lt;/strong&gt;：故障现象和影响范围&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;问题原因&lt;/strong&gt;：直接根因（P6 判断的核心依据）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;处理进展&lt;/strong&gt;：应急处置时间线（暴露的二次问题也要整改）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;优化措施&lt;/strong&gt;：审核目标&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python3 extract_from_excel.py --file postmortem.xlsx --sheet &lt;span class=&#34;m&#34;&gt;202603&lt;/span&gt; --output measures.json&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;3.2 规则预检&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;32-规则预检&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#32-%e8%a7%84%e5%88%99%e9%a2%84%e6%a3%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在 LLM 审核之前，先用规则引擎做自动预检，快速识别明显问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;P1 模糊词检测&lt;/strong&gt;：正则匹配&amp;quot;加强/注意/优化/完善/强化/落实&amp;quot;等词&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;P5 时间缺失检测&lt;/strong&gt;：判断是否有&amp;quot;YYYY-MM-DD&amp;quot;格式日期&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;P9 Owner 检测&lt;/strong&gt;：判断是否存在&amp;quot;团队/大家/相关同学&amp;quot;等多人表述&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;预检可以过滤掉 60%～70% 的明显不合格项，减少 LLM 的处理量，也让后续的深度审核更聚焦。&lt;/p&gt;
&lt;h3&gt;3.3 LLM 深度审核&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;33-llm-深度审核&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#33-llm-%e6%b7%b1%e5%ba%a6%e5%ae%a1%e6%a0%b8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;规则预检覆盖不了语义层面的问题，比如&amp;quot;整改措施和根因是否对应&amp;quot;（P6）、&amp;ldquo;覆盖面是否足够&amp;rdquo;（P7），这些需要理解上下文。&lt;/p&gt;
&lt;p&gt;LLM 审核的关键是&lt;strong&gt;建立正确的上下文&lt;/strong&gt;：先读问题描述和根因，再审核优化措施。&lt;/p&gt;
&lt;p&gt;以一个真实脱敏案例为例：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原始措施&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;研发同学加强变更规范意识，后续变更操作前做好充分测试验证。&lt;/p&gt;

&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;根因&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;配置项缺少格式校验，变更时未触发自动化测试流程。&lt;/p&gt;

&lt;/blockquote&gt;
&lt;p&gt;这条措施违反了 P1（模糊词&amp;quot;加强&amp;quot;）、P2（无 Owner、无截止日期）、P5（无日期）、&lt;strong&gt;P6（根因是缺少技术卡点，措施却是教育意识，根本没有对应）&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LLM 生成的改写建议&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;由 &lt;code&gt;&amp;lt;Owner&amp;gt;&lt;/code&gt; 在 &lt;code&gt;2026-04-15&lt;/code&gt; 前，为配置项变更接口增加格式校验逻辑，并在 CI 流水线中加入配置项变更的自动化测试门禁。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;完成标准：CI 门禁上线，历史配置项的格式校验覆盖率 ≥ 95%&lt;/li&gt;
&lt;li&gt;验收方式：提交 CI 配置变更 PR 链接 + 测试报告截图，由 &lt;code&gt;&amp;lt;技术 lead&amp;gt;&lt;/code&gt; 确认&lt;/li&gt;
&lt;li&gt;防复发：门禁阻断不合规变更，覆盖范围：全业务同类配置项&lt;/li&gt;
&lt;/ul&gt;

&lt;/blockquote&gt;
&lt;p&gt;改写建议不是&amp;quot;建议修改&amp;quot;，而是&lt;strong&gt;直接给出可复制替换的版本&lt;/strong&gt;，研发同学改一下 Owner 和日期就能用。&lt;/p&gt;
&lt;h3&gt;3.4 输出报告&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;34-输出报告&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#34-%e8%be%93%e5%87%ba%e6%8a%a5%e5%91%8a&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;最终生成 Excel 报告，包含：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每条措施的逐项 P1～P9 评分&lt;/li&gt;
&lt;li&gt;改写建议（可直接使用）&lt;/li&gt;
&lt;li&gt;统计摘要：不合格率、高频违反原则 Top3&lt;/li&gt;
&lt;li&gt;总体结论：通过 / 条件通过 / 退回修改&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;判定规则：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;总体结论&lt;/th&gt;
					&lt;th&gt;触发条件&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;✅ 通过&lt;/td&gt;
					&lt;td&gt;不合格率 &amp;lt; 10% 且无严重 P6 问题&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;⚠️ 条件通过&lt;/td&gt;
					&lt;td&gt;不合格率 10%～30%，或有 P6 问题&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;❌ 退回修改&lt;/td&gt;
					&lt;td&gt;不合格率 ≥ 30%，或任意一条同时违反 P1+P2+P5&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;四、实际效果&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四实际效果&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e5%ae%9e%e9%99%85%e6%95%88%e6%9e%9c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在实际使用中，这套方案有几个明显的价值：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 审核标准统一&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;不同审核者对同一条措施的判断结果趋于一致，减少了&amp;quot;凭感觉&amp;quot;的主观差异。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 改写建议质量高&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;原来人工审核只能说&amp;quot;这条不好，请修改&amp;quot;，现在直接给出改好的版本，修改成本大幅降低，研发同学更愿意认真对待。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 发现了 P6 是最高频违反原则&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;统计下来，根因对应（P6）是最常见的问题——大量措施在解决&amp;quot;表象&amp;quot;而非&amp;quot;根因&amp;quot;。这个发现本身就很有价值：说明团队在根因分析环节还不够深入，光治措施质量还不够，根因分析能力也需要提升。&lt;/p&gt;
&lt;h2&gt;五、延伸思考：复盘质量是工程文化的晴雨表&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五延伸思考复盘质量是工程文化的晴雨表&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e5%bb%b6%e4%bc%b8%e6%80%9d%e8%80%83%e5%a4%8d%e7%9b%98%e8%b4%a8%e9%87%8f%e6%98%af%e5%b7%a5%e7%a8%8b%e6%96%87%e5%8c%96%e7%9a%84%e6%99%b4%e9%9b%a8%e8%a1%a8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&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;AI 在这里扮演的角色，不是替代人做判断，而是&lt;strong&gt;让标准显式化、让执行自动化&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;标准显式化的价值在于：一旦评审规则变成文档和代码，所有人都知道&amp;quot;好的措施长什么样&amp;quot;，新人也能快速对齐。&lt;/p&gt;
&lt;p&gt;执行自动化的价值在于：人工审核是高重复劳动，容易疲劳、容易妥协。自动化不会累，不会因为&amp;quot;这个团队比较忙&amp;quot;就降低标准。&lt;/p&gt;
&lt;p&gt;最终目标不是让机器打分，而是&lt;strong&gt;让复盘真正有效&lt;/strong&gt;——每条优化措施都落地，每次故障都不白经历。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;这套方案目前作为 OpenClaw 的一个 Skill 在使用，输入故障复盘 Excel，几分钟内输出审核报告。如果你的团队也有类似的质量管理需求，思路是通用的：把专家经验提炼成结构化规则，用 LLM 处理语义层面的判断，用脚本处理格式和输出。&lt;/p&gt;
&lt;h2&gt;六、当前限制与未来方向&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;六当前限制与未来方向&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%ad%e5%bd%93%e5%89%8d%e9%99%90%e5%88%b6%e4%b8%8e%e6%9c%aa%e6%9d%a5%e6%96%b9%e5%90%91&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;目前这套方案的使用流程还有一定的手工成本：从系统中导出故障信息，让团队成员在企微在线文档里填写复盘内容，审核完成后再将在线文档导出成 Excel，最后交给 AI 做分析。&lt;/p&gt;
&lt;p&gt;这个&amp;quot;导出 → 分析&amp;quot;的中间环节，本质上是因为 &lt;strong&gt;AI 与企微在线文档之间还没有打通&lt;/strong&gt;。所有信息都在文档里，但 AI 只能处理导出后的 Excel 文件。&lt;/p&gt;
&lt;p&gt;如果未来 AI 能直接读取企微在线文档的内容，整个流程就可以进一步简化：团队填完复盘文档后，直接触发 AI 审核，无需任何导出操作。这不只是省了一个步骤，更重要的是&lt;strong&gt;把审核时机提前&lt;/strong&gt;——可以在复盘会议结束的当天就给出反馈，而不是等人工整理完 Excel 之后。&lt;/p&gt;
&lt;p&gt;这也是 AI 与企业内部系统深度集成的一个典型方向：不是替换现有工具，而是在现有工具之间搭桥，让数据流动起来，让质量反馈更及时。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>Skills 开发技巧 2：让大模型思考，让脚本执行</title>
      <link>https://www.helight.info/blog/2026/0324-skills-dev-tips/</link>
      <pubDate>Tue, 24 Mar 2026 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0324-skills-dev-tips/</guid>
      <description>
        
        
        &lt;p&gt;今天我集中开发了三个 Skills，分别是项目管理晨会汇总、站点证书监控与自动续签、博客自动发布。做完之后回头看，有一些开发模式上的心得值得总结——&lt;strong&gt;大模型负责思考，脚本负责执行&lt;/strong&gt;，这是我在这个过程中反复验证的核心理念。&lt;/p&gt;
&lt;h2&gt;一、三个真实案例，三份收益&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一三个真实案例三份收益&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e4%b8%89%e4%b8%aa%e7%9c%9f%e5%ae%9e%e6%a1%88%e4%be%8b%e4%b8%89%e4%bb%bd%e6%94%b6%e7%9b%8a&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 项目管理晨会汇总（pm-scrum）&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-项目管理晨会汇总pm-scrum&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e9%a1%b9%e7%9b%ae%e7%ae%a1%e7%90%86%e6%99%a8%e4%bc%9a%e6%b1%87%e6%80%bbpm-scrum&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这个 Skill 对接 TAPD，每天早上自动拉取当前迭代的需求、任务、风险，生成结构化日报发到企微。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;收益&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;以前每天晨会前要手动打开 TAPD，点进迭代看板，挨个确认哪些完成了、哪些逾期了、哪些没人认领，整理成消息发出去，10 分钟起步。现在一句话触发，30 秒出报告。&lt;/p&gt;
&lt;p&gt;更重要的是，&lt;strong&gt;风险识别变系统化了&lt;/strong&gt;。以前靠肉眼扫，容易漏；现在脚本按规则（R1～R7）遍历每一条需求和子任务，无负责人、无排期、逾期未完成，一条都跑不掉。今天实际跑下来，迭代2 的 11 个需求里发现了 11 条高风险 + 6 条中风险，这要靠人工发现整理，至少得看10分钟。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关键实现&lt;/strong&gt;：迭代判断这里我踩了个坑——最初脚本直接取第一条 &lt;code&gt;status=open&lt;/code&gt; 的迭代，结果拿到的是已经过期的迭代1（3月21日结束），数据完全错了。后来改成按日期范围判断：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fetch_iteration&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;wid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;today&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;date&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;today&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isoformat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;iters&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tapd_list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;iterations_get&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;workspace_id&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;open&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;limit&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 过滤：今天必须在迭代的起止日期范围内&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;active&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;it&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;it&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iters&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;it&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;startdate&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;today&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;it&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;enddate&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;active&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;active&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sort&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;lambda&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;startdate&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reverse&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;active&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# 无活跃迭代：返回特殊标记 + 候选列表，由 LLM 给出建议&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;_no_active&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;candidates&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这段逻辑由 LLM 一次写好，之后每次执行结果完全确定，不再因为 LLM 判断方式的变化而漂移。&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;2. 站点证书监控与自动续签（site-health-monitor）&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-站点证书监控与自动续签site-health-monitor&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e7%ab%99%e7%82%b9%e8%af%81%e4%b9%a6%e7%9b%91%e6%8e%a7%e4%b8%8e%e8%87%aa%e5%8a%a8%e7%bb%ad%e7%ad%besite-health-monitor&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这个 Skill 每天定时检测 6 个站点的可用性和 SSL 证书有效期，发现证书快过期时自动 SSH 登录远程机器，用 certbot + dns-tencentcloud 插件续签，然后 nginx reload。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;收益&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;今天跑了一次，发现 一个域名的证书只剩 5 天，已经触发了告警阈值（7天）。系统自动执行续签，整个过程：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;检测到证书预警（5天）
  → SSH 登录 IP:Port
  → sudo -s → export 腾讯云密钥
  → certbot certonly -a dns-tencentcloud -d 域名 
  → nginx -t → nginx -s reload
  → 证书更新&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;全程无人工干预，我是在看日志的时候才知道这件事发生了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关键实现&lt;/strong&gt;：续签这个流程如果让 LLM 直接执行，每次 SSH 命令的拼法、certbot 参数的组合都可能有细微差别，一旦某个参数不对证书就续不上。把它固化成脚本：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;renew_domain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ssh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;domain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secret_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;secret_key&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dry_run&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sudo -s -- sh -c &amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;export TENCENTCLOUD_SECRET_ID=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;secret_id&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;TENCENTCLOUD_SECRET_KEY=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;secret_key&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;; &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;certbot certonly -a dns-tencentcloud --agree-tos --non-interactive &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;-d &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;domain&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; -d www.&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;domain&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;rc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stdout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ssh_exec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ssh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cmd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dry_run&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dry_run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;RuntimeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;certbot 失败: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stdout&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;每次执行的命令完全一致，报错信息清晰，LLM 只需要读结果、判断成功还是失败。&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;3. 博客自动发布（blog-writer）&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-博客自动发布blog-writer&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-%e5%8d%9a%e5%ae%a2%e8%87%aa%e5%8a%a8%e5%8f%91%e5%b8%83blog-writer&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这个 Skill 负责博客从写作到上线的完整流程：生成文章骨架 → 写正文 → 生成 Banner 图 → Hugo 验证 → 提交 PR → 等待 merge → push Gitee → SSH 登录远程机器执行 &lt;code&gt;make&lt;/code&gt; 更新博客 → Playwright 截图验证首页。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;收益&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;以前发一篇博客：本地写 → hugo 验证 → git commit → push → 登服务器拉代码 → make → 打开浏览器看效果，每次 15-20 分钟，而且这么多步骤都需要在不断地切换工具来操作，繁琐麻烦，现在是可以一气呵成了。&lt;/p&gt;
&lt;p&gt;现在整个流程跑下来是全自动的，我只需要：①确认文章内容 ②merge PR。其他的由 Skill 完成，包括最后的截图验证——部署完自动打开浏览器截图发给我，眼见为实。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;关键实现&lt;/strong&gt;：部署这步，服务器上的博客目录归 root 所有，ubuntu 用户没有写权限。如果让 LLM 决定怎么切换用户，每次可能用 &lt;code&gt;sudo su&lt;/code&gt;、&lt;code&gt;sudo -i&lt;/code&gt;、&lt;code&gt;sudo -s&lt;/code&gt; 等不同方式，行为不稳定。固化到脚本：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;SSH_USER&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ubuntu&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;BLOG_DIR&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/data/www/blog&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;deploy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dry_run&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;rc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stdout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ssh_run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;sudo -s -- sh -c &amp;#39;cd &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BLOG_DIR&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &amp;amp;&amp;amp; make 2&amp;gt;&amp;amp;1&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;dry_run&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dry_run&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;RuntimeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;make 失败: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stdout&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2&gt;二、核心理念：为什么要「让脚本执行」&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二核心理念为什么要让脚本执行&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e6%a0%b8%e5%bf%83%e7%90%86%e5%bf%b5%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e8%ae%a9%e8%84%9a%e6%9c%ac%e6%89%a7%e8%a1%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;从上面三个案例可以看出两个共同点。&lt;/p&gt;
&lt;h3&gt;1. 不确定性收敛&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-不确定性收敛&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e4%b8%8d%e7%a1%ae%e5%ae%9a%e6%80%a7%e6%94%b6%e6%95%9b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;大模型的输出是概率采样，每次都有细微差异。用同样的 prompt 让它生成 curl 命令，今天可能是 &lt;code&gt;-H &amp;quot;Content-Type: application/json&amp;quot;&lt;/code&gt;，明天可能多个空格或者参数顺序不同，大多数时候没问题，但在关键执行路径上，这种不确定性是隐患。&lt;/p&gt;
&lt;p&gt;把执行逻辑写成脚本，LLM 的不确定性就被限制在「生成代码」这一步。代码一旦写好，每次执行路径完全确定：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;LLM（不确定）→ 生成脚本（一次）→ 脚本执行（永远确定）&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;而不是：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;LLM（不确定）→ 执行命令（每次都可能不同）&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;2. Token 消耗优化&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-token-消耗优化&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-token-%e6%b6%88%e8%80%97%e4%bc%98%e5%8c%96&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;脚本执行不消耗 Token，只有 LLM 处理文本才消耗。&lt;/p&gt;
&lt;p&gt;以项目管理报告为例，如果让 LLM 直接用工具一条条拉 TAPD 数据、处理 JSON、过滤风险项，全程 LLM 参与，单次消耗 8000+ Token。&lt;/p&gt;
&lt;p&gt;改成脚本后：脚本负责数据拉取和处理，LLM 只读最终结果生成报告，单次降到 2000 以内，降幅超过 75%。&lt;/p&gt;
&lt;p&gt;数据处理、格式转换、条件判断，这些都是「确定性工作」，没有理由让 LLM 参与。&lt;/p&gt;
&lt;h3&gt;3. 只告诉大模型它不知道的&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-只告诉大模型它不知道的&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-%e5%8f%aa%e5%91%8a%e8%af%89%e5%a4%a7%e6%a8%a1%e5%9e%8b%e5%ae%83%e4%b8%8d%e7%9f%a5%e9%81%93%e7%9a%84&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是我在写 SKILL.md（技能说明文档）时总结出的另一个原则。&lt;/p&gt;
&lt;p&gt;最开始我习惯在 SKILL.md 里写得很详细，把所有背景知识都加进去，结果文档越来越长，每次触发 Skill 都要把一大段已知知识塞进上下文，Token 消耗居高不下，LLM 反而容易在细枝末节上绕圈子。&lt;/p&gt;
&lt;p&gt;后来我意识到：&lt;strong&gt;大模型对通用知识已经有很强的基础，不需要你教它怎么写 Python、怎么用 SSH、怎么解析 JSON。它真正需要的，是它无法凭通用知识推断的部分&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你的项目的具体路径（&lt;code&gt;/data/www/blog&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;你的服务器的端口（&lt;code&gt;2330&lt;/code&gt; 而不是默认的 &lt;code&gt;22&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;你的业务规则（证书剩余 7 天触发告警，不是 30 天也不是 3 天）&lt;/li&gt;
&lt;li&gt;你踩过的坑（&lt;code&gt;sudo -s&lt;/code&gt; 而不是 &lt;code&gt;sudo su&lt;/code&gt;，因为目录归 root 所有）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些是大模型无法从互联网训练数据里学到的，必须显式告诉它。而「Python 怎么读文件」、「certbot 的基本用法」这类通用知识，写进 SKILL.md 纯粹是浪费 Token。&lt;/p&gt;
&lt;p&gt;一个简单的判断标准：&lt;strong&gt;如果这条信息在 Stack Overflow 上能搜到，就不用写；如果只存在于你的系统或你的决策里，就必须写。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这个原则用在 Skill 开发上，让我的 SKILL.md 从动辄 500 行压缩到 100 行以内，触发时的上下文更小，LLM 更聚焦，执行更准确。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;反例：脱敏规则&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;今天有一个很典型的反例，印证了这个原则。&lt;/p&gt;
&lt;p&gt;我在给 blog-writer Skill 增加「敏感信息脱敏」功能时，第一反应是把所有脱敏类型整理成一张详细的表格写进 SKILL.md——IP 地址用 &lt;code&gt;&amp;lt;YOUR_IP&amp;gt;&lt;/code&gt; 替换、Token 用 &lt;code&gt;&amp;lt;API_KEY&amp;gt;&lt;/code&gt; 替换、数据库连接串用 &lt;code&gt;&amp;lt;DSN&amp;gt;&lt;/code&gt; 替换……洋洋洒洒列了十几行。&lt;/p&gt;
&lt;p&gt;写完之后想了想：&lt;strong&gt;这些信息大模型早就知道&lt;/strong&gt;。IP、Token、密码、API Key 是敏感信息，是业界常识，Stack Overflow 上随便一篇安全文章都会提到。我把它写进 SKILL.md，不过是在用大模型自己的知识教大模型，纯属浪费 Token。&lt;/p&gt;
&lt;p&gt;最终版本是一句话：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;生成博客正文时，对所有敏感信息进行脱敏处理，替换为语义明确的占位符。&lt;/p&gt;

&lt;/blockquote&gt;
&lt;p&gt;大模型看到这句话，凭通用知识就能正确执行——该脱敏什么、怎么替换，它都清楚。十几行表格能做到的事，一句话就够了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;写 SKILL.md 的核心原则&lt;/strong&gt;：只写大模型不知道的（你的系统配置、你的业务规则、你踩过的坑），其余的信任它的通用能力。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;三、执行循环：自愈式开发模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三执行循环自愈式开发模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e6%89%a7%e8%a1%8c%e5%be%aa%e7%8e%af%e8%87%aa%e6%84%88%e5%bc%8f%e5%bc%80%e5%8f%91%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;基于这个理念，我现在写 Skill 的标准流程是：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;Task      明确目标
  ↓
Plan      LLM 规划步骤，设计数据流
  ↓
Code      LLM 生成 Python 脚本
  ↓
Execute   脚本执行，返回结果或报错
  ↓
Feedback  LLM 分析输出，报错则定位修复，重回 Code&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Feedback 这步是关键。脚本非零退出不是终点，而是 LLM 的信号：「出错了，看 stderr 修。」这个自愈循环让 Skill 在遇到环境变化时能自己恢复，而不是崩掉让人工干预。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plan&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;       &lt;span class=&#34;c1&#34;&gt;# LLM 读取此输出做 Feedback&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;Exception&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ERROR: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;         &lt;span class=&#34;c1&#34;&gt;# 非零退出码 → 触发 LLM 自愈循环&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;四、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;三个 Skill 开发下来，这套模式给我的最直接感受：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;稳&lt;/strong&gt;：关键路径行为确定，不会因为 LLM 今天&amp;quot;心情不好&amp;quot;而执行出不同结果&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;省&lt;/strong&gt;：Token 消耗降了一半以上，对话更快，成本更低&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;好调试&lt;/strong&gt;：脚本可以独立运行，加日志、加单测，不用把整个 Agent 跑起来验证一个逻辑&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;大模型的脑子很灵，但需要一双确定的手。脚本就是那双手。&lt;/p&gt;
&lt;p&gt;在 AI Agent 开发中，这个分工越清晰，系统越健壮。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>OpenClaw Skills 优化实践：用 Progressive Disclosure 原则压缩 AI Agent 的上下文开销</title>
      <link>https://www.helight.info/blog/2026/0312-openclaw-skill-optimize/</link>
      <pubDate>Thu, 12 Mar 2026 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0312-openclaw-skill-optimize/</guid>
      <description>
        
        
        &lt;p&gt;最近在用 OpenClaw（一款基于 Claude 的 AI Agent 工具）为自己的工作流开发了几个自动化 Skill，跑了一段时间后发现一个问题：随着 Skill 越写越详细，响应质量反而开始下降，有时候 Agent 会忽略某些关键步骤，或者混淆不同 Skill 的指令。&lt;/p&gt;
&lt;p&gt;排查一圈后发现根本原因：&lt;strong&gt;SKILL.md 写得太长，把无关细节都塞进了上下文窗口，产生了认知噪音。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这篇文章记录我把三个 Skill 从&amp;quot;事无巨细&amp;quot;优化为&amp;quot;按需加载&amp;quot;的全过程，以及背后的设计原理。&lt;/p&gt;
&lt;h2&gt;一、OpenClaw Skill 是什么&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一openclaw-skill-是什么&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80openclaw-skill-%e6%98%af%e4%bb%80%e4%b9%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;OpenClaw 的 Skill 系统可以理解为&amp;quot;给 AI Agent 的专项说明书&amp;quot;。每个 Skill 是一个目录，包含：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;skill-name/
├── SKILL.md          # 核心指令（必须）
├── scripts/          # 可执行脚本
├── references/       # 参考文档（按需加载）
└── assets/           # 模板/图片等资产&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Agent 在每次对话时，会把所有 Skill 的 &lt;strong&gt;frontmatter&lt;/strong&gt;（name + description，约 100 词）常驻在上下文里。当用户的请求命中某个 Skill 时，才加载它的 SKILL.md 正文。&lt;code&gt;references/&lt;/code&gt; 里的文件则由 Agent 在需要时自行读取，不会自动进入上下文。&lt;/p&gt;
&lt;p&gt;这个&amp;quot;三级加载&amp;quot;机制就是 &lt;strong&gt;Progressive Disclosure（渐进式披露）&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;Level 1：Metadata（name &amp;#43; description）  → 始终在上下文，~100 词
Level 2：SKILL.md body                   → Skill 触发时加载，建议 &amp;lt;500 行
Level 3：references/ 文件               → Agent 按需读取，无大小限制&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;二、问题：Skills 越写越臃肿&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二问题skills-越写越臃肿&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e9%97%ae%e9%a2%98skills-%e8%b6%8a%e5%86%99%e8%b6%8a%e8%87%83%e8%82%bf&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我开发的三个主要 Skill：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Skill&lt;/th&gt;
					&lt;th&gt;功能&lt;/th&gt;
					&lt;th&gt;优化前 SKILL.md 行数&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;tech-news-fetcher&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;抓取10个 RSS 源生成科技新闻日报&lt;/td&gt;
					&lt;td&gt;76 行&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;blog-writer&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;生成 Hugo 博客文章并提交 PR&lt;/td&gt;
					&lt;td&gt;120 行&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;file-manager&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;分析和整理开发项目文件结构&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;531 行&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;file-manager&lt;/code&gt; 是重灾区。531 行里混杂着：常见场景举例、最佳实践清单、故障排查手册、高级用法、批量处理脚本……全部堆在 SKILL.md，一旦触发就全部进入上下文。&lt;/p&gt;
&lt;p&gt;另外发现几个具体问题：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. frontmatter description 信息失真&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tech-news-fetcher&lt;/code&gt; 的 description 里写着「CSDN」作为新闻源，但早已替换为 IT之家——触发词和实际行为对不上，影响 Agent 的 Skill 选择判断。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 细节与流程混在一起&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;blog-writer&lt;/code&gt; 的 SKILL.md 里，Step 2.5（生成 Banner）这一节嵌入了大段图标映射规则，像这样：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 机器人 → AI / Agent / LLM 主题
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 盾牌 → 安全 / 风险主题
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 放大镜 → 搜索 / 分析主题
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 灯泡 → 创新 / 思考主题
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- 齿轮 → 工程 / 架构主题&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这些细节在每次博客流程中几乎不需要查阅——它们本应是脚本内部逻辑，放进 SKILL.md 只会增加噪音。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. 角色定位写死了个人信息&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;blog-writer&lt;/code&gt; 的 description 里硬编码了 &amp;ldquo;helight&amp;rdquo;，技术上这个 Skill 若被分享出去，触发逻辑会产生歧义。&lt;/p&gt;
&lt;h2&gt;三、优化原则：只放&amp;quot;不在这里就找不到&amp;quot;的内容&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三优化原则只放不在这里就找不到的内容&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e4%bc%98%e5%8c%96%e5%8e%9f%e5%88%99%e5%8f%aa%e6%94%be%e4%b8%8d%e5%9c%a8%e8%bf%99%e9%87%8c%e5%b0%b1%e6%89%be%e4%b8%8d%e5%88%b0%e7%9a%84%e5%86%85%e5%ae%b9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;新版 skill-creator 的核心指导思想总结成一句话：&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Default assumption: Claude is already very smart. Only add context Claude doesn&amp;rsquo;t already have.&lt;/strong&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;p&gt;每加一行内容，都要问自己：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;这件事 Claude 不查这里也知道吗？&amp;rdquo; → 如果是，删掉&lt;/li&gt;
&lt;li&gt;&amp;ldquo;这个细节只在特定场景下用到吗？&amp;rdquo; → 如果是，移到 &lt;code&gt;references/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;这是步骤（How）还是背景（Why/What）？&amp;rdquo; → 步骤留 SKILL.md，背景移 references&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;三层内容分配原则&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三层内容分配原则&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e5%b1%82%e5%86%85%e5%ae%b9%e5%88%86%e9%85%8d%e5%8e%9f%e5%88%99&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;SKILL.md body（&amp;lt;500行）：
  ✅ 核心工作流（每次执行都要看的步骤）
  ✅ 关键命令（带最常用参数）
  ✅ 安全边界（必须注意的约束）
  ❌ FAQ 和常见问题
  ❌ 常见场景举例
  ❌ 细节参数说明

references/（按需加载）：
  ✅ 参数详细说明
  ✅ 常见场景与最佳实践
  ✅ 故障排查手册
  ✅ 领域模板/规则文档&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;四、三个 Skill 的实际改造&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四三个-skill-的实际改造&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e4%b8%89%e4%b8%aa-skill-%e7%9a%84%e5%ae%9e%e9%99%85%e6%94%b9%e9%80%a0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;4.1 tech-news-fetcher&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;41-tech-news-fetcher&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#41-tech-news-fetcher&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;h4&gt;问题分析&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;问题分析&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;这个 Skill 的问题看起来不大，但实际上有两处隐性错误会悄悄影响 Agent 的判断质量。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一个问题：description 信息过期。&lt;/strong&gt; 原版 description 里明确列出了10个新闻源，其中包括「CSDN」。但在开发早期，CSDN 的 RSS 接口返回 HTTP 401，已经替换为「IT之家」。description 是 Agent 判断&amp;quot;这个 Skill 能干什么&amp;quot;的唯一依据——如果 description 和实际行为不一致，Agent 在推理时会产生一个微妙的认知偏差：它以为自己会抓 CSDN，结果没有，但又不知道原因。&lt;/p&gt;
&lt;p&gt;更深层的问题是：description 里把10个来源全部罗列出来，显得像是一份&amp;quot;功能清单&amp;quot;而非&amp;quot;触发说明&amp;quot;。触发一个 Skill 的关键信息应该是&lt;strong&gt;什么场景下用它&lt;/strong&gt;，而不是它内部包含哪些资源。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二个问题：主要用法没有体现在 SKILL.md 里。&lt;/strong&gt; 随着使用深入，Hugo Blog 模式已经成为主要用途（直接生成博客内容并提交 PR），但原版 SKILL.md 只写了 Obsidian 模式。Agent 每次执行时，要么需要用户额外说明，要么凭&amp;quot;记忆&amp;quot;推断——这两种情况都不可靠。&lt;/p&gt;
&lt;h4&gt;改造内容&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;改造内容&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%94%b9%e9%80%a0%e5%86%85%e5%ae%b9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;description 删掉来源清单，改为场景触发词为主，并加入&amp;quot;生成今日新闻博客&amp;quot;这类 Hugo 触发词&lt;/li&gt;
&lt;li&gt;SKILL.md 重构为&amp;quot;Hugo 模式优先，Obsidian 模式次之&amp;quot;，主用法第一眼就能看到&lt;/li&gt;
&lt;li&gt;FAQ（某些源抓不到怎么办、图片慢怎么办）和反封禁机制细节（UA 轮换逻辑、请求间隔参数）→ 新建 &lt;code&gt;references/usage.md&lt;/code&gt;，这些是偶发场景才需要查的内容&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## 主要用法（Hugo Blog 模式）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python3 scripts/fetch_news.py --hugo-blog /projects/hxblog --date 2026-03-10
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## Obsidian 模式
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python3 scripts/fetch_news.py --output-dir ~/Documents/Obsidian/科技新闻&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;结果：&lt;/strong&gt; 76 行 → 40 行，↓47%。更重要的是，description 和实际行为重新对齐，Agent 的 Skill 选择判断准确率会提升。&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;4.2 blog-writer&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;42-blog-writer&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#42-blog-writer&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;h4&gt;问题分析&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;问题分析-1&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90-1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;&lt;code&gt;blog-writer&lt;/code&gt; 的问题集中在两个层面：&lt;strong&gt;信息结构错位&lt;/strong&gt;和&lt;strong&gt;可复用性缺陷&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一个问题：步骤中嵌入了规格说明。&lt;/strong&gt; Step 2.5（生成 Banner）这一步写成这样：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;**Banner 设计规范（312×240）：**
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 手绘 sketch 风，米白底，炭笔线条
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 左侧：标题 + 副标题 + 关键词彩色胶囊
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 右侧：1~2 个手绘卡通图标（自动根据关键词选取）
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 机器人 → AI / Agent / LLM 主题
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 盾牌 → 安全 / 风险主题
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 放大镜 → 搜索 / 分析主题
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 灯泡 → 创新 / 思考主题
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; 齿轮 → 工程 / 架构主题
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;- 多留白，不堆砌元素&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这段内容的性质是&lt;strong&gt;脚本规格说明&lt;/strong&gt;，描述的是 &lt;code&gt;gen_banner.py&lt;/code&gt; 的内部设计逻辑，而不是&amp;quot;怎么执行这一步&amp;quot;的操作指令。Agent 每次执行博客生成流程，都会把这段塞进上下文——但实际上，除非用户要求定制 banner 风格，否则这段内容从来不会被用到。&lt;strong&gt;每次白白占用几十个 token，换来的是零收益。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二个问题：description 里硬编码了个人信息。&lt;/strong&gt; 原版 description 写的是&amp;quot;帮助 helight 写技术博客文章&amp;quot;。这在功能上没问题，但一旦把这个 Skill 分享给其他人，触发逻辑就会歧义：Agent 会认为这个 Skill 是专属于 helight 的，在其他用户的语境下可能不触发，或者触发后产生奇怪的行为（比如在文章里自动填写 helight 的信息）。好的 Skill 应该在 description 里描述&lt;strong&gt;任务类型&lt;/strong&gt;，不应该绑定具体的使用者身份。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三个问题：流程有缺漏。&lt;/strong&gt; PR merge 后需要同步推送到 Gitee，但原版 Step 5 没有这一步。这不是&amp;quot;细节问题&amp;quot;，而是实际执行时每次都要额外补一条命令——说明 SKILL.md 的工作流描述与实际操作存在断层。&lt;/p&gt;
&lt;h4&gt;改造内容&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;改造内容-1&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%94%b9%e9%80%a0%e5%86%85%e5%ae%b9-1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;description 改为通用表述：&amp;ldquo;帮助写技术博客文章并提交到 Hugo 博客仓库&amp;rdquo;，去掉 &amp;ldquo;helight&amp;rdquo; 的绑定&lt;/li&gt;
&lt;li&gt;Banner 规格说明（尺寸、图标映射、配色逻辑）→ 新建 &lt;code&gt;references/banner-spec.md&lt;/code&gt;；Step 2.5 只保留执行命令&lt;/li&gt;
&lt;li&gt;Step 5 补充 &lt;code&gt;git push gitee main&lt;/code&gt;，流程与实际操作完全对齐&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;结果：&lt;/strong&gt; 120 行 → 60 行，↓50%。更重要的是，Skill 的可复用性提升，流程不再有缺漏。&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;4.3 file-manager&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;43-file-manager&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#43-file-manager&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;h4&gt;问题分析&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;问题分析-2&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%97%ae%e9%a2%98%e5%88%86%e6%9e%90-2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;这是三个 Skill 里问题最严重的，也是最典型的反面教材——&lt;strong&gt;把 Skill 写成了用户手册&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;531 行的 SKILL.md 包含了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;四步工作流（这是必要的）&lt;/li&gt;
&lt;li&gt;每步详细说明，包括&amp;quot;What it does&amp;quot;逐条列举（大量冗余）&lt;/li&gt;
&lt;li&gt;四个典型使用场景，每个场景都展开成完整的操作步骤（典型的防御性写作）&lt;/li&gt;
&lt;li&gt;最佳实践清单：DO / DON&amp;rsquo;T 各5条（这是给人读的）&lt;/li&gt;
&lt;li&gt;故障排查：4类问题 × 详细解决方案（偶发场景，不该常驻上下文）&lt;/li&gt;
&lt;li&gt;高级用法：自定义配置、批量处理脚本（极低频需求）&lt;/li&gt;
&lt;li&gt;限制说明：6条已知局限（这是写给读者看的，不是 Agent 执行时需要的）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;根本问题是：写这个 Skill 的时候，假设的受众是&amp;quot;人类用户在读文档&amp;quot;，而不是&amp;quot;AI Agent 在执行任务&amp;quot;。&lt;/strong&gt; 两者的信息需求截然不同：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;人类读文档：需要背景、需要 Why、需要举例、需要边界说明，越完整越好&lt;/li&gt;
&lt;li&gt;AI Agent 执行任务：只需要 How、只需要当前步骤、需要约束条件，越精简越好&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;防御性写法（&amp;ldquo;万一用户问到场景X，这里有答案&amp;rdquo;）在人类文档里是美德，在 AI Skill 里是负担——因为 Agent 在处理 &lt;code&gt;file-manager&lt;/code&gt; 相关请求时，会把全部 531 行一次性加载进上下文，不管当前任务用不用得到场景X的内容。&lt;/p&gt;
&lt;p&gt;以&amp;quot;最佳实践&amp;quot;这节为例，原版是这样的：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; ✅ DO: Always use dry-run first
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; ✅ DO: Create backups before major changes
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; ✅ DO: Commit to Git before reorganizing
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; ✅ DO: Review reports before executing
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; ✅ DO: Test project functionality after changes
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; ❌ DON&amp;#39;T: Skip dry-run mode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; ❌ DON&amp;#39;T: Delete backups immediately
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这10条里，有效信息只有两条核心约束（先 dry-run、先备份），其余都是这两条的变体或推论。Agent 其实完全能从&amp;quot;先 dry-run、先备份&amp;quot;推导出后面8条——重复写出来只是在消耗上下文配额。&lt;/p&gt;
&lt;h4&gt;改造内容&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;改造内容-2&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%94%b9%e9%80%a0%e5%86%85%e5%ae%b9-2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;核心原则：每一行 SKILL.md 都必须是&amp;quot;执行时必看&amp;quot;的内容。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;移出到 &lt;code&gt;references/scenarios.md&lt;/code&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;保留在 SKILL.md：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;四步工作流表格（执行时必看，决策入口）&lt;/li&gt;
&lt;li&gt;每步一条核心命令（执行时必须知道）&lt;/li&gt;
&lt;li&gt;5 条安全规则（执行时必须遵守的约束）&lt;/li&gt;
&lt;li&gt;4 条故障排查（一行一条，精简到只有原因+解法）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;重构后核心部分：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## Workflow
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| Step | When to use          | Script               |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;|------|---------------------|----------------------|
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| 1. Analyze  | 首次/变更前  | file_analyzer.py     |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| 2. Plan     | 预览目标结构 | structure_planner.py |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| 3. Organize | 执行迁移     | file_organizer.py    |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| 4. Clean up | 清理冗余     | cleanup_manager.py   |&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;四步、四个脚本、决策标准，一目了然。需要了解某步骤的典型场景？读 &lt;code&gt;references/scenarios.md&lt;/code&gt;。需要知道清理规则的细节？读 &lt;code&gt;references/cleanup_rules.md&lt;/code&gt;。这些文件只在真正需要时才被加载。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;结果：&lt;/strong&gt; 531 行 → 87 行，↓&lt;strong&gt;84%&lt;/strong&gt;。上下文开销减少了五分之四，而实际执行能力没有任何损失——因为所有细节都在 references 里待命。&lt;/p&gt;
&lt;h2&gt;五、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这次优化让我重新理解了&amp;quot;给 AI 写文档&amp;quot;和&amp;quot;给人写文档&amp;quot;的本质区别：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;给人写文档&lt;/strong&gt;：越全越好，用户可以跳读，信息冗余有益无害。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;给 AI 写文档&lt;/strong&gt;：越精越好，上下文窗口是共享资源，每一行都有成本。塞进去的信息不是&amp;quot;备用知识&amp;quot;，而是会参与每次推理的&amp;quot;噪音候选&amp;quot;。&lt;/p&gt;
&lt;p&gt;Progressive Disclosure 原则在 AI 场景里格外重要——不是因为 AI 读不懂复杂文档，而是因为&lt;strong&gt;加载了不需要的内容会降低需要的内容的权重&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;三个 Skill 优化后的整体效果：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Skill&lt;/th&gt;
					&lt;th&gt;优化前&lt;/th&gt;
					&lt;th&gt;优化后&lt;/th&gt;
					&lt;th&gt;压缩率&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;tech-news-fetcher&lt;/td&gt;
					&lt;td&gt;76 行&lt;/td&gt;
					&lt;td&gt;40 行&lt;/td&gt;
					&lt;td&gt;↓47%&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;blog-writer&lt;/td&gt;
					&lt;td&gt;120 行&lt;/td&gt;
					&lt;td&gt;60 行&lt;/td&gt;
					&lt;td&gt;↓50%&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;file-manager&lt;/td&gt;
					&lt;td&gt;531 行&lt;/td&gt;
					&lt;td&gt;87 行&lt;/td&gt;
					&lt;td&gt;↓84%&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;下一步计划把 references 文件也做结构化索引，让 Agent 能更精准地判断&amp;quot;什么情况下读哪个文件&amp;quot;，进一步减少不必要的文件加载。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>OpenClaw 火爆背后的冷思考：AI Agent 工具的能力边界与使用门槛</title>
      <link>https://www.helight.info/blog/2026/0311-openclaw-reflection/</link>
      <pubDate>Wed, 11 Mar 2026 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0311-openclaw-reflection/</guid>
      <description>
        
        
        &lt;p&gt;最近一段时间，OpenClaw（也叫&amp;quot;小龙虾&amp;quot;）在技术圈里掀起了不小的浪花。朋友圈、技术群、各大社区里时不时就能看到&amp;quot;OpenClaw 帮我自动干了某某事&amp;quot;之类的帖子，隐隐有一种&amp;quot;AI 要取代程序员了&amp;quot;的氛围在蔓延。我自己也用了一段时间，做了不少有趣的实验，但用得越多，反而越有一些疑惑和冷静的思考想分享出来。&lt;/p&gt;
&lt;h2&gt;一、OpenClaw 为什么火了？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一openclaw-为什么火了&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80openclaw-%e4%b8%ba%e4%bb%80%e4%b9%88%e7%81%ab%e4%ba%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;OpenClaw 是一个基于大语言模型的 AI Agent 工具平台，核心能力是通过自然语言指令，让 AI 自主规划并执行多步任务——不只是&amp;quot;回答问题&amp;quot;，而是真的&amp;quot;去做事&amp;quot;：读文件、写代码、调接口、跑脚本、提交 PR……&lt;/p&gt;
&lt;p&gt;它火起来的原因，我觉得有几个关键点：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 门槛感知极低&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;打开对话框，说一句&amp;quot;帮我每天抓取科技新闻生成博客&amp;quot;，它就开始干了。对于不熟悉编程的人来说，这种体验是颠覆性的——以前要找工程师开发好几天的东西，现在几句话就能跑起来。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 能力展示效果好&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Agent 执行任务的过程是可见的：它会一步步告诉你它在干什么，调了哪个 API，写了什么代码，遇到了什么报错又是怎么修的。这种&amp;quot;边想边干&amp;quot;的透明感，比传统工具的黑盒体验好很多，容易让人产生&amp;quot;这真的很智能&amp;quot;的感觉。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Skills 生态让能力可扩展&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;OpenClaw 支持 Skill 插件，社区里已经有了搜索、新闻、天气、代码执行等各种 Skill，确实能做相当多的事情。&lt;/p&gt;
&lt;p&gt;但正因为这些亮点，大家的期待值也被拉得很高——而现实往往比想象中复杂。&lt;/p&gt;
&lt;h2&gt;二、我的实际使用案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二我的实际使用案例&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e6%88%91%e7%9a%84%e5%ae%9e%e9%99%85%e4%bd%bf%e7%94%a8%e6%a1%88%e4%be%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我最近几天高强度用了一下 OpenClaw，做了几件具体的事，来分享一下真实体验。&lt;/p&gt;
&lt;h3&gt;案例一：每日科技新闻自动化 Pipeline&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;案例一每日科技新闻自动化-pipeline&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%a1%88%e4%be%8b%e4%b8%80%e6%af%8f%e6%97%a5%e7%a7%91%e6%8a%80%e6%96%b0%e9%97%bb%e8%87%aa%e5%8a%a8%e5%8c%96-pipeline&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是我折腾时间最长的一个任务。需求是：每天自动从 TechCrunch、The Verge、36氪等 10 个 RSS 源抓取新闻，翻译英文内容，生成带 banner 图的 Hugo 博客文章，并以 PR 形式提交到 GitHub。&lt;/p&gt;
&lt;p&gt;整个过程 OpenClaw 确实帮我完成了——但这里有几个细节值得说：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;调试过程并不轻松&lt;/strong&gt;：中间经历了日期时区偏差导致海外文章 0 条、CSDN 源返回 401 被替换、SSL 证书错误跳过、&lt;code&gt;extract_first_image&lt;/code&gt; 函数被意外删除等至少 7 个问题，每一个都需要我能看懂错误信息并给出正确的方向。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;翻译质量需要人工判断&lt;/strong&gt;：用的 MyMemory 免费 API，&amp;ldquo;Yann LeCun&amp;rsquo;s AMI Labs raises $1.03 billion&amp;quot;翻译成&amp;quot;Yann LeCun的AMI Labs筹集了$ 10.3亿&amp;rdquo;，基本可用，但偶尔有语序问题，我需要能识别出来。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;图片生成需要审美判断&lt;/strong&gt;：banner 图的字体、颜色、布局，AI 生成的初稿说实话差强人意，我反复描述需求才调整到可接受的程度。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;结论&lt;/strong&gt;：这个任务最终完成了，但我全程参与了几乎每一个决策点，花了小半天天。如果换一个不懂 Python / RSS / Hugo / Git 的人来操作，大概率会在某个步骤卡死。&lt;/p&gt;
&lt;h3&gt;案例二：开发 blog-writer Skill&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;案例二开发-blog-writer-skill&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%a1%88%e4%be%8b%e4%ba%8c%e5%bc%80%e5%8f%91-blog-writer-skill&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;让 OpenClaw 帮我开发一个&amp;quot;博客写作辅助 Skill&amp;quot;，能生成符合我博客风格的文章草稿并自动提交 PR。&lt;/p&gt;
&lt;p&gt;这个案例相对顺利，因为需求描述清晰，参考资料（现有博客文章格式）唾手可得。但我仍然需要：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;明确告诉它我的 front matter 格式是什么样的&lt;/li&gt;
&lt;li&gt;提供现有文章作为风格参考&lt;/li&gt;
&lt;li&gt;审查每个脚本逻辑是否合理（&lt;code&gt;init_post.py&lt;/code&gt; 和 &lt;code&gt;submit_pr.py&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI 帮我省去了大量重复性的代码编写，但它无法凭空&amp;quot;知道&amp;quot;我的个人博客规范——这些知识必须由我来提供和校验。&lt;/p&gt;
&lt;h3&gt;案例三：设置每日定时任务&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;案例三设置每日定时任务&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%a1%88%e4%be%8b%e4%b8%89%e8%ae%be%e7%bd%ae%e6%af%8f%e6%97%a5%e5%ae%9a%e6%97%b6%e4%bb%bb%e5%8a%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;让它每天早上 9:40 自动生成昨日工作日记。这个需求本身并不复杂，但设置 cron job 的过程中，我需要：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;了解 OpenClaw 的 cron payload 格式（&lt;code&gt;agentTurn&lt;/code&gt; vs &lt;code&gt;systemEvent&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;知道 isolated session 和 main session 的区别&lt;/li&gt;
&lt;li&gt;确认时区设置对不对&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些都是需要阅读文档或有使用经验才能掌握的细节，完全不是&amp;quot;说一句话就搞定&amp;quot;。&lt;/p&gt;
&lt;h2&gt;三、OpenClaw 的真实能力边界&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三openclaw-的真实能力边界&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89openclaw-%e7%9a%84%e7%9c%9f%e5%ae%9e%e8%83%bd%e5%8a%9b%e8%be%b9%e7%95%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;用了这些案例之后，我有几个比较清醒的认识：&lt;/p&gt;
&lt;h3&gt;1. 安全边界比你想象的更保守&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-安全边界比你想象的更保守&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e5%ae%89%e5%85%a8%e8%be%b9%e7%95%8c%e6%af%94%e4%bd%a0%e6%83%b3%e8%b1%a1%e7%9a%84%e6%9b%b4%e4%bf%9d%e5%ae%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;OpenClaw 对涉及敏感操作有明确的限制：删除操作要确认、外部发送要确认、秘钥信息不能乱存。这是好事，但也意味着它并不是&amp;quot;无所不为&amp;quot;的全能工具。你的 GitHub Token、数据库密码这些东西，它会明确提示风险，不会帮你绕过安全机制。&lt;/p&gt;
&lt;p&gt;而且 OpenClaw 运行在容器环境里，网络访问受限，很多内网资源、私有 API 天然就访问不到。&lt;/p&gt;
&lt;h3&gt;2. 执行能力依赖于任务的可描述性&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-执行能力依赖于任务的可描述性&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e6%89%a7%e8%a1%8c%e8%83%bd%e5%8a%9b%e4%be%9d%e8%b5%96%e4%ba%8e%e4%bb%bb%e5%8a%a1%e7%9a%84%e5%8f%af%e6%8f%8f%e8%bf%b0%e6%80%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;AI Agent 做得好的事情，本质上是&amp;quot;可以被精确描述成步骤&amp;quot;的事情：抓 RSS → 过滤 → 翻译 → 写文件 → git push，每一步都有明确的输入输出。&lt;/p&gt;
&lt;p&gt;但如果你的需求是&amp;quot;帮我优化这段业务逻辑&amp;quot;或者&amp;quot;帮我设计这个系统的架构&amp;quot;，它能给出建议，但执行层面的判断仍然依赖你的专业能力。&lt;/p&gt;
&lt;h3&gt;3. 调试和纠错需要专业背景&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-调试和纠错需要专业背景&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-%e8%b0%83%e8%af%95%e5%92%8c%e7%ba%a0%e9%94%99%e9%9c%80%e8%a6%81%e4%b8%93%e4%b8%9a%e8%83%8c%e6%99%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是我感触最深的一点。AI 在执行过程中会报错、会走弯路，这很正常。但是否能识别出&amp;quot;这个错误方向走错了&amp;quot;、&amp;ldquo;这个方案有隐患&amp;rdquo;，需要操作者有足够的技术背景。&lt;/p&gt;
&lt;p&gt;我在科技新闻项目里，光是判断&amp;quot;SSL WRONG_VERSION_NUMBER 是代理问题还是源站问题&amp;quot;就需要一定的网络知识。对于没有这些背景的人，AI 报的错误就像天书。&lt;/p&gt;
&lt;h3&gt;4. Prompt 质量决定输出质量&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;4-prompt-质量决定输出质量&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#4-prompt-%e8%b4%a8%e9%87%8f%e5%86%b3%e5%ae%9a%e8%be%93%e5%87%ba%e8%b4%a8%e9%87%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;跟所有大模型工具一样，你描述需求的方式直接决定结果好不好。&amp;ldquo;帮我写个爬虫&amp;quot;和&amp;quot;帮我用 Python 标准库（不用 requests/beautifulsoup）写一个 RSS 解析器，支持 Atom 和 RSS 2.0 格式，对 HTTP 403 做 UA 轮换处理&amp;rdquo;——这两句话得到的结果差异是天壤之别的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;能写出好 Prompt 本身就是一项需要持续学习的技能。&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;四、开源的代价：安全与稳定性的隐忧&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四开源的代价安全与稳定性的隐忧&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e5%bc%80%e6%ba%90%e7%9a%84%e4%bb%a3%e4%bb%b7%e5%ae%89%e5%85%a8%e4%b8%8e%e7%a8%b3%e5%ae%9a%e6%80%a7%e7%9a%84%e9%9a%90%e5%bf%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;OpenClaw 是一个开源项目，这是它迅速扩散的重要原因之一——任何人都可以拉起来跑，社区贡献让功能迭代很快。但开源也意味着一些不得不正视的问题。&lt;/p&gt;
&lt;h3&gt;1. 安全性难以企业级保障&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-安全性难以企业级保障&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e5%ae%89%e5%85%a8%e6%80%a7%e9%9a%be%e4%bb%a5%e4%bc%81%e4%b8%9a%e7%ba%a7%e4%bf%9d%e9%9a%9c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;开源项目的安全审计往往依赖社区，而不是专职安全团队。在 AI Agent 这个场景里，安全的复杂性比传统软件高出一个数量级：模型的 Prompt Injection 防护、工具调用的权限隔离、敏感数据的流转链路……这些都是高度依赖工程规范和持续审计的领域。OpenClaw 目前对敏感操作做了一定的拦截，但距离企业级的安全基线还有相当距离。&lt;/p&gt;
&lt;p&gt;我在使用过程中，GitHub Token 明文出现在脚本里、RSS 抓取时绕过 SSL 验证这类问题都曾短暂出现——对个人项目无伤大雅，放到企业环境就是合规红线。&lt;/p&gt;
&lt;h3&gt;2. 服务稳定性无法 SLA 保障&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-服务稳定性无法-sla-保障&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e6%9c%8d%e5%8a%a1%e7%a8%b3%e5%ae%9a%e6%80%a7%e6%97%a0%e6%b3%95-sla-%e4%bf%9d%e9%9a%9c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;作为开源工具自部署，稳定性完全取决于自己的运维水平。容器崩了、依赖版本冲突、大模型接口抖动……这些在开发环境可以手动处理，但如果要跑一个真正的生产级自动化工作流，这种不确定性是很大的风险。&lt;/p&gt;
&lt;h3&gt;3. 商业产品正在加速入场&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-商业产品正在加速入场&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-%e5%95%86%e4%b8%9a%e4%ba%a7%e5%93%81%e6%ad%a3%e5%9c%a8%e5%8a%a0%e9%80%9f%e5%85%a5%e5%9c%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;有意思的是，就在 OpenClaw 这类开源工具火热的同时，各大商业公司也在快马加鞭地布局这个赛道。腾讯、字节、阿里等公司相继发布或内测自己的 AI Agent / Claw 类产品，这些商业版本的核心优势恰恰是开源版的弱项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;安全性&lt;/strong&gt;：有专属安全团队持续审计，对接企业内部权限体系&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;稳定性&lt;/strong&gt;：SLA 保障，有专职 oncall&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;合规性&lt;/strong&gt;：数据不出域，满足国内监管要求&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;集成深度&lt;/strong&gt;：与企业内部系统（代码仓库、工单、监控）有更深的打通&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于个人开发者和小团队来说，OpenClaw 这类开源工具是很好的探索起点；但对于企业级落地场景，商业产品在可靠性和合规性上的优势会越来越明显。这也是技术产品的规律：开源跑得快，商业跑得稳。&lt;/p&gt;
&lt;p&gt;两者并不矛盾，更可能的走向是：开源社区持续探索边界，商业产品选择性地把成熟能力产品化、标准化，最终让更多场景真正用得上、用得放心。&lt;/p&gt;
&lt;h2&gt;五、理性看待 AI Agent 工具，拥抱而不盲从&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五理性看待-ai-agent-工具拥抱而不盲从&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e7%90%86%e6%80%a7%e7%9c%8b%e5%be%85-ai-agent-%e5%b7%a5%e5%85%b7%e6%8b%a5%e6%8a%b1%e8%80%8c%e4%b8%8d%e7%9b%b2%e4%bb%8e&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我并不是要泼冷水。OpenClaw 确实帮我在短时间内完成了以前需要花好几天才能搭建的自动化工作流，这是实打实的效率提升。&lt;/p&gt;
&lt;p&gt;但我想说的是：&lt;strong&gt;它是一个强大的放大器，不是替代品。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;它能把一个有经验的工程师的效率放大 3~5 倍，让你把更多精力放在判断和设计上，而不是重复性的代码编写。但如果你本身对这个领域没有积累，它并不能帮你从零开始&amp;quot;无痛&amp;quot;地完成复杂任务。&lt;/p&gt;
&lt;p&gt;就像给一个不会开车的人一辆跑车，不会因为车更好就能开得更快——反而可能更危险。&lt;/p&gt;
&lt;p&gt;真正用好 OpenClaw 的姿势，我觉得是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;明确需求&lt;/strong&gt;：越具体越好，边界越清晰越好&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全程参与&lt;/strong&gt;：不是甩手掌柜，而是技术监理&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;持续学习&lt;/strong&gt;：理解它在做什么，才能在它走偏时及时纠正&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;积累 Skill&lt;/strong&gt;：把常用的工作流封装成 Skill，才能真正实现复用&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;六、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;六总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%ad%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;OpenClaw 的火热是有原因的，它确实代表了一种新的人机协作范式。但在这波热潮里保持清醒同样重要——不要因为它能&amp;quot;自动干活&amp;quot;就觉得什么都能交给它，也不要因为几次失败就彻底否定它的价值。&lt;/p&gt;
&lt;p&gt;对我来说，最好的状态是：把它当作一个聪明但需要指导的实习生。你负责把关方向、审核结果、处理边界情况，它负责帮你高速执行那些有章可循的重复性工作。&lt;/p&gt;
&lt;p&gt;这个分工，目前看来还挺管用。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;本文结合了作者近期使用 OpenClaw 开发科技新闻自动化 Pipeline、blog-writer Skill 以及定时任务等实际案例，欢迎交流。&lt;/em&gt;&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>2026-03-10 科技新闻日报</title>
      <link>https://www.helight.info/blog/2026/0310%E7%A7%91%E6%8A%80%E6%96%B0%E9%97%BB/</link>
      <pubDate>Tue, 10 Mar 2026 08:00:00 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2026/0310%E7%A7%91%E6%8A%80%E6%96%B0%E9%97%BB/</guid>
      <description>
        
        
        &lt;h1&gt;科技新闻日报 · 2026-03-10&lt;/h1&gt;&lt;blockquote&gt;
  &lt;p&gt;📅 抓取日期：2026-03-10&lt;br&gt;
📰 共收录 &lt;strong&gt;100&lt;/strong&gt; 条资讯&lt;br&gt;
🌏 来源：海外 40条, 国内 60条&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;目录&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;目录&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%9b%ae%e5%bd%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#ai--%e6%9c%ba%e5%99%a8%e5%ad%a6%e4%b9%a0&#34;&gt;🤖 AI / 机器学习&lt;/a&gt; (52)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e6%89%8b%e6%9c%ba--%e6%b6%88%e8%b4%b9%e7%94%b5%e5%ad%90&#34;&gt;📱 手机 / 消费电子&lt;/a&gt; (8)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e4%ba%91%e8%ae%a1%e7%ae%97--%e5%9f%ba%e7%a1%80%e8%ae%be%e6%96%bd&#34;&gt;☁️ 云计算 / 基础设施&lt;/a&gt; (3)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%bd%91%e7%bb%9c%e5%ae%89%e5%85%a8&#34;&gt;🔒 网络安全&lt;/a&gt; (2)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%a7%91%e6%8a%80%e5%95%86%e4%b8%9a&#34;&gt;💰 科技商业&lt;/a&gt; (3)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e7%a7%91%e5%ad%a6--%e5%89%8d%e6%b2%bf%e6%8a%80%e6%9c%af&#34;&gt;🔬 科学 / 前沿技术&lt;/a&gt; (4)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#%e5%85%b6%e4%bb%96%e7%a7%91%e6%8a%80%e8%b5%84%e8%ae%af&#34;&gt;📰 其他科技资讯&lt;/a&gt; (28)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;🤖 AI / 机器学习&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-ai--机器学习&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-ai--%e6%9c%ba%e5%99%a8%e5%ad%a6%e4%b9%a0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/apple-now-makes-one-in-four-iphones-in-india-report/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;苹果现在在印度生产四分之一的iPhone ：报告&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;苹果现在在印度生产四分之一的iphone-报告&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%8b%b9%e6%9e%9c%e7%8e%b0%e5%9c%a8%e5%9c%a8%e5%8d%b0%e5%ba%a6%e7%94%9f%e4%ba%a7%e5%9b%9b%e5%88%86%e4%b9%8b%e4%b8%80%e7%9a%84iphone-%e6%8a%a5%e5%91%8a&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Apple now makes one in four iPhones in India: report&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;创始人峰会2026 ，波士顿：不要错过高达300 $的门票优惠。立即注册。Disrupt 2026通行证最高可节省$ 680。今晚太平洋时间晚上11:59结束。据彭博社报道，苹果目前正在印度生产25 ％的iPhone ，达到摩根大通在2022年预测的里程碑，这是其减少对中国依赖的长期计划的一部分。彭博社报道称，去年，在全球生产的大约2.2亿至2.3亿部iPhone中，印度占据了5500万部。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/apple-now-makes-one-in-four-iphones-in-india-report/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/yann-lecuns-ami-labs-raises-1-03-billion-to-build-world-models/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Yann LeCun的AMI Labs筹集了$ 10.3亿用于构建世界模型&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;yann-lecun的ami-labs筹集了-103亿用于构建世界模型&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#yann-lecun%e7%9a%84ami-labs%e7%ad%b9%e9%9b%86%e4%ba%86-103%e4%ba%bf%e7%94%a8%e4%ba%8e%e6%9e%84%e5%bb%ba%e4%b8%96%e7%95%8c%e6%a8%a1%e5%9e%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Yann LeCun’s AMI Labs raises $1.03 billion to build world models&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;创始人峰会2026 ，波士顿：不要错过高达300美元的门票优惠。立即注册。购买Disrupt 2026通行证，最多可节省680美元。今晚太平洋时间晚上11:59结束。立即注册。图片来源： Ruhani Kaur/彭博社通过Getty Images/Getty Images AI Yann LeCuns AMI Labs筹集了10.3亿美元，用于建立世界模型Anna Heim太平洋时间晚上10:00 · 2026年3月9日AMI Labs ，这是图灵奖得主Yann LeCun在离开Meta后共同创立的新合资企业，以35亿美元的投资前估值筹集了10.3亿美元。AM&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/yann-lecuns-ami-labs-raises-1-03-billion-to-build-world-models/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/an-iphone-hacking-toolkit-used-by-russian-spies-likely-came-from-u-s-military-contractor/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;俄罗斯间谍使用的iPhone黑客工具包可能来自美国军事承包商&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;俄罗斯间谍使用的iphone黑客工具包可能来自美国军事承包商&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bf%84%e7%bd%97%e6%96%af%e9%97%b4%e8%b0%8d%e4%bd%bf%e7%94%a8%e7%9a%84iphone%e9%bb%91%e5%ae%a2%e5%b7%a5%e5%85%b7%e5%8c%85%e5%8f%af%e8%83%bd%e6%9d%a5%e8%87%aa%e7%be%8e%e5%9b%bd%e5%86%9b%e4%ba%8b%e6%89%bf%e5%8c%85%e5%95%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;An iPhone-hacking toolkit used by Russian spies likely came from U.S military contractor&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;谷歌发现了一系列黑客工具，他们说这些工具被俄罗斯间谍集团和中国的网络犯罪集团使用。美国政府国防承包商的消息来源称，其中一些黑客工具是他们的。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/an-iphone-hacking-toolkit-used-by-russian-spies-likely-came-from-u-s-military-contractor/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/electric-air-taxi-maker-archer-hits-back-at-joby-in-countersuit-alleging-concealed-chinese-ties/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;电动空中出租车制造商Archer在反诉中回击Joby ，指控隐瞒中国关系&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;电动空中出租车制造商archer在反诉中回击joby-指控隐瞒中国关系&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%94%b5%e5%8a%a8%e7%a9%ba%e4%b8%ad%e5%87%ba%e7%a7%9f%e8%bd%a6%e5%88%b6%e9%80%a0%e5%95%86archer%e5%9c%a8%e5%8f%8d%e8%af%89%e4%b8%ad%e5%9b%9e%e5%87%bbjoby-%e6%8c%87%e6%8e%a7%e9%9a%90%e7%9e%92%e4%b8%ad%e5%9b%bd%e5%85%b3%e7%b3%bb&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Electric air taxi maker Archer hits back at Joby in countersuit alleging concealed Chinese ties&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;创始人峰会2026 ，波士顿：不要错过高达300 $的门票优惠。立即注册。Disrupt 2026通行证最高可节省$ 680。今晚太平洋时间晚上11:59结束。立即注册。图片来源： Archer Aviation Transportation电动空中出租车制造商Archer在反诉中回击Joby ，指控隐瞒中国关系Kirsten Korosec太平洋时间下午6:41 · 2026年3月9日电动空中出租车开发商Archer Aviation周一以自己的反诉回应诉讼，竞争对手Joby Aviation涉嫌欺诈&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/electric-air-taxi-maker-archer-hits-back-at-joby-in-countersuit-alleging-concealed-chinese-ties/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/founders-fund-nears-6-billion-close-for-latest-growth-fund-sources-say/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;消息人士称， Founders Fund的最新成长基金接近$ 6B收盘价&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;消息人士称-founders-fund的最新成长基金接近-6b收盘价&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%b6%88%e6%81%af%e4%ba%ba%e5%a3%ab%e7%a7%b0-founders-fund%e7%9a%84%e6%9c%80%e6%96%b0%e6%88%90%e9%95%bf%e5%9f%ba%e9%87%91%e6%8e%a5%e8%bf%91-6b%e6%94%b6%e7%9b%98%e4%bb%b7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Founders Fund nears $6B close for latest growth fund, sources say&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;新一轮融资是在Founders Fund关闭其第三只成长型基金后不到一年的时间内完成的，这只$ 46亿的工具主要用于对其成功后期公司的后续投资。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/founders-fund-nears-6-billion-close-for-latest-growth-fund-sources-say/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/electric-air-taxis-are-about-to-take-flight-in-26-states/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;电动空中出租车即将在26个州起飞&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;电动空中出租车即将在26个州起飞&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%94%b5%e5%8a%a8%e7%a9%ba%e4%b8%ad%e5%87%ba%e7%a7%9f%e8%bd%a6%e5%8d%b3%e5%b0%86%e5%9c%a826%e4%b8%aa%e5%b7%9e%e8%b5%b7%e9%a3%9e&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Electric air taxis are about to take flight in 26 states&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;创始人峰会2026 ，波士顿：不要错过高达300 $的门票优惠。立即注册。Disrupt 2026通行证最高可节省$ 680。今晚太平洋时间晚上11:59结束。立即注册。图片来源： Joby Aviation Transportation电动空中出租车即将在26个州起飞Kirsten Korosec太平洋夏令时下午3:30 · 2026年3月9日美国联邦航空管理局（ FAA ）批准了八个试点项目，将允许少数几家公司，包括Archer Aviation、Beta Technologies、Joby Aviation和Wisk&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/electric-air-taxis-are-about-to-take-flight-in-26-states/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/openai-and-google-employees-rush-to-anthropics-defense-in-dod-lawsuit/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;OpenAI和谷歌员工在国防部诉讼中急于为Anthropic辩护&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;openai和谷歌员工在国防部诉讼中急于为anthropic辩护&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#openai%e5%92%8c%e8%b0%b7%e6%ad%8c%e5%91%98%e5%b7%a5%e5%9c%a8%e5%9b%bd%e9%98%b2%e9%83%a8%e8%af%89%e8%ae%bc%e4%b8%ad%e6%80%a5%e4%ba%8e%e4%b8%baanthropic%e8%be%a9%e6%8a%a4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;OpenAI and Google employees rush to Anthropic’s defense in DOD lawsuit&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;根据法庭文件，超过30名OpenAI和谷歌DeepMind员工签署了一份声明，支持Anthropic针对国防部的诉讼，此前该机构将该人工智能公司标记为供应链风险。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/openai-and-google-employees-rush-to-anthropics-defense-in-dod-lawsuit/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/anthropic-launches-code-review-tool-to-check-flood-of-ai-generated-code/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Anthropic推出代码审查工具，以检查AI生成的大量代码&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;anthropic推出代码审查工具以检查ai生成的大量代码&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#anthropic%e6%8e%a8%e5%87%ba%e4%bb%a3%e7%a0%81%e5%ae%a1%e6%9f%a5%e5%b7%a5%e5%85%b7%e4%bb%a5%e6%a3%80%e6%9f%a5ai%e7%94%9f%e6%88%90%e7%9a%84%e5%a4%a7%e9%87%8f%e4%bb%a3%e7%a0%81&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Anthropic launches code review tool to check flood of AI-generated code&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Anthropic在Claude Code中推出了Code Review ，这是一个多代理系统，可自动分析AI生成的代码，标记逻辑错误，并帮助企业开发人员管理使用AI生成的越来越多的代码。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/anthropic-launches-code-review-tool-to-check-flood-of-ai-generated-code/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/bluesky-ceo-jay-graber-steps-down/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Bluesky首席执行官Jay Graber辞职&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;bluesky首席执行官jay-graber辞职&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#bluesky%e9%a6%96%e5%b8%ad%e6%89%a7%e8%a1%8c%e5%ae%98jay-graber%e8%be%9e%e8%81%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Bluesky CEO Jay Graber steps down&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;创始人峰会2026 ，波士顿：不要错过高达300 $的门票优惠。立即注册。Disrupt 2026通行证最高可节省$ 680。今晚太平洋时间晚上11:59结束。立即注册。图片来源： TechCrunch Startups Bluesky首席执行官杰伊·格雷伯（ Jay Graber ）于太平洋标准时间2026年3月9日中午12:32下台。该公司周一宣布， Bluesky首席执行官杰伊·格雷伯（ Jay Graber ）将从最高领导职位下台，并过渡到首席创新官的新职位。Graber ，他帮助发展了X和Threads的竞争对手&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/bluesky-ceo-jay-graber-steps-down/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/periwinkle-at-protocol-bluesky-self-hosted-social-media/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Periwinkle让Bluesky AT Protocol上的自托管社交媒体变得更加轻松&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;periwinkle让bluesky-at-protocol上的自托管社交媒体变得更加轻松&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#periwinkle%e8%ae%a9bluesky-at-protocol%e4%b8%8a%e7%9a%84%e8%87%aa%e6%89%98%e7%ae%a1%e7%a4%be%e4%ba%a4%e5%aa%92%e4%bd%93%e5%8f%98%e5%be%97%e6%9b%b4%e5%8a%a0%e8%bd%bb%e6%9d%be&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Periwinkle is making self-hosted social media on Bluesky’s AT Protocol even easier&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;创始人峰会2026 ，波士顿：不要错过高达300 $的门票优惠。立即注册。Disrupt 2026通行证最高可节省$ 680。今晚太平洋时间晚上11:59结束。立即注册。图片来源： Arterra/Contributor （在新窗口中打开）/Getty Images Social Periwinkle让Blueskys AT Protocol上的自托管社交媒体变得更加容易Sarah Perez 11:18 AM PDT · 2026年3月9日柏林创业公司Periwinkle为那些希望离开由&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/periwinkle-at-protocol-bluesky-self-hosted-social-media/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/openai-acquires-promptfoo-to-secure-its-ai-agents/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;OpenAI收购Promptfoo以保护其AI代理&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;openai收购promptfoo以保护其ai代理&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#openai%e6%94%b6%e8%b4%adpromptfoo%e4%bb%a5%e4%bf%9d%e6%8a%a4%e5%85%b6ai%e4%bb%a3%e7%90%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;OpenAI acquires Promptfoo to secure its AI agents&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;创始人峰会2026 ，波士顿：不要错过高达300 $的门票优惠。立即注册。Disrupt 2026通行证最高可节省$ 680。今晚太平洋时间晚上11:59结束。立即注册。OpenAI周一宣布已收购Promptfoo ，这是一家成立于2024年的人工智能安全初创公司，旨在保护LLM免受在线对手的攻击。前沿实验室在一篇博客文章中表示，一旦交易完成， Promptfoos技术将整合到其AI代理企业平台OpenAI Frontier中。自主人工智能的发展&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/openai-acquires-promptfoo-to-secure-its-ai-agents/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.theverge.com/policy/891686/dhs-government-shutdown-ice-cbp-tsa-airports&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;政府关闭正在打击机场—但不是ICE&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;政府关闭正在打击机场但不是ice&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%94%bf%e5%ba%9c%e5%85%b3%e9%97%ad%e6%ad%a3%e5%9c%a8%e6%89%93%e5%87%bb%e6%9c%ba%e5%9c%ba%e4%bd%86%e4%b8%8d%e6%98%afice&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;The government shutdown is hitting airports — but not ICE&lt;/em&gt;
&lt;strong&gt;来源：The Verge&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;上周末，全国各地的机场一片混乱，据报道，由于人员短缺，成千上万的旅客排着长达数小时的安全队伍等待。运输安全管理局（ TSA ）和海岸警卫队工作人员在数周无薪后转向食品银行寻求援助。但在政府部分关闭的情况下，旨在削减国土安全部[]&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.theverge.com/policy/891686/dhs-government-shutdown-ice-cbp-tsa-airports&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.theverge.com/tech/891676/kalshi-iran-prediction-markets&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;从上周开始，一切都在赌博&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;从上周开始一切都在赌博&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%8e%e4%b8%8a%e5%91%a8%e5%bc%80%e5%a7%8b%e4%b8%80%e5%88%87%e9%83%bd%e5%9c%a8%e8%b5%8c%e5%8d%9a&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Everything from the last week of everything is gambling now&lt;/em&gt;
&lt;strong&gt;来源：The Verge&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Kalshi在上周提起集体诉讼后面临用户的强烈反对，该诉讼指控其未能按照承诺支付伊朗最高领导人阿亚图拉·阿里·哈梅内伊何时离职或被免职的赌注。哈梅内伊在上个月对伊朗的袭击中丧生，但根据[]&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.theverge.com/tech/891676/kalshi-iran-prediction-markets&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.theverge.com/ai-artificial-intelligence/891514/anthropic-pentagon-lawsuit-amicus-brief-openai-google&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;OpenAI和谷歌的员工支持Anthropic对五角大楼的诉讼&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;openai和谷歌的员工支持anthropic对五角大楼的诉讼&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#openai%e5%92%8c%e8%b0%b7%e6%ad%8c%e7%9a%84%e5%91%98%e5%b7%a5%e6%94%af%e6%8c%81anthropic%e5%af%b9%e4%ba%94%e8%a7%92%e5%a4%a7%e6%a5%bc%e7%9a%84%e8%af%89%e8%ae%bc&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Employees across OpenAI and Google support Anthropic’s lawsuit against the Pentagon&lt;/em&gt;
&lt;strong&gt;来源：The Verge&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;周一， Anthropic就被指定为供应链风险向国防部提起诉讼。几个小时后，来自OpenAI和谷歌的近40名员工（包括谷歌首席科学家兼Gemini负责人杰夫·迪恩（ Jeff Dean ） ）提交了一份法庭之友简报，支持Anthropic的诉讼，详细说明了他们对特朗普政府&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.theverge.com/ai-artificial-intelligence/891514/anthropic-pentagon-lawsuit-amicus-brief-openai-google&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.theverge.com/gadgets/891598/disney-plus-hulu-academy-awards-deal-sale&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;您可以以$ 15的价格获得三个月的Disney Plus和Hulu&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;您可以以-15的价格获得三个月的disney-plus和hulu&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%82%a8%e5%8f%af%e4%bb%a5%e4%bb%a5-15%e7%9a%84%e4%bb%b7%e6%a0%bc%e8%8e%b7%e5%be%97%e4%b8%89%e4%b8%aa%e6%9c%88%e7%9a%84disney-plus%e5%92%8chulu&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;You can get three months of Disney Plus and Hulu for $15&lt;/em&gt;
&lt;strong&gt;来源：The Verge&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;如果您正在寻找本周末观看奥斯卡颁奖典礼的方式，或者正在寻找《秘密特工》等提名作品，那么迪士尼Plus和Hulu捆绑包值得一看。仪式将于3月15日在Hulu上首次直播，现在，新的和符合条件的回头订阅者可以获得[]&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.theverge.com/gadgets/891598/disney-plus-hulu-academy-awards-deal-sale&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/story/yann-lecun-raises-dollar1-billion-to-build-ai-that-understands-the-physical-world/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Yann LeCun筹集了10亿美元用于构建理解物理世界的人工智能&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;yann-lecun筹集了10亿美元用于构建理解物理世界的人工智能&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#yann-lecun%e7%ad%b9%e9%9b%86%e4%ba%8610%e4%ba%bf%e7%be%8e%e5%85%83%e7%94%a8%e4%ba%8e%e6%9e%84%e5%bb%ba%e7%90%86%e8%a7%a3%e7%89%a9%e7%90%86%e4%b8%96%e7%95%8c%e7%9a%84%e4%ba%ba%e5%b7%a5%e6%99%ba%e8%83%bd&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Yann LeCun Raises $1 Billion to Build AI That Understands the Physical World&lt;/em&gt;
&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;保存这个故事保存这个故事由Meta的前首席人工智能科学家Yann LeCun共同创立的新巴黎初创公司Advanced Machine Intelligence （ AMI ）周一宣布，它已筹集超过10 $ 10亿用于开发人工智能世界模型。LeCun认为，大多数人类推理都基于物理世界，而不是语言，人工智能世界模型对于开发真正的人类智能是必要的。“您将LLM [大型语言模型]的能力扩展到&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/story/yann-lecun-raises-dollar1-billion-to-build-ai-that-understands-the-physical-world/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/story/nvidia-planning-ai-agent-platform-launch-open-source/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;英伟达计划推出开源人工智能代理平台&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;英伟达计划推出开源人工智能代理平台&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%8b%b1%e4%bc%9f%e8%be%be%e8%ae%a1%e5%88%92%e6%8e%a8%e5%87%ba%e5%bc%80%e6%ba%90%e4%ba%ba%e5%b7%a5%e6%99%ba%e8%83%bd%e4%bb%a3%e7%90%86%e5%b9%b3%e5%8f%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Nvidia Is Planning to Launch an Open-Source AI Agent Platform&lt;/em&gt;
&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;保存此故事保存此故事Nvidia计划为AI代理商推出一个开源平台，熟悉公司计划的人士告诉WIRED。这家芯片制造商一直在向企业软件公司推销该产品，称为NemoClaw。该平台将允许这些公司派遣人工智能代理为自己的员工执行任务。消息人士称，无论其产品是否在英伟达芯片上运行，公司都将能够访问该平台。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/story/nvidia-planning-ai-agent-platform-launch-open-source/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/story/anthropic-claims-business-is-in-peril-due-to-supply-chain-risk-designation/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;人类声称五角大楼的争斗可能会花费数十亿美元&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;人类声称五角大楼的争斗可能会花费数十亿美元&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%ba%e7%b1%bb%e5%a3%b0%e7%a7%b0%e4%ba%94%e8%a7%92%e5%a4%a7%e6%a5%bc%e7%9a%84%e4%ba%89%e6%96%97%e5%8f%af%e8%83%bd%e4%bc%9a%e8%8a%b1%e8%b4%b9%e6%95%b0%e5%8d%81%e4%ba%bf%e7%be%8e%e5%85%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Anthropic Claims Pentagon Feud Could Cost It Billions&lt;/em&gt;
&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;这家AI初创公司的高管表示，在特朗普政府将其标记为供应链风险后，公司暂停了交易谈判，并警告说，这种影响可能会导致重大的收入损失。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/story/anthropic-claims-business-is-in-peril-due-to-supply-chain-risk-designation/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/story/openai-deepmind-employees-file-amicus-brief-anthropic-dod-lawsuit/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;OpenAI和Google Workers提交法庭之友简报，支持Anthropic反对美国政府&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;openai和google-workers提交法庭之友简报支持anthropic反对美国政府&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#openai%e5%92%8cgoogle-workers%e6%8f%90%e4%ba%a4%e6%b3%95%e5%ba%ad%e4%b9%8b%e5%8f%8b%e7%ae%80%e6%8a%a5%e6%94%af%e6%8c%81anthropic%e5%8f%8d%e5%af%b9%e7%be%8e%e5%9b%bd%e6%94%bf%e5%ba%9c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;OpenAI and Google Workers File Amicus Brief in Support of Anthropic Against the US Government&lt;/em&gt;
&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;保存此故事保存此故事OpenAI和Google的30多名员工，包括Google DeepMind首席科学家Jeff Dean ，周一提交了一份法庭之友简报，以支持Anthropic与美国政府的法律斗争。员工们写道： “如果允许继续进行，这种惩罚美国领先的人工智能公司之一的努力无疑将对美国在人工智能领域及其他领域的工业和科学竞争力产生影响。”&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/story/openai-deepmind-employees-file-amicus-brief-anthropic-dod-lawsuit/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/story/casabrews-5700-espresso-machine-java-base/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;您的浓缩咖啡机不一定要花哨才能煮出好咖啡&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;您的浓缩咖啡机不一定要花哨才能煮出好咖啡&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%82%a8%e7%9a%84%e6%b5%93%e7%bc%a9%e5%92%96%e5%95%a1%e6%9c%ba%e4%b8%8d%e4%b8%80%e5%ae%9a%e8%a6%81%e8%8a%b1%e5%93%a8%e6%89%8d%e8%83%bd%e7%85%ae%e5%87%ba%e5%a5%bd%e5%92%96%e5%95%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Your Espresso Machine Doesn’t Have to Be Fancy to Make Good Coffee&lt;/em&gt;
&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;LoaderSave StorySave this storyCommentLoaderSave storySave this storyCoffee是原创的生物黑客和全国最受欢迎的生产力工具。随着我们适应夏令时的转变，咖啡因上瘾的有线评论团队正在撰写我们最喜欢的咖啡冲泡程序和设备。今天，评论家Peter Cottell解释了为什么咖啡机不必比Casabrews 5700更豪华。留意关于其他有线作家的其他Java.Base故事&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/story/casabrews-5700-espresso-machine-java-base/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/story/anthropic-sues-department-of-defense-over-supply-chain-risk-designation/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;美国国防部因供应链风险认定而提起诉讼&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;美国国防部因供应链风险认定而提起诉讼&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%be%8e%e5%9b%bd%e5%9b%bd%e9%98%b2%e9%83%a8%e5%9b%a0%e4%be%9b%e5%ba%94%e9%93%be%e9%a3%8e%e9%99%a9%e8%ae%a4%e5%ae%9a%e8%80%8c%e6%8f%90%e8%b5%b7%e8%af%89%e8%ae%bc&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Anthropic Sues Department of Defense Over Supply-Chain-Risk Designation&lt;/em&gt;
&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;保存此故事保存此故事Anthropic于周一向美国国防部和其他联邦机构提起联邦诉讼，质疑其将人工智能公司指定为“供应链风险”。五角大楼上周正式批准了《人类学》，限制了长达数周的公开分歧，即限制其生成人工智能技术在自主武器等军事应用中的使用。“我们认为此举在法律上不合理，我们别无选择&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/story/anthropic-sues-department-of-defense-over-supply-chain-risk-designation/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/story/feeld-was-a-dating-app-for-the-freaks-now-some-people-call-it-normie-hell/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Feeld是Freaks的约会应用程序。现在有些人称之为“诺米地狱”&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;feeld是freaks的约会应用程序现在有些人称之为诺米地狱&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#feeld%e6%98%affreaks%e7%9a%84%e7%ba%a6%e4%bc%9a%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e7%8e%b0%e5%9c%a8%e6%9c%89%e4%ba%9b%e4%ba%ba%e7%a7%b0%e4%b9%8b%e4%b8%ba%e8%af%ba%e7%b1%b3%e5%9c%b0%e7%8b%b1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Feeld Was a Dating App for the Freaks. Now Some People Call It ‘Normie Hell’&lt;/em&gt;
&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;LoaderSave StorySave this storyCommentLoaderSave StorySave this storyAlise Morales刚好在约会应用程序上Feeld当晚，一名男子被ICE特工拘留，距离她在纽约布鲁克林的公寓一英里。35岁的喜剧演员莫拉莱斯刚刚离婚，在市场上买了一些纯粹休闲的东西。就在那时，她看到了保罗的个人资料。她说：「我花了好几次时间，才得到我所看到的。」他当时32岁，异性恋，像莫拉莱斯一样，&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/story/feeld-was-a-dating-app-for-the-freaks-now-some-people-call-it-normie-hell/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.technologyreview.com/2026/03/09/1134063/how-ai-is-turning-the-iran-conflict-into-theater/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;人工智能如何将伊朗冲突变成战场&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;人工智能如何将伊朗冲突变成战场&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%ba%e5%b7%a5%e6%99%ba%e8%83%bd%e5%a6%82%e4%bd%95%e5%b0%86%e4%bc%8a%e6%9c%97%e5%86%b2%e7%aa%81%e5%8f%98%e6%88%90%e6%88%98%e5%9c%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;How AI is turning the Iran conflict into theater&lt;/em&gt;
&lt;strong&gt;来源：MIT Technology Review&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;这个故事最初出现在我们的人工智能每周通讯《算法》上。要先在收件箱中获取此类故事，请在此处注册。「有人想在旧金山举办聚会，在100英寸的电视上播放吗？ ”X上那篇文章的作者指的是一个在线情报仪表板，&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.technologyreview.com/2026/03/09/1134063/how-ai-is-turning-the-iran-conflict-into-theater/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/p/3716670530106761?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;光帆科技董红光：把AI耳机做成“第二台主机”，很难，却正确&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;光帆科技董红光把ai耳机做成第二台主机很难却正确&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%89%e5%b8%86%e7%a7%91%e6%8a%80%e8%91%a3%e7%ba%a2%e5%85%89%e6%8a%8aai%e8%80%b3%e6%9c%ba%e5%81%9a%e6%88%90%e7%ac%ac%e4%ba%8c%e5%8f%b0%e4%b8%bb%e6%9c%ba%e5%be%88%e9%9a%be%e5%8d%b4%e6%ad%a3%e7%a1%ae&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;文｜邱晓芬 编辑｜苏建勋 2026年，AI硬件热到发烫。 OpenAI、Meta、苹果、阿里千问、字节等大厂都加入了入口争夺战，通过自研或重金外部收购团队，补上他们在AI上最后一块短板。而AI可穿戴设备，毫无疑问成为所有大厂们“补入口”的集体选择。 中国的公司也在快速吸收粮草弹药。作为全球第一家发布带摄像头AI耳机的公司，近期《智能涌现》获悉，「光帆科技」连续完成种子++轮和种子+++轮两轮融资。 本次融资由联想集团和小鹏汽车（星航资本）联合领投，高秉强教授、Brizan Ventures、ForeBright Concerto参投，多家老股东连续追投，募集资金将重点用于面向下一代人机交互的AI可穿戴硬件及Agent OS相关领域的落地。 据了解，「光帆科技」整个种子轮的融资总金额近3亿元，资方名单中囊括了众多产业资本，除了本轮的小鹏汽车和联想以外，还包括韶音、歌尔、宁德系（柏睿资本）、兆易创新系（清辉投资、零以创投）等。 尽管置身AI硬件热浪当中，「光帆科技」的创始人董红光却是个很克制的人。在和我们交流时，董红光语速缓慢，为了严谨，他喜欢引用过去的科技发展史来佐证自己的观点。 克制的&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/p/3716670530106761?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/p/3715521730933127?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;用智能吉他起家后，这家公司又用AI音乐工作站拿下百万美元众筹，营收数亿｜Insight全球&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;用智能吉他起家后这家公司又用ai音乐工作站拿下百万美元众筹营收数亿insight全球&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%94%a8%e6%99%ba%e8%83%bd%e5%90%89%e4%bb%96%e8%b5%b7%e5%ae%b6%e5%90%8e%e8%bf%99%e5%ae%b6%e5%85%ac%e5%8f%b8%e5%8f%88%e7%94%a8ai%e9%9f%b3%e4%b9%90%e5%b7%a5%e4%bd%9c%e7%ab%99%e6%8b%bf%e4%b8%8b%e7%99%be%e4%b8%87%e7%be%8e%e5%85%83%e4%bc%97%e7%ad%b9%e8%90%a5%e6%94%b6%e6%95%b0%e4%ba%bfinsight%e5%85%a8%e7%90%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;作者｜黄楠 编辑｜袁斯来 编者按：当出海越来越成为一家中国公司核心战略时，如何征战全球市场就成为一个极其专业的话题。在全球化的演变中，已有不少中国品牌站立潮头。鉴于此，硬氪特推出「Insight全球」专栏，从品牌成长与变迁，探索中国品牌出海的前沿方向与时代契机，为出海玩家与行业提供思考与启发。 这是我们专栏第61期——拿火音乐从广州起步，以“材料创新+智能交互”模式，2017年推出全球首款一体成型碳纤维吉他LAVA ME，在智能吉他赛道中迅速破局；2024年发布无弦吉他“精灵”，降低用户上手门槛；2025年将上百款经典效果器数字化复刻、推出LAVA STUDIO，海外众筹超226万美元刷新品类纪录。。目前全年营收达数亿元。 拿火音乐（LAVA MUSIC）创始人陆子天像个从独立音乐节后台出走的乐手。 他留长发，说话温和，初次见面会略显寡言少语，你很难想象他经营着一家年营收数亿的硬件公司。 比起用语言介绍产品，陆子天更习惯起身拿起吉他弹上一段。采访几个小时中，我们从Guns N’Roses、Nirvana听到了周杰伦，理解了效果器、音色这些专业名词究竟意味着什么。 其实，陆子天的履历更像&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/p/3715521730933127?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/p/3716450088793732?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;上海交大教授创业，用AI研发新材料，交大系基金投资｜36氪首发&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;上海交大教授创业用ai研发新材料交大系基金投资36氪首发&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%8a%e6%b5%b7%e4%ba%a4%e5%a4%a7%e6%95%99%e6%8e%88%e5%88%9b%e4%b8%9a%e7%94%a8ai%e7%a0%94%e5%8f%91%e6%96%b0%e6%9d%90%e6%96%99%e4%ba%a4%e5%a4%a7%e7%b3%bb%e5%9f%ba%e9%87%91%e6%8a%95%e8%b5%8436%e6%b0%aa%e9%a6%96%e5%8f%91&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;作者丨欧雪 编辑丨袁斯来 硬氪获悉，AI for Materials（人工智能赋能新材料研发）领域的初创企业——索格智算宣布完成超千万元种子轮融资。本轮融资由启高资本领投，交大菡源资产、紫竹小苗和紫竹科投跟投。资金将主要用于原创AI计算引擎的持续研发、研发团队扩充以及算力基础设施建设。 索格智算成立于2025年9月，创始团队源自上海交通大学，由数学学院特聘教授、人工智能新材料研究中心主任徐振礼领衔。团队其他核心成员也拥有数学、人工智能、高性能计算与材料科学的交叉学科背景。 硬氪了解到，在新材料研发领域，传统计算模拟方式往往面临“高精度-高效率-低成本”的不可能三角。尤其是材料模拟中的长程相互作用，一直是制约计算精度的瓶颈。 索格智算致力于用算法突破解决新材料研发周期长、成本高的行业痛点。其核心技术之一在于其提出的新型神经网络描述子——SOG-Net。该算法通过将总势能分解为短程与长程项独立建模并高效耦合，引入可训练的高斯和函数，自适应拟合库仑、色散等长程作用，显著降低了复杂系统能量与力的预测误差。 SOG-Net原理图（图源/企业） 同时，基于原创算法，团队研发了随机分批分子动力学模拟&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/p/3716450088793732?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/p/3716375591794051?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;8点1氪丨胖东来12名店长共分2.4亿资产利润；Mac mini销量暴增或因OpenClaw爆火导致；2026年中国电影票房在全球占比超28%，领跑全球电影市场&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;8点1氪丨胖东来12名店长共分24亿资产利润mac-mini销量暴增或因openclaw爆火导致2026年中国电影票房在全球占比超28领跑全球电影市场&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#8%e7%82%b91%e6%b0%aa%e4%b8%a8%e8%83%96%e4%b8%9c%e6%9d%a512%e5%90%8d%e5%ba%97%e9%95%bf%e5%85%b1%e5%88%8624%e4%ba%bf%e8%b5%84%e4%ba%a7%e5%88%a9%e6%b6%a6mac-mini%e9%94%80%e9%87%8f%e6%9a%b4%e5%a2%9e%e6%88%96%e5%9b%a0openclaw%e7%88%86%e7%81%ab%e5%af%bc%e8%87%b42026%e5%b9%b4%e4%b8%ad%e5%9b%bd%e7%94%b5%e5%bd%b1%e7%a5%a8%e6%88%bf%e5%9c%a8%e5%85%a8%e7%90%83%e5%8d%a0%e6%af%94%e8%b6%8528%e9%a2%86%e8%b7%91%e5%85%a8%e7%90%83%e7%94%b5%e5%bd%b1%e5%b8%82%e5%9c%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;今日热点导览 国内成品油零售调价将开启上调窗口，加满一箱油将多花27.5元 2026年中国电影票房在全球占比超28%，领跑全球电影市场 中国有望成首个在月球找到水的国家 腾讯据称将以新资金重返派拉蒙收购华纳兄弟的交易 腾讯：旗下全场景AI智能体WorkBuddy正式上线 消息称苹果上调首款折叠机备货量，较原定目标增加20% TOP 3 大新闻 特朗普称对伊朗战事“已基本结束”：比预计快得多 记者当地时间3月9日获悉，美国总统特朗普表示，美国对伊朗的战争可能很快就会结束。据悉，特朗普在一次电话采访中说：“我觉得这场战争已基本结束了，差不多了。他们已经没有海军，没有通信系统，也没有空军了。” 特朗普还说，这比他最初预计的4到5周的时间框架“进展快得多”。 当被问及伊朗新任最高领袖穆杰塔巴·哈梅内伊时，特朗普表示：“我对他没什么可说的，完全没有。”特朗普声称“心中已有人选来接替哈梅内伊”，但没有进一步说明。 （央视新闻） 胖东来12名店长共分2.4亿资产利润，超8成员工拒绝“降薪增假” 3月8日，胖东来创始人于东来在社交平台发文分享胖东来经验，公布公司40亿元资产利润的分配标准：管理团队占比&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/p/3716375591794051?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/p/3715472798527617?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;氪星晚报｜国家超算互联网OpenClaw服务接入飞书、企业微信；WPS发布iPadOS首款原生桌面级Office；“红房子・启元”AI妇产科垂直大模型发布&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;氪星晚报国家超算互联网openclaw服务接入飞书企业微信wps发布ipados首款原生桌面级office红房子启元ai妇产科垂直大模型发布&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%b0%aa%e6%98%9f%e6%99%9a%e6%8a%a5%e5%9b%bd%e5%ae%b6%e8%b6%85%e7%ae%97%e4%ba%92%e8%81%94%e7%bd%91openclaw%e6%9c%8d%e5%8a%a1%e6%8e%a5%e5%85%a5%e9%a3%9e%e4%b9%a6%e4%bc%81%e4%b8%9a%e5%be%ae%e4%bf%a1wps%e5%8f%91%e5%b8%83ipados%e9%a6%96%e6%ac%be%e5%8e%9f%e7%94%9f%e6%a1%8c%e9%9d%a2%e7%ba%a7office%e7%ba%a2%e6%88%bf%e5%ad%90%e5%90%af%e5%85%83ai%e5%a6%87%e4%ba%a7%e7%a7%91%e5%9e%82%e7%9b%b4%e5%a4%a7%e6%a8%a1%e5%9e%8b%e5%8f%91%e5%b8%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;大公司： 由菜鸟运营的全国首个跨境电商零售出口“前置监管仓”正式启用 36氪获悉，近日，由菜鸟运营的全国首个跨境电商零售出口“前置监管仓”在山东威海正式启用，服务于速卖通平台。在与海关部门深度协同下，海关监管首次深度嵌入电商仓库生产作业流程，出口货物通关实现秒级申报放行，就地装箱后当晚即可搭乘班轮出海。 国家超算互联网OpenClaw服务接入飞书、企业微信 36氪获悉，国家超算互联网宣布，其OpenClaw服务已打通飞书、企业微信。用户可根据任务规模，灵活选择多种模型API调用服务，并接入飞书、企业微信客户端使用。目前，超算互联网OpenClaw已预置各类大模型（如MinMax-M2.1、MinMax-M2.5、Qwen-235B等），以提供高性能、低成本的推理算力。 光洋股份：与逐际动力签署战略合作协议，致力于一体化关节模组的标准化开发 36氪获悉，光洋股份公告，公司与深圳逐际动力科技有限公司签署《战略合作协议》，双方拟整合资源，优势互补，致力于一体化关节模组的标准化开发。合作产品：包括但不限于轴承，齿轮、减速机、驱动器等关键零部件以及一体化关节模组设计的开发和代加工。协议为合作意向&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/p/3715472798527617?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/p/3715205580058756?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;提前披露中东美军动向，这家AI卫星情报公司完成新一轮融资｜硬氪首发&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;提前披露中东美军动向这家ai卫星情报公司完成新一轮融资硬氪首发&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%8f%90%e5%89%8d%e6%8a%ab%e9%9c%b2%e4%b8%ad%e4%b8%9c%e7%be%8e%e5%86%9b%e5%8a%a8%e5%90%91%e8%bf%99%e5%ae%b6ai%e5%8d%ab%e6%98%9f%e6%83%85%e6%8a%a5%e5%85%ac%e5%8f%b8%e5%ae%8c%e6%88%90%e6%96%b0%e4%b8%80%e8%bd%ae%e8%9e%8d%e8%b5%84%e7%a1%ac%e6%b0%aa%e9%a6%96%e5%8f%91&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;本文约1300字，建议阅读3分钟 作者 | 乔钰杰 编辑 | 袁斯来 硬氪获悉，地理空间情报分析公司觅熵科技（杭州）有限公司（MizarVision）（以下简称“觅熵科技”）近日宣布完成pre-A轮融资，本轮融资由现象资本独家投资，融资金额超千万元人民币，资金将主要用于业务拓展。 觅熵科技成立于2021年，总部位于杭州，是国内首家专注于将商业卫星遥感与AI深度融合，服务实时地理情报的创新企业。公司通过聚合全球多模态实时传感器信息，构建专属的AI情报大模型，对地理空间信息进行深度解读，改变了传统的情报信息的使用方式，让来自太空视角的数据可以更好服务各行业决策。 值得注意，在近期的中东地缘热点事件中，觅熵科技多次提前公布区域美军装备分布和战略目标活动。 公司创始人兼CEO刘明向硬氪介绍，传统遥感数据行业更多解决的是“看得见”的问题，而真正的难点在于“看得懂”。在卫星制造与发射成本依然高企的背景下，觅熵科技选择从数据应用切入，通过AI算法挖掘潜在线索，优化卫星资源的使用效率，从而为原本仅有传感器与用户的简单链条，补齐了数据分析与应用服务这一关键环节。 公司创始团队成员来自多个不同领域，包括华&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/p/3715205580058756?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/p/3714634245009800?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;获近亿元融资，一家AI公司的两周转型小龙虾实战故事&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;获近亿元融资一家ai公司的两周转型小龙虾实战故事&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%8e%b7%e8%bf%91%e4%ba%bf%e5%85%83%e8%9e%8d%e8%b5%84%e4%b8%80%e5%ae%b6ai%e5%85%ac%e5%8f%b8%e7%9a%84%e4%b8%a4%e5%91%a8%e8%bd%ac%e5%9e%8b%e5%b0%8f%e9%be%99%e8%99%be%e5%ae%9e%e6%88%98%e6%95%85%e4%ba%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;文｜邓咏仪 编辑｜苏建勋 Nodesk AI创始人宋健和他的创业公司NoDesk AI，在过去两周里，完成了一场极限AI竞赛： 2025年春节前，OpenClaw开始爆火。NoDesk AI创始人宋健带着团队，用两周时间开发了新产品DeskClaw。 最初，NoDesk只是为了内部使用，让自己的电商Agent业务团队基于OpenClaw提升效率。但开发完成后，团队感受到外界喷涌的需求，马上决定对外发布。2026年2月14日，DeskClaw个人版第一个版本上线。 △NoDesk AI创始人宋健与冲刺中的团队，图源：企业提供 在成立NoDesk AI之前，宋健是一个难得的To B创业“多面手”——从阿里和腾讯出来后，他在2014年创办了电商DaaS公司“多准数据”，做电商消费者洞察和大数据精准营销，在SaaS寒冬来临之前完成并购退出。而后，他也曾在智谱AI等公司任职，探索基础模型到Agent应用的落地。 NoDesk AI刚刚完成一轮近亿元融资，由湖畔山南、初心资本、高途、顺福资本共同投资。但没来得及庆祝，NoDesk AI团队马上就投入到新一轮战斗中。 “已经不能用人类时间来衡量AI时&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/p/3714634245009800?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/p/3714480200085633?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;前vivo手机明星产品经理宋紫薇创办「薇光点亮」，获红杉、蓝驰、蚂蚁、鼎晖超亿元融资丨智能涌现独家&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前vivo手机明星产品经理宋紫薇创办薇光点亮获红杉蓝驰蚂蚁鼎晖超亿元融资丨智能涌现独家&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8dvivo%e6%89%8b%e6%9c%ba%e6%98%8e%e6%98%9f%e4%ba%a7%e5%93%81%e7%bb%8f%e7%90%86%e5%ae%8b%e7%b4%ab%e8%96%87%e5%88%9b%e5%8a%9e%e8%96%87%e5%85%89%e7%82%b9%e4%ba%ae%e8%8e%b7%e7%ba%a2%e6%9d%89%e8%93%9d%e9%a9%b0%e8%9a%82%e8%9a%81%e9%bc%8e%e6%99%96%e8%b6%85%e4%ba%bf%e5%85%83%e8%9e%8d%e8%b5%84%e4%b8%a8%e6%99%ba%e8%83%bd%e6%b6%8c%e7%8e%b0%e7%8b%ac%e5%ae%b6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;作者丨邱晓芬 编辑丨苏建勋 AI硬件的创业风潮正席卷整个消费电子领域，前小米中国区市场部总经理王腾、小米互联网业务部总经理马骥等手机圈高管纷纷下场创业，产品形态包括AI睡眠硬件、AI耳机、AI影像硬件等等。 2024年10月，vivo明星手机产品经理宋紫薇也在微博宣布投身AI智能硬件领域创业 。此后，关于其创业方向一直众说纷纭。 《智能涌现》从知情人士处获悉，宋紫薇的创业公司「薇光点亮」将打造以时尚AI Agent为核心的智能硬件产品矩阵。知情人士称，其内部正在研发首款AI原生时尚终端，硬件形态或为落地镜，其时尚智能体将深度融合用户日常的照镜、穿搭等高频场景。 另据《智能涌现》独家获悉，「薇光点亮」近期完成过亿元的Pre-A融资，由红杉中国、蓝驰创投联合领投，蚂蚁战投、鼎晖投资、鞍羽资本跟投，老股东九合创投持续追加投资，所筹资金将重点用于人才建设、智能硬件研发、垂类模型训练、时尚Agent关键应用场景落地等。 知情人士称，宋紫薇创业以来，“新公司的节奏很快”。早在五个月前，「薇光点亮」已经完成由中科创星、九合创投的数千万人民币的天使轮融资。 宋紫薇 图源微博 宋紫薇是硬科技领域的流量人&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/p/3714480200085633?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/newsflashes/3716886646273665?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;黑芝麻智能配股融资6.31亿港元&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;黑芝麻智能配股融资631亿港元&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%bb%91%e8%8a%9d%e9%ba%bb%e6%99%ba%e8%83%bd%e9%85%8d%e8%82%a1%e8%9e%8d%e8%b5%84631%e4%ba%bf%e6%b8%af%e5%85%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;36氪获悉，3月9日，黑芝麻智能公告，公司与认购人无极资本（Infini Capital）订立认购协议，配发及发行合共约3354.46万股认购股份，每股认购价为18.88港元，较公司3月9日收盘价19.29港元折让2.13%，总代价约为6.31亿港元。据公告，本次募集资金主要用于新一代高性能芯片的研发，拓展机器人产品线及端侧AI产品线，加速产品商业化落地。下一篇金浦钛业：全资子公司与中研创星签订租赁经营合作协议，合作期三年36氪获悉，金浦钛业公告，全资子公司徐州钛白化工有限责任公司，拟以现有生产线与江苏中研创星材料科技有限公司开展租赁经营合作事宜，合作期三年，合作期内净利润为正时双方按约定比例分配利润，净利润为负时由中研创星独自承担所有成本和损失等。双方将签订《租赁经营合作协议》。3月10日，公司召开第九届董事会第八次会议审议通过了相关议案。 8点1氪丨胖东来12名店长共分2.4亿资产利润；Mac mini销量暴增或因OpenClaw爆火导致；2026年中国电影票房在全球占比超28%，领跑全球电影市场 OpenClaw 3.8继续炸场，龙虾不睡觉，全球程序员连夜赶工&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/newsflashes/3716886646273665?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/newsflashes/3716864143734147?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;蚂蚁集团启动2026春季校园招聘：技术岗占比达85%，超七成聚焦AI领域&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;蚂蚁集团启动2026春季校园招聘技术岗占比达85超七成聚焦ai领域&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%9a%82%e8%9a%81%e9%9b%86%e5%9b%a2%e5%90%af%e5%8a%a82026%e6%98%a5%e5%ad%a3%e6%a0%a1%e5%9b%ad%e6%8b%9b%e8%81%98%e6%8a%80%e6%9c%af%e5%b2%97%e5%8d%a0%e6%af%94%e8%be%be85%e8%b6%85%e4%b8%83%e6%88%90%e8%81%9a%e7%84%a6ai%e9%a2%86%e5%9f%9f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;36氪获悉，蚂蚁集团启动2026年度春季校园招聘。本次春招技术类岗位占比高达85%，其中超70%的岗位与人工智能直接相关，重点聚焦大模型算法、多模态生成、数据智能及基础平台研发、AI安全等核心领域。下一篇安达维尔：全资子公司与上海飞机制造有限公司签订销售框架合同36氪获悉，安达维尔公告，公司全资子公司北京安达维尔民用航空技术有限公司与上海飞机制造有限公司签订了《ARJ21新支线项目和C919大型客机项目批产厨房插件采购框架合同》，合同总价款不超过4.97亿元（不含税）。该合同旨在明确双方在国产大飞机部件供应协作中的具体权利与义务。实际销售金额以后续收到的采购定单或签订的专项协议为准，对公司2026年度的财务状况和经营成果是否构成重大影响存在不确定性。 8点1氪丨胖东来12名店长共分2.4亿资产利润；Mac mini销量暴增或因OpenClaw爆火导致；2026年中国电影票房在全球占比超28%，领跑全球电影市场 OpenClaw 3.8继续炸场，龙虾不睡觉，全球程序员连夜赶工&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/newsflashes/3716864143734147?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://sspai.com/post/106710&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;年度征文｜「你是专家」这句话，到底是在帮 AI 还是在害你？&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;年度征文你是专家这句话到底是在帮-ai-还是在害你&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b4%e5%ba%a6%e5%be%81%e6%96%87%e4%bd%a0%e6%98%af%e4%b8%93%e5%ae%b6%e8%bf%99%e5%8f%a5%e8%af%9d%e5%88%b0%e5%ba%95%e6%98%af%e5%9c%a8%e5%b8%ae-ai-%e8%bf%98%e6%98%af%e5%9c%a8%e5%ae%b3%e4%bd%a0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：少数派&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;编者按：本文是少数派 2025 年度征文活动#TeamSilicon25标签下的入围文章。本文仅代表作者本人观点，少数派只略微调整排版。 今年的征文活动更有创意，「只能用 AI」和「不能用 AI」两大赛道激情 PK，硅基生物和碳基生物都将决出各自领域的佼佼者。我们会在征文结束后统一组织投票活动，但在正式投票之前，如果你喜欢这篇文章，不妨通过充电或评论的方式支持作者，让内容创作者获得更多维度的鼓励。 你大概也听过这样的「提示词秘籍」：跟 AI 聊天时，先来一句「你是一位资深 XX 专家」，效果立竿见影。社交媒体上，这类技巧被包装成万能钥匙，仿佛给 AI 套上一件白大褂，它就真的会看病了。 我决定用最笨的办法来验证：设计对照实验，调 API，跑数据，让结果说话。 接下来你会看到的，是 120 多次 API 调用、2 个模型、5 轮实验后的真实记录。有些结果在意料之中，有些则让我出了一身冷汗。 事情的起点很简单。某天我在帮家人解释路由器信号问题时，顺手给 AI 加了一句「你是一位给爸妈写科普的数码博主」。结果出来的解释确实更通俗了——5GHz 变成了「短跑运动员」，2.4GHz 变成了「马拉松选手」。 这让我好奇：这种改善是巧合，还是规律？如果加上专家身份有时候会更好，那有没有可能在某些场景下反而更糟？ 毕竟网上那些「提示词大全」从来只展示成功案例，你永远不知道它省略了多少翻车现场。 在&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://sspai.com/post/106710&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://sspai.com/post/107001&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;派早报：达摩院发布脂肪肝筛查 AI 模型 MAOSS 等&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;派早报达摩院发布脂肪肝筛查-ai-模型-maoss-等&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%b4%be%e6%97%a9%e6%8a%a5%e8%be%be%e6%91%a9%e9%99%a2%e5%8f%91%e5%b8%83%e8%84%82%e8%82%aa%e8%82%9d%e7%ad%9b%e6%9f%a5-ai-%e6%a8%a1%e5%9e%8b-maoss-%e7%ad%89&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：少数派&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;3 月 9 日，阿里巴巴达摩院发布文章，宣布于近日联合中国医科大学附属盛京医院、南京大学附属鼓楼医院等机构研发出脂肪肝筛查 AI 模型 MAOSS。该模型通过平扫 CT 影像、血清指标等常见检查，可精准筛查肝脂肪分期、评估肝纤维化进展，将高风险患者检出率从 16.6% 提升至 52.4%，为早期干预提供预警信号，实现慢性肝病管理「关口前移」。论文已发布于《Nature Communications》。来源 华硕于 3 月 9 日在国内电商平台上架 NUC 16 Pro 迷你主机，该机采用英特尔酷睿 Ultra X7 358H + 32GB RAM + 1TB 存储规格，定价为 10999 元。该机尺寸为 14.4 x 11.7 x 4.2mm，正面带有华硕徽标及 2 个 USB-A 3.2 Gen 2 10Gbps 接口、1 个 USB-C Gen 2 10Gbps 接口。机顶左上角带有 NUC 标识，机背提供 2 个雷电 4 接口、2 个 HDMI 2.1（可选 2 个 DP）、2 个 USB-A 3.2 Gen 2 10Gbps 接口、2 个 2.5G 网口。配置上，该机搭载 16 核心英特尔酷睿 Ultra X7 358H 处理器，使用双风扇散热，板载 32GB LPDDR5x 8533MHz RAM。该机支持 PCIe 5.0 SSD，支持免工具快拆升级。机身网卡支持 Wi&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://sspai.com/post/107001&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://sspai.com/post/106985&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;一次常规的升级，一个适合更多人的选择：新款 iPad Air 首发体验&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一次常规的升级一个适合更多人的选择新款-ipad-air-首发体验&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e6%ac%a1%e5%b8%b8%e8%a7%84%e7%9a%84%e5%8d%87%e7%ba%a7%e4%b8%80%e4%b8%aa%e9%80%82%e5%90%88%e6%9b%b4%e5%a4%9a%e4%ba%ba%e7%9a%84%e9%80%89%e6%8b%a9%e6%96%b0%e6%ac%be-ipad-air-%e9%a6%96%e5%8f%91%e4%bd%93%e9%aa%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：少数派&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;不同于 iPhone，iPad 可以说是市面上综合性能和体验几乎没有对手的存在，也正因如此，即使是已经维持「例行升级」好几代的 iPad Air，在升级到了 M4 芯片的版本之后，依然也有可圈之处，并且是值得大多数人选择的那一款 iPad。 自从 2020 年第四代产品面世以来，iPad Air 系列的这套模具至今已经有 6 年之久：经典的直角边框设计，也是目前整个 iPad 家族使用的设计语言。也就是说，搭载 M4 芯片的这台 iPad Air，与上一代产品在外形方面没有任何区别，配件也完全通用。 为了更好地配合连接键盘之后的横屏使用形态，iPad Air 从 2022 年推出的第五代产品开始，将前置摄像头移动到了横向边框的位置；但是比较遗憾的是，经过了 4 代产品的 3 次迭代，最新款的 iPad Air 依然不支持在 iPhone 上已成基础能力的 Face ID 解锁方式，依然必须通过 Touch ID 指纹进行解锁、安全认证及支付等操作。 配件方面，适配 iPad Air 的妙控键盘也没有任何更新，继续采用 PU 聚氨酯材料，触控板为机械式的按压结构，不像 iPad Pro 的妙控键盘已在此前升级为手感更好的铝金属掌托及通过 Taptic Engine 提供模拟触觉反馈的触控板。 Apple 产品的「Air」系列一直给人以更加轻薄和便携的印象，MacBook Air 如此&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://sspai.com/post/106985&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;http://www.huxiu.com/article/4840479.html?f=wangzhan&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;全网疯抢的AI“小龙虾”到底割了多少打工人的韭菜？&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;全网疯抢的ai小龙虾到底割了多少打工人的韭菜&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%a8%e7%bd%91%e7%96%af%e6%8a%a2%e7%9a%84ai%e5%b0%8f%e9%be%99%e8%99%be%e5%88%b0%e5%ba%95%e5%89%b2%e4%ba%86%e5%a4%9a%e5%b0%91%e6%89%93%e5%b7%a5%e4%ba%ba%e7%9a%84%e9%9f%ad%e8%8f%9c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：虎嗅&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;事先声明：我只是个臭搞钱的，不是搞技术的。本期视频是以普通用户的视角来看待小龙虾热潮的，绝不代表高玩视角，专业人士请移步专业讨论，或者尽情笑话我。经过几天高强度测试和对周边玩家的访谈，我还得出了以下观点：1、这东西的门槛不止安装，希望更高效的训练AI，基础代码技能、对AI底层技术理解能力还是要有的，但提示词的想法，创意，尤其是精炼或许更重要。2、Token成本确实不低，希望大厂们卷起来，不过相比海外已经很便宜了。3、确实有少数玩家能把小龙虾布置得服服帖帖，但是这群人是少数，并且每个行业都有这种少数人存在。4、正因为有门槛，所以消除门槛肯定是大厂们都要抢着做的事情，正如之前的计算机出现了操作系统一样，实现进一步的技术平权后，才是真正百花齐放的时候。5、现在看到的“高中生用小龙虾当老板”之类的，特别让你焦虑的文章，基本下面不是课程，就是卖产品，要么就付费社群。6、截至目前，小龙虾确实“越用越聪明了”，他和我都在进化，互相磨合，期待它未来的表现。7、焦虑要有，但需适可而止。下载虎嗅APP，第一时间获取深度独到的商业科技资讯，连接更多创新人群与线下活动&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;http://www.huxiu.com/article/4840479.html?f=wangzhan&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;http://www.huxiu.com/article/4840155.html?f=wangzhan&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;看完今年两会代表们的热门建议，更接地气、更懂老百姓了&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;看完今年两会代表们的热门建议更接地气更懂老百姓了&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%9c%8b%e5%ae%8c%e4%bb%8a%e5%b9%b4%e4%b8%a4%e4%bc%9a%e4%bb%a3%e8%a1%a8%e4%bb%ac%e7%9a%84%e7%83%ad%e9%97%a8%e5%bb%ba%e8%ae%ae%e6%9b%b4%e6%8e%a5%e5%9c%b0%e6%b0%94%e6%9b%b4%e6%87%82%e8%80%81%e7%99%be%e5%a7%93%e4%ba%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：虎嗅&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;高考英语降到100分、拒绝高价彩礼、防止AI冲击就业、带货博主负责产品真实性、废除劳务派遣制度、驾照考试增加智驾内容……今年两会代表和委员的议案提案好像比往年都更精彩、更贴近生活了。下载虎嗅APP，第一时间获取深度独到的商业科技资讯，连接更多创新人群与线下活动&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;http://www.huxiu.com/article/4840155.html?f=wangzhan&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/3Edwvdt46RR8Sd1ewSkQ?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;OpenClaw 大更新：最值得关注的不是 GPT-5.4，而是 memory&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;openclaw-大更新最值得关注的不是-gpt-54而是-memory&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#openclaw-%e5%a4%a7%e6%9b%b4%e6%96%b0%e6%9c%80%e5%80%bc%e5%be%97%e5%85%b3%e6%b3%a8%e7%9a%84%e4%b8%8d%e6%98%af-gpt-54%e8%80%8c%e6%98%af-memory&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;最近，最火的 Agent 项目 OpenClaw 又迎来一次大更新：支持 GPT-5.4、加入 Context Engine 插件接口、记忆系统可以热插拔，GitHub Star 也突破了 28 万。 表面看，这次更新内容很多：搜索、插件、通信渠道、容器部署、安全机制……几乎是一次全面升级。但如果只抓一个最关键的变化，其实是这一点：OpenClaw 开始重做 memory。 因为这段时间，OpenClaw 被吐槽最多的地方，其实就是“记性不太行”。你前面说过的东西，它后面可能就忘了；或者同一件事反复记、反复问，memory 越用越乱。很多人一开始以为这是模型不够聪明，后来才发现问题不完全在模型，而在它原来的记忆机制。 过去的 OpenClaw memory 更像“有事再去翻笔记”。系统会把内容写进日志文件和长期记忆文件，需要的时候再通过 memory_search 和 memory_get 这些工具去查。这其实是一种典型的 tools 逻辑：需要时再调用工具，把上下文找出来。 问题在于，这种方式看起来像“按需调用、更省资源”，但实际往往更慢、更费 token，因为每一次工具调用本身也有成本。而且它太依赖 Agent 自己先“想起来去查”，一旦没触发工具，这段记忆就等于不存在。同时，它在知识更新、时间推理、多会话上下文上的表现也不理想：写入新内容时，往往不知道旧记忆里已经有什么，结果&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/3Edwvdt46RR8Sd1ewSkQ?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/WDSbYFmuBNTG1652FzXB?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;OpenAI 也要 IPO 了，但这次只能争“全球第三”&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;openai-也要-ipo-了但这次只能争全球第三&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#openai-%e4%b9%9f%e8%a6%81-ipo-%e4%ba%86%e4%bd%86%e8%bf%99%e6%ac%a1%e5%8f%aa%e8%83%bd%e4%ba%89%e5%85%a8%e7%90%83%e7%ac%ac%e4%b8%89&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;看起来，2026 年可能要变成“大模型上市年”了：MiniMax、智谱之后，国内的阶跃星辰，以及海外的 OpenAI、Anthropic 也都开始认真准备 IPO。那么全球第三家上市的大模型公司，到底会是谁？ 据 The Information 报道，OpenAI 已确定由 Cooley 与 Wachtell Lipton Rosen &amp;amp; Katz 两家律所协助推进 IPO，目标上市窗口为 2026 年第四季度。在上市流程中，聘请律所通常早于投行入场，这意味着 OpenAI 的上市准备已经迈出了一个实质性步骤。 两家律所对 OpenAI 来说并不陌生。Wachtell 此前主导了 OpenAI 最近两笔重要收购：以 65 亿美元收购 Jony Ive 旗下的 io products，以及 11 亿美元收购产品分析公司 Statsig。而 Cooley 则是科技 IPO 圈的老牌选手，曾参与英伟达、Snowflake 等公司的上市项目。 英伟达 CEO 黄仁勋在周三的话也侧面印证了这一点，他表示，英伟达将向 OpenAI 投资 300 亿美元，“我认为投资 1000 亿美元的机会大概率不会出现，原因是他们很快就会上市。”并且还补了一句：“这可能是我们最后一次有机会投资这样一家具有重大影响力的公司。” 另外，根据 2 月 27 日的消息，OpenAI 官方发文确认已完成 1100 亿美&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/WDSbYFmuBNTG1652FzXB?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/4Gtk5H856ItBdN4PCkkC?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;“不用AI就滚”！千人工程师被强制 AI 写代码，Coinbase工程总监操盘，把 GitHub 都打崩了&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;不用ai就滚千人工程师被强制-ai-写代码coinbase工程总监操盘把-github-都打崩了&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%8d%e7%94%a8ai%e5%b0%b1%e6%bb%9a%e5%8d%83%e4%ba%ba%e5%b7%a5%e7%a8%8b%e5%b8%88%e8%a2%ab%e5%bc%ba%e5%88%b6-ai-%e5%86%99%e4%bb%a3%e7%a0%81coinbase%e5%b7%a5%e7%a8%8b%e6%80%bb%e7%9b%91%e6%93%8d%e7%9b%98%e6%8a%8a-github-%e9%83%bd%e6%89%93%e5%b4%a9%e4%ba%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;如果要说哪家公司在 AI 编程上足够激进，Coinbase 绝对首屈一指。 2025 年 8 月，Coinbase 发生了一件“强制上车”事件：公司给所有工程师配齐了 GitHub Copilot 和 Cursor 的企业授权，本是一次工具升级，却被其 CEO Brian Armstrong 直接变成了“忠诚度测试”。他要求工程师全员接入 AI 工具，但有人提醒他，全员采用不可能这么快，可能要几个月才能让一半工程师真正用起来。 Armstrong 听完直接“暴走”，表示一周之内必须全员完成 AI 工具 onboarding。到了周六，他真的拉了一个会议，点名那些没完成的人，当面问原因。有人是度假刚回来、理由充分；也有人说不出为什么，结果就是当场被开除，手段相当强硬。 一个月后，Armstrong 的激进又达到了新的程度：他在 X 上公开表示，Coinbase 目前约 40% 的日常代码已经由 AI 生成，而他的目标是在 30 天内把这个比例推到 50% 以上。 在工程侧，这个压力自然落到了工程总监 Chintan Turakhia 身上。他在最近一期播客里分享说，大规模部署 AI 对团队来说是“要么适应，要么灭亡”。但难点也摆在那儿——Coinbase 不是几十人的创业公司，而是一支超过一千名工程师的队伍，光让所有人都用起来就相当不容易了。 更别说还要把它落到一个正在重写的真实产品&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/4Gtk5H856ItBdN4PCkkC?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/t48Z8yiJ4rZGJZePxDLR?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;“养虾”火遍全网，AI Agent 安全问题不容忽视&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;养虾火遍全网ai-agent-安全问题不容忽视&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%bb%e8%99%be%e7%81%ab%e9%81%8d%e5%85%a8%e7%bd%91ai-agent-%e5%ae%89%e5%85%a8%e9%97%ae%e9%a2%98%e4%b8%8d%e5%ae%b9%e5%bf%bd%e8%a7%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;最近刷国内社交平台，会发现一个很奇怪的现象：全国突然开始流行“养虾”。 在各大社交平台上，“上门安装龙虾”的帖子已经多到刷屏：有人专门提供 OpenClaw 上门安装服务，收费 500～1000 元一次，到家帮你部署，现场验收。有点像当年的“上门装宽带”，只是这次装的是 AI Agent。 今天更离谱的一幕出现在深圳腾讯大厦。腾讯云干脆在楼下摆了一个“龙虾安装站”，给大家免费安装 OpenClaw。现场排起了长队，其中还包括小孩和头发花白的老人。 还有消息提到，腾讯云这次一共派出了 20 位工程师到场摆摊讲解，支持用户自带电脑，现场安装云端 OpenClaw。 如果说腾讯是开启云服务器养虾（通过轻量云 Lighthouse 一键部署），那么小米则是直接把“龙虾”搬到了手机上。就在今天，小米手机版 AI Agent「Xiaomi miclaw」正式开启封测。 不过，热闹归热闹，安全问题同样不能忽视。OpenClaw 创始人 Peter 早就提醒过，这个项目最初并不是为了公网环境设计的，但阻止不了大家把它直接放公网上。他直言：“哪怕我在隐秘文档里反复说‘别这么做’，这也不是它的设计用途。” Peter 表示，Openclaw 的 Web 服务最早只是一个本地调试工具，默认使用场景是本地可信网络，所以没有公网必需的安全机制。 腾讯也显然意识到了这一点，专门给 OpenClaw 配了《安全&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/t48Z8yiJ4rZGJZePxDLR?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/hIg1OifpYrt5Vo517yqo?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;AWS 推出智能体插件，实现云部署自动化&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;aws-推出智能体插件实现云部署自动化&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#aws-%e6%8e%a8%e5%87%ba%e6%99%ba%e8%83%bd%e4%bd%93%e6%8f%92%e4%bb%b6%e5%ae%9e%e7%8e%b0%e4%ba%91%e9%83%a8%e7%bd%b2%e8%87%aa%e5%8a%a8%e5%8c%96&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;AWS 近期发布了 Agent Plugins for AWS 开源仓库，旨在为 AI 编程智能体提供在 AWS 上进行应用架构设计、部署与运维的专项能力。首个 deploy-on-aws 插件可接收“部署到 AWS”等自然语言指令，自动生成完整的部署流水线，并提供架构建议、成本估算及基础设施即代码（IaC），实现部署工作流的革新。 该插件目前支持 Claude Code 和 Cursor，紧随 Cursor 近期市场的上线。AWS 将智能体插件定位为一项最佳实践，用于引导编程智能体输出可靠结果，同时避免模型上下文膨胀。开发者无需在提示词中反复粘贴 AWS 指南，而是可以将这些指南封装为可复用、可版本化的能力，由智能体在相关场景下直接调用。 AWS Agentic AI 的 AI 产品负责人 Marcelo S. 在 LinkedIn 帖子中将此次发布定位为解决规模化层面的一个根本性挑战： 对于那些多年致力于技术组织规模化的人而言，代码编写与规模化部署之间的矛盾，往往是导致研发效率停滞的关键所在。 此外，他强调可借助模型上下文协议（Model Context Protocol）来弥合这一差距，并确保： 我们的 AI 工具并非只生成文本，而是能够以精准、符合最佳实践的方式在我们的技术生态系统中主动执行操作。 AWS 社区构建者 Kento Ikeda 在 DEV.to 的博文中指出，&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/hIg1OifpYrt5Vo517yqo?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/DCo7S8AHJiZ0tbks5QIH?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ztopia：基于 Milvus 与 Claude Code 打造企业级 Agent｜QCon北京&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;ztopia基于-milvus-与-claude-code-打造企业级-agentqcon北京&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#ztopia%e5%9f%ba%e4%ba%8e-milvus-%e4%b8%8e-claude-code-%e6%89%93%e9%80%a0%e4%bc%81%e4%b8%9a%e7%ba%a7-agentqcon%e5%8c%97%e4%ba%ac&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;从「AI For What」到「Value From AI」，100+可落地实践案例打通 AI 实战最后一公里！ 4 月 16 日-4 月 18 日，QCon 全球软件开发大会将在北京举办。本届大会锚定 Agentic AI 时代的软件工程重塑，聚焦 Agentic AI、多智能体协作、算力优化、技术债治理、多模态和 AI 原生基础设施等前沿话题，邀请来自腾讯、阿里、百度、华为、蚂蚁、小米、网易等企业技术专家，带来百余项真实落地案例，系统性分享前沿洞察与实战干货，以技术共创探索 AI 落地新路径。 Zilliz 合伙人栾小凡已确认出席 “Agentic Engineering” 专题，并发表题为《Ztopia：基于 Milvus 与 Claude Code 打造企业级 Agent》的主题分享。在企业环境中，数据散落在飞书、Google Workspace、GitHub、Jira、Figma、CI/CD 等数十个系统中，形成严重的信息孤岛。他们构建了 Ztopia——一个以 Milvus 向量数据库为记忆基础、以 Claude Code 为推理引擎的企业级 Agent 系统，将分散的企业数据统一纳入 Agent 的长期记忆体系。本次演讲将分享 Ztopia 的整体架构设计，重点探讨向量数据库在 Agent 记忆系统中的实践——包括记忆的存储、检索、更新与遗忘策略，以及如何通过 MCP&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/DCo7S8AHJiZ0tbks5QIH?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/v1pK4PZN44ORoUZr8Fgu?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GitHub 发布年度开源趋势报告：2026 年开源生态将更趋全球化，AI 带来新挑战&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;github-发布年度开源趋势报告2026-年开源生态将更趋全球化ai-带来新挑战&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#github-%e5%8f%91%e5%b8%83%e5%b9%b4%e5%ba%a6%e5%bc%80%e6%ba%90%e8%b6%8b%e5%8a%bf%e6%8a%a5%e5%91%8a2026-%e5%b9%b4%e5%bc%80%e6%ba%90%e7%94%9f%e6%80%81%e5%b0%86%e6%9b%b4%e8%b6%8b%e5%85%a8%e7%90%83%e5%8c%96ai-%e5%b8%a6%e6%9d%a5%e6%96%b0%e6%8c%91%e6%88%98&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;GitHub 发布年度开源趋势报告，基于 Octoverse 2025 的数据，帮助开源社区为新一年做好规划。报告呈现出的图景是：开源社区规模空前庞大，而随之而来的结构性压力也日益加剧。 2025 年的核心数据十分亮眼：全年约有 3600 万新开发者加入 GitHub，仅印度就新增 520 万，巴西、印度尼西亚、日本和德国也实现了显著增长。在负责撰写这份分析的 GitHub 员工 Dylan Birtolo 看来，这些数字并非单纯的虚荣指标，而是标志着开源贡献者的地域分布、工作方式与协作模式正在发生根本性重构。 这对项目治理带来了巨大影响。当绝大多数贡献者来自不同时区、语言与文化背景时，曾经维系社区的非正式规范逐渐淡化。原本适用于少数城市集中式团队的模式已无法跨大陆扩展。GitHub 的分析指出，缺乏清晰书面治理规范（如贡献指南、行为准则、审核要求与决策文档）的项目将难以可持续地应对规模增长。 AI 是 2025 年开源领域的核心议题，但并非全是行业乐于宣扬的光鲜一面。AI 降低了新开发者的入门门槛，让他们能够更快理解代码库、编写补丁并参与贡献。但这也带来了负面影响：维护者正面临报告中所称的 “AI slop（AI 垃圾）”泛滥——大量高产、低质、且常常存在错误的贡献。这些内容耗费审核者精力，对项目却几乎没有帮助。 这一问题的规模之大，以至于 GitHub 将其比作一场针对人类注意&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/v1pK4PZN44ORoUZr8Fgu?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/DC0RIBly3IkxTTUMfy6U?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;谷歌发布智能体架构扩展原则&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;谷歌发布智能体架构扩展原则&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%b0%b7%e6%ad%8c%e5%8f%91%e5%b8%83%e6%99%ba%e8%83%bd%e4%bd%93%e6%9e%b6%e6%9e%84%e6%89%a9%e5%b1%95%e5%8e%9f%e5%88%99&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;来自谷歌与麻省理工学院的研究人员发表了一篇论文，提出了一个用于扩展多智能体系统的预测框架。该框架揭示了工具使用与系统协同之间存在权衡关系，可用于为特定任务选择最优的智能体架构。 该扩展模型依赖于系统的多个预测因素，包括底层大语言模型的智能指数、单智能体的基线性能、智能体数量、工具数量以及协调指标。研究人员发现模型中存在三种主导效应：工具‑协调权衡——对工具需求较高的任务，在多智能体带来的开销下表现会更差；能力饱和——当单智能体基线性能超过某一阈值后，增加智能体的收益会逐渐递减；以及拓扑依赖的错误放大——集中式编排能够减轻这种错误放大效应。他们还发现，最优的协调策略取决于任务类型：金融推理任务更适合采用集中式编排，而网页导航任务在分散式策略下表现更佳。在独立测试集上进行评估时，该扩展框架对最优协调策略的预测准确率达到 87%。谷歌表示： 随着 Gemini 等基础模型的持续进步，我们的研究表明：更智能的模型并不会取代对多智能体系统的需求，反而会加速其发展——前提是采用正确的架构。从启发式方法转向定量原则，我们便能构建出下一代 AI 智能体，它们不仅数量更多，而且更智能、更安全、更高效。 谷歌团队根据智能体的不同协调方式将多智能体架构分为以下几类：独立式——智能体之间无协调；集中式——智能体仅与中央编排器通信；分散式——点对点协调；混合式——兼顾集中式与分散式。每种架构都包含若干配置参&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/DC0RIBly3IkxTTUMfy6U?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/o4mjG1WsSWgVPHsJS2CQ?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;OpenClaw中国行启动：在中国发起一场AI装机运动&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;openclaw中国行启动在中国发起一场ai装机运动&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#openclaw%e4%b8%ad%e5%9b%bd%e8%a1%8c%e5%90%af%e5%8a%a8%e5%9c%a8%e4%b8%ad%e5%9b%bd%e5%8f%91%e8%b5%b7%e4%b8%80%e5%9c%baai%e8%a3%85%e6%9c%ba%e8%bf%90%e5%8a%a8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;当我装上 OpenClaw，开始和它协作的那一刻，命运的齿轮开始转动。如果说大模型的出现，让专业的开发者先尝到了红利；AI 智能体的出现，让很多 IT 从业者尝到了甜头；那么 OpenClaw 的出现，则让 AI 真正地，能够非常丝滑和简单地进入平常百姓家，未来，每一个人都有可能从 AI 中获取能力的提升。 但这也注定不是一个轻而易举实现的事情，实现目标的过程中，总是需要相应的台阶。极客邦科技作为一个有着 18 年历史，一直服务技术人，服务开发者的生态企业，好像过去所做的，就是一直在搭建这些台阶，只是在通往 AI 开发者的路上，这些台阶都装上了 AI 的翅膀。 没有那么多的豪言壮语，也没有那么多的铿锵决心，脑海中的这句话倒一直给着我力量： 2000 年前后，很多开发者第一次接触 Linux，是在一种叫 Linux Install Fest 的活动上。 大家带着自己的电脑来到现场，一起安装 Linux，一起解决各种奇怪的问题，一起聊技术。 模型能力不断突破，AI 应用层出不穷，但很多人依然会遇到三个问题： OpenClaw 中国行是一次面向 AI 开发者的全国巡回活动。 所以，你也大概看到了，我们选择的基本都是有 TGO 鲲鹏会分会的地方，如果暂时还没有包含你所在的城市，随时联系我，咱们一起共创，说不准下一次活动就在你的城市举行。 如果你正在做 AI 项目，也非常欢迎来展示，我们和专&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/o4mjG1WsSWgVPHsJS2CQ?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/670.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;OpenClaw 3.8 更新炸场：龙虾不睡觉，全球程序员连夜赶工&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;openclaw-38-更新炸场龙虾不睡觉全球程序员连夜赶工&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#openclaw-38-%e6%9b%b4%e6%96%b0%e7%82%b8%e5%9c%ba%e9%be%99%e8%99%be%e4%b8%8d%e7%9d%a1%e8%a7%89%e5%85%a8%e7%90%83%e7%a8%8b%e5%ba%8f%e5%91%98%e8%bf%9e%e5%a4%9c%e8%b5%b6%e5%b7%a5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;3 月 8 日凌晨，OpenClaw 3.7 发布；3 月 9 日下午，OpenClaw 3.8 就发布了。这帮人的发版节奏，有点过于疯狂了！全球程序员跟着连夜赶工。一句话让你看懂这次更新这次更新只干了四件大事：1.你的智能体终于知道是谁在跟它说话了（ACP 溯源）2.部署前终于可以先存档再冲（openclaw backup）3.Telegram 的重复消息彻底凉了4.12+ 项安全修复，补了一堆你可能都没发现的洞官方自己也说：我们修复的问题比制造的多。进步了。重点一：ACP 溯源 —— 你的 Agent 终于认识你了说人话：之前你问智能体帮我做个报告，它根本不知道你是谁、有什么权限、该信你到什么程度。就像你雇了个保安，但他连门禁卡都不认，见谁都放进来 —— 这合理吗？3.8 之后，不一样了。OpenClaw 引入了 ACP（Agent Communication Protocol）溯源机制。现在每条发给智能体的指令，都自带身份证 —— 智能体能识别是谁发的、从哪个入口来的、有没有权限干这件事。对普通用户来说，这意味着：多人协作场景下，Agent 不再无法无天权限管控更精细，想拦的消息&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/670.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/667.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;黑鲨预热凤鸣耳夹式蓝牙耳机 Pro，3 月 20 日发布&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;黑鲨预热凤鸣耳夹式蓝牙耳机-pro3-月-20-日发布&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%bb%91%e9%b2%a8%e9%a2%84%e7%83%ad%e5%87%a4%e9%b8%a3%e8%80%b3%e5%a4%b9%e5%bc%8f%e8%93%9d%e7%89%99%e8%80%b3%e6%9c%ba-pro3-%e6%9c%88-20-%e6%97%a5%e5%8f%91%e5%b8%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，黑鲨今天在微博预热凤鸣耳夹式蓝牙耳机 Pro 新品，主打 AI 入耳、无感贴合，号称“澎湃音质，声声入魂”，3 月 20 日 17:00 发布。值得注意的是，黑鲨已在昨天宣布了相同日期举行的 2026 年春季新品发布会，届时将推出冰封制冷背夹 6 Max 磁吸版、冰封液冷背夹 6 Ultra、冰封直播制冷背夹、笔记本散热器风神 Pro 等散热器新品。作为比较，黑鲨最近几个月主要推出了刀锋 3 磁吸充电宝、磁吸蓝牙音箱、磁吸无线充、凤鸣头戴式耳机、冷暖鼠标、游戏指套等产品。IT之家了解到，黑鲨上月还在海外发布了一款名为 Black Shark Gaming Tablet 的电竞小平板，该机匹配一块 8.8 英寸 2560 × 1600 分辨率 144Hz 面板，采用高通骁龙 8s Gen 3 处理器 + 12GB LPDDR5X RAM + 256GB UFS 4.0 存储配置，内置 7300 mAh 电池。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/667.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/660.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;阿里云将在上海金山建设超大规模算力中心，重点部署平头哥“真武”芯片&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;阿里云将在上海金山建设超大规模算力中心重点部署平头哥真武芯片&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%98%bf%e9%87%8c%e4%ba%91%e5%b0%86%e5%9c%a8%e4%b8%8a%e6%b5%b7%e9%87%91%e5%b1%b1%e5%bb%ba%e8%ae%be%e8%b6%85%e5%a4%a7%e8%a7%84%e6%a8%a1%e7%ae%97%e5%8a%9b%e4%b8%ad%e5%bf%83%e9%87%8d%e7%82%b9%e9%83%a8%e7%bd%b2%e5%b9%b3%e5%a4%b4%e5%93%a5%e7%9c%9f%e6%ad%a6%e8%8a%af%e7%89%87&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，阿里云昨天与上海市金山区政府签署战略合作协议，加速建设阿里飞天云智能华东算力中心，将成为华东地区规模最大的智算枢纽之一。IT之家在此援引官方公众号消息，根据新合作协议，该超大规模算力中心将重点部署平头哥“真武”芯片，通过构建从底层芯片、智算平台到上层应用的全栈自主算力底座，力争成为绿色算力中心标杆。同时，阿里云将深度参与金山区政务服务与城市治理的数字化转型，支持金山区建设稳定可靠的政务服务基础设施，并通过 AI 技术提升公共服务的实时响应效率。值得注意的是，阿里云与上海市金山区的合作由来已久，总投资 400 亿元的阿里云金山算力中心早在 2021 年就扎根金山。据IT之家此前援引《科创板日报》消息，接近阿里的消息人士透露，平头哥真武 PPU 芯片总出货量已达数十万片，超过寒武纪，在国产 GPU 厂商中领先。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/660.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/656.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;零刻将推预装 OpenClaw 的龙虾红专属迷你主机，还有 SSD 升级包&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;零刻将推预装-openclaw-的龙虾红专属迷你主机还有-ssd-升级包&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%9b%b6%e5%88%bb%e5%b0%86%e6%8e%a8%e9%a2%84%e8%a3%85-openclaw-%e7%9a%84%e9%be%99%e8%99%be%e7%ba%a2%e4%b8%93%e5%b1%9e%e8%bf%b7%e4%bd%a0%e4%b8%bb%e6%9c%ba%e8%bf%98%e6%9c%89-ssd-%e5%8d%87%e7%ba%a7%e5%8c%85&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，随着 OpenClaw 在全球走红，零刻今日推出一体化 AI 解决方案 —— 从预装 OpenClaw 的专属龙虾红配色整机，到双系统自由切换版本，再到即插即用的 SSD 升级包。全新整机方案全系预装整机均采用全金属机身，搭配龙虾红专属配色。根据使用场景与性能需求，零刻提供以下三大类整机选择：1、预装 OpenClaw + 本地大模型版型号：GTR9 Pro 395、SER10 MAX 470、SER9 Pro 370、GTi15 Ultra 285H、GTi14 Pro 185H本地运行意味着每一次对话与推理均在设备端完成，不再消耗云端 Token，长期高频使用可节省费用。核心 AI 推理在设备端完成，从架构层面减少不必要的数据传输环节，降低信息外流风险。例如 GTR9 Pro 395 搭载 AMD AI Max + 395 处理器，最高显存可达 96G，GPT-OSS120B 参数模型推理速度约 52 tokens / 秒。2、预装 OpenClaw 云端模型版型号：SER9 Pro 255、EQR7 Pro 7735HS、EQi12 Pro 123&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/656.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/627.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;华为终端公布问界 M6 汽车「脉冲蓝」配色官图，可选黑曜套件&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;华为终端公布问界-m6-汽车脉冲蓝配色官图可选黑曜套件&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8d%8e%e4%b8%ba%e7%bb%88%e7%ab%af%e5%85%ac%e5%b8%83%e9%97%ae%e7%95%8c-m6-%e6%b1%bd%e8%bd%a6%e8%84%89%e5%86%b2%e8%93%9d%e9%85%8d%e8%89%b2%e5%ae%98%e5%9b%be%e5%8f%af%e9%80%89%e9%bb%91%e6%9b%9c%e5%a5%97%e4%bb%b6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，华为终端官方今日放出了问界 M6 汽车的「脉冲蓝」配色。问界 M6「脉冲蓝」配色，光影流转间随角异色。深邃的蓝与澄澈的青无缝衔接，如能量脉冲划过车身曲面，瞬间张力被光影定格。目光所及，动势已然迸发。图片显示，问界 M6 的「脉冲蓝」车标为黑色，同时车窗饰条等也为熏黑设计，并提供红色刹车卡钳，预计为黑曜运动套件。据IT之家了解，问界 M6 采用俯冲动感姿态设计，搭载顶置激光雷达、半隐藏式门把手、晶耀大灯等，车尾配备 AITO 发光尾灯。车长 4960mm，宽 1985mm，高 1736mm，轴距为 2950mm。华为常务董事、产品投资评审委员会主任、终端 BG 董事长余承东在 2 月预告了问界 M6 的全部车色，包括橙、白、黑、银、青、紫、蓝等。目前，「活力橙」「流光青」「星夜紫」「钛空银」和「脉冲蓝」五款配色的外观高清图均已公开。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/627.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;📱 手机 / 消费电子&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-手机--消费电子&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e6%89%8b%e6%9c%ba--%e6%b6%88%e8%b4%b9%e7%94%b5%e5%ad%90&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;&lt;a href=&#34;https://www.theverge.com/ai-artificial-intelligence/891723/apple-homepad-delay-rumor&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;苹果智能家居显示屏谣言现在指向iOS 27的秋季发布&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;苹果智能家居显示屏谣言现在指向ios-27的秋季发布&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%8b%b9%e6%9e%9c%e6%99%ba%e8%83%bd%e5%ae%b6%e5%b1%85%e6%98%be%e7%a4%ba%e5%b1%8f%e8%b0%a3%e8%a8%80%e7%8e%b0%e5%9c%a8%e6%8c%87%e5%90%91ios-27%e7%9a%84%e7%a7%8b%e5%ad%a3%e5%8f%91%e5%b8%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Apple smart home display rumors now point to a fall launch with iOS 27&lt;/em&gt;
&lt;strong&gt;来源：The Verge&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;据报道，传闻中的“带屏幕的HomePod”将于2025年推出，然后是今年春天，现在，根据最新更新，它已经上架，直到今年秋天。Leaker Kosutami上周在X上发布了同样多的内容，今天，彭博记者Mark Gurman跟进了[]&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.theverge.com/ai-artificial-intelligence/891723/apple-homepad-delay-rumor&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/review/apple-iphone-17e/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;苹果iPhone 17E评测： MagSafe与众不同&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;苹果iphone-17e评测-magsafe与众不同&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%8b%b9%e6%9e%9ciphone-17e%e8%af%84%e6%b5%8b-magsafe%e4%b8%8e%e4%bc%97%e4%b8%8d%e5%90%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Apple iPhone 17e Review: MagSafe Makes a Difference&lt;/em&gt;
&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;立即购买多种购买选项在百思买以599美元的价格购买Apple 600美元CommentLoader保存故事保存此故事CommentLoader保存故事保存此故事评级： 7/10 WIRED完美的性能。可靠的一日电池续航时间。坚固的摄像头。现在有MagSafe。提高了屏幕耐用性。TIRED屏幕卡在60 Hz。仍然没有超宽带芯片。单后置摄像头是有限的。您是否愿意以相同的价格购买全新的MacBook Neo-整台电脑或Apple最便宜的iPhone 17e智能手机或&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/review/apple-iphone-17e/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://arstechnica.com/gadgets/2026/03/testing-apples-2026-16-inch-macbook-pro-m5-max-and-its-new-performance-cores/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;测试Apple 2026 16英寸MacBook Pro、M5 Max及其新的“性能”内核&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;测试apple-2026-16英寸macbook-prom5-max及其新的性能内核&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%b5%8b%e8%af%95apple-2026-16%e8%8b%b1%e5%af%b8macbook-prom5-max%e5%8f%8a%e5%85%b6%e6%96%b0%e7%9a%84%e6%80%a7%e8%83%bd%e5%86%85%e6%a0%b8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Testing Apple&amp;rsquo;s 2026 16-inch MacBook Pro, M5 Max, and its new &amp;ldquo;performance&amp;rdquo; cores&lt;/em&gt;
&lt;strong&gt;来源：Ars Technica&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;文字设置故事文字大小小标准大宽度&lt;em&gt;标准宽链接标准橙色&lt;/em&gt;仅限订阅者了解更多尽量减少到导航Apple的M5 Pro和M5 Max对Apple的高端笔记本电脑和台式机芯片的构建方式做出了巨大的改变。我们已经深入介绍了这些变化，但从本质上讲： M5 Pro和M5 Max不再是单片芯片，所有CPU和GPU内核以及所有其他内容都集成在单个硅芯片中。使用“全新的融合架构&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://arstechnica.com/gadgets/2026/03/testing-apples-2026-16-inch-macbook-pro-m5-max-and-its-new-performance-cores/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://sspai.com/post/106983&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;一次有诚意的升级，一份加量不加价的体验：iPhone 17e 首发体验&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一次有诚意的升级一份加量不加价的体验iphone-17e-首发体验&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e6%ac%a1%e6%9c%89%e8%af%9a%e6%84%8f%e7%9a%84%e5%8d%87%e7%ba%a7%e4%b8%80%e4%bb%bd%e5%8a%a0%e9%87%8f%e4%b8%8d%e5%8a%a0%e4%bb%b7%e7%9a%84%e4%bd%93%e9%aa%8ciphone-17e-%e9%a6%96%e5%8f%91%e4%bd%93%e9%aa%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：少数派&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;作为新一代 iPhone 机型的入门版本，iPhone 17e 不仅补齐了前一代机型的若干基础体验，在价格方面也较此前表现出了意外的诚意：起售价格不变的基础上，存储容量加倍起步，让新一代的 iPhone 全线产品彻底告别 128GB 时代。要知道，同时更新的 iPad Air (M4) 机型，还依然保持着 128GB 的存储容量选项。 外观方面，iPhone 17e 与 iPhone 16e 相比没有任何变化，同样的尺寸与相近的重量、同样的单摄镜头模组，以及依然未配备灵动岛的屏幕。不同的是，超瓷晶面板 2 成了新一代 iPhone 的标配，同样能为 iPhone 17e 提供多达 3 倍的抗刮划能力，并且还有能够减少眩光的抗反射涂层。 最为吸引人的是，在原有黑色和白色之外，iPhone17e 新增了全新的浅粉色选项。在 iPhone 17e 的玻璃背板上，浅粉色带来的依旧是「素净」的视觉效果：粉色在背板中若隐若现，并会随光线变化呈现不同的视觉色彩效果。为了更好地衬托全新的浅粉色，Apple 也推出了同色的 MagSafe 硅胶保护壳和斜挎挂绳，让 iPhone 17e 能与配件搭配相得益彰。 令人略感失望却又不出所料的是，iPhone 17e 的屏幕继续保持了「刘海」设计，没有支持许多人期待的灵动岛功能。 不过，在更大的起始容量、更耐用的屏幕面板、终于支持 MagSafe 等升级的&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://sspai.com/post/106983&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/665.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;群联 CEO 潘健成：NAND 原厂报价近期无预警一夜跳涨 50%&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;群联-ceo-潘健成nand-原厂报价近期无预警一夜跳涨-50&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%be%a4%e8%81%94-ceo-%e6%bd%98%e5%81%a5%e6%88%90nand-%e5%8e%9f%e5%8e%82%e6%8a%a5%e4%bb%b7%e8%bf%91%e6%9c%9f%e6%97%a0%e9%a2%84%e8%ad%a6%e4%b8%80%e5%a4%9c%e8%b7%b3%e6%b6%a8-50&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，参考台媒《电子时报》报道，SSD 第三方主控大厂群联 CEO 潘健成表示，NAND 市场供需失衡状况超出预期，近日 NAND 原厂报价突然无预警“一夜飙涨 50%”，反映供应端当前极度吃紧。群联目前的库存水位已提升至 500 亿新台币（IT之家注：现汇率约合 110.45 亿元人民币）；该企业已同上游存储器原厂和下游主要客户都达成了 LTA（长期协议）；为保持供应稳定，公司正与部分供应商协商预付款以获得产能优先分配权，保障企业级产品生产。群联当前的业务也显著转向非消费级领域：企业级产品对其整体营收的贡献有望在本季度达到 30%，而群联当前的库存中仅有 3% 是零售端产品。群联表示，其 QLC UFS 正在接受头部智能手机 OEM 的测试验证，企业级 PCIe Gen6 SSD 主控样品计划今年 8 月交付，PCIe Gen7 世代芯片也在开发中。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/665.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/657.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;荣耀新款游戏本曝光：i7-14650HX+RTX5060、16GB DDR5+512GB/1TB SSD，有望归属 WIN 系列&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;荣耀新款游戏本曝光i7-14650hxrtx506016gb-ddr5512gb1tb-ssd有望归属-win-系列&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%8d%a3%e8%80%80%e6%96%b0%e6%ac%be%e6%b8%b8%e6%88%8f%e6%9c%ac%e6%9b%9d%e5%85%89i7-14650hxrtx506016gb-ddr5512gb1tb-ssd%e6%9c%89%e6%9c%9b%e5%bd%92%e5%b1%9e-win-%e7%b3%bb%e5%88%97&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，博主 @数码闲聊站 今日发文，称好像摸到了一台荣耀游戏本。该机搭载 Intel i7-14650HX 处理器 + RTX5060 显卡，辅以 16GB DDR5+512GB/1TB SSD，同时风扇怼满。博主“建议”这款笔记本命名 WIN 游戏本，和 WIN 手机一起打性能认知。另外博主还透露，荣耀 WIN 2 新机已开模测试，卷核心 + 外围配置。IT之家注意到，去年 12 月，荣耀终端股份有限公司 PC 产品总经理 @朱臣才-荣耀 发文称，荣耀全新游戏本即将发布（具体发布时间暂未公布）。而在同月的荣耀新品发布会上，荣耀官方明确表示，全新游戏本产品将在今年推出，且是《三角洲行动》职业联赛指定笔记本。相关阅读：《荣耀预告全新游戏本产品，明年发布》《荣耀游戏本将至？林林预告 WIN Gaming&amp;rsquo;s coming soon》&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/657.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/655.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;保时捷推出 Cayenne S 纯电版：最大功率 490 千瓦，起售价约 12.6 万美元&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;保时捷推出-cayenne-s-纯电版最大功率-490-千瓦起售价约-126-万美元&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bf%9d%e6%97%b6%e6%8d%b7%e6%8e%a8%e5%87%ba-cayenne-s-%e7%ba%af%e7%94%b5%e7%89%88%e6%9c%80%e5%a4%a7%e5%8a%9f%e7%8e%87-490-%e5%8d%83%e7%93%a6%e8%b5%b7%e5%94%ae%e4%bb%b7%e7%ba%a6-126-%e4%b8%87%e7%be%8e%e5%85%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，有时候，一个产品阵容里最有意思的车型，往往不是旗舰款。保时捷深谙此道，这也是其旗下多数车系都提供丰富配置版本的原因。如今，纯电版卡宴又迎来了一款全新车型 ——Cayenne S 纯电版（Cayenne S Electric）。作为家族第三位成员，新车定位介于基础版与卡宴 Turbo 纯电版之间。至少从数据上看，其参数十分亮眼，搭载双电机四驱系统，常规状态下可输出 536 马力（400 千瓦），启动弹射起步后，最大功率可达 657 马力（490 千瓦）。这足以让这台中大型纯电 SUV 在 3.6 秒内完成 0–60 英里 / 小时（0–96 公里 / 小时）加速，最高时速可达 155 英里 / 小时（250 公里 / 小时）。对于一台家用大型 SUV 而言，这样的动力堪称强悍。作为对比，基础版保时捷卡宴纯电版最大功率为 435 马力。开启超增压功能后，0–60 英里 / 小时加速需 4.5 秒，四分之一英里加速为 13.2 秒，最高时速 143 英里 / 小时（230 公里 / 小时）。两台电机均为永磁同步电机，后置电机采用直油冷却技术，以应对高负荷工况下&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/655.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/621.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;UBI Research：OLED 在平板 / 笔记本 / 显示器市场占比均不足 10%&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;ubi-researcholed-在平板--笔记本--显示器市场占比均不足-10&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#ubi-researcholed-%e5%9c%a8%e5%b9%b3%e6%9d%bf--%e7%ac%94%e8%ae%b0%e6%9c%ac--%e6%98%be%e7%a4%ba%e5%99%a8%e5%b8%82%e5%9c%ba%e5%8d%a0%e6%af%94%e5%9d%87%e4%b8%8d%e8%b6%b3-10&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，韩国显示领域研调机构 UBI Research 当地时间 10 日表示，OLED 在平板电脑 / 笔记本电脑 / 显示器这三个细分市场的渗透率分别仅有 5.9% / 4.4% / 2.0%，与智能手机领域的 52.9% 存在很大差距。这意味着，中尺寸的 IT OLED 仍有很大的增长潜力，是推动 OLED 行业未来进一步发展的关键点。不过要想将潜在市场转变为实际市占，尚处起步阶段的 IT OLED 还有很多路要走。▲ 配备 OLED 显示屏的华硕无畏 Pro 16 2026 酷睿版以笔记本电脑面板为例，高端市场可接受 OLED 相对 LCD 存在 80&lt;del&gt;150% 的溢价，而到主流市场这一容忍度就只剩 20&lt;/del&gt;50%，IT OLED 需要大幅改善成本结构才能从 LCD 手中赢得份额。UBI Research 分析称，仅生产线从 G6 转移到 G8.6 一项就有望带来 32% 的成本降低；单堆栈 OLED 也可节约成本，但这需要 RGB 发光材料的技术改进；以彩色滤光片 (COE) 取代偏振片也是关键改进点之一。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/621.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;☁️ 云计算 / 基础设施&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-云计算--基础设施&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e4%ba%91%e8%ae%a1%e7%ae%97--%e5%9f%ba%e7%a1%80%e8%ae%be%e6%96%bd&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/09/it-looks-like-the-doj-isnt-going-to-break-up-live-nation-and-ticketmaster/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;看来司法部不会拆分Live Nation和Ticketmaster&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;看来司法部不会拆分live-nation和ticketmaster&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%9c%8b%e6%9d%a5%e5%8f%b8%e6%b3%95%e9%83%a8%e4%b8%8d%e4%bc%9a%e6%8b%86%e5%88%86live-nation%e5%92%8cticketmaster&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;It looks like the DOJ isn’t going to break up Live Nation and Ticketmaster&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;创始人峰会2026 ，波士顿：不要错过高达300 $的门票优惠。立即注册。Disrupt 2026通行证最高可节省$ 680。今晚太平洋时间晚上11:59结束。立即注册。图片来源： Mario Tama/Getty Images Media &amp;amp; Entertainment看起来美国司法部不会在太平洋时间2026年3月9日上午11:49分解Live Nation和Ticketmaster Amanda Silberling。经过一场备受瞩目的反垄断诉讼，美国司法部周一表示，它已与Ticketmaster及其母公司达成初步和解。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/09/it-looks-like-the-doj-isnt-going-to-break-up-live-nation-and-ticketmaster/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.technologyreview.com/2026/03/09/1132352/the-usability-imperative-for-securing-digital-asset-devices/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;保护数字资产设备的可用性势在必行&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;保护数字资产设备的可用性势在必行&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bf%9d%e6%8a%a4%e6%95%b0%e5%ad%97%e8%b5%84%e4%ba%a7%e8%ae%be%e5%a4%87%e7%9a%84%e5%8f%af%e7%94%a8%e6%80%a7%e5%8a%bf%e5%9c%a8%e5%bf%85%e8%a1%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;The usability imperative for securing digital asset devices&lt;/em&gt;
&lt;strong&gt;来源：MIT Technology Review&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;当托尼·法德尔（ Tony Fadell ）开始研究iPod时，可用性往往胜过安全性。结果是一个迭代过程。每次有人发现安全漏洞或破解设备的方法时，开发小组都会迭代添加措施并解决问题。然而，经常会发现缺陷，安全的设计&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.technologyreview.com/2026/03/09/1132352/the-usability-imperative-for-securing-digital-asset-devices/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/Z1jrMb7rSgZxCQThslh0?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Google Cloud云监控指标全面支持OpenTelemetry&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;google-cloud云监控指标全面支持opentelemetry&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#google-cloud%e4%ba%91%e7%9b%91%e6%8e%a7%e6%8c%87%e6%a0%87%e5%85%a8%e9%9d%a2%e6%94%af%e6%8c%81opentelemetry&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;近期，Google Cloud宣布在云监控服务中全面支持OpenTelemetry协议（OTLP），此举标志着其在跨观测技术栈统一遥测数据采集方面迈出了重要一步。借助这次部署，用户现在可以使用一个供应商无关的管道，将 OTLP 格式的指标数据与追踪记录和日志同步发送至云监控服务，从而实现更灵活的、基于标准的监控部署，并简化遥测数据采集流程，提升其一致性。 本次更新是对之前已经支持的 OTLP 追踪数据摄取的进一步深化，彰显了 Google Cloud 将 OpenTelemetry 作为遥测数据通用格式和 API 的坚定承诺。开发人员可以使用OpenTelemetry SDK生成指标，然后通过 OTLP 直接发送到云监控，或者通过 OpenTelemetry 收集器。在默认情况下，摄取的 OTLP 指标数据以类似于 Prometheus 的数据格式存储，并且可以使用标准的监控工具进行全量查询。 Google Cloud 在支持 OTLP 指标方面做了多项增强，改善了可观测性工作流，包括：delta-type指标（通过仅报告计数器变化来减少客户端内存占用）；显示动态桶大小的指数直方图；扩展命名约定，支持点和斜杠，使之更符合标准的 OpenTelemetry 语义规范。这些特性有助于弥合云原生监控工具、第三方遥测管道与 Google Cloud 自有监控基础设施之间的差距。 除了原生&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/Z1jrMb7rSgZxCQThslh0?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;🔒 网络安全&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-网络安全&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e7%bd%91%e7%bb%9c%e5%ae%89%e5%85%a8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/654.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;比亚迪仰望 U8L「白玉金」车色上线：24K 真金车标、承袭宋瓷「白釉描金」匠艺&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;比亚迪仰望-u8l白玉金车色上线24k-真金车标承袭宋瓷白釉描金匠艺&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%af%94%e4%ba%9a%e8%bf%aa%e4%bb%b0%e6%9c%9b-u8l%e7%99%bd%e7%8e%89%e9%87%91%e8%bd%a6%e8%89%b2%e4%b8%8a%e7%ba%bf24k-%e7%9c%9f%e9%87%91%e8%bd%a6%e6%a0%87%e6%89%bf%e8%a2%ad%e5%ae%8b%e7%93%b7%e7%99%bd%e9%87%89%e6%8f%8f%e9%87%91%e5%8c%a0%e8%89%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，比亚迪仰望汽车今日宣布，仰望 U8L「白玉金」车色正式上线。据介绍，该色承袭宋瓷「白釉描金」匠艺，以萤石白为底、日珥金为点缀，同时还采用 24K 真金车标设计。据IT之家此前报道，在 3 月 5 日晚的比亚迪二代刀片电池暨闪充技术发布会上，比亚迪发布了 2026 款仰望 U7 、U8 和 U8L 鼎世版车型，新车搭载第二代刀片电池及闪充技术。仰望 U8L 2026 款提升了续航，新增闪充技术，同时还提供三大安全升级：应急浮水紧急自动激活、NOA 爆胎稳行稳停、全场景隐私安全，老款车型后续也能通过 OTA 获得这些功能，售价 130 万元起。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/654.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/653.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;SteamOS 系统 3.7.20 发布，添加 NTsync 驱动、修复大量 Bug&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;steamos-系统-3720-发布添加-ntsync-驱动修复大量-bug&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#steamos-%e7%b3%bb%e7%bb%9f-3720-%e5%8f%91%e5%b8%83%e6%b7%bb%e5%8a%a0-ntsync-%e9%a9%b1%e5%8a%a8%e4%bf%ae%e5%a4%8d%e5%a4%a7%e9%87%8f-bug&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，V社昨天为 SteamOS 系统发布 3.7.20 版更新，主要整合了此前在测试版修复的 Bug 以及功能优化。IT之家了解到，本次更新最显著的变化集中在无障碍功能以及 Steam Input 手柄设置。同时还修复了界面元素闪烁、“最近游戏”页面缩略图分辨率过低、按键映射、Switch Pro 手柄的灯在不该亮时亮起等长期存在问题。底层方面，V社这次将此前测试的 NTsync 驱动合并进主线版本，该驱动可在使用 Proton 兼容层时更接近 Windows NT 的同步机制，某些情况下可为部分游戏带来明显性能提升。同时，此次更新还改进了桌面、Steam Deck 与移动设备的界面布局和导航，聊天界面新增 / store 指令。此外，本次更新还修复了安全漏洞 CVE-2025-66005 和 CVE-2025-14338，为 InputPlumber dbus 接口 启用 polkit。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/653.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;💰 科技商业&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-科技商业&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e7%a7%91%e6%8a%80%e5%95%86%e4%b8%9a&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;&lt;a href=&#34;https://techcrunch.com/2026/03/10/uzbekistans-uzum-valuation-rises-1-5x-in-seven-months-to-2-3b/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;乌兹别克斯坦的Uzum估值在七个月内跃升超过50 ％至23亿$&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;乌兹别克斯坦的uzum估值在七个月内跃升超过50-至23亿&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b9%8c%e5%85%b9%e5%88%ab%e5%85%8b%e6%96%af%e5%9d%a6%e7%9a%84uzum%e4%bc%b0%e5%80%bc%e5%9c%a8%e4%b8%83%e4%b8%aa%e6%9c%88%e5%86%85%e8%b7%83%e5%8d%87%e8%b6%85%e8%bf%8750-%e8%87%b323%e4%ba%bf&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Uzbekistan’s Uzum valuation leaps over 50% in seven months to $2.3B&lt;/em&gt;
&lt;strong&gt;来源：TechCrunch&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;创始人峰会2026 ，波士顿：不要错过高达300 $的门票优惠。立即注册。Disrupt 2026通行证最高可节省$ 680。今晚太平洋时间晚上11:59结束。立即注册。图片来源： Uzum Commerce Uzbekistans Uzum的估值在七个月内跃升超过50% ，达到23亿$ Jagmeet Singh 12:15 AM PDT · 2026年3月10日乌兹别克斯坦金融科技公司Uzum的估值达到23亿$ —比七个月前高出约53% —因为投资者对该国新兴数字经济的押注越来越大。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://techcrunch.com/2026/03/10/uzbekistans-uzum-valuation-rises-1-5x-in-seven-months-to-2-3b/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/newsflashes/3716859598304901?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;陕西煤业：2025年净利润165.48亿元，同比减少25.99%&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;陕西煤业2025年净利润16548亿元同比减少2599&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%99%95%e8%a5%bf%e7%85%a4%e4%b8%9a2025%e5%b9%b4%e5%87%80%e5%88%a9%e6%b6%a616548%e4%ba%bf%e5%85%83%e5%90%8c%e6%af%94%e5%87%8f%e5%b0%912599&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;36氪获悉，陕西煤业公告，2025年营业总收入1581.89亿元，同比减少14.10%；实现归属于上市公司股东的净利润165.48亿元，同比减少25.99%。业绩下降主要受煤炭产品销售价格同比下降影响，同时交易性金融资产公允价值变动增加收益以及投资收益增加。原文链接下一篇江苏：引导有条件的地区设立脑机接口产业投资基金，吸引社会资本参与，助力种子期、初创期企业发展壮大36氪获悉，江苏省工信厅等九部门印发《江苏省脑机接口产业创新发展行动方案》，其中提到，强化金融支持。发挥省战略性新兴产业母基金引导作用，支持相关产业专项基金及子基金投向应用场景广阔、成长性强的脑机接口项目。引导有条件的地区设立脑机接口产业投资基金，吸引社会资本参与，助力种子期、初创期企业发展壮大。依托省科技金融综合服务平台，汇聚“苏科贷”“专精特新贷”等政银合作信贷产品，鼓励金融机构开发服务脑机接口产业的特色金融产品，提供涵盖“股债贷保担”的一站式综合科技金融服务。 8点1氪丨胖东来12名店长共分2.4亿资产利润；Mac mini销量暴增或因OpenClaw爆火导致；2026年中国电影票房在全球占比超28%，领跑全球电影市场 OpenClaw 3.8继续炸场，龙虾不睡觉，全球程序员连夜赶工&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/newsflashes/3716859598304901?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/630.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;美国电动空中出租车监管松绑，26 州最早今夏启动测试&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;美国电动空中出租车监管松绑26-州最早今夏启动测试&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%be%8e%e5%9b%bd%e7%94%b5%e5%8a%a8%e7%a9%ba%e4%b8%ad%e5%87%ba%e7%a7%9f%e8%bd%a6%e7%9b%91%e7%ae%a1%e6%9d%be%e7%bb%9126-%e5%b7%9e%e6%9c%80%e6%97%a9%e4%bb%8a%e5%a4%8f%e5%90%af%e5%8a%a8%e6%b5%8b%e8%af%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，美国联邦航空管理局（FAA）已批准 8 项试点计划，允许包括 Archer Aviation、Beta Technologies、Joby Aviation 和 Wisk 在内的多家企业最早于今年夏季开展电动飞行器的大规模测试。美国运输部部长肖恩 · 达菲当地时间周一发表讲话称，这项为期三年、覆盖 26 个州的计划，旨在确保美国企业在用于个人出行、区域交通、货运物流和应急医疗的下一代飞行器领域保持领先地位。据IT之家了解，该试点项目全称为先进空中交通与电动垂直起降飞行器融合试点计划，于去年由美国总统唐纳德 · 特朗普通过行政令宣布推出，目的是加速这类未来飞行器的研发进程。近年来，众多电动垂直起降飞行器（eVTOL）企业纷纷涌现，承诺推出城市空中出租车及其他区域电动飞行器。然而，这类飞行器实现商业运营需要数年时间和数亿美元资金，且 FAA 对任何新型飞行器的认证流程都长达数年。此次试点计划允许相关企业在未获得完整监管认证的情况下，即可开展 eVTOL 飞行器测试。这种加速推进的时间表，有望为 Archer、Beta、Joby 等近年上市的 eVTOL 企业&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/630.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;🔬 科学 / 前沿技术&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-科学--前沿技术&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e7%a7%91%e5%ad%a6--%e5%89%8d%e6%b2%bf%e6%8a%80%e6%9c%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;&lt;a href=&#34;https://36kr.com/newsflashes/3716890509653384?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;乘联分会崔东树：1月二手车转籍比例达到35%当期历史高位&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;乘联分会崔东树1月二手车转籍比例达到35当期历史高位&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b9%98%e8%81%94%e5%88%86%e4%bc%9a%e5%b4%94%e4%b8%9c%e6%a0%911%e6%9c%88%e4%ba%8c%e6%89%8b%e8%bd%a6%e8%bd%ac%e7%b1%8d%e6%af%94%e4%be%8b%e8%be%be%e5%88%b035%e5%bd%93%e6%9c%9f%e5%8e%86%e5%8f%b2%e9%ab%98%e4%bd%8d&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;36氪获悉，乘联分会秘书长崔东树发文表示，2026年1月，全国二手车市场交易量173万台，环比降8%，同比增18%，交易金额为1106亿元，同比增14.8%。2025年1-12月，二手车累计交易量2011万台，同比增2.5%，交易额12898亿元，增0.4%。近几年二手车的转籍比例在25到30%之间波动的趋势，2026年1月达到35%的当期历史高位。2026年1月，全国新能源二手车市场交易量15.8万台，环比降6%，同比增长74%，新能源渗透率12.2%。2025年1-12月，新能源二手车累计交易量161万台，同比增43%。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/newsflashes/3716890509653384?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/669.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;比亚迪领汇 e7 全国 127 城首批展车已到店，覆盖上海、天津、重庆等&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;比亚迪领汇-e7-全国-127-城首批展车已到店覆盖上海天津重庆等&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%af%94%e4%ba%9a%e8%bf%aa%e9%a2%86%e6%b1%87-e7-%e5%85%a8%e5%9b%bd-127-%e5%9f%8e%e9%a6%96%e6%89%b9%e5%b1%95%e8%bd%a6%e5%b7%b2%e5%88%b0%e5%ba%97%e8%a6%86%e7%9b%96%e4%b8%8a%e6%b5%b7%e5%a4%a9%e6%b4%a5%e9%87%8d%e5%ba%86%e7%ad%89&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，比亚迪领汇汽车今日宣布，领汇 e7 全国 127 城首批展车已到店，覆盖上海、天津、重庆等城市，主打“发布即布局，布局即到店”。IT之家注意到，比亚迪领汇汽车旗下首款车型领汇 e7 已于上个月官宣，该车设计延续比亚迪海洋网家族风格。根据官方最新预热，领汇 e7 将搭载比亚迪闪充技术，可实现“5 分钟充好、9 分钟充饱”。参考工信部申报信息，该车基本延续比亚迪 e7 整体造型，前后换装领汇新车标，车型充电口位置从右前翼子板区调整至车身右后侧。该车尺寸长宽高分别为 4780×1900×1515mm，轴距 2820mm。动力方面，新车搭载前置单电机，分 100kW、130kW 版本；搭载弗迪磷酸铁锂刀片电池，电池循环寿命达 60 万公里，匹配营运周期；CLTC 续航有 450km、550km 等版本可选；采用宽温域热泵空调，冬季能耗更低。相关阅读：《比亚迪全新品牌“领汇”官宣，致力于打造“技术不妥协、价格更亲民”的新能源汽车产品》《比亚迪领汇 e7 新车预热：5 分钟充好，9 分钟充饱》&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/669.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/668.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;拿起就刷离口即停：追觅 NB01 无按键电动牙刷发布，支持 30 天免费用&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;拿起就刷离口即停追觅-nb01-无按键电动牙刷发布支持-30-天免费用&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%8b%bf%e8%b5%b7%e5%b0%b1%e5%88%b7%e7%a6%bb%e5%8f%a3%e5%8d%b3%e5%81%9c%e8%bf%bd%e8%a7%85-nb01-%e6%97%a0%e6%8c%89%e9%94%ae%e7%94%b5%e5%8a%a8%e7%89%99%e5%88%b7%e5%8f%91%e5%b8%83%e6%94%af%e6%8c%81-30-%e5%a4%a9%e5%85%8d%e8%b4%b9%e7%94%a8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;追觅现已推出无按键感应式电动牙刷 NB01，主打“拿起就刷、离口即停”的全自动交互。搭载智能压力智控与高频声波马达，2 刷头套装官方定价 349 元。预付定金尾款立减 60 元 → 实付仅 299 元晒单返 60 元 E 卡赠 20 元京东超市卡折合实付 219 元，支持 30 天免费试用：京东追觅电动牙刷 NB01 无按键黑科技实付 299 元直达链接这款牙刷搭载 FitClean 无键感应系统，摒弃物理按键，实现手持唤醒、入口启振、离口即停的无感操作。搭配四色智感灯环实时显示运行状态；支持 IPX7 级整机防水，运行噪音低于 60 分贝。牙刷内置高精度压力智控模块，可在 50g-380g 压力区间自动匹配清洁档位，用力过度持续 3 秒自动减速降档，呵护牙龈与牙釉质。搭载 36000 次 / 分钟高频声波马达，标配净澈型、柔护型双效刷头，适配不同口腔护理需求。IT之家附牙刷主要参数如下：产品型号：NB01防水等级：IPX7电池容量：800mAh充电方式：底座式充电核心功能：无按键感应启停、智能压力自动调速马达性能：36000 次 / 分钟高频声波震动京东追觅电动牙刷 NB01 无按键&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/668.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/661.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;重达 600 公斤，NASA 退役卫星范艾伦探测器 A 即将坠回地球&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;重达-600-公斤nasa-退役卫星范艾伦探测器-a-即将坠回地球&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%87%8d%e8%be%be-600-%e5%85%ac%e6%96%a4nasa-%e9%80%80%e5%bd%b9%e5%8d%ab%e6%98%9f%e8%8c%83%e8%89%be%e4%bc%a6%e6%8e%a2%e6%b5%8b%e5%99%a8-a-%e5%8d%b3%e5%b0%86%e5%9d%a0%e5%9b%9e%e5%9c%b0%e7%90%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，专家称，美国国家航空航天局（NASA）一颗大型卫星在轨道运行近 14 年后，将于当地时间 3 月 10 日坠回地球。据IT之家了解，这颗航天器是范艾伦探测器 A，重 1323 磅（600 公斤），于 2012 年 8 月与其孪生探测器范艾伦探测器 B 一同发射，用于研究以其命名的地球辐射带。两颗探测器均于 2019 年退役，如今范艾伦探测器 A 的在轨生涯即将结束。截至当地时间周一下午（3 月 9 日），美国太空部队预测，这颗卫星将于美国东部时间周二 19:45（北京时间周三 7:45）再入地球大气层，误差在 24 小时左右。NASA 官员在当地时间周一的最新公告中表示：“NASA 预计探测器大部分结构将在穿越大气层时燃烧殆尽，但部分部件预计会在再入过程中幸存。对地球人员造成伤害的风险很低 —— 约为 1/4200。”这一约 0.02% 的低受伤风险，是考虑到地球表面约 70% 被水覆盖。因此，任何幸存的残骸都很可能坠入开阔海域，而非城市及其周边地区。太空部队给出的再入时间仅为预估。随着更多、更精准的数据获取，未来几小时内该时间将更新。范艾伦探测器（原名&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/661.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;📰 其他科技资讯&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-其他科技资讯&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%85%b6%e4%bb%96%e7%a7%91%e6%8a%80%e8%b5%84%e8%ae%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;&lt;a href=&#34;https://www.theverge.com/tech/891562/bluesky-new-ceo&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Bluesky首席执行官Jay Graber将辞职&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;bluesky首席执行官jay-graber将辞职&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#bluesky%e9%a6%96%e5%b8%ad%e6%89%a7%e8%a1%8c%e5%ae%98jay-graber%e5%b0%86%e8%be%9e%e8%81%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Bluesky CEO Jay Graber will step aside&lt;/em&gt;
&lt;strong&gt;来源：The Verge&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;杰伊·格雷伯（ Jay Graber ）于2021年成为Bluesky的第一位首席执行官，当时该网络及其AT协议作为Twitter研究项目从生活中脱颖而出，走向独立，但现在她将离开这个角色，正如《连线》杂志此前报道的那样。风险资本家和前Automattic首席执行官托尼·施耐德（ Toni Schneider ）担任临时首席执行官，直至[]&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.theverge.com/tech/891562/bluesky-new-ceo&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/story/flying-cars-will-take-off-in-american-skies-this-summer/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;“飞行汽车”将于今年夏天在美国的天空中起飞&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;飞行汽车将于今年夏天在美国的天空中起飞&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%a3%9e%e8%a1%8c%e6%b1%bd%e8%bd%a6%e5%b0%86%e4%ba%8e%e4%bb%8a%e5%b9%b4%e5%a4%8f%e5%a4%a9%e5%9c%a8%e7%be%8e%e5%9b%bd%e7%9a%84%e5%a4%a9%e7%a9%ba%e4%b8%ad%e8%b5%b7%e9%a3%9e&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;‘Flying Cars’ Will Take Off in American Skies This Summer&lt;/em&gt;
&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;装载机保存故事保存此故事注释装载机保存故事保存此故事美国交通部周一宣布，新型飞机，即可以像直升机一样在很小的空间内起降但功能像飞机一样的“飞行汽车” ，最早将于6月开始在美国领空运营。包括纽约和新泽西、德克萨斯、佛罗里达和新墨西哥州阿尔伯克基在内的美国八个地区将参加为期三年的试点项目，&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/story/flying-cars-will-take-off-in-american-skies-this-summer/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/story/bluesky-ceo-jay-graber-is-stepping-down/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Bluesky首席执行官杰伊·格雷伯（ Jay Graber ）即将辞职&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;bluesky首席执行官杰伊格雷伯-jay-graber-即将辞职&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#bluesky%e9%a6%96%e5%b8%ad%e6%89%a7%e8%a1%8c%e5%ae%98%e6%9d%b0%e4%bc%8a%e6%a0%bc%e9%9b%b7%e4%bc%af-jay-graber-%e5%8d%b3%e5%b0%86%e8%be%9e%e8%81%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Bluesky CEO Jay Graber Is Stepping Down&lt;/em&gt;
&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;保存此故事保存此故事Jay Graber将辞去Bluesky的负责人一职， Bluesky是专门向WIRED宣布的社交媒体平台。风险投资家托尼·施耐德（ Toni Schneider ）将担任临时首席执行官，直至找到永久替代人选。Graber在一份关于人事变动的声明中写道： “随着Bluesky的成熟，公司需要一位经验丰富的运营商，专注于扩展和执行，而我则回到我最擅长的领域：构建新事物。” Graber于2019年加入Bluesky ，当时它是一名研究员&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/story/bluesky-ceo-jay-graber-is-stepping-down/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/story/sony-wh-1000xm6-deal-326/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Our Favorite Wireless Headphones Are $60 Off&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;our-favorite-wireless-headphones-are-60-off&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#our-favorite-wireless-headphones-are-60-off&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;LoaderSave StorySave this storyCommentLoaderSave storySave this story如果您一直渴望一款新的无线耳机可以长途飞行或拥挤的通勤，但坚持要好价钱，那么您的时机已经到来。黑色和白金银色的索尼WH-1000XM6仅需398 $ ，而午夜蓝色和沙粉色则标记为限时优惠。这是我们最喜欢的无线耳机，具有一流的降噪功能、出色的电池续航时间和&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/story/sony-wh-1000xm6-deal-326/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.wired.com/gallery/best-base-layers/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;最佳基础层（ 2026年） ：美利奴羊毛、合成羊毛等&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;最佳基础层-2026年-美利奴羊毛合成羊毛等&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%9c%80%e4%bd%b3%e5%9f%ba%e7%a1%80%e5%b1%82-2026%e5%b9%b4-%e7%be%8e%e5%88%a9%e5%a5%b4%e7%be%8a%e6%af%9b%e5%90%88%e6%88%90%e7%be%8a%e6%af%9b%e7%ad%89&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Best Base Layers (2026): Merino Wool, Synthetic, and More&lt;/em&gt;
&lt;strong&gt;来源：Wired&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;加载器保存故事保存此故事评论加载器保存故事保存此故事本文特色最佳超轻美利奴羊毛基层IBEX羊毛专业技术人员阅读更多$ 120 Ibex （女式）最佳中等重量基层Icebreaker美利奴200绿洲保暖上衣阅读更多$ 120 REI （男式）最佳重量基层智能羊毛经典保暖美利奴基层阅读更多$ 115智能羊毛（男式）极度寒冷的最佳基层Minus33重量级育空保暖长袖阅读更多$ 150减33 （男式）基层&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.wired.com/gallery/best-base-layers/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://arstechnica.com/space/2026/03/after-years-of-missteps-blue-origin-to-finally-offer-meaningful-stock-options/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;在远远落后于行业其他部门后，蓝色起源制定了新的股票期权计划&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;在远远落后于行业其他部门后蓝色起源制定了新的股票期权计划&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9c%a8%e8%bf%9c%e8%bf%9c%e8%90%bd%e5%90%8e%e4%ba%8e%e8%a1%8c%e4%b8%9a%e5%85%b6%e4%bb%96%e9%83%a8%e9%97%a8%e5%90%8e%e8%93%9d%e8%89%b2%e8%b5%b7%e6%ba%90%e5%88%b6%e5%ae%9a%e4%ba%86%e6%96%b0%e7%9a%84%e8%82%a1%e7%a5%a8%e6%9c%9f%e6%9d%83%e8%ae%a1%e5%88%92&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;After falling far behind the rest of industry, Blue Origin creates new stock option plan&lt;/em&gt;
&lt;strong&gt;来源：Ars Technica&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;文字设置故事文字尺寸小标准大宽度&lt;em&gt;标准宽链接标准橙色&lt;/em&gt;订阅者仅了解详情最小化到导航2004年夏天创立太空公司两年后， Jeff Bezos写了一封信，向新员工致敬，信中写道： “欢迎来到蓝色起源！“这封信的副本随后被提供给新员工近二十年。在信中，贝索斯曾质疑蓝色起源是否是一项不错的投资。“我接受蓝色&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://arstechnica.com/space/2026/03/after-years-of-missteps-blue-origin-to-finally-offer-meaningful-stock-options/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://arstechnica.com/reviews/2026/03/quad-cortex-mini-insane-amp-modeling-power-for-the-discerning-guitarist/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Quad Cortex迷你放大器建模器：所有功率，一半大小&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;quad-cortex迷你放大器建模器所有功率一半大小&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#quad-cortex%e8%bf%b7%e4%bd%a0%e6%94%be%e5%a4%a7%e5%99%a8%e5%bb%ba%e6%a8%a1%e5%99%a8%e6%89%80%e6%9c%89%e5%8a%9f%e7%8e%87%e4%b8%80%e5%8d%8a%e5%a4%a7%e5%b0%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Quad Cortex mini amp modeler: All the power, half the size&lt;/em&gt;
&lt;strong&gt;来源：Ars Technica&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;文字设置故事文字大小小标准大宽度&lt;em&gt;标准宽链接标准橙色&lt;/em&gt;仅限订阅者了解更多尽量减少到导航在今年1月在洛杉矶举行的大型NAMM音乐技术展上，六款产品获得了“最佳展示”奖。他们中的一些人去了雅马哈和Boss等主要的音乐和电子品牌，但其中一个去了Neural DSP ，这是一家规模小得多的公司，由智利移民到芬兰于2017年创立。从赫尔辛基地区的基地来看， Neural已经成为&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://arstechnica.com/reviews/2026/03/quad-cortex-mini-insane-amp-modeling-power-for-the-discerning-guitarist/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://arstechnica.com/tech-policy/2026/03/us-blindsides-states-with-surprise-settlement-in-live-nation-ticketmaster-trial/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Live Nation/Ticketmaster审判中的美国盲点州意外和解&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;live-nationticketmaster审判中的美国盲点州意外和解&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#live-nationticketmaster%e5%ae%a1%e5%88%a4%e4%b8%ad%e7%9a%84%e7%be%8e%e5%9b%bd%e7%9b%b2%e7%82%b9%e5%b7%9e%e6%84%8f%e5%a4%96%e5%92%8c%e8%a7%a3&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;US blindsides states with surprise settlement in Live Nation/Ticketmaster trial&lt;/em&gt;
&lt;strong&gt;来源：Ars Technica&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;文本设置故事文本大小小标准大宽度&lt;em&gt;标准宽链接标准橙色&lt;/em&gt;订阅者仅了解详情最小化导航特朗普政府同意停止追求Live Nation和Ticketmaster的分手，作为在审判过程中蒙蔽州检察长的和解的一部分。来自27个州和哥伦比亚特区的司法部长正在继续在没有美国政府的情况下追究此案，至少目前是这样。美国司法部和大多数&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://arstechnica.com/tech-policy/2026/03/us-blindsides-states-with-surprise-settlement-in-live-nation-ticketmaster-trial/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://arstechnica.com/science/2026/03/an-unlikely-set-of-clues-helps-reconstruct-ancient-chinese-disasters/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;一组不太可能的线索有助于重建中国古代的灾难&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一组不太可能的线索有助于重建中国古代的灾难&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e7%bb%84%e4%b8%8d%e5%a4%aa%e5%8f%af%e8%83%bd%e7%9a%84%e7%ba%bf%e7%b4%a2%e6%9c%89%e5%8a%a9%e4%ba%8e%e9%87%8d%e5%bb%ba%e4%b8%ad%e5%9b%bd%e5%8f%a4%e4%bb%a3%e7%9a%84%e7%81%be%e9%9a%be&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;An unlikely set of clues helps reconstruct ancient Chinese disasters&lt;/em&gt;
&lt;strong&gt;来源：Ars Technica&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;文本设置故事文本大小小标准大宽度&lt;em&gt;标准宽链接标准橙色&lt;/em&gt;订阅者仅了解详情尽量减少到航行太平洋温暖的水域可能给中国古代文明的摇篮带来了毁灭性的洪水，根据最近的一项研究，其作者将三条截然不同的证据联系起来讲述这个故事。大约3000年前，中国商代的人们可能没有意识到大洪水席卷他们的&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://arstechnica.com/science/2026/03/an-unlikely-set-of-clues-helps-reconstruct-ancient-chinese-disasters/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://arstechnica.com/tech-policy/2026/03/nintendo-sues-for-full-tariff-refund-after-backlash-over-price-hikes/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;任天堂起诉阻止特朗普躲避全额关税退税&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;任天堂起诉阻止特朗普躲避全额关税退税&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%bb%e5%a4%a9%e5%a0%82%e8%b5%b7%e8%af%89%e9%98%bb%e6%ad%a2%e7%89%b9%e6%9c%97%e6%99%ae%e8%ba%b2%e9%81%bf%e5%85%a8%e9%a2%9d%e5%85%b3%e7%a8%8e%e9%80%80%e7%a8%8e&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Nintendo sues to prevent Trump from dodging full tariff refunds&lt;/em&gt;
&lt;strong&gt;来源：Ars Technica&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;文本设置故事文本大小小标准大宽度&lt;em&gt;标准宽链接标准橙色&lt;/em&gt;订阅者仅了解详情最小化到导航上周五，任天堂与数千家公司一起起诉特朗普政府，要求获得全额退款，以及根据《国际紧急经济权力法》（ IEEPA ）收取的数十亿美元非法关税的利息。任天堂在其投诉中坚称，特朗普政府已经承认，超过2000亿美元的退款&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://arstechnica.com/tech-policy/2026/03/nintendo-sues-for-full-tariff-refund-after-backlash-over-price-hikes/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://arstechnica.com/science/2026/03/tuck-and-turn-or-bend-and-twist-how-falling-cats-land-on-their-feet/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;灵活的猫刺揭示了“坠落的猫”问题&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;灵活的猫刺揭示了坠落的猫问题&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%81%b5%e6%b4%bb%e7%9a%84%e7%8c%ab%e5%88%ba%e6%8f%ad%e7%a4%ba%e4%ba%86%e5%9d%a0%e8%90%bd%e7%9a%84%e7%8c%ab%e9%97%ae%e9%a2%98&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Flexible feline spines shed light on &amp;ldquo;falling cat&amp;rdquo; problem&lt;/em&gt;
&lt;strong&gt;来源：Ars Technica&lt;/strong&gt; | 海外&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;文本设置故事文本尺寸小标准大宽度&lt;em&gt;标准宽链接标准橙色&lt;/em&gt;仅限订阅者了解详情最小化导航为什么坠落的猫咪似乎总是站着落地？科学家们一直在争论精确的机制很长一段时间-事实上，至少从1700年开始-进行各种各样的实验来确定发生了什么。这项研究仍在继续，发表在《解剖记录》杂志上的一篇论文报道了分析跳蚤的新实验&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://arstechnica.com/science/2026/03/tuck-and-turn-or-bend-and-twist-how-falling-cats-land-on-their-feet/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/p/3716851288241541?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;搭乘人形机器人概念，首开股份再涨停&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;搭乘人形机器人概念首开股份再涨停&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%90%ad%e4%b9%98%e4%ba%ba%e5%bd%a2%e6%9c%ba%e5%99%a8%e4%ba%ba%e6%a6%82%e5%bf%b5%e9%a6%96%e5%bc%80%e8%82%a1%e4%bb%bd%e5%86%8d%e6%b6%a8%e5%81%9c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;3月10日，随着人形机器人概念持续走强，因为投资了宇树科技等机器人公司，作为地产企业的首开股份也迎来了股价大涨，以9.94%的涨幅涨停。 首开股份的主营业务为地产开发，近年来受地产市场下行拖累，公司业绩持续下滑。据首开股份1月24日发布的业绩数据，其2025年1-12月共实现签约金额178.45亿元，预计2025年实现归属于母公司所有者的净利润为-55亿元至-69亿元。虽然相比2024年81.4亿元的亏损金额有所减少，但仍持续出现巨额亏损。 由于业绩持续下滑，过去几年内首开股份的股价也屡创新低，曾于2024年7月31日下跌至1.94元/股，相比2019年的股价高点跌掉了约78.6%。 但在2025年，首开股份开始以财务投资的方式进入机器人领域。 其中最关键的一笔投在了明星公司宇树科技。2025年7月，北京首开盈信投资管理有限公司（下称“首开盈信”）认购了金石成长股权投资（杭州）合伙企业（有限合伙）（以下简称“金石成长基金”）。而金石成长在2024年9月首次持股宇树科技，2025年5月认缴出资，持股比例至4.7683%。 通过金石成长基金，首开股份成为了国内最大人形机器人公司宇树科技的股&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/p/3716851288241541?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/p/3716518378993281?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;从“平替”到“价值领跑”：国货运动品牌全面突破｜世研消费指数品牌榜Vol.158&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;从平替到价值领跑国货运动品牌全面突破世研消费指数品牌榜vol158&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%8e%e5%b9%b3%e6%9b%bf%e5%88%b0%e4%bb%b7%e5%80%bc%e9%a2%86%e8%b7%91%e5%9b%bd%e8%b4%a7%e8%bf%90%e5%8a%a8%e5%93%81%e7%89%8c%e5%85%a8%e9%9d%a2%e7%aa%81%e7%a0%b4%e4%b8%96%e7%a0%94%e6%b6%88%e8%b4%b9%e6%8c%87%e6%95%b0%e5%93%81%e7%89%8c%e6%a6%9cvol158&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;本次监测周期内，安踏、骆驼和李宁以1.95、1.91、1.82的综合热度位列榜单综合热度前三。 图源：世研大消费指数 国货运动品牌全面领跑，文化与科技突破双轮驱动赢得市场认可 从品牌分布来看，安踏、骆驼、李宁包揽前三，国产品牌在TOP10中占据七席，与耐克、阿迪达斯等国际巨头形成有力抗衡。 这一格局的深层动因，在于国货品牌完成了从“性价比竞争”到“价值竞争”的战略跃迁。 安踏儿童1月携手专业篮球俱乐部举办“王的风范”全明星赛，以“运动+体验+商业”的创新模式激活儿童消费新活力。李宁则在米兰时装周以「THE ATHLETE IN ALL OF US」为主题发布2026秋冬系列，在米兰冬奥会倒计时20天之际，作为中国奥委会官方合作伙伴亮相国际舞台，将专业运动与时尚审美完美融合。 与此同时，骆驼在ISPO展会上发布“中国荒野冲锋衣”，其威锋科技面料防水指数达20750mmH₂O，并邀请七星山荒野求生达人现场分享，将赛事流量精准转化为品牌资产。 这些动作共同指向一个趋势：国货品牌已构建起“文化认同+科技创新”的双重护城河，消费者对国货的信赖正从情感偏好转向价值认同。 户外运动赛道持续高热，场景&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/p/3716518378993281?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/newsflashes/3716884776203912?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;金浦钛业：全资子公司与中研创星签订租赁经营合作协议，合作期三年&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;金浦钛业全资子公司与中研创星签订租赁经营合作协议合作期三年&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%87%91%e6%b5%a6%e9%92%9b%e4%b8%9a%e5%85%a8%e8%b5%84%e5%ad%90%e5%85%ac%e5%8f%b8%e4%b8%8e%e4%b8%ad%e7%a0%94%e5%88%9b%e6%98%9f%e7%ad%be%e8%ae%a2%e7%a7%9f%e8%b5%81%e7%bb%8f%e8%90%a5%e5%90%88%e4%bd%9c%e5%8d%8f%e8%ae%ae%e5%90%88%e4%bd%9c%e6%9c%9f%e4%b8%89%e5%b9%b4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;36氪获悉，金浦钛业公告，全资子公司徐州钛白化工有限责任公司，拟以现有生产线与江苏中研创星材料科技有限公司开展租赁经营合作事宜，合作期三年，合作期内净利润为正时双方按约定比例分配利润，净利润为负时由中研创星独自承担所有成本和损失等。双方将签订《租赁经营合作协议》。3月10日，公司召开第九届董事会第八次会议审议通过了相关议案。原文链接下一篇2连板中南文化：公司目前经营正常，无应披露而未披露的重大事项36氪获悉，中南文化公告，公司股票交易价格连续两个交易日收盘价格涨幅偏离值累计超过20%，属于异常波动情况。公司前期披露的信息无需更正或补充，控股股东及实际控制人在股票异常波动期间未买卖公司股票。公司目前经营正常，内外部经营环境未发生重大变化，无应披露而未披露的重大事项，也无其他处于筹划阶段的重大事项。 8点1氪丨胖东来12名店长共分2.4亿资产利润；Mac mini销量暴增或因OpenClaw爆火导致；2026年中国电影票房在全球占比超28%，领跑全球电影市场 OpenClaw 3.8继续炸场，龙虾不睡觉，全球程序员连夜赶工&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/newsflashes/3716884776203912?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/newsflashes/3716880041473673?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;2连板中南文化：公司目前经营正常，无应披露而未披露的重大事项&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2连板中南文化公司目前经营正常无应披露而未披露的重大事项&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2%e8%bf%9e%e6%9d%bf%e4%b8%ad%e5%8d%97%e6%96%87%e5%8c%96%e5%85%ac%e5%8f%b8%e7%9b%ae%e5%89%8d%e7%bb%8f%e8%90%a5%e6%ad%a3%e5%b8%b8%e6%97%a0%e5%ba%94%e6%8a%ab%e9%9c%b2%e8%80%8c%e6%9c%aa%e6%8a%ab%e9%9c%b2%e7%9a%84%e9%87%8d%e5%a4%a7%e4%ba%8b%e9%a1%b9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;36氪获悉，中南文化公告，公司股票交易价格连续两个交易日收盘价格涨幅偏离值累计超过20%，属于异常波动情况。公司前期披露的信息无需更正或补充，控股股东及实际控制人在股票异常波动期间未买卖公司股票。公司目前经营正常，内外部经营环境未发生重大变化，无应披露而未披露的重大事项，也无其他处于筹划阶段的重大事项。原文链接下一篇现货黄金日内涨幅扩大至1%36氪获悉，现货黄金日内涨幅扩大至1%，报5188.02美元/盎司。 8点1氪丨胖东来12名店长共分2.4亿资产利润；Mac mini销量暴增或因OpenClaw爆火导致；2026年中国电影票房在全球占比超28%，领跑全球电影市场 OpenClaw 3.8继续炸场，龙虾不睡觉，全球程序员连夜赶工&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/newsflashes/3716880041473673?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/newsflashes/3716868210439810?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;和硕2月营收同比下降17.58％&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;和硕2月营收同比下降1758&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%92%8c%e7%a1%952%e6%9c%88%e8%90%a5%e6%94%b6%e5%90%8c%e6%af%94%e4%b8%8b%e9%99%8d1758&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;3月10日，和硕公布，2026年2月营收为新台币679.82亿元，同比下降17.58％。（界面）原文链接下一篇蚂蚁集团启动2026春季校园招聘：技术岗占比达85%，超七成聚焦AI领域36氪获悉，蚂蚁集团启动2026年度春季校园招聘。本次春招技术类岗位占比高达85%，其中超70%的岗位与人工智能直接相关，重点聚焦大模型算法、多模态生成、数据智能及基础平台研发、AI安全等核心领域。 8点1氪丨胖东来12名店长共分2.4亿资产利润；Mac mini销量暴增或因OpenClaw爆火导致；2026年中国电影票房在全球占比超28%，领跑全球电影市场 OpenClaw 3.8继续炸场，龙虾不睡觉，全球程序员连夜赶工&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/newsflashes/3716868210439810?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/newsflashes/3716870454719879?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;现货黄金日内涨幅扩大至1%&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;现货黄金日内涨幅扩大至1&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%8e%b0%e8%b4%a7%e9%bb%84%e9%87%91%e6%97%a5%e5%86%85%e6%b6%a8%e5%b9%85%e6%89%a9%e5%a4%a7%e8%87%b31&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;36氪获悉，现货黄金日内涨幅扩大至1%，报5188.02美元/盎司。下一篇和硕2月营收同比下降17.58％3月10日，和硕公布，2026年2月营收为新台币679.82亿元，同比下降17.58％。（界面） 8点1氪丨胖东来12名店长共分2.4亿资产利润；Mac mini销量暴增或因OpenClaw爆火导致；2026年中国电影票房在全球占比超28%，领跑全球电影市场 OpenClaw 3.8继续炸场，龙虾不睡觉，全球程序员连夜赶工&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/newsflashes/3716870454719879?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://36kr.com/newsflashes/3716860227810688?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;安达维尔：全资子公司与上海飞机制造有限公司签订销售框架合同&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;安达维尔全资子公司与上海飞机制造有限公司签订销售框架合同&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%ae%89%e8%be%be%e7%bb%b4%e5%b0%94%e5%85%a8%e8%b5%84%e5%ad%90%e5%85%ac%e5%8f%b8%e4%b8%8e%e4%b8%8a%e6%b5%b7%e9%a3%9e%e6%9c%ba%e5%88%b6%e9%80%a0%e6%9c%89%e9%99%90%e5%85%ac%e5%8f%b8%e7%ad%be%e8%ae%a2%e9%94%80%e5%94%ae%e6%a1%86%e6%9e%b6%e5%90%88%e5%90%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：36氪&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;36氪获悉，安达维尔公告，公司全资子公司北京安达维尔民用航空技术有限公司与上海飞机制造有限公司签订了《ARJ21新支线项目和C919大型客机项目批产厨房插件采购框架合同》，合同总价款不超过4.97亿元（不含税）。该合同旨在明确双方在国产大飞机部件供应协作中的具体权利与义务。实际销售金额以后续收到的采购定单或签订的专项协议为准，对公司2026年度的财务状况和经营成果是否构成重大影响存在不确定性。原文链接下一篇陕西煤业：2025年净利润165.48亿元，同比减少25.99%36氪获悉，陕西煤业公告，2025年营业总收入1581.89亿元，同比减少14.10%；实现归属于上市公司股东的净利润165.48亿元，同比减少25.99%。业绩下降主要受煤炭产品销售价格同比下降影响，同时交易性金融资产公允价值变动增加收益以及投资收益增加。 8点1氪丨胖东来12名店长共分2.4亿资产利润；Mac mini销量暴增或因OpenClaw爆火导致；2026年中国电影票房在全球占比超28%，领跑全球电影市场 OpenClaw 3.8继续炸场，龙虾不睡觉，全球程序员连夜赶工&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://36kr.com/newsflashes/3716860227810688?f=rss&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://sspai.com/post/106845&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;年度征文 | 信息消费：七年后的再审视&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;年度征文--信息消费七年后的再审视&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b4%e5%ba%a6%e5%be%81%e6%96%87--%e4%bf%a1%e6%81%af%e6%b6%88%e8%b4%b9%e4%b8%83%e5%b9%b4%e5%90%8e%e7%9a%84%e5%86%8d%e5%ae%a1%e8%a7%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：少数派&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;本文按照少数派 2025 年度征文活动 #TeamCarbon25 赛道的要求写成。由于作者为少数派成员，本文不参加奖项评选。文章仅代表作者本人观点。 2019 年初，我写过一篇关于信息消费心得的文章，以「放弃」为线索，记录了自己在碎片信息、新闻、长文章、播客和视频等不同内容形态上做减法的过程。此后我偶尔重读，觉得当时的想法大体上没有过时，但也确实留下了不少可以补充和修正的空间。 又过了七年有余。这期间，信息获取的外部环境也在剧烈变化：传统媒体继续式微，算法推荐愈加强势，生成式 AI 更从根本上改变了大众生产和消费内容的方式。这些变化叠加在一起，让我觉得有必要重新整理一次自己的实践和想法。 显然，这篇文章和上次一样，只是个人经验的记录，未必是正确或者值得借鉴的。事实上，我对自己在信息消费上的判断从来没有真正确信过，过去几年也在不断地检视和推翻旧的看法和习惯。将来回头看这篇，大概又会觉得不少地方需要修正。但也正因如此，趁想法还没有被下一轮自我否定覆盖之前，把它们记下来或许是值得的。 过去很长一段时间，我的视野几乎完全被非虚构内容占据，特别是分析、说明类的文本；虚构和「形而上」主题的作品基本缺席。我当时的观念是：阅读的目的是获取可供实用的知识，而知识应当以事实、数据和论证为载体。「虚」的东西既不提供事实，也不能用于实践，在上面花时间似乎缺乏正当理由。 这种偏好很大程度上来源于我对科技的&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://sspai.com/post/106845&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://sspai.com/post/106567&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;年度征文｜「体商」叙事：在你的二极管感到疼痛之前&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;年度征文体商叙事在你的二极管感到疼痛之前&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b4%e5%ba%a6%e5%be%81%e6%96%87%e4%bd%93%e5%95%86%e5%8f%99%e4%ba%8b%e5%9c%a8%e4%bd%a0%e7%9a%84%e4%ba%8c%e6%9e%81%e7%ae%a1%e6%84%9f%e5%88%b0%e7%96%bc%e7%97%9b%e4%b9%8b%e5%89%8d&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：少数派&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;编者按：本文是少数派 2025 年度征文活动#TeamCarbon25标签下的入围文章。本文仅代表作者本人观点，少数派只略微调整排版。 今年的征文活动更有创意，「只能用 AI」和「不能用 AI」两大赛道激情 PK，硅基生物和碳基生物都将决出各自领域的佼佼者。我们会在征文结束后统一组织投票活动，但在正式投票之前，如果你喜欢这篇文章，不妨通过充电或评论的方式支持作者，让内容创作者获得更多维度的鼓励。 作者声明：本文中提及了一些「人工智能生成文本」的案例，但所有这些文本的具体内容都经过了人工复述和转写。作者并未使用 AI 直接生成本文中的任何句子，或对任何句子直接进行修改/润色。 你完全错了。年轻人，我告诉你，要击倒对方，最好的方法就是用手枪。练武的目标，是要将人的体能推到最高极限。如果你想达到这种境界，就必须要了解宇宙苍生。 在电影《精武英雄》中，象征武学最高境界的船越文夫，讲出了也许是整个动作电影史上最具人文哲思的一句台词。这句台词完全可以代表我在人工智能（以下均简称 AI）时代转向体育科学的初衷，也代表了我在「体商」这个话题上的立场：人在这个主题上的写作，是很难被 AI 超越或取代的。 AI 可以是手枪，但习武或用枪的主体始终是人。手枪是工具，人才是武器。 「体商」是我提出的一个小小概念，一定程度上基于丹尼尔·西格尔（Daniel Siegel, 2021）对心智（Mind）的界定&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://sspai.com/post/106567&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;http://www.huxiu.com/article/4840187.html?f=wangzhan&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;B站，巨头眼里的香饽饽&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;b站巨头眼里的香饽饽&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#b%e7%ab%99%e5%b7%a8%e5%a4%b4%e7%9c%bc%e9%87%8c%e7%9a%84%e9%a6%99%e9%a5%bd%e9%a5%bd&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：虎嗅&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;作者｜Eastland头图｜视觉中国2026年3月5日，哔哩哔哩（NASDA:BILI；HK:09626)发布《2025年第四季度及全年业绩公告》。根据报告，2025年营收303.5亿、同比增长13.1%；净利润11.9亿，首次实现年度盈利。2025年前三季度，哔哩哔哩（以下简称B站）累计盈利6.77亿，全年盈利早在投资人意料之中。靓丽财报公布后，股价放量下跌。可见，“利好出尽是利空”不是A股独有的现象。美国资本市场有句俗语——Buy the rumor, sell the news.3月6日，B站在纽交所收于24.67美元，对应市值102亿美元。从“不懂商业化”到营收连续突破百亿关口，从巨亏75亿（2022年）到净赚11.9亿，B站证明了自己的赚钱能力。日活过亿，人均观看时长超过100分钟，月均付费用户3400万……现在不亏钱了，市值才100亿美元，无疑是巨头眼里的香饽饽。但由于B站防备在先，被恶毒并购的可能性极小。广告业务贡献突出2015年，B站营收仅1.31亿（人民币，下同）被讥笑不懂商业化。2017年，营收增至24.7亿；2020年、2022年先后跃过100亿、200亿两大关口&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;http://www.huxiu.com/article/4840187.html?f=wangzhan&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/4DecoT319BYJzDpIhrl4?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;谷歌提升了 GKE 集群中节点池自动创建的速度&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;谷歌提升了-gke-集群中节点池自动创建的速度&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%b0%b7%e6%ad%8c%e6%8f%90%e5%8d%87%e4%ba%86-gke-%e9%9b%86%e7%be%a4%e4%b8%ad%e8%8a%82%e7%82%b9%e6%b1%a0%e8%87%aa%e5%8a%a8%e5%88%9b%e5%bb%ba%e7%9a%84%e9%80%9f%e5%ba%a6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;谷歌云显著减少了为 Kubernetes 集群配置新节点池所需的时间。 官方公告概要介绍了本次更新如何解决大规模计算集群扩展过程中常见的延迟问题。这正是广泛运行分布式工作负载的企业所普遍面临的痛点。 改进的重点是谷歌的 Kubernetes 引擎（GKE）及其节点自动配置功能。该功能可以根据待处理的 Pod 的特定要求自动创建节点池。这一增强对于在动态环境中保持高可用性至关重要。 通常，快速扩展的挑战来自在云环境中新建基础设施组件的开销。当集群需要一个当前节点池中不存在的新类型的节点时，系统必须向底层的 Compute Engine API 发起一系列的请求，以便分配资源、配置网络并将节点加入集群。这个过程可能会引入延迟，影响应用程序的响应性，特别是在需求突然激增或部署高容量批处理作业时。 为了解决这些瓶颈，谷歌优化了 GKE 控制平面与计算基础设施之间的通信机制。新的功能增强实现了更高效的请求批处理，减少了各种云服务握手过程的开销。通过改进控制平面处理这些操作的方式，与以前的版本相比，现在平台可以更快地将新节点置于就绪状态。这对于使用异构集群的用户尤其有用，因为这类集群需要各种机器类型来执行不同的任务。 虽然长期以来， GKE 都提供了自动扩展功能，但这些性能提升使其更接近于 Karpenter 等可选的生态系统工具的能力。Karpenter 最初由亚马逊云科技公司开发，现在是一&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/4DecoT319BYJzDpIhrl4?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/4E0eyN5brr2D1xeh3kcX?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;从集中管控到团队自治：重新思考基础设施交付模式&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;从集中管控到团队自治重新思考基础设施交付模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%8e%e9%9b%86%e4%b8%ad%e7%ae%a1%e6%8e%a7%e5%88%b0%e5%9b%a2%e9%98%9f%e8%87%aa%e6%b2%bb%e9%87%8d%e6%96%b0%e6%80%9d%e8%80%83%e5%9f%ba%e7%a1%80%e8%ae%be%e6%96%bd%e4%ba%a4%e4%bb%98%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;阿迪达斯对其数据平台的基础设施交付方式进行了全面改革，从集中式的 IaC 模型转向去中心化模式。此次变革将基础设施定义的所有权从中央平台团队转移到按业务域划分的团队，体现了行业向“产品化平台工程”转型的趋势。该转型旨在在治理与自治之间取得平衡，以应对数据平台在多个团队与多种使用场景扩张过程中暴露出的扩展性挑战。 在原有模式下，单一的平台工程团队负责 IaC 仓库、管理部署流水线，并在整个组织内执行统一标准。这种集中式结构在早期增长阶段确保了一致性与合规性。然而，随着多个领域团队陆续接入平台，请求数量不断增加，待处理积压逐渐扩大，团队间的协调也带来了额外开销。工程师们指出，这种限制源自交付模型本身，而非底层工具问题。 核心问题在于交付模型本身——它已无法支撑组织当前所需的速度与自治程度。 为解决这些约束，阿迪达斯数据平台团队重新定义了基础设施的交付方式以及交付主体。新的运营模式将责任下放给领域团队，使其能够在预定义边界和标准化模式下，自主创建与管理基础设施。平台工程师不再执行具体的基础设施变更，而是转向维护可复用的构建模块、工具框架和治理策略，以支持自治式交付。 此次重构引入了分层的 IaC 结构：可复用模块封装资源定义；“栈”将模块组合为可部署单元；消费配置则引用经批准的栈用于生产部署。这种分层设计在允许非生产环境实验的同时，限制对基础组件的直接修改。在去中心化环境中，明确哪些内容&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/4E0eyN5brr2D1xeh3kcX?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.infoq.cn/article/jHctpRRbJaQjINj7y2lY?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Uber的混合云数据：工程师如何攻破解大规模复制难题&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;uber的混合云数据工程师如何攻破解大规模复制难题&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#uber%e7%9a%84%e6%b7%b7%e5%90%88%e4%ba%91%e6%95%b0%e6%8d%ae%e5%b7%a5%e7%a8%8b%e5%b8%88%e5%a6%82%e4%bd%95%e6%94%bb%e7%a0%b4%e8%a7%a3%e5%a4%a7%e8%a7%84%e6%a8%a1%e5%a4%8d%e5%88%b6%e9%9a%be%e9%a2%98&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：InfoQ中文&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Uber 工程团队对其数据复制平台做了全面升级，现在每天可以在混合云和本地数据湖之间移动数以 PB 计的数据，解决了由于工作负载迅速增长而引起的扩展挑战。该平台基于 Hadoop 开源框架Distcp构建，现在每天处理超过 1PB 的数据复制和数十万个作业，而且速度更快、可靠性和可观测性更高，使得数据分析、机器学习和灾难恢复都达到了前所未有的规模。 Distcp是一个开源框架，它使用 Hadoop 的MapReduce跨多个节点并行复制大型数据集。文件被分割成块，并分配给在YARN容器中运行的 Copy Mapper 任务。Resource Manager 分配资源，Application Master 监控作业执行并协调合并，Copy Committer 在目的地组装最终文件。Uber 的 HiveSync 团队针对 PB 级工作负载优化了这一架构。他们将准备任务移到了 Application Master，实现了列表功能和提交过程的并行化，并提高了小规模传输的效率。 最初，HiveSync是基于 Airbnb 的ReAir项目，使用批量和增量复制实现 Uber HDFS 和云数据湖的同步。对于大于 256MB 的数据集，它通过异步工作进程并行提交 Distcp 作业，并用一个监控线程跟踪进度。随着每日复制的数据量从 250TB 增长到超过 1PB，数据集从 30000 扩展到&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.infoq.cn/article/jHctpRRbJaQjINj7y2lY?utm_source=rss&amp;amp;utm_medium=article&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/664.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;任职 11 年后，特斯拉 OTA 更新系统缔造者离职&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;任职-11-年后特斯拉-ota-更新系统缔造者离职&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%bb%e8%81%8c-11-%e5%b9%b4%e5%90%8e%e7%89%b9%e6%96%af%e6%8b%89-ota-%e6%9b%b4%e6%96%b0%e7%b3%bb%e7%bb%9f%e7%bc%94%e9%80%a0%e8%80%85%e7%a6%bb%e8%81%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，特斯拉失去了一位为公司打造出核心功能之一 —— 车载远程 OTA 升级的总监。在特斯拉任职超过 11 年、主导开发 OTA 升级系统并助力车辆通过该功能持续进化的托马斯 · 德米特里克（Thomas Dmytryk），已决定离职。他在领英发布长文宣布“为这段经历画上句号”，言语间全是正面评价：“在特斯拉度过精彩的 11 年后，我将为这段旅程画上句号。这是一生难忘的经历：始终处在舆论焦点，坚持不懈地创新，不断突破极限。特斯拉是才华横溢、充满热情之人的理想之地。能长期身处这样的企业文化中，我感到无比幸运。”长期高强度的研发与创造节奏，似乎让他不堪重负。德米特里克并未透露未来的具体计划，看起来他会先休息一段时间，再开启新事业：“未来？依旧无比光明。特斯拉的雄心未减，作为一家能改变数十亿人生活的变革性企业，它才刚刚起步。那我为何现在离开？人生一直是我的指引，此刻我需要陪伴自己的家人。我一直敬佩特斯拉的高层领导力与远见，但最让我惊叹的，是一线员工的坚韧、聪慧与奉献。是你们让特斯拉势不可挡。祝大家一切顺利，收获辉煌成就。”据IT之家了解，OTA 远程升级是特斯拉最核&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/664.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/663.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;保险费吃掉部分网约车司机 25% 净收入，天能控股董事长张天任建议平台共担车险&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;保险费吃掉部分网约车司机-25-净收入天能控股董事长张天任建议平台共担车险&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bf%9d%e9%99%a9%e8%b4%b9%e5%90%83%e6%8e%89%e9%83%a8%e5%88%86%e7%bd%91%e7%ba%a6%e8%bd%a6%e5%8f%b8%e6%9c%ba-25-%e5%87%80%e6%94%b6%e5%85%a5%e5%a4%a9%e8%83%bd%e6%8e%a7%e8%82%a1%e8%91%a3%e4%ba%8b%e9%95%bf%e5%bc%a0%e5%a4%a9%e4%bb%bb%e5%bb%ba%e8%ae%ae%e5%b9%b3%e5%8f%b0%e5%85%b1%e6%8b%85%e8%bd%a6%e9%99%a9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，据中国经营报 3 月 8 日报道，全国人大代表、天能控股集团董事长张天任围绕降低网约车保费提出建议。张天任指出，根据天能控股集团的调研数据，高额保费已成为网约车司机的负担，部分司机的保费支出占净收入比例超四分之一，甚至更高。同时，一方面，平台分担保费比例低，部分平台出资不足 5%，且在风险发生后多以‘协调者’身份参与，未实质性承担赔偿责任；另一方面，平台过高的抽成进一步削弱了司机的保费承担能力，部分平台存在‘隐性抽成’（如信息费、服务费等）情况，同时聚合平台存在叠加抽成的问题。针对上述一系列问题，张天任建议，采取“组合拳”进行综合治理。一是在源头上，他建议，进一步规范网约车平台抽成比例，保障司机收入空间，如推动将主流平台抽成比例控制在 18%—25% 之间，聚合平台信息服务费降至 5% 以内，且不得允许合作平台额外提高抽成。二是建议交通运输部门牵头制定《网约车平台风险分担指引》，如要求平台将保费分担比例从不足 5% 提高至 10%—15%，可通过“平台补贴 + 司机自付”的方式共同缴纳商业险，通过平台保费分担机制以平衡风险责任。三是建议由交通运输部门牵头&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/663.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/659.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;QNAP 威联通推出 TS-h1077AFU：10× SATA 盘位 1U 全闪 NAS&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;qnap-威联通推出-ts-h1077afu10-sata-盘位-1u-全闪-nas&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#qnap-%e5%a8%81%e8%81%94%e9%80%9a%e6%8e%a8%e5%87%ba-ts-h1077afu10-sata-%e7%9b%98%e4%bd%8d-1u-%e5%85%a8%e9%97%aa-nas&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，QNAP 威联通本月 4 日宣布推出拥有 10 个 2.5 英寸 SATA 盘位的 1U 机架式全闪存 NAS 存储 TS-h1077AFU。这一型号面向入门企业级市场，可以相对较低的成本提供全闪存解决方案的高性能。TS-h1077AFU 基于 AMD 锐龙 7000 系列 8 核心 16 线程处理器，配备核心显卡，拥有 4 个 DDR5 ECC UDIMM 内存插槽（IT之家注：预装 32GB），板载 5GB 闪存用于双启动防护，运行采用 ZFS 架构的 QuTS hero 操作系统。其配备一对 350W 冗余电源，提供 2 个 PCIe Gen4 ×8 扩展槽，还提供了 2×2.5GbE + 2×10GbE 共四个 RJ45 网口，此外还包括 2 个 USB-A 10Gbps。&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/659.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3&gt;&lt;a href=&#34;https://www.ithome.com/0/927/650.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;消息称日产与 Uber 正就 Robotaxi 合作展开最终谈判&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;消息称日产与-uber-正就-robotaxi-合作展开最终谈判&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%b6%88%e6%81%af%e7%a7%b0%e6%97%a5%e4%ba%a7%e4%b8%8e-uber-%e6%ad%a3%e5%b0%b1-robotaxi-%e5%90%88%e4%bd%9c%e5%b1%95%e5%bc%80%e6%9c%80%e7%bb%88%e8%b0%88%e5%88%a4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;来源：IT之家&lt;/strong&gt; | 国内&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;IT之家 3 月 10 日消息，《日经》当地时间昨日报道称，日产与 Uber 正就 Robotaxi 合作展开最终谈判。如果双方达成正式协议，Uber 将在其网约车部署由 Wayve 技术驱动的日产自动驾驶出租车。▲ 日产下一代 ProPILOT 辅助驾驶测试车辆，搭载 Wayve 技术报道指出，日产和 Wayve 的 Robotaxi 项目正在开发之中，计划 2027 财年开始交付支持城区“离手”自动驾驶的量产车型。相关车辆有望在日本境内和全球其它区域接入 Uber 平台。IT 之家小伙伴记得用最会买打车，享受折扣价的同时还可以获得返利，单单都能省钱！&lt;/p&gt;
&lt;p&gt;🔗 &lt;a href=&#34;https://www.ithome.com/0/927/650.htm&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;查看原文&lt;/a&gt;&lt;/p&gt;

&lt;/blockquote&gt;
&lt;hr&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;由 tech-news-fetcher skill 自动生成 · 2026-03-10 17:04:09&lt;/em&gt;&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>使用 Go 构建 MCP Server</title>
      <link>https://www.helight.info/blog/2025/0320-mcpgolang/</link>
      <pubDate>Thu, 20 Mar 2025 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2025/0320-mcpgolang/</guid>
      <description>
        
        
        &lt;h2&gt;一、MCP 介绍&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一mcp-介绍&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80mcp-%e4%bb%8b%e7%bb%8d&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 基本介绍&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-基本介绍&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e5%9f%ba%e6%9c%ac%e4%bb%8b%e7%bb%8d&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;MCP（Model Context Protocol，模型上下文协议）是由 Anthropic 公司（Claude 大模型的创造者）于 2024 年 11 月推出的一种开放标准协议，旨在统一大型语言模型（LLM）与外部数据源和工具之间的通信方式。MCP 的核心目标是解决当前 AI 应用开发中的数据孤岛和碎片化集成问题。&lt;/p&gt;
&lt;h3&gt;2. 协议特点&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-协议特点&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e5%8d%8f%e8%ae%ae%e7%89%b9%e7%82%b9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;MCP 可以被理解为 AI 大模型的&amp;quot;万能接口&amp;quot;，类似于 USB-C 接口在硬件领域的作用，它提供了一种标准化的方法，使 AI 模型能够与不同的数据源和工具进行无缝交互。通过 MCP，开发者可以更轻松地构建复杂的 AI 应用，而无需为每个工具或数据源编写专门的集成代码。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;MCP 是一个标准协议，如同电子设备的 Type C 协议(可以充电也可以传输数据)，使 AI 模型能够与不同的 API 和数据源无缝交互。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MCP 旨在替换碎片化的 Agent 代码集成，从而使 AI 系统更可靠，更有效。通过建立通用标准，服务商可以基于协议来推出它们自己服务的 AI 能力，从而支持开发者更快的构建更强大的 AI 应用。开发者也不需要重复造轮子，通过开源项目可以建立强大的 AI Agent 生态。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MCP 可以在不同的应用/服务之间保持上下文，从而增强整体自主执行任务的能力。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;可以理解为 MCP 是将不同任务进行分层处理，每一层都提供特定的能力、描述和限制。而 MCP Client 端根据不同的任务判断，选择是否需要调用某个能力，然后通过每层的输入和输出，构建一个可以处理复杂、多步对话和统一上下文的 Agent。&lt;/p&gt;
&lt;h3&gt;3. AI Agent 和 MCP 间的关系&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-ai-agent-和-mcp-间的关系&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-ai-agent-%e5%92%8c-mcp-%e9%97%b4%e7%9a%84%e5%85%b3%e7%b3%bb&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;AI Agent 是一个智能系统，它可以自主运行以实现特定目标。传统的 AI 聊天仅提供建议或者需要手动执行任务，AI Agent 则可以分析具体情况，做出决策，并自行采取行动。&lt;/li&gt;
&lt;li&gt;AI Agent 可以利用 MCP 提供的功能描述来理解更多的上下文，并在各种平台/服务自动执行任务。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;4. MCP 如何工作&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;4-mcp-如何工作&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#4-mcp-%e5%a6%82%e4%bd%95%e5%b7%a5%e4%bd%9c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;MCP 采用客户端-服务器架构，MCP 架构主要包含以下核心组件：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;MCP 客户端&lt;/strong&gt;：通常是 AI 大模型，如 Claude、GPT 等，集成在 Host 中的协议客户端，负责将 LLM 请求转换为标准化消息，并与 Server 通信。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP 服务器&lt;/strong&gt;：提供各种功能的服务，如数据检索、工具调用等，它一般是一个轻量级程序，连接本地或远程数据源（如数据库、API），执行具体操作并返回结果。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP 协议&lt;/strong&gt;：定义客户端和服务器之间的通信规范&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;上下文管理器&lt;/strong&gt;：负责维护对话上下文和状态&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2025/0320-mcpgolang/imgs/mcp.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;MCP 的基本工作流程如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用户向 AI 模型（MCP 客户端）发送请求&lt;/li&gt;
&lt;li&gt;AI 模型分析请求，确定需要调用的外部工具或数据&lt;/li&gt;
&lt;li&gt;AI 模型通过 MCP 协议向相应的 MCP 服务器发送请求&lt;/li&gt;
&lt;li&gt;MCP 服务器处理请求并返回结果&lt;/li&gt;
&lt;li&gt;AI 模型整合结果，生成最终回复给用户&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;二、cline 配置本地模型&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二cline-配置本地模型&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8ccline-%e9%85%8d%e7%bd%ae%e6%9c%ac%e5%9c%b0%e6%a8%a1%e5%9e%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我做测试使用的客户端是 vscode+cline，cline 在 vscode 的插件市场中直接安装即可。cline 对 MCP 的支持也是非常好的。因为要使用到大模型，所以这里还要给 cline 配置一个大模型。
外网开放的免费模型一般都不太好用，所以我一般都是配置本地模型来测试，这里也介绍一下 cline 如何配置本地模型。我这里配置了 ollama 启动的 qwen2.5:14b 模型。如下图配置即可，这个配置过程比较简单。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2025/0320-mcpgolang/imgs/clineconf.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;三、MCP 服务开发&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三mcp-服务开发&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89mcp-%e6%9c%8d%e5%8a%a1%e5%bc%80%e5%8f%91&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 典型应用场景&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-典型应用场景&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e5%85%b8%e5%9e%8b%e5%ba%94%e7%94%a8%e5%9c%ba%e6%99%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;​实时数据分析：LLM 通过 MCP 直接查询数据库生成动态报告（如销售数据可视化）。&lt;/li&gt;
&lt;li&gt;​跨平台自动化：结合本地文件读写和 API 调用，实现“读取文档 → 生成会议摘要 → 发送邮件”全流程自动化。&lt;/li&gt;
&lt;li&gt;​隐私敏感任务：医疗数据存储在本地 Server，模型处理时不外传，符合 GDPR 合规要求。&lt;/li&gt;
&lt;li&gt;​工具增强生成：例如代码编辑器中集成 MCP Server，根据用户需求调用图像生成工具自动插入图片。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;2. 案例开发&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-案例开发&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e6%a1%88%e4%be%8b%e5%bc%80%e5%8f%91&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这部分代码参考了这篇文章：https://mp.weixin.qq.com/s/JmPxMBRZa8UhsIOQVgupLw
，这篇文章主要是一个按照时区获取时间的工具，我在测试 ok 之后扩展了一个天气获取的工具。&lt;/p&gt;
&lt;p&gt;天气接口使用的是腾讯云的接口，大家可以直接使用免费额度，代码也是直接从腾讯云 api 的介绍中拷贝过来的，这里做了简单的封装调用。&lt;/p&gt;
&lt;p&gt;下面的代码直接拷贝过去就可以使用，不过天气 api 的 key要替换成你自己的。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-golang&#34; data-lang=&#34;golang&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;package&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;crypto/hmac&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;crypto/sha1&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;encoding/base64&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;io&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;io/ioutil&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;gourl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;net/url&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;strings&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;github.com/mark3labs/mcp-go/mcp&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;github.com/mark3labs/mcp-go/server&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// GetWeaher(&amp;#34;北京&amp;#34;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Create MCP server&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewMCPServer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;MCPDemo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Add Get time tool&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;timetool&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewTool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;current_time&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;WithDescription&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Get current time with timezone, Asia/Shanghai is default&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;WithString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;timezone&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Required&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;current time timezone&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Add tool handler&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;AddTool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;timetool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;currentTimeHandler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// add weather tool&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;weathertool&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewTool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;current_weather&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;WithDescription&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Get current weather with city name, 北京 is default, 需要输入中文&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;WithString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;city&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Required&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Description&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;city name&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Add tool handler&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;AddTool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;weathertool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;weatherHandler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Start the stdio server&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ServeStdio&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Server error: %v\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;currentTimeHandler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;CallToolRequest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;CallToolResult&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;timezone&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ok&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Arguments&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;timezone&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ok&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewToolResultError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;timezone must be a string&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;loc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;LoadLocation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;timezone&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewToolResultError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;parse timezone with error: %v&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewToolResultText&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;`current time is %s`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;In&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;loc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;weatherHandler&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;CallToolRequest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;CallToolResult&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;city&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ok&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Arguments&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;city&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ok&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewToolResultError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;city must be a string&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;GetWeaher&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;city&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewToolResultError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;read response body with error: %v&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mcp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewToolResultText&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;calcAuthorization&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;secretId&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;secretKey&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;auth&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;timeLocation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;LoadLocation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Etc/GMT&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;In&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;timeLocation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Mon, 02 Jan 2006 15:04:05 GMT&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;signStr&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;x-date: %s\nx-source: %s&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// hmac-sha1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mac&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;hmac&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;New&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;sha1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;New&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;secretKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mac&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([]&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;signStr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;sign&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;base64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;StdEncoding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;EncodeToString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;mac&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;auth&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;hmac id=\&amp;#34;%s\&amp;#34;, algorithm=\&amp;#34;hmac-sha1\&amp;#34;, headers=\&amp;#34;x-date x-source\&amp;#34;, signature=\&amp;#34;%s\&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;secretId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;sign&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;auth&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;urlencode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;gourl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Values&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Encode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;GetWeaher&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;city&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 云市场分配的密钥Id&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;secretId&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;xxx&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 云市场分配的密钥Key&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;secretKey&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;xxx&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;usagePlan-xxx&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 签名&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;auth&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;calcAuthorization&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;secretId&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;secretKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 请求方法&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;method&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 请求头&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;X-Source&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;X-Date&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;auth&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 查询参数&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;make&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;areaCn&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;city&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;areaCode&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;ip&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;lat&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;lng&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;need1hour&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;need3hour&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;needIndex&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;needObserve&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;needalarm&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// body参数&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bodyParams&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;make&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// url参数拼接&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;https://service-6drgk6su-1258850945.gz.apigw.tencentcs.com/release/lundear/weather1d&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%s?%s&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;urlencode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;queryParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bodyMethods&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;PUT&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;PATCH&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;io&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Reader&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bodyMethods&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;method&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;strings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewReader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;urlencode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bodyParams&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;application/x-www-form-urlencoded&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Timeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Second&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;NewRequest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;method&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;panic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;range&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Header&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;k&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Do&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;panic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;defer&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bodyBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ioutil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ReadAll&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;panic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bodyBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bodyBytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;四、Cline 上配置自己开发的 MCP 服务&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四cline-上配置自己开发的-mcp-服务&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9bcline-%e4%b8%8a%e9%85%8d%e7%bd%ae%e8%87%aa%e5%b7%b1%e5%bc%80%e5%8f%91%e7%9a%84-mcp-%e6%9c%8d%e5%8a%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在 Cline 上添加 MCP 服务点击右上角“+”号旁边的 4 个小方块按钮即可进入。里面有默认的服务市场和已经安装，我们在已经安装这个 tab 中选择 “Configure MCP Servers”，打开配置文件编辑，填写以下内容：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;mcpServers&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;helight-mcpServers&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/Users/helightxu/aillm/mcpgolangtest/mcp-server&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;env&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;disabled&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;autoApprove&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;current_weather&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;current_time&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;主要就是MCP 服务的名称，里面服务二进制地址等配置。这里还有一个“autoApprove”配置项，这个就是在执行命令的时候是否需要人工二次确认还是自动确认。配置之后就可以看到下图的内容了。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2025/0320-mcpgolang/imgs/helight-mcp.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;这里还可以点击下面的“Restart Server”，对服务进行重启，重启之后也会获取最新的服务工具信息。在你重新编译 MCP 服务之后，这里一般需要点击重启一下。&lt;/p&gt;
&lt;h2&gt;五、案例测试&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五案例测试&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e6%a1%88%e4%be%8b%e6%b5%8b%e8%af%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 时间获取案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-时间获取案例&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e6%97%b6%e9%97%b4%e8%8e%b7%e5%8f%96%e6%a1%88%e4%be%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这里输入“当前东京的时间是多少”，执行过程如下，就会在大模型解析之后去调用我们的工具进行执行获取结果，并且会对工具返回的结果使用大模型进行再次组织。
&lt;img src=&#34;https://www.helight.info/blog/2025/0320-mcpgolang/imgs/timeget.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;2. 天气获取案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-天气获取案例&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e5%a4%a9%e6%b0%94%e8%8e%b7%e5%8f%96%e6%a1%88%e4%be%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;天气这里也是，提问：“深圳的天气怎么样”，在大模型分析之后就会调用我们的天气获取工具进行天气信息获取，获取之后再使用大模型进行信息组织和展示。
&lt;img src=&#34;https://www.helight.info/blog/2025/0320-mcpgolang/imgs/weatherget.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;这里是对信息的再次组织
&lt;img src=&#34;https://www.helight.info/blog/2025/0320-mcpgolang/imgs/weatherget2.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;五、MCP 的优势和典型应用场景&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五mcp-的优势和典型应用场景&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94mcp-%e7%9a%84%e4%bc%98%e5%8a%bf%e5%92%8c%e5%85%b8%e5%9e%8b%e5%ba%94%e7%94%a8%e5%9c%ba%e6%99%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 核心优势&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-核心优势&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e6%a0%b8%e5%bf%83%e4%bc%98%e5%8a%bf&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;从系统集成和开放集成的角度来看，我认为 MCP会带来以下的突破。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;​打破数据孤岛：通过统一协议连接异构系统（如本地文档、云服务），减少大量的适配代码开发量。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;​双向动态交互：支持实时请求-响应和主动通知（如 WebSocket），相比传统 API 的静态交互更灵活。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;隐私与安全:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;数据隔离：敏感操作（如医疗数据处理）在本地 Server 完成，无需向 LLM 提供商暴露密钥。&lt;/li&gt;
&lt;li&gt;权限控制：Server 可自主定义访问范围，防止越权操作。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;​开发效率提升: 开发者只需关注业务逻辑，无需重复实现通信层，例如通过 Python SDK 快速构建天气查询服务。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;2. MCP 目前比较典型的应用场景&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-mcp-目前比较典型的应用场景&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-mcp-%e7%9b%ae%e5%89%8d%e6%af%94%e8%be%83%e5%85%b8%e5%9e%8b%e7%9a%84%e5%ba%94%e7%94%a8%e5%9c%ba%e6%99%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我认为目前 MCP 的一些典型应用场景会在以下几个方面，不过这个应该发展会很快，未来也许会有更为复杂的应用场景出现。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;智能助手增强&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;MCP 可以显著增强智能助手的能力，使其能够：&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;ol start=&#34;2&#34;&gt;
&lt;li&gt;企业知识管理&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在企业环境中，MCP 可以帮助：&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;ol start=&#34;3&#34;&gt;
&lt;li&gt;垂直领域应用&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;MCP 在各个垂直领域都有广泛应用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;医疗&lt;/strong&gt;：连接医疗记录系统、诊断工具和医学知识库&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;金融&lt;/strong&gt;：整合市场数据、风险评估工具和交易系统&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;教育&lt;/strong&gt;：连接学习资源、评估工具和个性化学习系统&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;制造&lt;/strong&gt;：连接生产系统、质量控制工具和供应链管理系统&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;六、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;六总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%ad%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我认为这种模式应该是 AI 应用的趋势，不做大模型，而是做大模型、内容信息和工具之间的一种胶水层，是一种思考模式的实现。感觉未来大厂的这些工具都会向这个方向发展。在特定的领域之内，结合大模型、具体场景信息和相关工具，思考组织执行方式和流程，最终完成一个自动化大规模计算的复杂任务。比如复杂的 k8s 集群运维，复杂大规模的数据分析。&lt;/p&gt;
&lt;p&gt;多智能体协作系统应该是未来的大趋势。而 MCP 在多智能体系统中的应用是其最强大的特性之一。通过 MCP，多个 AI 智能体可以协同工作，各自负责不同的任务，并通过标准化的接口进行通信。&lt;/p&gt;
&lt;p&gt;多智能体可能的一个架构：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;多智能体系统
├── 协调者智能体（Coordinator Agent）
├── 专家智能体 1（Expert Agent 1）
├── 专家智能体 2（Expert Agent 2）
├── ...
└── 专家智能体 N（Expert Agent N）&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;六、参考&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;六参考&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%ad%e5%8f%82%e8%80%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://mp.weixin.qq.com/s/JmPxMBRZa8UhsIOQVgupLw&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://mp.weixin.qq.com/s/JmPxMBRZa8UhsIOQVgupLw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://guangzhengli.com/blog/zh/model-context-protocol/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://guangzhengli.com/blog/zh/model-context-protocol/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>Open-Manus开源多智能体工具部署全攻略</title>
      <link>https://www.helight.info/blog/2025/0315-openmanus/</link>
      <pubDate>Sat, 15 Mar 2025 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2025/0315-openmanus/</guid>
      <description>
        
        
        &lt;h2&gt;一、Open-Manus 产品技术解析&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一open-manus-产品技术解析&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80open-manus-%e4%ba%a7%e5%93%81%e6%8a%80%e6%9c%af%e8%a7%a3%e6%9e%90&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Manus 在火爆之后，也看了它的视频，感觉是非常厉害，程序员又要把程序干掉了，所以也想体验一把，但是没有邀请码，在看到 Open-Manus 之后也想试用一把，体验一下那种动动嘴让机器干冒烟就可以把活干好的感觉。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2025/0315-openmanus/imgs/openmanus.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Open-Manus 是由 MetaGPT 团队的五名开发者在短时间内开发的开源 AI 工具项目。它旨在复刻或替代近期火爆的 AI 产品 Manus，提供一个透明、可本地运行的 AI 工具，能够执行类似 Manus 的任务，如自动化生成报告、处理复杂工作流等。具体含义和相关信息如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;开发背景：OpenManus 是在 Manus 爆火之后，由 MetaGPT团队开发的开源项目。该项目旨在提供一个免费且易用的替代方案，挑战 Manus 的“稀缺性”和“高门槛”。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;技术实现：OpenManus 是一个基于 Python 开发的智能代理系统，采用模块化设计，主要包含 agent、flow、tool 等核心模块。它使用 pydantic 进行数据验证，支持异步操作，提高系统性能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;核心功能：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;智能代理：实现了多种类型的代理，如 Manus（ReAct）、Planning 等。&lt;/li&gt;
&lt;li&gt;工具集成：内置多个实用工具，包括 PythonExecute（执行Python代码）、GoogleSearch（网络搜索）、BrowserUseTool（浏览器操作）、FileSaver（文件保存）等。&lt;/li&gt;
&lt;li&gt;配置灵活性：OpenManus 支持多种LLM模型配置（如 OpenAI、Azure 等），并允许用户自定义系统提示词和工具集。&lt;/li&gt;
&lt;li&gt;使用简便性：提供 main.py 和 run_flow.py 两种启动方式，以及交互式命令行界面，方便用户上手。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;开源地址：OpenManus 的官方 GitHub 地址为 &lt;a href=&#34;https://github.com/mannaandpoem/OpenManus&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://github.com/mannaandpoem/OpenManus&lt;/a&gt;，自发布以来，该项目获得了大量关注，短时间内star数已接近34K。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;与 Manus 相比，OpenManus 提供了免费、无需邀请码的使用体验，以及更加透明的代码基础。尽管可能在某些功能上不如Manus 全面，但它作为一个开源项目，为开发者和用户提供了一个研究和实验的平台。&lt;/p&gt;
&lt;p&gt;项目在GitHub开源仅两周即获得34K Star，位列Trending榜单TOP 3。&lt;/p&gt;
&lt;h2&gt;二、环境部署指南&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二环境部署指南&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e7%8e%af%e5%a2%83%e9%83%a8%e7%bd%b2%e6%8c%87%e5%8d%97&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;部署这里比较简单，根据在 github 上的介绍就可以很容易的安装起来，它介绍了几种安装部署方式，这里使用了 conda 本地安装方式，具体操作如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;创建一个 conda 环境:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;conda create -n open_manus &lt;span class=&#34;nv&#34;&gt;python&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;3.12
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;conda activate open_manus&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;克隆代码到本地&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/mannaandpoem/OpenManus.git
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; OpenManus&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;安装 python依赖&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install -r requirements.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;三、模型配置实践&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三模型配置实践&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89%e6%a8%a1%e5%9e%8b%e9%85%8d%e7%bd%ae%e5%ae%9e%e8%b7%b5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;OpenManus 本身是不提供大模型的，需要在它的配置文件中配置本地或者远程模型地址。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;首先生成一个配置文件，可以直接复制它样例配置文件，再来修改：&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cp config/config.example.toml config/config.toml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;编辑 config/config.toml 添加相关配置，具体如下，我测试 2 种方式：
1. 是本地模型方式，我使用了 &amp;ldquo;qwen2.5:14b&amp;rdquo;。但是这种需要本地机器比较强悍，不然容易出现访问模型超时。
2. 使用 &amp;ldquo;claude-3-5-sonnet&amp;rdquo;，这个是直接使用外部接口地址。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;[llm]
# model = &amp;#34;claude-3-5-sonnet&amp;#34;
# base_url = &amp;#34;https://api.openai.com/v1&amp;#34;
# api_key = &amp;#34;sk-xxxxxx&amp;#34;
model = &amp;#34;qwen2.5:14b&amp;#34;
base_url = &amp;#34;http://localhost:11434/v1&amp;#34;
api_key = &amp;#34;ollama&amp;#34;

# Optional configuration for specific LLM models
[llm.vision]
# model = &amp;#34;gpt-4o&amp;#34;
# base_url = &amp;#34;https://api.openai.com/v1&amp;#34;
# api_key = &amp;#34;sk-...&amp;#34;  # Replace with your actual API key
model = &amp;#34;qwen2.5:14b&amp;#34;
base_url = &amp;#34;http://localhost:11434/v1&amp;#34;
api_key = &amp;#34;ollama&amp;#34;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;四、核心功能实测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四核心功能实测&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e6%a0%b8%e5%bf%83%e5%8a%9f%e8%83%bd%e5%ae%9e%e6%b5%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;最后直接在命令行中执行下面的命令就可以启动了。后面就可以直接在命令行中交流。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python main.py&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;另外自动化报告生成&lt;/p&gt;
&lt;p&gt;bash
python run_flow.py &amp;ndash;task &amp;ldquo;分析2024 Q2区块链行业趋势&amp;rdquo; &amp;ndash;output report.md&lt;/p&gt;
&lt;h2&gt;五、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;整体体验效果感觉还凑和，我根据网上的例子测试抓取新闻并总结，按理来说是一个非常好实现的，但是最终生成的内容非常一般，感觉没法使用，但是流程确实是跑动起来了。&lt;/p&gt;
&lt;p&gt;但是感觉这种模式应该是 AI 应用的趋势，不做大模型，而是做大模型、内容信息和工具之间的一种胶水层，是一种思考模式的实现。而且最近 MCP 也是非常火爆，感觉未来大厂的这些工具都会向这个方向发展。在特定的领域之内，结合大模型、具体场景信息和相关工具，思考组织执行方式和流程，最终完成一个自动化大规模计算的复杂任务。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>基于ESP32的Python物联网开发实践 - 通过HTTP API控制LED灯</title>
      <link>https://www.helight.info/blog/2025/0308-esp32/</link>
      <pubDate>Sat, 08 Mar 2025 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2025/0308-esp32/</guid>
      <description>
        
        
        &lt;h2&gt;一、Esp32&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一esp32&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80esp32&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;一时兴起买了一个 esp32 的小板子，想玩玩，此前主要使用Arduino进行开发，但受限于其缺乏原生蓝牙和WiFi模块，所以感觉还是不够好玩。现在 esp32 的板子便宜的 10 多块钱一个，基本都有集成的蓝牙和 wifi。我买的是这个板子。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2025/0308-esp32/imgs/641.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;昨晚到了之后直接拿一个数据线连接了 mac，使用 thonny 来测试连接，一切都很舒畅，在macOS系统上可便捷完成开发环境配置，而且可以使用 python 来开发。感觉也可以给小朋友来玩了。&lt;/p&gt;
&lt;p&gt;今天先试试一个简单的例子：通过一个 http 接口的返回结果来控制一个 led 灯的明灭。&lt;/p&gt;
&lt;h2&gt;二、硬件准备与电路连接：&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二硬件准备与电路连接&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e7%a1%ac%e4%bb%b6%e5%87%86%e5%a4%87%e4%b8%8e%e7%94%b5%e8%b7%af%e8%bf%9e%e6%8e%a5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;电路连接如下图所示，比较简单，采用一个电阻与LED灯串联电路设计（电阻用于限流保护LED）。led 要注意正负极。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2025/0308-esp32/imgs/640.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;三、LED基础控制实现：&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三led基础控制实现&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89led%e5%9f%ba%e7%a1%80%e6%8e%a7%e5%88%b6%e5%ae%9e%e7%8e%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;使用 python 写非常简单，代码如下，基本流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;引入 GPIO 控制库&lt;/li&gt;
&lt;li&gt;初始化引脚，设置为输出模式&lt;/li&gt;
&lt;li&gt;对引脚进行 on() 函数和 off() 函数调用控制&lt;/li&gt;
&lt;li&gt;这里另外加了一个 time 控制延时&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;machine&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;test_led&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;p5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Pin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Pin&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OUT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;p5&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;led on&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;p5&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;off&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;led off&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;四、网络连接配置&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四网络连接配置&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e7%bd%91%e7%bb%9c%e8%bf%9e%e6%8e%a5%e9%85%8d%e7%bd%ae&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这里的代码是网上直接找的，现成的，几乎没啥改动。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;ssid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;xxx&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;password&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;xxxx&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;wlan&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;network&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;WLAN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;network&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STA_IF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;wlan&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;active&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;wlan&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ssid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;password&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wlan&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isconnected&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Waiting for connection...&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Connected on &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{ip}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ip&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;wlan&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ifconfig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;五、服务端API设计&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五服务端api设计&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e6%9c%8d%e5%8a%a1%e7%ab%afapi%e8%ae%be%e8%ae%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;编写一个简单的 api，设计随机响应逻辑：当随机值&amp;gt;50时返回成功状态码，否则返回错误状态。我是在我自己的服务中增加了一个 api：/api/test/led。我是属于 golang 的 gin 框架开发，也是非常简单，基本代码如下：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-golang&#34; data-lang=&#34;golang&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// 根据随机数返回结果&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;CtrlLed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;gin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;clientIP&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ClientIP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Header&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;funlog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;SLoger&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;led ctrl ip clientIP &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;clientIP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;funlog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;SLoger&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;led ctrl headers &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tdata&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;rand&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Intn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tdata&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;funlog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;SLoger&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;led ctrl ok &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tdata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;OkWithMessage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;clientIP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34; ok&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;funlog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;SLoger&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;led ctrl error &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;tdata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;FailWithMessageCode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;clientIP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34; error&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;五、客户端请求实现&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五客户端请求实现&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e5%ae%a2%e6%88%b7%e7%ab%af%e8%af%b7%e6%b1%82%e5%ae%9e%e7%8e%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;urequests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;check_ledAPI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;urequests&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;http://192.168.2.26/api/test/led&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;parsed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parsed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parsed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parsed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ret ok: &amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parsed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;msg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;ret error try again&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;六、系统联调测试&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;六系统联调测试&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%ad%e7%b3%bb%e7%bb%9f%e8%81%94%e8%b0%83%e6%b5%8b%e8%af%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ctrl_led&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;p5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Pin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Pin&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OUT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;True&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;islight&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;check_ledAPI&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;islight&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;p5&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;led on&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;p5&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;off&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;led off&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sleep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;ctrl_led&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;测试日志如下:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;MPY: soft reboot
Connected on 192.168.2.247
{&amp;#39;code&amp;#39;: 0, &amp;#39;data&amp;#39;: {}, &amp;#39;msg&amp;#39;: &amp;#39;192.168.2.247 ok&amp;#39;}
&amp;lt;class &amp;#39;dict&amp;#39;&amp;gt;
ret ok: 192.168.2.247 ok
led on
{&amp;#39;code&amp;#39;: 500, &amp;#39;data&amp;#39;: {}, &amp;#39;msg&amp;#39;: &amp;#39;192.168.2.247 error&amp;#39;}
&amp;lt;class &amp;#39;dict&amp;#39;&amp;gt;
ret error try again
led off
{&amp;#39;code&amp;#39;: 500, &amp;#39;data&amp;#39;: {}, &amp;#39;msg&amp;#39;: &amp;#39;192.168.2.247 error&amp;#39;}
&amp;lt;class &amp;#39;dict&amp;#39;&amp;gt;
ret error try again
led off
{&amp;#39;code&amp;#39;: 0, &amp;#39;data&amp;#39;: {}, &amp;#39;msg&amp;#39;: &amp;#39;192.168.2.247 ok&amp;#39;}
&amp;lt;class &amp;#39;dict&amp;#39;&amp;gt;
ret ok: 192.168.2.247 ok
led on&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;七、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;七总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%83%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;整体效果还是挺好的，开发过程基本没啥卡点，使用 python 开发也非常方便丝滑，确实现在玩这类板子还是非常方便有趣的。该方案兼具趣味性和教学价值，适合作为青少年编程教育的实践案例。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>快速给公众号接入腾讯混元大模型</title>
      <link>https://www.helight.info/blog/2024/aihao/</link>
      <pubDate>Tue, 24 Sep 2024 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2024/aihao/</guid>
      <description>
        
        
        &lt;h2&gt;引言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;引言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%bc%95%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;最近也折腾了一下大模型的使用，目前看大模型的智能程度已经不错了，至少在文字类的工作中处理中应该是非常有优势，而且目前很多工具都非常成熟，使用门槛也减低了一定程度。&lt;/p&gt;
&lt;p&gt;前几天折腾了 dify，感觉配置非常方便，很多工作拖拖拉拉的就可以搞定。所以今天也看了一下腾讯混元的一个服务：腾讯元器。也是可以通过拖拖拉拉就可以搭建一个大模型的使用 bot。&lt;/p&gt;
&lt;p&gt;让我非常惊讶的是，我发现可以直接和公众号绑定，而且可以可以把公众号中的内容作为私有数据库，做一个公众号 RAG 应用。&lt;/p&gt;
&lt;p&gt;先看看效果：&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/1.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;操作详解&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;操作详解&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%93%8d%e4%bd%9c%e8%af%a6%e8%a7%a3&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;创建智能体&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;创建智能体&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%88%9b%e5%bb%ba%e6%99%ba%e8%83%bd%e4%bd%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;元器网址：https://yuanqi.tencent.com/&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/2.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;在这里直接添加一个智能体，我这里已经添加了，可以直接看我添加的内容。如下图展示，主要是名称，介绍，头像，角色设定等等信息。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/3.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;我这里要展示的是公众号内容的展示，所以这里重点是要把公众的内容关联起来，如下图配置，添加知识库。&lt;/p&gt;
&lt;h3&gt;使用公众号内容创建知识库&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;使用公众号内容创建知识库&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bd%bf%e7%94%a8%e5%85%ac%e4%bc%97%e5%8f%b7%e5%86%85%e5%ae%b9%e5%88%9b%e5%bb%ba%e7%9f%a5%e8%af%86%e5%ba%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/4.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;点击添加之后会有一个：创建知识库，在创建知识库的时候选择公众号文章。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/5.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;这里需要公众号授权，也是非常简单，有多个公众号的话，要选择你要创建知识库的号，这里就会自动去拉去公众号的文章作为知识库内容了。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/6.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;添加了之后看知识库这里就会有一个项目，这里就是刚刚添加的公众内容组成的知识库了。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/7.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;可以点击知识库看具体的一些配置信息。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/8.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;可以看到这里有 107 篇文章录入，如果有文章处理问题也会展示。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/9.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;可以到里面看具体的问题是什么，目前看知识库重点处理的还是文字信息，对于图片信息处理还是不太支持。这里我这篇文章就是文字太少。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/10.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;可以点击刷新让知识库继续处理。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/11.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;正常处理的内容都是这样的。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/12.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;智能体发布使用&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;智能体发布使用&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%99%ba%e8%83%bd%e4%bd%93%e5%8f%91%e5%b8%83%e4%bd%bf%e7%94%a8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在智能要发布审批之后才能使用， 主要使用方式有 4 种，&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;网页直接使用，就是腾讯元器&lt;/li&gt;
&lt;li&gt;小程序或者 app 使用，腾讯元宝&lt;/li&gt;
&lt;li&gt;直接扫码进公众号使用&lt;/li&gt;
&lt;li&gt;使用 api 调用&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/13.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;下图是网页直接使用。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/14.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;绑定到公众号菜单中使用&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;绑定到公众号菜单中使用&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%bb%91%e5%ae%9a%e5%88%b0%e5%85%ac%e4%bc%97%e5%8f%b7%e8%8f%9c%e5%8d%95%e4%b8%ad%e4%bd%bf%e7%94%a8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;首先要登录公众号，把元宝的这个小程序绑定到公众号上，绑定方式如下图。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/15.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;在元器中点击使用方式中的腾讯元宝，在这里获取元宝小程序的 appid 和小程序路径。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/16.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;把这两个信息填写到公众号菜单中，然后发布即可&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/17.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;这样就可以直接在公众号的菜单中访问，但是我发现直接和公众号对话也是可以调用的。
&lt;img src=&#34;https://www.helight.info/blog/2024/aihao/imgs/18.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;目前 ai 的发展实在太快了，各方面的应用都是飞速发展。尤其在文生文方面已经是比较成熟了。这里直接快捷的把小程序私有内容和大模型结合确实是一个非常好的落地点。&lt;/p&gt;
&lt;p&gt;但是这里怎么发挥更大的价值还有待进一步探索。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>微信小程序答题系统介绍</title>
      <link>https://www.helight.info/blog/2024/dati/</link>
      <pubDate>Sat, 18 May 2024 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2024/dati/</guid>
      <description>
        
        
        &lt;h2&gt;一、微信小程序答题系统介绍&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一微信小程序答题系统介绍&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e5%be%ae%e4%bf%a1%e5%b0%8f%e7%a8%8b%e5%ba%8f%e7%ad%94%e9%a2%98%e7%b3%bb%e7%bb%9f%e4%bb%8b%e7%bb%8d&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;去年做了一个小系统，一个微信小程序的答题系统，作为一个答题竞赛使用，有以下一些要求：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;独立微信小程序&lt;/li&gt;
&lt;li&gt;题库要能够自定义&lt;/li&gt;
&lt;li&gt;支持多选题和单选题&lt;/li&gt;
&lt;li&gt;支持排行榜&lt;/li&gt;
&lt;li&gt;支持多轮竞赛&lt;/li&gt;
&lt;li&gt;支持限定名单用户参与&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;界面&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;界面&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%95%8c%e9%9d%a2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;引导页&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;引导页&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%bc%95%e5%af%bc%e9%a1%b5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;img src=&#34;imgs/1.jpg&#34; alt=&#34;图片描述&#34; width=&#34;70%&#34; height=&#34;auto&#34;&gt;
&lt;h3&gt;引导页&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;引导页-1&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%bc%95%e5%af%bc%e9%a1%b5-1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;img src=&#34;imgs/2.jpg&#34; alt=&#34;图片描述&#34; width=&#34;70%&#34; height=&#34;auto&#34;&gt;
&lt;h4&gt;用户绑定和白名单控制&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;用户绑定和白名单控制&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%94%a8%e6%88%b7%e7%bb%91%e5%ae%9a%e5%92%8c%e7%99%bd%e5%90%8d%e5%8d%95%e6%8e%a7%e5%88%b6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;img src=&#34;imgs/3.jpg&#34; alt=&#34;图片描述&#34; width=&#34;70%&#34; height=&#34;auto&#34;&gt;
&lt;h3&gt;答题页&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;答题页&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%ad%94%e9%a2%98%e9%a1%b5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;img src=&#34;imgs/4.jpg&#34; alt=&#34;图片描述&#34; width=&#34;70%&#34; height=&#34;auto&#34;&gt;
&lt;h3&gt;排行榜&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;排行榜&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%8e%92%e8%a1%8c%e6%a6%9c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;img src=&#34;imgs/5.jpg&#34; alt=&#34;图片描述&#34; width=&#34;70%&#34; height=&#34;auto&#34;&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>微信公众号预约系统介绍</title>
      <link>https://www.helight.info/blog/2024/yuyue/</link>
      <pubDate>Thu, 18 Jan 2024 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2024/yuyue/</guid>
      <description>
        
        
        &lt;h2&gt;一、预约系统功能介绍&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一预约系统功能介绍&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e9%a2%84%e7%ba%a6%e7%b3%bb%e7%bb%9f%e5%8a%9f%e8%83%bd%e4%bb%8b%e7%bb%8d&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;主体功能：对一个地方的使用时间进行预约管理，比如有一间会议室，它上午时间段和下午时间段的预约使用。&lt;/p&gt;
&lt;p&gt;所以这里分为 2 部分主要能力：1） 客户预约前端；2）管理员使用的管理端。&lt;/p&gt;
&lt;h3&gt;1 、客户预约前端主要功能：&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-客户预约前端主要功能&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e5%ae%a2%e6%88%b7%e9%a2%84%e7%ba%a6%e5%89%8d%e7%ab%af%e4%b8%bb%e8%a6%81%e5%8a%9f%e8%83%bd&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&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;li&gt;对预约信息查看&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2 、管理员使用管理端主要功能：&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-管理员使用管理端主要功能&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e7%ae%a1%e7%90%86%e5%91%98%e4%bd%bf%e7%94%a8%e7%ae%a1%e7%90%86%e7%ab%af%e4%b8%bb%e8%a6%81%e5%8a%9f%e8%83%bd&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&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;li&gt;管理员信息管理&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;二、预约系统界面展示&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二预约系统界面展示&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8c%e9%a2%84%e7%ba%a6%e7%b3%bb%e7%bb%9f%e7%95%8c%e9%9d%a2%e5%b1%95%e7%a4%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1 、客户预约前端&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-客户预约前端&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e5%ae%a2%e6%88%b7%e9%a2%84%e7%ba%a6%e5%89%8d%e7%ab%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/yuyue/imgs/640.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/yuyue/imgs/641.webp&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/yuyue/imgs/642.webp&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;2 、管理员使用管理端&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-管理员使用管理端&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-%e7%ae%a1%e7%90%86%e5%91%98%e4%bd%bf%e7%94%a8%e7%ae%a1%e7%90%86%e7%ab%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/yuyue/imgs/643.webp&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/yuyue/imgs/644.webp&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/yuyue/imgs/645.webp&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2024/yuyue/imgs/646.webp&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;以上就是所有功能。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>【译】平台工程: 入门所需的所有知识</title>
      <link>https://www.helight.info/blog/2023/platform-engineering-101/</link>
      <pubDate>Tue, 27 Jun 2023 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2023/platform-engineering-101/</guid>
      <description>
        
        
        &lt;h2&gt;平台工程: 入门所需的所有知识&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台工程-入门所需的所有知识&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b-%e5%85%a5%e9%97%a8%e6%89%80%e9%9c%80%e7%9a%84%e6%89%80%e6%9c%89%e7%9f%a5%e8%af%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;数字平台正在形成一种提供服务和吸引用户的新方式。多亏了他们，才有可能为客户提供全渠道的体验，达到他们与公司互动的所有接入点。因此，组织可以利用这些机会来创建新的业务模型。&lt;/p&gt;
&lt;p&gt;鉴于它们的广泛使用，在本文中，我们希望提供一个指南，以理解围绕数字平台而创建和发展的整个生态系统的基本原理。特别地，我们将解释开始使用云平台时需要了解的&lt;strong&gt;基本概念&lt;/strong&gt;，并提供最重要的术语表。&lt;/p&gt;
&lt;h2&gt;数字平台：理解什么是成功的原因&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;数字平台理解什么是成功的原因&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%95%b0%e5%ad%97%e5%b9%b3%e5%8f%b0%e7%90%86%e8%a7%a3%e4%bb%80%e4%b9%88%e6%98%af%e6%88%90%e5%8a%9f%e7%9a%84%e5%8e%9f%e5%9b%a0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;当然，首先要了解的概念是&lt;strong&gt;数字平台&lt;/strong&gt;，它是数字转型背后的工具。数字平台在用户与组织交互的外部渠道和组织的内部系统(例如CRM、电子商务、管理系统等)之间&lt;strong&gt;架起了数字鸿沟的桥梁&lt;/strong&gt;。此外，该平台帮助&lt;strong&gt;系统减负&lt;/strong&gt;，增加了所提供服务的可扩展性和灵活性，并缩短了上市时间。&lt;/p&gt;
&lt;p&gt;一个结构良好的平台通常使用现代云原生技术开发，并分为三个层次:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;-数据管理层：数据从组织系统中解耦，聚合在一个视图中，最终近乎&lt;a href=&#34;https://blog.mia-platform.eu/en/fast-data-evolve-your-users-experience-with-real-time-information&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;实时&lt;/a&gt;可用。&lt;/li&gt;
&lt;li&gt;一个专用于业务逻辑的层：这里运行了一个&lt;a href=&#34;https://blog.mia-platform.eu/en/microservices-the-architectural-style-for-modern-applications&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;微服务&lt;/a&gt;架构，它包含了与公司核心业务相关的所有功能。&lt;/li&gt;
&lt;li&gt;数字产品层，也就是一套 api，可以方便地连接外部渠道并缩短上市时间。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2023/platform-engineering-101/imgs/Digital-Platform02.svg&#34; alt=&#34;Digital Platform&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;平台工程：构建基础平台&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台工程构建基础平台&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b%e6%9e%84%e5%bb%ba%e5%9f%ba%e7%a1%80%e5%b9%b3%e5%8f%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;当讨论数字平台时，首先要考虑的概念之一是&lt;strong&gt;平台工程&lt;/strong&gt;，根据&lt;a href=&#34;https://www.gartner.com/en/articles/what-s-new-in-the-2022-gartner-hype-cycle-for-emerging-technologies&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Gartner的定义&lt;/a&gt;， &lt;strong&gt;这是构建和运营用于软件交付和生命周期管理的内部自助开发者平台(IDPs)的学科&lt;/strong&gt;。这个术语指的是平台的初始设计阶段，这当然是必要的，也可能很耗时，尤其是从头开始的时候。但是平台工程还包括设计之后的实现阶段，以及最重要的维护阶段，这是&lt;strong&gt;持续改进、扩展和更新&lt;/strong&gt;平台功能的工作。&lt;/p&gt;
&lt;p&gt;云平台一直在发展。每天都在开发新的工具，包括开源软件和专有软件，可以通过集成来促进或扩展某些操作。除此之外，&lt;a href=&#34;https://mia-platform.eu/solutions/platform-engineer-devops/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;strong&gt;平台工程师&lt;/strong&gt;&lt;/a&gt;及其团队(也称为平台团队，我们将在后面看到)的日常工作重点是根据组织的需求&lt;strong&gt;创建工作流和自动化逻辑&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;平台工程正蓬勃发展，它被认为是一个非常具有颠覆性的趋势，以至于许多人认为它可以取代 DevOps 和 SRE。阅读这篇&lt;a href=&#34;https://blog.mia-platform.eu/en/is-platform-engineering-putting-an-end-to-devops-and-sre&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;博客文章&lt;/a&gt;以了解更多!&lt;/p&gt;
&lt;h2&gt;平台经济：寻找平台的价值&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台经济寻找平台的价值&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e7%bb%8f%e6%b5%8e%e5%af%bb%e6%89%be%e5%b9%b3%e5%8f%b0%e7%9a%84%e4%bb%b7%e5%80%bc&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;数字平台，特别是云平台的现象现在非常普遍，它创造了一个完整的经济，称为&lt;strong&gt;平台经济&lt;/strong&gt;。有趣的是，云平台提供的模块化和灵活性使即使是小公司也能&lt;strong&gt;与更结构化的竞争对手竞争&lt;/strong&gt;。事实上，引领平台经济的创新科技公司，如 Uber、Spotify 和 Airbnb，是在市场上支持自己的最成功的公司。&lt;/p&gt;
&lt;p&gt;要进一步探索，请阅读我们博客上的这篇文章：&lt;a href=&#34;https://blog.mia-platform.eu/en/platform-economy-why-you-need-a-modular-it-architecture&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;平台经济:为什么你需要模块化IT架构&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;平台公司：基于平台组织公司&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台公司基于平台组织公司&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%85%ac%e5%8f%b8%e5%9f%ba%e4%ba%8e%e5%b9%b3%e5%8f%b0%e7%bb%84%e7%bb%87%e5%85%ac%e5%8f%b8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;上面提到的平台经济的主要参与者是&lt;strong&gt;平台公司&lt;/strong&gt;，它们是围绕数字平台构建商业模式的公司。采用这种方法最初需要大量的组织和运营工作，但是从长远来看，它提供了灵活性、敏捷性以及在出现业务机会时演化和抓住业务机会的能力。&lt;/p&gt;
&lt;p&gt;平台公司&lt;strong&gt;专注于客户&lt;/strong&gt;，客户是所有战略决策的中心。这意味着与技术实现或业务流程相关的复杂性不应该从外部感知；最重要的是，&lt;strong&gt;内部复杂性不应该影响最终用户及其体验&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;想了解更多关于这个主题的信息，请下载我们的免费白皮书&lt;a href=&#34;https://resources.mia-platform.eu/en/white-paper-why-and-how-to-evolve-into-a-platform-company&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;为什么以及如何发展成一个平台公司&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;平台团队：每天都在改进平台&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台团队每天都在改进平台&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%9b%a2%e9%98%9f%e6%af%8f%e5%a4%a9%e9%83%bd%e5%9c%a8%e6%94%b9%e8%bf%9b%e5%b9%b3%e5%8f%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;一旦平台在公司内部创建和实现，就有必要&lt;strong&gt;每天都在它上面工作&lt;/strong&gt;，以优化和扩展它的功能。这项工作通常由一个专门的团队完成，称为&lt;strong&gt;平台团队&lt;/strong&gt;，由具有不同技能和经验的成员组成，尽可能跨职能。&lt;/p&gt;
&lt;p&gt;平台团队的客户是公司的开发人员。平台团队的目的是确保其他团队在使用平台时尽可能获得无障碍和自助的体验：因此，平台团队必须专注于软件生命周期的所有方面。&lt;/p&gt;
&lt;h2&gt;开发者平台：改善开发体验&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;开发者平台改善开发体验&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%bc%80%e5%8f%91%e8%80%85%e5%b9%b3%e5%8f%b0%e6%94%b9%e5%96%84%e5%bc%80%e5%8f%91%e4%bd%93%e9%aa%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;The IDP aims to serve the entire IT department of the organization&lt;/strong&gt;. Specifically, this tool allows to:
&lt;strong&gt;开发者平台&lt;/strong&gt;(也称为开发者门户)旨在简化开发团队的工作并改善&lt;a href=&#34;https://blog.mia-platform.eu/en/how-a-frictionless-developer-experience-improves-software-development&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;开发者体验&lt;/a&gt;。为了更简单和更高效，创建两个开发人员平台可能是有用的，专用于具有不同需求的不同团队:一个&lt;a href=&#34;https://blog.mia-platform.eu/en/5-tips-for-implementing-internal-developer-portal-in-your-company&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;内部开发人员平台&lt;/a&gt; (IDP)用于组织的内部开发人员，一个&lt;a href=&#34;https://mia-platform.eu/solutions/external-developer-portal/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;外部开发人员平台&lt;/a&gt; (EDP)用于外部开发人员。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;IDP旨在服务于组织的整个 IT 部门&lt;/strong&gt;。具体来说，这个工具允许:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在一个受管制的环境中管理所有项目;&lt;/li&gt;
&lt;li&gt;实现整个 DevOps 周期的工业化和自动化，以提高生产力;&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;/li&gt;
&lt;/ul&gt;
&lt;p&gt;相反，&lt;strong&gt;EDP 负责改善与组织外部开发人员的合作&lt;/strong&gt;，通常来自合作公司或客户，通过提供公共 api 和文档的自助生态系统。EDP 允许 &lt;strong&gt;API 转化为货币化资源&lt;/strong&gt;，将它们视为实际产品(&lt;a href=&#34;https://blog.mia-platform.eu/en/api-as-a-product-why-apis-are-at-the-heart-of-digital-business&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;API即产品&lt;/a&gt; - AaaP)，以及发布服务和提供软件试用版本的安全访问。&lt;/p&gt;
&lt;h2&gt;平台即服务 (PaaS)：免费享用所有的好处&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台即服务-paas免费享用所有的好处&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%8d%b3%e6%9c%8d%e5%8a%a1-paas%e5%85%8d%e8%b4%b9%e4%ba%ab%e7%94%a8%e6%89%80%e6%9c%89%e7%9a%84%e5%a5%bd%e5%a4%84&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;正如它所提到的，数字平台提供了许多好处，特别如果它是为使用它的组织定制的。然而，有几种情况&lt;strong&gt;从头开始构建自己的平台是不可能的，也是不划算的&lt;/strong&gt;：在从头开始构建期间，以及平台启动和运行后的日常维护期间，所需的时间、资源和人力都是相当大的。&lt;/p&gt;
&lt;p&gt;在这种情况下，有一种方法可以从平台的所有优势中受益，而无需投入精力来构建和维护它：这种服务被称为&lt;strong&gt;平台即服务(PaaS)&lt;/strong&gt;。通过 PaaS，公司可以&lt;strong&gt;专注于开发自己的软件代码&lt;/strong&gt;，更好地为客户服务，因为他们不用担心系统和基础设施管理。&lt;/p&gt;
&lt;h2&gt;结论&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;结论&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%bb%93%e8%ae%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在本文中，我们收集了与云平台生态系统相关的一些关键概念，重点关注平台工程的世界。我们的目标是提供一个介绍性的概述，只涵盖一个非常丰富、巨大和不断发展的生态系统的一小部分。我们通过创建一个&lt;strong&gt;指南，提供你进入云平台世界的必要工具&lt;/strong&gt;来做到这一点，云平台是一个快节奏和不断增长的世界，每天都有新的工具和机会出现。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>【译】在 IT 系统的开发和运营中使用生成式人工智能的潜在好处</title>
      <link>https://www.helight.info/blog/2023/using-generative-ai/</link>
      <pubDate>Tue, 30 May 2023 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2023/using-generative-ai/</guid>
      <description>
        
        
        &lt;h1&gt;前言&lt;/h1&gt;&lt;p&gt;很多团队正在试验如何使用生成性 AI 来开发和运营 IT 系统。&lt;/p&gt;
&lt;p&gt;生成式 AI 可以自动生成 IT 系统中使用的代码或模型。这有助于加快开发过程并减少所需的人工劳动量。生成式人工智能还可以为 IT 系统创建人类开发人员可能没有考虑过的新设计或解决方案。&lt;/p&gt;
&lt;p&gt;通过分析大量数据和识别模式，&lt;a href=&#34;https://dzone.com/articles/the-exponential-growth-of-generative-ai-opportunit&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;生成式 AI&lt;/a&gt;可以为复杂问题开发新颖的解决方案。&lt;/p&gt;
&lt;p&gt;生成式 AI&lt;a href=&#34;https://dzone.com/articles/understanding-architecture-models-of-chatbot-and-r&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;模型&lt;/a&gt;学习大型数据集中的模式和特征，然后生成与这些模式和组件匹配的新内容。但是，它们无法创建训练数据中不存在的全新或原创内容。&lt;/p&gt;
&lt;p&gt;虽然生成式 AI 模型可以产生逼真的内容，但必须注意它们不具备独立思考或创造力的能力。他们只能根据从训练数据中学到的知识生成新内容。&lt;/p&gt;
&lt;p&gt;然而，值得注意的是，生成式 AI 仍处于早期阶段，许多挑战仍有待克服。例如，可能不太容易确保生成的代码或模型是高质量的并满足要求。此外，对于生成式 AI 中的偏见和公平性存在担忧，因为这些算法可能会受到它们所训练的数据中的现有偏见而把这种偏见永久化。&lt;/p&gt;
&lt;p&gt;生成人工智能的一些案例已经可以在数周或数月内在企业内就可以实施。相比之下，其它案例可能需要更多的研究和开发才能在商业环境中有效使用。采用的时间表还取决于所解决问题的复杂性和组织可用的资源。因此，组织必须在投入资源开发和部署之前仔细评估生成式 AI 解决方案的可行性和潜在影响。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;架构设计&lt;/strong&gt; &lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;架构设计&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%9e%b6%e6%9e%84%e8%ae%be%e8%ae%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://dzone.com/articles/artificial-intelligence-in-architecture&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;使用 AI&lt;/a&gt;生成 IT 架构的好处之一是，与手动设计的系统相比，它可以设计更高效、可扩展和有弹性的系统。这是因为 AI&lt;a href=&#34;https://dzone.com/articles/exploring-ai-algorithms&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;算法&lt;/a&gt;可以快速有效地搜索大量可能的设计，以找到最适合给定任务或问题的设计。&lt;/p&gt;
&lt;p&gt;此外，生成式 AI 可以帮助组织快速且经济高效地设计和部署根据其特定需求定制的 IT 系统，从而减少手动设计和优化所需的时间和资源。&lt;/p&gt;
&lt;p&gt;通过把设计和优化过程的某些方面自动化，生成式 AI 有可能显着增强基于模式的解决方案蓝图和系统架构文档的开发工作。&lt;/p&gt;
&lt;p&gt;例如，生成式 AI 算法可以分析现有解决方案的大型数据集，并确定可应用于新解决方案的通用模式和设计原则。这有助于确定已经成功的最佳实践和设计模式，并使开发人员能够快速有效地将它们整合到新的解决方案中。&lt;/p&gt;
&lt;p&gt;生成式 AI 还可以根据预定义的目标和约束自动生成和评估不同的设计选项，从而帮助优化系统架构。这有助于确定满足项目要求的最有效的系统架构。&lt;/p&gt;
&lt;p&gt;此外，生成式 AI 可以根据已识别的模式和设计原则生成详细的图表、规范和其他支持文档，从而帮助自动化文档撰写过程。这有助于加快文档撰写过程并确保生成的文档准确且一致。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;设计&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;设计&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%ae%be%e8%ae%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;生成式 AI 还可用于帮助生成设计规范、基于行业模型的&lt;a href=&#34;https://dzone.com/articles/everything-you-should-know-about-apis&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;API&lt;/a&gt;规范、框架/实用程序功能建议和数据库配置。&lt;/p&gt;
&lt;p&gt;例如，生成式 AI 算法可以分析现有的设计模式、系统架构和代码库，以确定通用模式和最佳实践，并使用这些信息自动生成满足项目要求和约束的设计规范。&lt;/p&gt;
&lt;p&gt;同样，生成式人工智能可以分析行业模型并生成针对特定行业的 API 规范，为特定于行业需求的 API 设计和开发提供标准化方法。&lt;/p&gt;
&lt;p&gt;生成式 AI 还可以根据对现有代码库和开发趋势的分析，为最适合项目需求的框架和实用功能提供建议。这有助于减少手动研究和评估不同框架和实用程序所需的时间和精力，并使开发人员能够快速有效地确定最适合工作的工具。 &lt;/p&gt;
&lt;p&gt;最后，生成式 AI 可以根据项目要求自动生成数据库设计和实施建议，从而协助数据库配置。这有助于确保数据库针对性能、可伸缩性和可靠性进行优化，并满足项目的需求。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;测试&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;测试&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%b5%8b%e8%af%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;生成式人工智能还可以为各种测试场景生成测试用例和测试数据，包括主要流程、备用路径、异常流程和错误处理。通过分析系统架构并识别常见模式和最佳实践，生成式人工智能可以生成涵盖广泛场景的测试用例和&lt;a href=&#34;https://dzone.com/articles/what-is-test-data-why-is-data-driven-testing-neces&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;测试数据&lt;/a&gt;，确保系统得到全面测试，并识别和解决潜在问题。&lt;/p&gt;
&lt;p&gt;除了生成测试用例和测试数据外，生成式 AI 还可以生成用于渗透、混沌和性能测试的测试配置文件。通过分析系统架构并识别潜在的漏洞和瓶颈，生成式人工智能可以生成模拟真实场景的测试配置文件，并提供对系统性能和弹性的宝贵见解。&lt;/p&gt;
&lt;p&gt;生成式人工智能还可以帮助选择和优化测试框架和工具。通过分析现有代码库并确定常见的测试模式和最佳实践，生成式 AI 可以建议最适合项目要求和约束的测试框架和工具，帮助确保测试过程高效且有效。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;部署&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;部署&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%83%a8%e7%bd%b2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;生成式 AI 还可以生产协助打包和部署工件和数据现代化脚本。&lt;/p&gt;
&lt;p&gt;生成式 AI 可以分析打包和部署工件的系统架构，并确定打包和部署软件系统的最佳实践和模式。基于这种分析，生成式 AI 可以生成部署脚本和模板，使部署过程自动化，并确保生成的工件是一致的、可靠的，并且针对目标环境进行了优化。&lt;/p&gt;
&lt;p&gt;对于数据现代化脚本，生成式 AI 可以分析现有数据架构并确定数据现代化的常见模式和最佳实践。基于这种分析，生成式 AI 可以生成数据迁移脚本和模板，使数据现代化过程自动化，确保数据的转换和迁移高效且有效。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;运营&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;运营&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%bf%90%e8%90%a5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;生成式 AI 还可用于协助事件分类和警报，以及服务管理的其他各个方面。&lt;/p&gt;
&lt;p&gt;在事件分类和警报中，生成 AI 可以分析历史事件数据并识别模式和趋势，这些模式和趋势有助于根据事件的潜在影响和严重程度确定事件和警报的优先级。此外，通过分析类似的工单、问题类别、解决方案类别和根本原因，生成式 AI 可以提出潜在的解决方案和建议来解决事件和警报，并为问题和工单推荐运行手册以简化解决过程。&lt;/p&gt;
&lt;p&gt;生成式 AI 还可以协助总结解决说明、根本原因和最终说明，提供事件的高级概述及其对开发、运营和客户使用价值流的影响。这有助于深入了解事件的根本原因以及事件对整体服务交付的影响。&lt;/p&gt;
&lt;p&gt;除了事件管理，生成式人工智能还可用于为常见问题和标准操作程序生成自动化脚本，有助于简化解决流程并减少人工干预所需的时间和精力。&lt;/p&gt;
&lt;p&gt;最后，生成式人工智能可以生成服务管理报告，为服务交付流程的绩效和有效性提供有价值的见解，包括事件量、解决时间和客户满意度等指标。通过分析这些报告，利益相关者可以深入了解服务交付流程的整体健康状况和绩效，并确定改进和优化的机会。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;自治系统&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;自治系统&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%87%aa%e6%b2%bb%e7%b3%bb%e7%bb%9f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;总有一天，生成式 AI 可用于创建自动化 IT 系统，这些系统能够在没有人为干预的情况下做出决策并采取行动。 &lt;/p&gt;
&lt;p&gt;GitOps 是一种用于管理和自动化 IT 系统的方法，也可以与生成 AI 一起使用以提高 IT 系统的效率和可靠性。GitOps 使用 Git 等版本控制系统来管理和自动化 IT 操作。&lt;/p&gt;
&lt;p&gt;生成式 AI 可用于创建可预测和预防潜在系统故障、识别性能瓶颈和优化资源利用率的模型。&lt;/p&gt;
&lt;p&gt;通过将 GitOps 与生成式 AI 结合使用，组织可以自动化 IT 系统的部署和管理，同时确保在部署之前对变更进行充分的测试和审计。这有助于提高 IT 系统的可靠性和安全性，同时减少 IT 运营所需的时间和精力。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;法律影响&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;法律影响&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%b3%95%e5%be%8b%e5%bd%b1%e5%93%8d&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在开发 IT 系统时使用生成式 AI 会涉及法律问题。与任何技术一样，应考虑潜在风险和法律问题。&lt;/p&gt;
&lt;p&gt;生成人工智能的主要法律问题之一是知识产权。例如，如果生成式 AI 系统创建了受版权保护的作品，则可能不清楚谁拥有该作品的权利。这可能导致所有权纠纷，甚至可能导致法律诉讼。&lt;/p&gt;
&lt;p&gt;另一个问题与责任有关。如果生成式 AI 系统创造了造成伤害的产品或服务，那么可能会出现谁应对这种伤害负责的问题。例如，如果使用生成式 AI 开发的自动驾驶汽车发生事故，谁该承担责任：制造商、软件开发商还是 AI 系统本身？&lt;/p&gt;
&lt;p&gt;隐私也是生成人工智能的一个重要法律问题。例如，如果系统根据用户数据生成内容，则可能存在有关如何收集、使用和存储该数据的问题。这可能会违反隐私法律和法规。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;结论&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;结论&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%bb%93%e8%ae%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;组织必须建立治理组织，以确保以合乎道德、负责任的方式使用生成人工智能，并遵守所有相关法律法规。这可能涉及制定政策和程序、建立监督和审查流程，以及培训员工正确使用技术。&lt;/p&gt;
&lt;p&gt;原文：&lt;a href=&#34;https://dzone.com/articles/potential-benefits-of-using-generative-ai-in-the-d&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://dzone.com/articles/potential-benefits-of-using-generative-ai-in-the-d&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>【译】SRE 实施的 6 个简单步骤</title>
      <link>https://www.helight.info/blog/2023/6-easy-steps-to-sre-implementation/</link>
      <pubDate>Fri, 28 Apr 2023 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2023/6-easy-steps-to-sre-implementation/</guid>
      <description>
        
        
        &lt;h1&gt;译说&lt;/h1&gt;&lt;p&gt;这篇文章对 SRE 的落地实践讲解的非常不错，所以也是加入到学习计划中了，今天整理完整，感觉可以分享给大家一起学习。&lt;/p&gt;
&lt;p&gt;但是这里说了 SLA，还没有介绍 SLI 和 SLO，还找到一篇文章对这块实践也介绍的比较好。&lt;/p&gt;
&lt;h1&gt;前言&lt;/h1&gt;&lt;p&gt;&lt;strong&gt;站点可靠性工程&lt;/strong&gt;( &lt;strong&gt;SRE&lt;/strong&gt;) 是一种管理和改进服务或应用程序的可靠性、性能和正常运行时间的方法。要实施 SRE，必须首先定义 SRE 团队的目的和目标，包括提高可用性和性能以及减少停机时间。接下来，确定 SRE 团队负责的服务和应用程序并确定其优先级。这可能包括核心业务服务、面向客户的应用程序以及数据库和网络等关键基础设施组件。此后，重点实施服务级别协议 (SLA)，为每项服务定义可接受的可用性、性能和可靠性级别。使用这些 SLA 来衡量团队在实现这些目标方面的成功程度。一旦 SLA 确定了，就要建立一个具有必要技能和专业知识的跨职能团队来支持相关服务和应用程序。这可能包括软件工程师、系统管理员、网络工程师和其他专家。然后建设流程和工具，例如监控和警报系统、部署自动化工具和性能分析工具。最后，请记住优化是一个持续的过程，并不断审查和改进 SRE 团队的流程和实践，以实现预期的目标。这可能包括定期回顾、持续学习和培训，以及根据需要采用新技术和技巧。实施流程和工具，例如监控和警报系统、部署自动化工具和性能分析工具。最后，请记住优化是一个持续的过程，并不断审查和改进 SRE 团队的程序和实践，以实现预期的目标。这可能包括定期回顾、持续学习和培训，以及根据需要采用新技术和技巧。&lt;/p&gt;
&lt;h1&gt;定义 SRE 团队的目标&lt;/h1&gt;&lt;p&gt;定义 SRE 团队的目标是实施 SRE 必不可少的第一步。这包括清楚地概述团队的目标是什么以及如何衡量成功。SRE 团队的一些共同目标包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;提高关键服务的可用性和性能：这意味着确保基本服务始终可用并以最佳水平运行。这可能涉及识别和解决可能导致中断或减速的潜在问题，并采取措施防止或减轻此类问题。&lt;/li&gt;
&lt;li&gt;减少从中断中恢复的平均时间：中断是不可避免的，但是从中恢复所需的时间会对业务产生重大影响。通过减少平均恢复时间 (MTTR)，SRE 团队可以帮助最大程度地减少中断的影响并更快地使服务恢复在线。&lt;/li&gt;
&lt;li&gt;提高部署成功率：部署更新和新功能到服务可能是一个复杂且有风险的过程。通过提高部署成功率，SRE 团队可以帮助确保变更顺利实施且不会中断服务。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;请务必注意，这些只是几个示例，SRE 团队的具体目标将取决于组织的需求和优先级。一旦定义了这些目标，SRE 团队就可以专注于实施实现这些目标所需的流程和工具。&lt;/p&gt;
&lt;h1&gt;为 SRE 确定服务和应用程序并确定优先级&lt;/h1&gt;&lt;p&gt;确定 SRE 团队将负责的服务和应用程序并确定其优先级是实施 SRE 的重要步骤。此过程涉及评估组织的服务和应用程序，并确定哪些对业务最关键并且需要 SRE 团队最多的关注。SRE 团队可能优先考虑的一些服务和应用程序示例包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;核心业务服务：这些是对业务运营必不可少的服务，通常有组织内的大量人员使用。例如包括内部电子邮件系统或客户关系管理平台。&lt;/li&gt;
&lt;li&gt;面向客户的应用程序是客户直接使用的应用程序和服务，例如零售网站或手机银行应用程序。确保这些应用程序的可靠性和性能对于维持客户满意度和忠诚度至关重要。&lt;/li&gt;
&lt;li&gt;主干组件：这些是支持组织的服务和应用程序的基础结构组件。例如包括数据库、网络系统和存储系统。确保这些组件的可靠性和性能对于组织的整体运营至关重要。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;请记住，SRE 团队负责的具体服务和应用程序将取决于组织的需求和优先级。一旦确定了这些服务和应用程序并确定了优先级，SRE 团队就可以专注于建设确保其可靠性和性能所需的流程和工具。&lt;/p&gt;
&lt;h1&gt;在 SRE 的服务级别协议中定义性能指标&lt;/h1&gt;&lt;p&gt;服务级别协议 (SLA) 是描述供应商（在本例中为 SRE 团队）向客户预期（例如，服务或应用程序的用户）提供的服务级别的合同。在 SRE 的上下文中，SLA 为 SRE 团队负责的服务和应用程序定义了可接受的可用性、性能和可靠性级别。SLA 中可能包含的性能指标类型的一些常见示例包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可用性：这是指服务或应用程序对用户可用的时间百分比。这可以根据正常运行时间来衡量，即服务或应用程序正常运行的时间百分比。&lt;/li&gt;
&lt;li&gt;性能：这是指服务或应用程序在速度、响应能力和效率方面的表现。&lt;/li&gt;
&lt;li&gt;可靠性：这是指服务或应用程序随着时间的推移正确且一致地运行的能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;不要忘记，SLA 中包含的具体指标和目标将取决于组织的需求和优先级以及相关的特定服务或应用程序。一旦定义了 SLA，SRE 团队就可以使用这些指标来衡量他们在实现目标方面的成功并确定改进的地方。&lt;/p&gt;
&lt;h1&gt;在 SRE 中实施服务水平协议&lt;/h1&gt;&lt;p&gt;一旦定义并实施了服务级别协议 (SLA)，实施 SRE 的下一步就是建立一个具有必要技能和专业知识的跨职能团队来支持相关服务和应用程序。跨职能团队由具有各种技能和专业知识的个人组成，他们可以有效地合作以实现共同的目标。在 SRE 的背景下，这可能包括在软件工程、系统管理、网络工程和其他专业领域具有专业知识的个人。SRE 团队所需的特定技能和专业知识将取决于组织的需求和优先级以及团队负责的特定服务和应用程序。例如，负责支持面向客户的 Web 应用程序的团队可能需要具有 Web 开发和前端设计经验的软件工程师以及具有 Web 服务器和网络专业知识的系统管理员。建立一个跨职能团队是必不可少的，因为它允许团队利用广泛的专业知识和技能，这对于确保相关服务和应用程序的可靠性和性能是必要的。通过建立一个可以有效协作并利用每个成员技能的团队，SRE 团队可以更有效地支持组织的关键服务和应用程序。&lt;/p&gt;
&lt;h1&gt;开发和建设 SRE 的流程和工具&lt;/h1&gt;&lt;p&gt;一旦定义了服务级别协议 (SLA) 并建立了跨职能团队，实施 SRE 的下一步就是开发和建设有助于团队的流程和工具实现其目的和目标。SRE 团队可能使用的技术和工具的一些示例包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;监控和警报系统：这些工具用于监控服务和应用程序的性能和可用性，并在出现问题时提醒 SRE 团队或其他相关方。这可能包括中断、时延增加或其他性能问题的警报。&lt;/li&gt;
&lt;li&gt;部署自动化工具用于将服务和应用程序更新和新功能的部署过程自动化。这可以降低出错的风险并提高部署的速度和效率。&lt;/li&gt;
&lt;li&gt;性能分析工具：这些工具用于分析服务和应用程序的性能，包括速度、响应能力和效率。这可以帮助 SRE 团队识别和解决可能影响服务性能的潜在问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;请务必注意，SRE 团队使用的特定流程和工具将取决于组织的需求和优先级以及团队负责的特定服务和应用程序。通过建设正确的流程和工具，SRE 团队可以更有效地支持组织的关键服务和应用程序并实现其目标。&lt;/p&gt;
&lt;h1&gt;优化 SRE 实践&lt;/h1&gt;&lt;p&gt;优化对于站点可靠性工程 (SRE) 的成功至关重要。为确保 SRE 团队能够持续改进并达到预期目标，审查和改进团队的处理流程和实践方法至关重要。SRE 团队可能用来优化其实践的一些方法包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;定期回顾：团队在会议中审查其流程和实践，并讨论哪些方面运作良好，哪些可以改进。通过定期进行回顾，SRE 团队可以确定需要改进的领域，并根据需要对其流程和实践进行更改。&lt;/li&gt;
&lt;li&gt;持续学习和培训：为了跟上 SRE 的最新技术和最佳实践，团队需要参与持续学习和培训。这可能包括参加会议、参加在线课程或参加专业发展计划。&lt;/li&gt;
&lt;li&gt;采用新技术和方法：随着 SRE 领域出现新技术和方法，团队可能有必要采用这些技术来保持竞争力和效率。这可能涉及评估新工具和技术，并确定它们如何改进团队的流程和实践。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;通过不断审查和改进其流程和实践，SRE 团队可以确保它能够满足预期的目标，并有效地支持组织的关键服务和应用程序。&lt;/p&gt;
&lt;p&gt;原文：&lt;a href=&#34;https://medium.com/@l.halicki/6-easy-steps-to-sre-implementation-51cc24e6edbc&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://medium.com/@l.halicki/6-easy-steps-to-sre-implementation-51cc24e6edbc&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>【译】什么是平台工程？如何建设？</title>
      <link>https://www.helight.info/blog/2023/platform-engineering2/</link>
      <pubDate>Sun, 23 Apr 2023 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2023/platform-engineering2/</guid>
      <description>
        
        
        &lt;h2&gt;译者说&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;译者说&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%af%91%e8%80%85%e8%af%b4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;上周刚和一帮大佬讨论了这个话题，今天看到这篇文章，感觉和我的思考非常一致。赶紧 chatgpt 翻译了一下，当然感觉 chatgpt 翻译还是不够，还需要再对照英文审核修改一下，但是对于学习来说非常够用了。&lt;/p&gt;
&lt;p&gt;如果大家正在做平台工程相关的事情，本文我认为非常值得推荐。&lt;/p&gt;
&lt;p&gt;原文地址：&lt;a href=&#34;https://dzone.com/articles/what-is-platform-engineering-how-to-get-started&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://dzone.com/articles/what-is-platform-engineering-how-to-get-started&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;引子&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;引子&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%bc%95%e5%ad%90&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;本指南探讨了平台工程、DevOps和SRE，探讨了平台工程的角色和职责，并讲授了实现的步骤。&lt;/p&gt;
&lt;p&gt;平台工程是构建和维护为开发人员提供自助服务平台的一个学科。该平台提供一组云原生工具和服务，以帮助开发人员快速高效地交付应用程序。平台工程的目标是通过标准化和自动化软件交付生命周期（SDLC）中的大部分任务来改善开发人员体验（DX）。开发人员可以专注于使用自动化平台编写和交付业务逻辑，而不是像基础设施的供应、安全管理和学习曲线等方面进行上下文切换。&lt;/p&gt;
&lt;p&gt;平台工程具有内向的视角，因为它专注于优化组织中的开发人员，以提高生产力。组织从开发人员以最佳水平工作中受益，因为这会导致更快的发布周期。平台通过提供让开发人员需要将其代码投入生产所需的一切能力，因此他们不必等待其他 IT 团队提供基础设施和工具。使开发人员日常活动更轻松和自主的自助服务平台称为内部开发人员平台（IDP）。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2023/platform-engineering2/imgs/pap.png&#34; alt=&#34;Internal Developer Platform (IDP)&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;什么是内部开发平台 (IDP)?&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;什么是内部开发平台-idp&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%80%e4%b9%88%e6%98%af%e5%86%85%e9%83%a8%e5%bc%80%e5%8f%91%e5%b9%b3%e5%8f%b0-idp&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;IDP 是一个平台，包括自助式的云原生工具和技术，开发人员可以使用这些工具来构建、测试、部署、监控或几乎任何与应用程序开发和交付相关的事情，尽可能少地增加开销。平台工程师或平台团队在咨询开发人员并了解他们独特的挑战和工作流程后构建它。&lt;/p&gt;
&lt;p&gt;在为许多大型高科技企业讨论和实施了 &lt;a href=&#34;https://dzone.com/articles/what-is-a-kubernetes-cicd-pipeline&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Kubernetes CI/CD 流水线&lt;/a&gt; 和 &lt;a href=&#34;https://docs.devtron.ai/usage/integrations/argocd&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GitOps 解决方案&lt;/a&gt; 之后，我们意识到一个典型的 IDP 应该包括一下 5 个特点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;要有一个 CI/CD 平台可以自动化部署 (&lt;a href=&#34;https://www.jenkins.io/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Jenkins&lt;/a&gt;, &lt;a href=&#34;https://hub.docker.com/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Docker Hub&lt;/a&gt;, &lt;a href=&#34;https://argo-cd.readthedocs.io/en/stable/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Argo CD&lt;/a&gt;, &lt;a href=&#34;https://devtron.ai/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Devtron&lt;/a&gt;, &lt;a href=&#34;https://spinnaker.io/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Spinnaker&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;管理容器需要有容器编排平台 (&lt;a href=&#34;https://kubernetes.io/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Kubernetes&lt;/a&gt;, &lt;a href=&#34;https://www.nomadproject.io/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Nomad&lt;/a&gt;, &lt;a href=&#34;https://docs.docker.com/engine/swarm/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Docker Swarm&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;要有用于身份验证、授权和秘密管理的安全管理工具(&lt;a href=&#34;https://www.vaultproject.io/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;HashiCorp Vault&lt;/a&gt;, &lt;a href=&#34;https://aws.amazon.com/secrets-manager/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;AWS Secrets Manager&lt;/a&gt;, &lt;a href=&#34;https://www.okta.com/products/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Okta Identity Cloud&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;要有基础设施即代码(IaC)工具，用于自动化基础设施配置(&lt;a href=&#34;https://www.terraform.io/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Terraform&lt;/a&gt;, &lt;a href=&#34;https://www.ansible.com/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Ansible&lt;/a&gt;, &lt;a href=&#34;https://www.chef.io/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Chef&lt;/a&gt;, &lt;a href=&#34;https://aws.amazon.com/cloudformation/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;AWS CloudFormation&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;要有所有集群的工作负载和应用可视化的可观察能力 (&lt;a href=&#34;https://devtron.ai/kubernetes-dashboard.html&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Devtron Kubernetes dashboard&lt;/a&gt;, &lt;a href=&#34;https://prometheus.io/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Prometheus&lt;/a&gt;, &lt;a href=&#34;https://grafana.com/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Grafana&lt;/a&gt;, &lt;a href=&#34;https://www.elastic.co/what-is/elk-stack&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;ELK stack&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2023/platform-engineering2/imgs/5p.webp&#34; alt=&#34;5 Pillars of Internal Developer Platform (IDP)&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;平台团队以一种易于开发人员使用且学习曲线最小的方式设计了 IDP。IDP 可以帮助减少开发人员的认知负荷，通过自动化重复的任务，减少维护开销，并消除对无休止的脚本的需要来提高 DX。IDP通过提供一个自助平台，使开发团队能够独立地管理资源、基础设施需求、部署和回滚。这增加了开发人员的自主权和责任感，减少了依赖性，并简化了开发周期。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;为什么平台很重要?&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;为什么平台很重要&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%ba%e4%bb%80%e4%b9%88%e5%b9%b3%e5%8f%b0%e5%be%88%e9%87%8d%e8%a6%81&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;平台工程可以帮助组织获得一些内部（开发人员）和外部（最终用户）的好处点：&lt;/p&gt;
&lt;p&gt;Kubernetes Dashboard 是一个基于 Kubernetes 架构开发的外部服务。在底层，仪表板使用 api 将所有集群范围内的信息读取到单个窗格中。它还使用 api 将资源和应用程序部署到集群中。CLI 和Kubernetes 仪表板都依赖于 kube-API-server 来处理请求。要开始使用 CLI，运维团队必须在同一个集群中部署 Kubernetes 仪表板（类似于 Kubectl 部署）。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;改善开发者体验(DX):&lt;/strong&gt; 过多的云原生工具增加了开发者的认知负荷，因为需要花费大量时间来决定为他们的特定用例使用哪种工具并掌握它。平台工程通过提供一组简化的、标准化的工具和服务来解决这个问题并改进 DX，这些工具和服务适合开发人员独特的工作流程。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;提高生产力:&lt;/strong&gt; IDP 提供了开发人员以自助方式测试和部署代码所需的一切。这减少了 SDLC 不同阶段的延迟，例如等待某人提供要部署的基础设施。平台工程通过帮助开发人员专注于核心开发工作来确保他们的生产力。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;通过设计实现标准化:&lt;/strong&gt; 在一个典型的软件组织中，IT 团队使用各种各样的工具，每个团队都不一样。在这种情况下，维护和跟踪事情变得复杂。平台工程通过标准化工具和服务解决了这个问题，并且更容易解决任何瓶颈，因为平台对于每个开发人员都是相同的。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;更快的发布:&lt;/strong&gt; 平台团队通过提供易于使用、可重用和可配置的工具链来确保开发人员致力于交付业务逻辑。因此，开发人员的生产力非常高，它可以可靠而安全地加快功能和创新的上市时间。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在组织中建立一个成功的平台团队并利用上述好处需要遵循一些共同的原则。将平台视为一种产品就是其中之一。&lt;/p&gt;
&lt;h2&gt;平台即产品&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台即产品&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%8d%b3%e4%ba%a7%e5%93%81&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;平台工程的&lt;strong&gt;核心原则之一&lt;/strong&gt;是将平台产品化。平台团队需要采用产品管理的思维来设计和维护一个不仅用户友好而且满足客户(应用开发人员)期望和需求的平台。它从围绕开发人员存在的问题收集数据点开始，并确定需要改进的领域。这可以提高部署频率，降低变更失败率，提高可靠性和安全性，改善 DX 等。&lt;/p&gt;
&lt;p&gt;需要注意的是，构建平台就是构建一个解决大多数团队面临的&lt;strong&gt;常见挑战问题&lt;/strong&gt; 的核心产品。&lt;strong&gt;这不是解决单个团队的问题，而是为多个团队提供产品来解决同一组问题&lt;/strong&gt;。例如，如果多个团队需要相同的基础设施，那么平台团队在共享的基础设施上工作并分发它是有意义的。重用平台和可重复性的想法至关重要，因为它允许应用程序交付的标准化、一致性和可伸缩性。&lt;/p&gt;
&lt;p&gt;与产品管理一样，平台团队拥有产品，选择特定的指标，并持续获取客户反馈以改善用户体验。平台的产品路线图根据反馈进行演进，并适应客户不断变化的需求和愿望。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;平台工程师的角色和职责&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台工程师的角色和职责&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b%e5%b8%88%e7%9a%84%e8%a7%92%e8%89%b2%e5%92%8c%e8%81%8c%e8%b4%a3&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;平台工程师的主要角色是设计和维护自助服务平台(IDP)，并为开发人员提供平台服务。它从与开发人员接触并了解他们的痛点开始：&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2023/platform-engineering2/imgs/role.webp&#34; alt=&#34;Developer requirements &amp;gt; platform engineer &amp;gt; platform services&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;倾听用户的意见&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;倾听用户的意见&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%80%be%e5%90%ac%e7%94%a8%e6%88%b7%e7%9a%84%e6%84%8f%e8%a7%81&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;直面开发人员和不同的 IT 团队，以了解他们的工程环境和挑战，并知道他们在优化什么。他们可能试图建立一个有效的 CI/CD 流水线或实施更好的访问控制，以及围绕软件交付的许多其他挑战。&lt;/p&gt;
&lt;h3&gt;优先级&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;优先级&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bc%98%e5%85%88%e7%ba%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;确定大多数团队共享的共同挑战，并将解决它们的优先级置于单个团队面临的问题之上。例如，如果大多数团队发现难以安全地存储和获取机密信息，那么最好的做法是优先为他们解决这个问题。&lt;/p&gt;
&lt;h3&gt;平台设计&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台设计&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e8%ae%be%e8%ae%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;为用户设计可以解决问题的 IDP 工具，并提供文档，使开发人员能够自助获取资源和基础设施。
采用秘密管理工具可以解决上述情况下关于安全管理秘密的挑战。平台设计的一部分还包括编写脚本来自动化常规开发任务，例如启动新环境和配置基础设施，以减少开发流程中的错误和阻力。&lt;/p&gt;
&lt;h3&gt;Metrics 指标&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;metrics-指标&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#metrics-%e6%8c%87%e6%a0%87&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;围绕目标选择特定的指标来衡量平台的有效性。例如，如果目标是提高 DX，则指标包括参与度分数、团队反馈等。类似地，如果目标是降低变更失败率或增加部署频率，则度量指标将发生变化。&lt;/p&gt;
&lt;h3&gt;收集反馈并维护平台&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;收集反馈并维护平台&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%94%b6%e9%9b%86%e5%8f%8d%e9%a6%88%e5%b9%b6%e7%bb%b4%e6%8a%a4%e5%b9%b3%e5%8f%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;继续倾听客户的意见并观察指标。收集用户反馈，为平台添加新工具，优化更好的用户体验。这还包括了解 DevOps 和云基础设施领域的最新工具和技术，并在必要时采用它们。&lt;/p&gt;
&lt;p&gt;DevOps 工程师或 SRE 的角色很容易与平台工程师的角色混淆，因为他们都管理底层基础设施并支持软件开发团队。虽然所有这些角色之间有某些重叠的职责，但每个角色都有其独特的侧重点。&lt;/p&gt;
&lt;h2&gt;平台工程 vs. DevOps&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台工程-vs-devops&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b-vs-devops&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;DevOps 是一种哲学，它为 SDLC 带来了一种文化转变，以提高软件交付速度和质量。DevOps 促进了开发团队和运维团队之间的协作和沟通，并加速了自动化，简化了部署。平台工程——是一种实践而不是一种哲学——也可以被认为是 DevOps 的下一个迭代，因为它与 DevOps 的一些核心原则是相同的：协作（与运维）、持续改进和自动化。&lt;/p&gt;
&lt;p&gt;平台团队和 DevOps 的日常任务在某些方面存在差异。DevOps 使用某些工具和自动化来简化代码的生产、管理，并使用日志和监控工具来观察代码。他们主要致力于&lt;a href=&#34;https://devtron.ai/blog/kubernetes-ci-cd-under-3-minutes/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;建立有效的CI/CD管道&lt;/a&gt;。平台工程师将 DevOps 使用的所有工具集成到一个共享平台中，不同的 IT 团队可以以企业级的水平使用该平台。这消除了团队对自己配置和管理基础设施和工具的需要，并节省了大量的时间、精力和资源。平台工程师还创建文档并优化平台，以便开发人员可以在他们的工作流程中自助服务工具和基础设施。&lt;/p&gt;
&lt;p&gt;平台团队只有在成熟的公司中才需要，公司中有许多使用复杂工具和基础架构的各种 IT 团队。自然，在这样的工程环境中，一个专门的平台团队来管理复杂性将是必要的。平台团队构建和管理基础设施，帮助 DevOps 加速持续交付。然而，DevOps 团队在初创公司中执行平台工程任务（例如配置Terraform）是很常见的。&lt;/p&gt;
&lt;h2&gt;平台工程 vs. SRE&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台工程-vs-sre&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b-vs-sre&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;SRE (Site reliability engineers)专注于确保应用的可靠性、安全性和始终可用。他们与开发人员和运维团队合作，创建支持交付高可靠应用程序的系统或基础设施。SRE 还执行容量规划和基础设施扩展，并管理和响应事件，以使平台满足所需的服务水平目标（slo）。另一方面，平台工程管理复杂的基础设施，并为开发人员构建高效的平台来优化 SDLC。虽然他们的工作平台和角色听起来很相似，但他们的目标不同。&lt;/p&gt;
&lt;p&gt;平台工程和 SRE 之间的主要区别在于他们面对的是谁并迎合他们的服务。SRE 面向最终用户，确保应用服务对他们来说是可靠和可用的。平台工程师面对内部开发人员，专注于改善他们的开发人员体验。两个团队的日常任务在这些目标方面有所不同。平台工程为快速交付应用程序提供了底层基础设施，而 SRE 也为交付高可靠性和可用性的应用程序提供了基础设施。SRE 更多地致力于故障排除和事件响应，平台工程师专注于复杂的基础设施和实现开发者自助服务。&lt;/p&gt;
&lt;p&gt;为了实现各自的目标，SRE 和平台团队在他们的工作流程中都使用不同的工具。SRE 主要使用如Prometheus 或 Grafana 等监控和日志工具来实时检测异常并设置自动警报。平台团队使用跨越软件交付过程不同阶段的各种工具集进行工作，例如容器编排工具、CI/CD 管道工具和 IaC 工具。总而言之，SRE 和平台团队致力于构建可靠且可扩展的基础设施，他们的目标不同，但使用的工具之间存在一些重叠。&lt;/p&gt;
&lt;h2&gt;如何在组织中实施平台工程&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;如何在组织中实施平台工程&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%a6%82%e4%bd%95%e5%9c%a8%e7%bb%84%e7%bb%87%e4%b8%ad%e5%ae%9e%e6%96%bd%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在只有几个工程师的初创公司中，平台团队不是立即需要的。一旦组织发展到多个 IT 团队，并开始处理复杂的工具和基础设施，理想情况是有平台工程师来管理这种复杂性。&lt;/p&gt;
&lt;h3&gt;创建角色（工程主管/工程副总裁）&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;创建角色工程主管工程副总裁&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%88%9b%e5%bb%ba%e8%a7%92%e8%89%b2%e5%b7%a5%e7%a8%8b%e4%b8%bb%e7%ae%a1%e5%b7%a5%e7%a8%8b%e5%89%af%e6%80%bb%e8%a3%81&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;当开发人员花更多时间配置工具和基础设施而不是交付业务逻辑时，像副总裁或工程主管这样的顶级工程师通常会创建平台工程师的角色。他们会发现，大多数IT团队都在解决同样的问题，比如创建新环境，这导致交付过程滞后。因此，工程主管将定义平台工程的范围，确定责任领域，并创建平台工程师/团队的角色。&lt;/p&gt;
&lt;h3&gt;创建一个内部开发人员平台（平台工程师/团队）&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;创建一个内部开发人员平台平台工程师团队&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%88%9b%e5%bb%ba%e4%b8%80%e4%b8%aa%e5%86%85%e9%83%a8%e5%bc%80%e5%8f%91%e4%ba%ba%e5%91%98%e5%b9%b3%e5%8f%b0%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b%e5%b8%88%e5%9b%a2%e9%98%9f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;平台工程师首先构建组织中已经使用的基础设施和工具的日志。然后他们会调研开发人员，了解他们面临的挑战，并使用解决企业层面问题的工具和服务构建内部开发人员平台。他们将以一种灵活的方式构建平台，并帮助不同的架构和部署风格。平台工程师还创建文档并进行培训，以帮助开发人员自助服务平台。对于平台工程师来说，拥有开发人员背景是理想的，这样他们就知道成为开发人员是什么样子，并更好地理解挑战。&lt;/p&gt;
&lt;h3&gt;培养用户(应用程序开发人员)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;培养用户应用程序开发人员&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9f%b9%e5%85%bb%e7%94%a8%e6%88%b7%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%bc%80%e5%8f%91%e4%ba%ba%e5%91%98&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一旦平台准备好了，平台工程师就会邀请应用程序开发人员。这需要内部营销，并让团队了解这个平台以及它可以解决什么问题。吸引用户的最好方法是把他们拉到平台上，而不是把平台扔给他们。这可以从一个小团队开始，并帮助他们克服挑战。例如，帮助一个小团队优化 CI/CD 流程，并在这个过程中提供最好的体验。早期采用者的口口相传将在整个组织中产生积极的涟漪效应，这将帮助平台吸引更多用户。&lt;/p&gt;
&lt;p&gt;平台工程不会止步于引导用户。这是一个持续的过程，平台要适应新出现的工具和技术以及用户不断变化的需求和要求。&lt;/p&gt;
&lt;h2&gt;结论：使用开源工具进行平台工程&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;结论使用开源工具进行平台工程&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%bb%93%e8%ae%ba%e4%bd%bf%e7%94%a8%e5%bc%80%e6%ba%90%e5%b7%a5%e5%85%b7%e8%bf%9b%e8%a1%8c%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;选择一个开源平台是很重要的，它是可以让平台工程师使用标准化的工具链来帮助开发人员加速软件交付。Devtron 就是这样一个平台，它通过自动化 CI/CD 平台、安全性和端到端 SDLC 的可观察性来帮助开发人员。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>平台工程是否终结了 DevOps 和 SRE？</title>
      <link>https://www.helight.info/blog/2023/platform-engineering/</link>
      <pubDate>Thu, 16 Feb 2023 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2023/platform-engineering/</guid>
      <description>
        
        
        &lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2023/platform-engineering/imgs/Platform-Engineering.jpg&#34; alt=&#34;Platform Engineering&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;平台工程、DevOps 和 SRE：是时候做出最终的选择了吗？大家都看到 IT 环境和技术都继续在速度的发展。业界也不断的为公司提供新技术和新工具，而且还提供管理信息系统和应用程序开发的新方法。&lt;/p&gt;
&lt;p&gt;关于软件开发的话题，平台工程的趋势现在正在加速发展，分析师和行业专家称其为&lt;strong&gt;当下最具颠覆性的哲学之一&lt;/strong&gt;。虽然有许多人认为，未来几年该范式将彻底改变信息技术领域，但也有人毫不犹豫地说，平台工程&lt;strong&gt;甚至可以取代一些近年来被认为最具创新性的实践，开始使用 DevOps、敏捷和 SRE&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;无论专家的预测和假设如何，然而，对于当今的企业而言，重要的是了解企业为什么要采用这类平台工程的方法。它会对内部开发团队和更广泛的 IT 部门产生什么影响？是否值得将其用作其他更成熟策略的替代品？如果是这样，需要怎么操作才能正确地做到这一点？&lt;/p&gt;
&lt;p&gt;在回答这些问题之前，让我们更详细地了解平台工程的组成部分，以及它为何有望在未来几年重塑 IT 管理的视野。&lt;/p&gt;
&lt;h2&gt;什么事平台工程?&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;什么事平台工程&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%80%e4%b9%88%e4%ba%8b%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;根据&lt;a href=&#34;https://www.gartner.com/en/articles/what-s-new-in-the-2022-gartner-hype-cycle-for-emerging-technologies&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Gartner 的定义&lt;/a&gt;，&lt;strong&gt;平台工程是为软件交付和生命周期管理构建和运营自助式内部开发人员平台 (IDP) 的学科&lt;/strong&gt;。作为这一趋势当前相关性的证明，在分析公司确定的 2022年的炒作周期中，平台工程的特点不少于三个平：&lt;a href=&#34;https://www.gartner.com/en/information-technology/glossary/hype-cycle&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;软件工程、新兴技术和云平台服务。&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;为了不断改善&lt;a href=&#34;https://blog.mia-platform.eu/en/the-4-pillars-of-successful-developer-experience-strategy&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;开发人员体验&lt;/a&gt;并提高开发团队的生产力，平台工程支持产品构建，即&lt;a href=&#34;https://blog.mia-platform.eu/en/5-tips-for-implementing-internal-developer-portal-in-your-company&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;内部开发人员平台&lt;/a&gt;(IDP)。这使团队变得自主，使他们能够自助访问他们需要启动、管理和监控开发过程的工具（或从头开始创建它们）。所有这一切同时也改善了&lt;a href=&#34;https://blog.mia-platform.eu/en/it-governance-the-challenge-of-governing-a-corporate-it-platform&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;IT 治理&lt;/a&gt;，因为该平台通过自己的设计指导开发人员遵守公司政策。事实上，该平台为开发团队提供了在应用程序生命周期的各个级别进行日常工作所需的工具和指导。&lt;/p&gt;
&lt;p&gt;该平台创建了一个中间层，以&lt;strong&gt;减少开发人员与底层基础设施交互所需的认知负担&lt;/strong&gt;，随着&lt;a href=&#34;https://blog.mia-platform.eu/en/microservices-the-architectural-style-for-modern-applications&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;微服务&lt;/a&gt;、&lt;a href=&#34;https://blog.mia-platform.eu/en/kubernetes-fundamentals-how-it-works-and-what-benefits-it-offers&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Kubernetes&lt;/a&gt;和云原生技术的普遍普及，服务往往会变得越来越复杂。而这显着简化了开发团队的工作，也鼓励了对基础设施缺乏经验或不熟悉的新团队成员的更快入职。所有这些都有助于更快地发布高质量的软件，同时确保无&lt;a href=&#34;https://blog.mia-platform.eu/en/how-a-frictionless-developer-experience-improves-software-development&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;摩擦的开发人员体验&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;需要指出的是，平台工程背后的理念是平台是一个不断发展的真实产品。因此，&lt;strong&gt;平台工程不仅限于平台的初始设计阶段，还涉及产品的实施和维护阶段&lt;/strong&gt;。事实上，随着组织需求的发展，确保最佳性能，需要持续工作来改进、扩展和更新功能。&lt;/p&gt;
&lt;h2&gt;平台工程：渐进式创新还是全面革命?&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台工程渐进式创新还是全面革命&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b%e6%b8%90%e8%bf%9b%e5%bc%8f%e5%88%9b%e6%96%b0%e8%bf%98%e6%98%af%e5%85%a8%e9%9d%a2%e9%9d%a9%e5%91%bd&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;平台工程带来的好处是不可否认的。这就是为什么许多分析师认为，&lt;strong&gt;在未来五年内，平台工程将在 IT 领域得到广泛采用&lt;/strong&gt;。&lt;a href=&#34;https://www.gartner.com/en/articles/what-is-platform-engineering&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;据 Gartner 称&lt;/a&gt;，到 2026 年，80% 的软件工程组织将建立平台团队，作为可重用服务、组件和应用交付工具的内部提供商。&lt;/p&gt;
&lt;p&gt;问题仍然是公司是否必须做出明确的领域选择，完全摒弃更成熟的方法，转而支持平台工程。&lt;/p&gt;
&lt;p&gt;当然，目前还没有明确的答案。但值得提醒的是，每次出现新趋势时，都会有人声称它将压倒以前的模型，甚至完全取代它们。例如，DevOps 的兴起，有人就声称这意味着敏捷的终结。然后，当 Google 引入 SRE（站点可靠性工程）的概念时，许多人预测 DevOps 将会过时。相反，&lt;strong&gt;SRE、DevOps 和敏捷仍然存在并被广泛使用&lt;/strong&gt;。此外，&lt;strong&gt;采用其中一种方法并不排除其他方法也被采用&lt;/strong&gt;。相反，最成功的组织往往是结合了所有这些方法的组织。&lt;/p&gt;
&lt;p&gt;今天的焦点是平台工程，如果我们要从过去得出结论，也许最合适的假设是&lt;strong&gt;新的实践将与现有的其他方法共存并对其他方式有补全&lt;/strong&gt;。&lt;/p&gt;
&lt;h2&gt;结论&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;结论&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%bb%93%e8%ae%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;未来的 IT 环境很可能会融合当今使用的理念，并且平台工程将逐渐增加。目标始终是&lt;strong&gt;改善开发人员体验并发布为最终用户创造价值的高质量软件&lt;/strong&gt;。这需要&lt;strong&gt;敏捷、DevOps、SRE 和平台工程之间的协同合作&lt;/strong&gt;，所有这些都服务于数字产品的创建。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>【译】2022 年 DevOps 状态报告中的可靠性和 SRE</title>
      <link>https://www.helight.info/blog/2023/sre-2022-state-report/</link>
      <pubDate>Wed, 15 Feb 2023 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2023/sre-2022-state-report/</guid>
      <description>
        
        
        &lt;h2&gt;Reliability and SRE in the 2022 State of DevOps Report&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;reliability-and-sre-in-the-2022-state-of-devops-report&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#reliability-and-sre-in-the-2022-state-of-devops-report&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在设计、编码、测试、打包和测试之后，当一个软件变更为被部署状态时，旅程就结束了。与此同时，一个新的旅程开始了：您的客户与您的服务的关系。正是在运营领域，发布进度拖延等抽象风险让位给了收入损失、信任下降和声誉受损等有形风险。只有当软件对用户可用时，它才能有助于(或威胁)组织的成功。因此，在过去的几年中，DevOps 研究与评估(&lt;a href=&#34;https://www.devops-research.com/research.html&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;DORA&lt;/a&gt;)项目逐步深化了我们对服务可靠性的研究，包括从部署到持续运行的可靠性。&lt;/p&gt;
&lt;p&gt;可靠性是一个广义的术语，指的是团队满足用户期望的能力——对于软件服务来说，它可能包括可用性、延迟、正确性或其他影响用户体验的一致性和质量的特性。谷歌的&lt;a href=&#34;http://sre.google/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;站点可靠性工程&lt;/a&gt; (SRE)实践已经被全球可靠性工程实践者社区所接受和扩展，它是一种优先考虑以用户为导向的测量、共同责任和协作、无指责学习的运维方法。从&lt;a href=&#34;https://services.google.com/fh/files/misc/state-of-devops-2021.pdf&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;2021年加速DevOps现状报告&lt;/a&gt;开始，我们开始询问受访者关于组织中的可靠性工程的详细问题。2022 年，我们继续扩大了调查范围，发现了现代可靠性工程广泛存在的进一步证据：大多数受访者报告称，他们采用 SRE 风格的实践。有了这些丰富的数据，今年我们进一步深入分析了可靠性的影响，以及它与技术对组织成功影响模型中其他动态因素的相互作用。&lt;/p&gt;
&lt;h3&gt;可靠性很重要&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可靠性很重要&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e9%9d%a0%e6%80%a7%e5%be%88%e9%87%8d%e8%a6%81&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;h4&gt;当可靠性较差时，对软件交付的改进对组织的结果没有任何影响，甚至是负面影响。&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;当可靠性较差时对软件交付的改进对组织的结果没有任何影响甚至是负面影响&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%bd%93%e5%8f%af%e9%9d%a0%e6%80%a7%e8%be%83%e5%b7%ae%e6%97%b6%e5%af%b9%e8%bd%af%e4%bb%b6%e4%ba%a4%e4%bb%98%e7%9a%84%e6%94%b9%e8%bf%9b%e5%af%b9%e7%bb%84%e7%bb%87%e7%9a%84%e7%bb%93%e6%9e%9c%e6%b2%a1%e6%9c%89%e4%bb%bb%e4%bd%95%e5%bd%b1%e5%93%8d%e7%94%9a%e8%87%b3%e6%98%af%e8%b4%9f%e9%9d%a2%e5%bd%b1%e5%93%8d&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;可靠性不仅仅是有一点好处的：它是必不可少的。在之前的研究中，我们发现软件交付性能（通过变更前置时间、部署频率、变更失败率和故障恢复时间的“&lt;a href=&#34;https://cloud.google.com/blog/products/devops-sre/using-the-four-keys-to-measure-your-devops-performance&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;四个关键指标&lt;/a&gt;”测量）是组织性能的预测。然而，今年的分析揭示了一个以前未见过的细微差别：软件交付对组织绩效的影响是以可靠性为基础的。当可靠性高时，高性能软件交付可以为组织预测更好的结果。但是当可靠性很差时，对软件交付的改进对组织的成果没有任何影响——甚至是负面影响。这肯定了可靠性工程师长期以来的一个信念：“&lt;a href=&#34;https://sre.google/workbook/reaching-beyond/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;可靠性是任何系统最重要的特征&lt;/a&gt;。”如果一项服务或产品不能满足用户的可靠性期望，那么快速发布华丽的新功能只会适得其反，因为用户无法正确地体验它们。软件交付依赖于可靠性的基础来创造价值。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2023/sre-2022-state-report/imgs/sre.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;可靠性是一个旅程&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可靠性是一个旅程&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e9%9d%a0%e6%80%a7%e6%98%af%e4%b8%80%e4%b8%aa%e6%97%85%e7%a8%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;任何有经验的领导者都会告诉你，进步很少是线性的：即使是像 SRE 这样的学科，经过广泛实践并有明显的好处，通往成功的道路也不太可能是直线的。DORA 描述了组织转型的“&lt;a href=&#34;https://cloud.google.com/architecture/devops/devops-tech-continuous-delivery#common_pitfalls_of_implementing_continuous_delivery&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;j曲线&lt;/a&gt;”，这是一种只有在经历挫折和吸取教训后才能持久成功的现象。今年，我们将团队的可靠性工程实践深度与其对服务的影响进行了比较：投资 SRE 是否会带来更高的可靠性？答案是肯定的，但有一个重要的警告：一开始不是。通过比较一系列 SRE 采用水平的可靠性结果，j曲线很明显。一个不认真实践SRE 的团队——也许在他们的 SRE 之旅的开始——可能不仅不会受益，而且会在用户体验的可靠性方面倒退。然而，在这些实践更深入地渗透之后，就会达到一个拐点，我们看到持续增长的可靠性工程能力会给可靠性带来巨大的好处。&lt;/p&gt;
&lt;p&gt;意识到采用 SRE 的好处可能需要时间，所以尽早、尽可能广泛地启动这一过程可能很有吸引力。但我们在此提出警告：组织范围内的文化转型举措通常会因过度扩张而失败。我们对此进行了研究，并在&lt;a href=&#34;https://services.google.com/fh/files/misc/state-of-devops-2019.pdf#page=69&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;之前的报告&lt;/a&gt;中报告了研究结果。而且，即使您成功地克服了困难，在多个团队中同时完全采用 SRE，成本也可能是不可接受的：您可能在早期经历的可靠性挫折，在整个组织中一下子放大，可能会产生灾难性的后果。因此，&lt;a href=&#34;https://sre.google/workbook/how-sre-relates/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;渐变&lt;/a&gt;的 SRE 原则也应适用于 SRE 本身的采用。&lt;/p&gt;
&lt;h3&gt;可靠性与人有关&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可靠性与人有关&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e9%9d%a0%e6%80%a7%e4%b8%8e%e4%ba%ba%e6%9c%89%e5%85%b3&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;回顾了十多年的 SRE 实践和理论，&lt;a href=&#34;https://sre.google/resources/practices-and-processes/enterprise-roadmap-to-sre/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;企业SRE路线图&lt;/a&gt;强调了文化的重要性，表明网站可靠性工程实际上是由文化产生的。工具和框架很重要；语言是必不可少的。但只有信任的、心理安全的文化才能支持持续学习的环境，这使 SRE 能够管理当今复杂的、动态的技术环境。DORA 在 2022 年的研究证明了文化和可靠性之间的相互作用：我们发现，&lt;a href=&#34;https://cloud.google.com/architecture/devops/devops-culture-westrum-organizational-culture&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Westrum模型&lt;/a&gt;定义的“生成”文化可以预测更高的可靠性结果。可靠性不仅对系统的用户有好处，对系统的制造商也有好处：服务高可靠性的团队工作倦怠的可能性要低1.6倍。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>【译】SRE和平台工程</title>
      <link>https://www.helight.info/blog/2023/sre-platformengineering/</link>
      <pubDate>Wed, 15 Feb 2023 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2023/sre-platformengineering/</guid>
      <description>
        
        
        &lt;h2&gt;DevOps、GitOps 和云原生工程组织的兴起&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;devopsgitops-和云原生工程组织的兴起&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#devopsgitops-%e5%92%8c%e4%ba%91%e5%8e%9f%e7%94%9f%e5%b7%a5%e7%a8%8b%e7%bb%84%e7%bb%87%e7%9a%84%e5%85%b4%e8%b5%b7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在过去的十年中，工程和技术组织已经汇集了一组用于构建和部署云原生应用程序的通用最佳实践。这些最佳实践包括持续交付、容器化和构建可观察系统。&lt;/p&gt;
&lt;p&gt;与此同时，云原生组织已经从根本上改变了他们的组织方式，从大型部门(开发、QA、运维、发布)转移到较小的独立开发团队。这些应用开发团队有两个新功能支持：站点可靠性工程和平台工程。SRE 和平台工程是传统运维团队的精神继承者，将软件工程的学科引入了运维的各个方面。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2023/sre-platformengineering/imgs/teams.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;SRE 和平台工程&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;sre-和平台工程&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#sre-%e5%92%8c%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;平台工程团队用软件工程原则来&lt;strong&gt;加速软件交付&lt;/strong&gt;。平台工程师确保应用程序开发团队在软件交付生命周期的所有方面都是高效的。&lt;/p&gt;
&lt;p&gt;SRE团队用软件工程原则来&lt;strong&gt;提高可靠性&lt;/strong&gt;。站点可靠性工程师将影响云应用整体可靠性的故障频率和影响降到最低。&lt;/p&gt;
&lt;p&gt;这两个团队经常混淆，这两个术语有时可以互换使用。事实上，一些组织将 SRE 和平台工程合并到相同的功能中。之所以会出现这种情况，是因为这两个角色都使用一套共同的原则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;平台即产品。这些团队应该花时间了解他们的内部客户，制定路线图，制定发布节奏计划，编写文档，以及完成软件产品中的所有事情。&lt;/li&gt;
&lt;li&gt;自助平台。这些团队构建自己的平台供内部使用。在这些平台中，最佳实践被代码化了，因此这些平台的用户不需要担心——他们只需要按下按钮。在&lt;a href=&#34;https://puppet.com/resources/report/2020-state-of-devops-report/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Puppet Labs 2020 年 DevOps 状况报告&lt;/a&gt;中，Puppet Labs 发现，高度化的 DevOps 组织比低度 DevOps 组织拥有更多的自助服务基础设施。&lt;/li&gt;
&lt;li&gt;持续关注&lt;a href=&#34;https://sre.google/sre-book/eliminating-toil/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;消除杂活&lt;/a&gt;。正如谷歌 SRE 书中定义的那样，杂活是手动的、重复的、自动化的、战术的工作。最好的 SRE 和平台团队能够识别并消除辛劳。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;平台工程&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台工程&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;平台工程师不断地检查从源代码到生产的整个软件开发生命周期。通过这个自查的过程，他们构建了一个工作流，使应用程序开发人员能够快速编写和发布软件。基本的工作流通常包括与持续集成系统相连接的源代码控制系统，以及将工件部署到生产环境中的方法。&lt;/p&gt;
&lt;p&gt;随着使用工作流的应用程序开发人员数量的增长，平台的需求也在变化。不同的应用程序开发团队需要类似但不同的工作流，因此自助服务基础设施变得很重要。自助服务的常见平台工程目标包括CI/CD、警报和部署工作流。&lt;/p&gt;
&lt;p&gt;除了自助服务，教育和协作也成为挑战。平台工程师发现，他们花越来越多的时间培训应用程序开发人员，让他们了解最佳实践和如何最好地使用平台。应用程序开发人员还发现他们依赖于其他应用程序开发人员团队，并期望平台工程团队为他们提供与不同团队高效协作的工具。&lt;/p&gt;
&lt;h2&gt;站点可靠性工程&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;站点可靠性工程&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%ab%99%e7%82%b9%e5%8f%af%e9%9d%a0%e6%80%a7%e5%b7%a5%e7%a8%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;站点可靠性工程师创建和改进系统，以自动可靠地运行应用程序。站点可靠性工程的概念起源于谷歌，详细记录在&lt;a href=&#34;https://sre.google/sre-book/introduction/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;谷歌 SRE 手册&lt;/a&gt;中。谷歌公司负责技术运维的高级副总裁 Ben Treynor Sloss 将 SRE 描述为“当你要求软件工程师设计运维团队时发生的事情”。&lt;/p&gt;
&lt;p&gt;SRE 定义服务水平目标（SLO），并构建系统来帮助服务实现这些目标。这些系统发展成为一个平台和工作流程，包括监控、事件管理、消除单点故障、故障缓解等。&lt;/p&gt;
&lt;p&gt;SRE 文化的一个关键部分是将每一个故障视为可靠性系统中的一个故障。严格的事后分析对于识别故障的根本原因至关重要，并将纠正措施引入自动化系统以继续提高可靠性。&lt;/p&gt;
&lt;h2&gt;New Relic 公司的 SRE 和 平台工程&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;new-relic-公司的-sre-和-平台工程&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#new-relic-%e5%85%ac%e5%8f%b8%e7%9a%84-sre-%e5%92%8c-%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我们中的一个人(Bjorn Freeman-Benson)一直管理着 New Relic 的工程组织，直到2015年，它从少数客户发展到成千上万的客户，所有客户每秒都向云端发送数百万个请求。New Relic 有独立的 SRE和平台工程团队，他们遵循上述一般原则。&lt;/p&gt;
&lt;p&gt;这些团队被分开建立的原因之一是，在这些角色中取得成功的人是不同的。虽然 SRE 和平台工程师除了需要经典的编程技能外，还需要强大的系统工程技能，但这些角色决定了非常不同的性格类型。SRE 倾向于享受危机管理，并在排除故障时获得肾上腺素飙升。SRE 经理能在巨大的压力下茁壮成长，擅长招募和管理想法相似的人。而平台工程师是更典型的软件工程师，他们更喜欢不间断地工作在大而复杂的问题上。平台工程经理更喜欢按照一致的节奏进行操作。&lt;/p&gt;
&lt;h2&gt;DevOps 和 GitOps&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;devops-和-gitops&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#devops-%e5%92%8c-gitops&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在过去的十年中，DevOps 已经成为描述这些实践的一个流行术语。最近，GitOps 也成为了一个流行术语。然而 DevOps 和 GitOps 与平台和 SRE 团队有什么关系呢?&lt;/p&gt;
&lt;p&gt;DevOps 和 GitOps 都是一套关于如何管理基础设施不同方面的松散编码原则。这两种方式的核心原则——自动化、基础设施即代码、软件工程的应用——还是非常相似的。&lt;/p&gt;
&lt;p&gt;DevOps 是一场广泛的运动，它专注于消除开发和运维之间的传统隔阂。随着时间的推移，基础设施自动化和考虑运维的工程应用等策略已经被广泛接受，这些成为更好地构建高可靠性应用程序的方法。&lt;/p&gt;
&lt;p&gt;GitOps 是一种应用程序交付方法。在 GitOps 中，声明性配置用于在任何时刻都以编码的方式来定义应用程序的所需的状态。这个配置编码在版本化的源代码控制系统中作为唯一的真实数据源进行管理。这确保了可审计性、可再现性和配置的一致性。&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;简而言之: DevOps 是 SRE 的一套指导原则，而 GitOps 是平台工程的一套指导原则。&lt;/p&gt;

&lt;/blockquote&gt;
&lt;h2&gt;提升应用开发效率&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;提升应用开发效率&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%8f%90%e5%8d%87%e5%ba%94%e7%94%a8%e5%bc%80%e5%8f%91%e6%95%88%e7%8e%87&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;站点可靠性工程和平台工程是优化用于构建云原生应用的工程组织的两个关键功能。SRE 团队致力于为高可靠的应用程序交付基础架构，而平台工程团队致力于为快速的应用程序开发交付基础架构。这两个团队共同提高了应用程序开发团队的生产力。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>2023 对云技术发展的一些思考</title>
      <link>https://www.helight.info/blog/2023/2023/</link>
      <pubDate>Wed, 18 Jan 2023 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2023/2023/</guid>
      <description>
        
        
        &lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;新的一年到来，总是要总结过去一年，展望新的一年。&lt;/p&gt;
&lt;p&gt;关于总结过去一年，现在不想写什么，或许以后会，太魔幻。&lt;/p&gt;
&lt;p&gt;新的一年开始，就开始推动项目各个小组开始制定 H1 的目标和规划。所以这段时间也在想那技术上23年会有哪些重点发展可以做的。因为目前主要做云原生技术下微服务开发平台的建设和业务支持，所以想在这里稍微张望和展望一下。&lt;/p&gt;
&lt;h2&gt;关于23年云技术的一些思考&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;关于23年云技术的一些思考&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%b3%e4%ba%8e23%e5%b9%b4%e4%ba%91%e6%8a%80%e6%9c%af%e7%9a%84%e4%b8%80%e4%ba%9b%e6%80%9d%e8%80%83&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1. 多云管理&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-多云管理&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-%e5%a4%9a%e4%ba%91%e7%ae%a1%e7%90%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;1. 出海是大的一个方向
2. 数据合规和地域保护
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;22 年大家都在积极主动的出海，尤其目前在做的游戏业务这方面，但是出海也有很多的问题，一方面国内很多公司都是自建idc或者租用idc，云的应用、云原生的应用至少在22年还没有成为一个普遍的方式。&lt;/p&gt;
&lt;p&gt;23 年的出海我目前看各个公司会更看重。一方面国内市场趋于饱和，另外一方面海外各国在 gdpr 的基础上都在不断完善海外互联网服务法律制度，经过这几年的打磨支队在趋于稳定（或许还有部分在变化，但是大的方向是明确的）。&lt;/p&gt;
&lt;p&gt;但是出海，在海外要想底成本的出海，云和云原生是目前最佳的方式，一方面你不用去海外自建机房或者租用idc构建，这个管理运营成本一笔不小的开支。另外应对海外尝试和全球化的支持，必然会有多个云服务商的接入，很难一朵云吃遍全世界。&lt;/p&gt;
&lt;p&gt;所以多云管理是一个有一定规模服务的公司必须要有的能力。通过高效的多云管理，降低内部开发同学对各种云的使用成本。就目前看各种云的使用还是有比较大的差异，好在云原生技术在不断延伸和落地在各个云上。&lt;/p&gt;
&lt;h3&gt;2. serverless&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-serverless&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-serverless&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;1. 带来的便利
2. serverlses 2个方向
	1. 以高隔离docker为基础+HPA调度
	2. 以高性能的ebpf+wasm的运行时
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;首先从应用的角度来看，开发者不是为了申请资源来的，开发者是为了开发应用功能，实现应用目标，至于底层的资源问题最好是能平台托管解决。让应用开发者更聚焦关注于应用。所以我认为这才是 serverless 的核心价值。&lt;/p&gt;
&lt;p&gt;serverless 提出来也有很多年了，从最初在个别场景下的使用，到现在很多场景下在落地了。当然我认为这是 serverless 思路和观念也在不断发展变化。&lt;/p&gt;
&lt;p&gt;最初我们接触的到 serverless 是一种非常理想的方式，方向很好，但是落地上有限，所以最初在云函数这种场景下尽心落地，包括最初的 openfaas，lambda，腾讯云的 cfs 等。包括说 knative 发展了这么多年还是有点影响力不足。&lt;/p&gt;
&lt;p&gt;但是随着发展目前发展思路有些变化结合 k8s的 CA，HPA 大部分场景都可以做到 serverless。但是今年我看到2中趋势的发展：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1. 以高隔离docker为基础+HPA调度
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这种目前很多类似腾讯云的 EKS，aws 的spots等，各个云厂商都有，目前我们也在大规模使用，大部分的前后台服务都可以低成本的迁移上去。未来是一种大趋势，在运维人力的节省上不止一点半点。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2. 以高性能的ebpf+wasm的运行时
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;wasm 最近有人在不断吹风说未来可以替代 docker，替代 k8s 等等。很多标题不管什么风就先来吹一波，很讨厌。&lt;/p&gt;
&lt;p&gt;但是从 serverless 发展的趋势来说以 ebpf+wasm 很有可能做起来的，之前的 serverless 都是基于 docker 的方式或者其他运行环境来做的，优化点也是如何优化 docker 的镜像大小，启动速度等等。但这方面 wasm 确实很有优势，wasm 技术这两年我也在持续关注，但是这几年的发展相对比较缓慢，一方面有技术的问题，另一方面有应用场景的问题。&lt;/p&gt;
&lt;p&gt;另外 serverless 中还有一个时间驱动服务，之前往往都是在应用层做事件捕获和驱动。效率和性能相对还是有问题的。但是 ebpf 的出现在这块应该可以做到一个很好的增强。&lt;/p&gt;
&lt;p&gt;所以对这块技术来说，向这两个方向发展的可能性会很大，第一种很可能在 23 年有很大规模的落地，但是这种 serverless 在实效性上还是不够，基本上都是1～2分钟内，但是好在迁移成本低，应用面比较广，应用程序基本不需要做太多修改。&lt;/p&gt;
&lt;p&gt;第二种还在技术研究上，可能有突破。 这种实现可做到秒级，甚至更低延时的扩缩容。但是应用程序要修改适配 wasm。&lt;/p&gt;
&lt;h3&gt;3. 应用可观测服务&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-应用可观测服务&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-%e5%ba%94%e7%94%a8%e5%8f%af%e8%a7%82%e6%b5%8b%e6%9c%8d%e5%8a%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;1. 核心是服务数据产品化，
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可观测性技术 22 年在技术理念上非常火爆，各种大会、各种技术、各种产品都在讲什么是可观测性，自己的可观测做的有多好。但是实际上市面上好的可观测产品并不多，做的也并不够多好。&lt;/p&gt;
&lt;p&gt;但是我认为 23 年这块的技术产品会越来越成熟，并且真正能够基于这些产品来解决问题。一方面，22 在技术理念的发展给这些产品的发展做了很好的布道铺垫。&lt;/p&gt;
&lt;p&gt;另一方面，我认为也是主要原因，云原生技术全面落地目前在一些大厂已经是事实，只有一些中小公司还在挣扎，但是我认为用不了多长时间也会全面接受云原生技术的。云原生技术的的落地，在应用的规范上起到很好的约束作用，让规模化、模式化的数据采集和分析成为可行。这样才能做出来一个产品大家基本都可以使用，而不是要重新修改适配各种场景。&lt;/p&gt;
&lt;p&gt;云的使用，使得可观测性变的更为重要，开发不直接接触底层，那整个底层和应用的各种分析就需要一个系统化的服务来支撑。可观测性平台产品就尤为重要了。&lt;/p&gt;
&lt;h3&gt;4. finops&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;4-finops&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#4-finops&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code&gt;目标是把云用的更好，更能体现服务和云的价值。解决应用开发者对成本的感知，并驱动其持续不断的优化。
1. 成本可观测
2. 成本可运营
3. 成本可分摊
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在国内外降本增效的大风之下，对成本的要求越来越精细。这方面云做的很好，目前很多云产品已经开始以分钟来计费。&lt;/p&gt;
&lt;p&gt;而对于应用开发者来说这种细粒度的计费非常有价值，让大家在做服务的时候可以看到自己的服务才买成本是多少，开发成本是多少，结合收益预计就可以判多做这个服务的必要性。尤其对于大多数的短期营销类活动，基本上上线几天，几周就下线了。&lt;/p&gt;
&lt;p&gt;这对于平台来说就更要有更高的要求，结合上面提到的多云管理，serverless，可观测。怎么能做到多云管理模式下的成本可观测，可运营。作为内部平台在多个业务在使用的时候还能清晰的做到成本计算和分摊。&lt;/p&gt;
&lt;p&gt;finops  的理念 22 年也是不少人在提出，并且各个产品也在不断的出现，但是 22 年的很多产品都集中在成本的可观测，可运营上，甚至可运营 22 也只能说实在探索实现，&lt;/p&gt;
&lt;p&gt;但是 23 年我认为这块的落地会更快，毕竟在管理成本可控的情况下，都希望好钢用在刀刃上。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>微服务架构设计和其设计模式介绍</title>
      <link>https://www.helight.info/blog/2022/microservices-design-patterns/</link>
      <pubDate>Tue, 27 Dec 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/microservices-design-patterns/</guid>
      <description>
        
        
        &lt;p&gt;之前在推上看到一张图片，感觉总结的挺好，在我也展开总结了之后发现了这张图的原文，所以整体翻译了一遍。还是非常有价值的，值得学习。&lt;/p&gt;
&lt;p&gt;原文地址：https://dzone.com/articles/microservice-architecture-and-design-patterns-for?fromrel=true&lt;/p&gt;
&lt;p&gt;强烈推荐。&lt;/p&gt;
&lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;微服务在企业中可以带来积极的影响。 因此，知道如何处理微服务架构（MSA）和一些微服务设计模式以及微服务架构中的常见目标或原则是很有必要的。 下面是微服务架构实现中要考虑的四个目标。&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;降低成本 — MSA 可以在设计，实现和维护 IT 服务等方面降低整体成本。&lt;/li&gt;
&lt;li&gt;提升发布速度 — MSA 可以提升项目从构想到部署上线的速度&lt;/li&gt;
&lt;li&gt;提升弹性 — MSA 可以提升我们服务网络的弹性&lt;/li&gt;
&lt;li&gt;有可见性 — MSA 能在服务和网上提供更好的可见性。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下面是你需要理解的微服务架构要考虑的哪些基本原则：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;可扩展性&lt;/li&gt;
&lt;li&gt;可用性&lt;/li&gt;
&lt;li&gt;弹性扩展&lt;/li&gt;
&lt;li&gt;灵活性&lt;/li&gt;
&lt;li&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;通过 DevOps 的持续交付&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;在推动解决方案或系统时，坚持这些原则会带来一些挑战和问题。这些问题在许多解决方案中都很常见。可以通过使用正确的设计模式来克服这些问题。微服务有多种设计模式，但是可以分为五类模式。每一类都包含许多子模式。具体如下图所示：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;blog/2022/microservices-design-patterns/imgs/1.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;微服务设计模式&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;微服务拆解模式 (Decomposition Patterns)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;微服务拆解模式-decomposition-patterns&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%be%ae%e6%9c%8d%e5%8a%a1%e6%8b%86%e8%a7%a3%e6%a8%a1%e5%bc%8f-decomposition-patterns&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;&lt;strong&gt;按业务能力解耦&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;按业务能力解耦&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%8c%89%e4%b8%9a%e5%8a%a1%e8%83%bd%e5%8a%9b%e8%a7%a3%e8%80%a6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;通过单一职责原则，微服务总是会把服务之间的耦合降低，微服务通过业务能力解耦，而且根据对应的业务能力来定义服务。业务能力这个概念来自于业务架构模型 [2]，业务的确是生产价值的，业务能力经常是对应于一个业务实体对象。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;订单管理对应于订单&lt;/li&gt;
&lt;li&gt;客户管理对应于客户&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;按子领域拆解（Decompose by Subdomain）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;按子领域拆解decompose-by-subdomain&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%8c%89%e5%ad%90%e9%a2%86%e5%9f%9f%e6%8b%86%e8%a7%a3decompose-by-subdomain&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;按照业务能力拆解一个应用应该是一个好的开始，但是你可能会遇到所谓的“神类”(God Classes)，就是哪些不容易解耦的类，而且这些类在多个服务之间很常见。领域驱动设计(DDD) 把应用问题的空间–业务–做为一个域(domain)。一个域有多个子域，而每一个子域对应于业务的不同的部分。&lt;/p&gt;
&lt;p&gt;子领域可以分为以下几类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;核心子领域(Core) — 区分业务的关键和应用中最有价值的部分&lt;/li&gt;
&lt;li&gt;支撑子领域(Supporting ) — 与业务相关，但不是关键部分，可以内部实现，也可以外包实现&lt;/li&gt;
&lt;li&gt;通用子领域(Generic ) — 不针对特定的业务，理想情况下使用现成的软件实现&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;比如订单管理的子域包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;产品目录服务&lt;/li&gt;
&lt;li&gt;库存管理服务&lt;/li&gt;
&lt;li&gt;订单管理服务&lt;/li&gt;
&lt;li&gt;交付管理服务&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;按事务拆解/两阶段提交（2PC）模式（Decompose by Transactions/Two-Phase Commit (2PC) Pattern）**&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;按事务拆解两阶段提交2pc模式decompose-by-transactionstwo-phase-commit-2pc-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%8c%89%e4%ba%8b%e5%8a%a1%e6%8b%86%e8%a7%a3%e4%b8%a4%e9%98%b6%e6%ae%b5%e6%8f%90%e4%ba%a42pc%e6%a8%a1%e5%bc%8fdecompose-by-transactionstwo-phase-commit-2pc-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;可以通过事务拆解服务，然后系统中将会有多个事务。 分布式事务处理中事务处理协调器[3]是非常重要的部分。分布式事务包括两个步骤：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;准备阶段 — 在此阶段中，事务中的所有参与者都准备提交并通知协调器他们已准备好完成事务了。&lt;/li&gt;
&lt;li&gt;提交或者回滚阶段 — 在此阶段中，事务协调器向所有参与者发出提交或回滚命令。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2PC 的问题是相对于单个微服务的执行时间来说他的耗时更长。即使所有的微服务在相同的网段中，协调微服务之间的事务依旧会拖慢整个系统。因此这个解决方案一般在高负载的场景中不使用的。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;扼杀模式（Strangler Pattern）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;扼杀模式strangler-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%89%bc%e6%9d%80%e6%a8%a1%e5%bc%8fstrangler-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;以上的三种设计模式用在对未开发的应用(greenfield apps)的拆解，但是 80% 的工作都是针对庞大的要从新开发的单体应用（遗留代码库）。扼杀模式（Strangler Pattern）就是为了解决这个问题而来的。在相同的 URI 空间中创建两个独立共存的应用，随着时间的推移，重构过的新应用将”扼杀“或者替代原来的应用，直到最终把庞大的单体应用关闭掉。扼杀应用（Strangler Application）的步骤分为转换，共存和消灭三步[4]：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;转换（Transform ） —  用新方式创建一个新的平行的站点。&lt;/li&gt;
&lt;li&gt;共存（Coexist ）—  保持老站点，将老站点重定向到新的站点，新站点逐步实现老站点的功能。&lt;/li&gt;
&lt;li&gt;消灭（Eliminate ） —  移除老站点的旧功能。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;&lt;strong&gt;隔板模式（Bulkhead Pattern）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;隔板模式bulkhead-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%9a%94%e6%9d%bf%e6%a8%a1%e5%bc%8fbulkhead-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;将应用程序的功能隔离并且运行多副本，以便如果其中一个挂了，其他程序可以继续运行并提供服务，这个设计模式称为隔板模式（Bulkhead）， 因为他类似于船体中一个个被隔离的分区。根据使用者负载和可用性要求，这些分区服务实例被分割到不同的组里面。这种设计模式有助于隔离故障（isolate failures）， 并允许即使在故障期间仍可为某些使用者提供服务功能。&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;边车模式（Sidecar Pattern）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;边车模式sidecar-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%be%b9%e8%bd%a6%e6%a8%a1%e5%bc%8fsidecar-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;将应用程序的组件部署到单独的容器中来提供资源隔离和功能封装，这个模式允许应用程序可以由多种的组件和技术组合而成，&lt;a href=&#34;https://dzone.com/articles/distributed-systems-sidecar-pattern&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;这种模式称为边车（Sidecar）&lt;/a&gt;， 因为类似摩托车旁边挂的边车。在这个模式中，边车挂载在父应用上，并为应用提供功能。边车和父应用拥有相同的生命周期，随着父应用创建而创建，销毁而销毁。边车模式有时称为“边踢模式（sidekick pattern）”。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;微服务的集成模式 （Integration Patterns for Microservices）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;微服务的集成模式-integration-patterns-for-microservices&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%be%ae%e6%9c%8d%e5%8a%a1%e7%9a%84%e9%9b%86%e6%88%90%e6%a8%a1%e5%bc%8f-integration-patterns-for-microservices&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;&lt;strong&gt;API网关模式（API Gateway Pattern）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;api网关模式api-gateway-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#api%e7%bd%91%e5%85%b3%e6%a8%a1%e5%bc%8fapi-gateway-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;当把一个应用拆解为多个小的微服务时，有一些问题就需要我们考虑并处理了：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对不同的微服务在不同的通道上有多次的调用。&lt;/li&gt;
&lt;li&gt;需要处理不同类型的协议。&lt;/li&gt;
&lt;li&gt;不同的消费者可能需要不同的响应格式。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;API 网关可以帮助解决由于使用微服务而带来的问题，包括但不限于上面提到的问题。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对于任何微服务调用 API 网关是唯一入口。&lt;/li&gt;
&lt;li&gt;可以作为一个代理服务来路由请求到相关的微服务。&lt;/li&gt;
&lt;li&gt;可以聚合后端的请求结果再发送给请求者。&lt;/li&gt;
&lt;li&gt;这个解决方案可以为每个指定类型的客户创建细粒度的 API。&lt;/li&gt;
&lt;li&gt;还可以在请求和响应间做协议转换。&lt;/li&gt;
&lt;li&gt;还可以把授权/认证功能从微服务中迁移到 API 网关上。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;聚合模式(Aggregator Pattern)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;聚合模式aggregator-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%81%9a%e5%90%88%e6%a8%a1%e5%bc%8faggregator-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在将业务功能分解为几个较小的逻辑代码段时，就要考虑如何对每个服务返回的数据进行协同，消费者不负责处理这个事情。&lt;/p&gt;
&lt;p&gt;聚合模式有助于解决此问题，它讨论了我们如何聚合来自不同服务的数据，然后将最终响应发送给消费者。 这可以通过两种方法来完成[6]：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;由一个组合微服务将调用所有需要的微服务，组合数据，转换数据，然后返回给调用者。&lt;/li&gt;
&lt;li&gt;API 网关也可以分发请求到多个微服务上，再聚合数据，然后发送消费者。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果要对任何业务逻辑进行处理，建议选择组合微服务。否则，API 网关就是既定的解决方案。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;代理模式(Proxy Pattern)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;代理模式proxy-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%a3%e7%90%86%e6%a8%a1%e5%bc%8fproxy-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;通过 API 网关只是暴露了微服务。 代理模式允许获取 API 的特征，例如安全和 GW 中 API 的分类。 如下面这个例子中，API 网关具有三个 API 模块：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;移动 API – 为FTGO移动客户端实现API&lt;/li&gt;
&lt;li&gt;浏览器 API-为浏览器中运行的 JavaScript 应用程序实现的 API&lt;/li&gt;
&lt;li&gt;公用 API-为第三方开发人员实现 API&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;网关路由模式（Gateway Routing Pattern）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;网关路由模式gateway-routing-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%bd%91%e5%85%b3%e8%b7%af%e7%94%b1%e6%a8%a1%e5%bc%8fgateway-routing-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;API 网关负责执行请求路由。 API 网关通过将请求路由到相应的服务来实现一些 API 的操作。 当 API 网关接收到请求时，它会查询路由映射表，该路由映射表指定了将哪个请求路由到哪个服务。 比如路由映射表可以将 HTTP 方法和路径映射到服务的 HTTP 的 URL 上。 这个功能与 Web 服务器（如 NGINX）提供的反向代理功能相同。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Chained Microservice Pattern&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;chained-microservice-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#chained-microservice-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;There will be multiple dependencies of for single services or microservice eg: Sale microservice has dependency products microservice and order microservice. Chained microservice design patterns will help you to provide the consolidated outcome to your request. The request received by a microservice-1, which is then communicating with microservice-2 and it may be communicating with microservice-3. All these services are synchronous calls.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;微服务链模式 (Chained Microservice Pattern)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;微服务链模式-chained-microservice-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%be%ae%e6%9c%8d%e5%8a%a1%e9%93%be%e6%a8%a1%e5%bc%8f-chained-microservice-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;单个服务或微服务将可能会有多个依赖关系， 例如：销售微服务依赖产品微服务和订单微服务。微服务链模式将根据你的请求提供合并的结果。microservice-1 接收请求，然后和microservice-2通信，并且可能和microservice-3通信。 所有的这些服务都是同步调用。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;分支模式（Branch Pattern）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;分支模式branch-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%88%86%e6%94%af%e6%a8%a1%e5%bc%8fbranch-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;微服务可能需要从包括其他微服务在内的多个来源获取数据，分支微服务模式是聚合器和链设计模式的混合，它允许同时处理来自两个或多个微服务的请求/响应。调用的微服务可以是微服务链。根据业务需求，分支模式还可用于调用不同的微服务链或单个链。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;客户端UI组合模式(Client-Side UI Composition Pattern)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;客户端ui组合模式client-side-ui-composition-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%ae%a2%e6%88%b7%e7%ab%afui%e7%bb%84%e5%90%88%e6%a8%a1%e5%bc%8fclient-side-ui-composition-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;当通过拆解业务功能/子域来开发服务时，负责用户体验的服务必须从多个微服务中获取数据。在单体服务世界中，从 UI 到后端服务只需要一次调用来查询数据并且刷新/提交 UI 页面。不过，现在不一样了。 在微服务中，UI 必须设计为屏幕/页面上具有多个部分/区域的框架。每个部分都将调用单独的后端微服务以获取数据。像 AngularJS 和 ReactJS 之类的框架可以轻松地做到这一点，这些屏幕称为单页应用程序（SPA）。每个团队都开发一个客户端 UI 组件，例如 AngularJS 指令，该组件实现针对该页面/屏幕区域的微服务调用。一个 UI 团队负责实现页面的框架，这个框架通过组合多个指定的服务 UI （service-specific UI）组件来构建页面/屏幕。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;数据库模式(Database Patterns)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;数据库模式database-patterns&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%95%b0%e6%8d%ae%e5%ba%93%e6%a8%a1%e5%bc%8fdatabase-patterns&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&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;li&gt;不同的服务有不同的数据存储要求。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;每一个服务对应一个数据库(Database per Service)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;每一个服务对应一个数据库database-per-service&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%af%8f%e4%b8%80%e4%b8%aa%e6%9c%8d%e5%8a%a1%e5%af%b9%e5%ba%94%e4%b8%80%e4%b8%aa%e6%95%b0%e6%8d%ae%e5%ba%93database-per-service&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;为了解决上述问题，必须为每个微服务设计一个数据库。该数据库只能是该服务私有的，并且只能通过微服务的 API 访问，不能被其他的微服务直接访问。例如，对关系型数据库，我们可以用以下方式：每个微服务有私有化的表(private-tables-per-service)，每个微服务有自己的 schema (schema-per-service), 或者每个微服务服务有私有的数据库服务器（database-server-per-service）。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;每一个服务共享数据库 (Shared Database per Service)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;每一个服务共享数据库-shared-database-per-service&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%af%8f%e4%b8%80%e4%b8%aa%e6%9c%8d%e5%8a%a1%e5%85%b1%e4%ba%ab%e6%95%b0%e6%8d%ae%e5%ba%93-shared-database-per-service&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;我们已经讨论了每个服务设一个数据库是微服务的理想选择，但它是微服务的反模式(anti-pattern)。如果一个单体应用要把它拆分为微服务，那么数据库的反范式化（denormalization ）就不那么容易。将每个微服务共享数据库不是理想的情况，但是是可行的解决方案。大多数人认为这是微服务的反模式，但对于要重构的应用，这是将应用程序分解成较小逻辑的一个很好机会。但是对于全新开发的应用不太适用。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;命令查询的责任分离 (Command Query Responsibility Segregation，CQRS)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;命令查询的责任分离-command-query-responsibility-segregationcqrs&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%91%bd%e4%bb%a4%e6%9f%a5%e8%af%a2%e7%9a%84%e8%b4%a3%e4%bb%bb%e5%88%86%e7%a6%bb-command-query-responsibility-segregationcqrs&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一旦我们实现了每个服务对应一个数据库，就需要将从多个微服务查询返回的数据合并起来。显然这是不可能的。CQRS 建议将应用分为两个部分 — 命令端 （command side）和查询端 （query side）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;命令端处理创建，更新和删除请求。&lt;/li&gt;
&lt;li&gt;查询端通过使用物化视图来处理查询部分。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;通常事件溯源模式(event sourcing pattern)和它一起用来为任何数据更改创建事件。通过订阅事件流，可以使物化视图保持不断的更新。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;事件溯源模式(event sourcing pattern)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;事件溯源模式event-sourcing-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8b%e4%bb%b6%e6%ba%af%e6%ba%90%e6%a8%a1%e5%bc%8fevent-sourcing-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;大多数应用程序都使用数据，一个典型的途径就是应用保持当前的状态。例如，传统的创建，读取，更新和删除（CRUD）中，典型的数据处理是从存储中读取数据，它包含经常使用事务锁定数据的限制。&lt;/p&gt;
&lt;p&gt;事件溯源模式定义了一系列事件驱动的数据的处理操作，每一个事件处理操作都会记录在仅追加存储中（append-only store）。应用程序代码发送一系列命令式的描述了数据上发生的动作的事件到事件持久化存储的地方。每个事件代表一组数据更改（例如，AddedItemToOrder）&lt;/p&gt;
&lt;p&gt;这些事件持久化存储在充当系统记录系统的事件存储中。事件存储系统中事件发布的典型应用场景是：在应用中保持实体的物化视图和事件的动作一样来改变他们，以及集成的外部系统。例如系统可以维护一个针对所有用户的物化视图，用来填充UI部分的数据。当应用程序添加新订单，添加或删除订单上的项目以及添加运输信息时，这些事件描述了这些数据变化可以被处理并且可以更新到物化视图上。下面是这个模式的纵览：&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;blog/2022/microservices-design-patterns/imgs/2.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Event Sourcing pattern[8]&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Saga模式(Saga Pattern)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;saga模式saga-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#saga%e6%a8%a1%e5%bc%8fsaga-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;当每一个微服务都有自己的数据库，并且一个业务事务跨越多个微服务的时候，我们是如何确保各个服务之间的数据一致性？每个请求都有一个补偿请求，该请求将在请求失败时执行。 它可以通过两种方式实现：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;编排（Choreography）指导  — 如果没有中央服务协调，则每个服务都会产生并侦听另一个服务的事件，并决定是否应采取措施。编排是指定两个或两个以上参与者的方式。 每一个参与者都无法控制对方的流程，或者任意可见的流程，这些可见的流程可以协调他们的活动和流程以共享信息和数值。当需要跨控制/可见性域进行协调时，请使用 Choreography 编排指导 。你可以在简单的情况下将编排视为网络协议，它规定了各参与者之间可接受的请求和响应模式。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;blog/2022/microservices-design-patterns/imgs/3.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Saga pattern — Choreography&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Orchestration —  一个Orchestration （对象）负责 Saga 的决策和业务逻辑顺序。当你已经控制流程中的所有参与者时，当它们全部处于一个控制范围内时，你可以控制活动的流程。当然，通常情况下，当你制定一个组织内的业务流程时，你已经控制了它。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;blog/2022/microservices-design-patterns/imgs/4.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Sage pattern — Orchestration&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;观察者模式(Observability Patterns)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;观察者模式observability-patterns&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%a7%82%e5%af%9f%e8%80%85%e6%a8%a1%e5%bc%8fobservability-patterns&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;&lt;strong&gt;日志聚合&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;日志聚合&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%97%a5%e5%bf%97%e8%81%9a%e5%90%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;考虑这样一种情况：一个应用包含多个微服务实例，每个请求经常在横跨多个微服务实例，那么每一个微服务实例都产生一个表转化格式的日志文件。 因此我们需要一个中心化的日志服务来将每个服务实例的日志收集起来。用户可以搜索分析并分析日志，并且配置一些当日志中出现特定信息的报警规则。例如：PCF 确实有一个日志聚合器 (Log aggregator),，用来收集 PCF 平台上各个应用组件（router, controller, Diego, 等等…）的日志。AWS Cloud Watch 也是这样做的。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;性能指标 Performance Metrics&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;性能指标-performance-metrics&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%80%a7%e8%83%bd%e6%8c%87%e6%a0%87-performance-metrics&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;因为采用了微服务架构而导致服务的数量增加，密切注意事务变得十分关键，以便监控微服务模式并且在问题发生的时候发出告警。&lt;/p&gt;
&lt;p&gt;指标服务用来收集每个单独操作的统计信息。它应该聚合一个应用服务的所有指标，以便提供报告和告警。 聚合指标包含两个模式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;推送 — 服务推送指标给指标服务 例如：NewRelic, AppDynamics&lt;/li&gt;
&lt;li&gt;拉取 — 指标服务可以从每个服务中拉取指标 例如：Prometheus&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;分布式跟踪 Distributed Tracing&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;分布式跟踪-distributed-tracing&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%88%86%e5%b8%83%e5%bc%8f%e8%b7%9f%e8%b8%aa-distributed-tracing&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;在微服务架构中，请求通常跨越多个微服务。 每个服务通过跨多个服务执行一个或多个操作来处理一个请求。 在进行故障排除时，需要有一个跟踪 ID，这样我们可以端对端的跟踪请求。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;可以使用以下方法来引入一个事务 ID：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;为每个外部请求分配唯一的外部请求 ID。&lt;/li&gt;
&lt;li&gt;将外部请求 ID 传递给所有服务。&lt;/li&gt;
&lt;li&gt;在所有日志消息中包含外部请求 ID。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;健康检查 Health Check&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;健康检查-health-check&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%81%a5%e5%ba%b7%e6%a3%80%e6%9f%a5-health-check&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;实施微服务架构后，有一种可能是：服务可能会启动但无法处理事务。每个服务都需要具有一个端点用来检查应用的健康度，例如health。这个 API 应该检查主机的状态，与其他服务/基础设施的连接以及其他任意特定的逻辑。&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;交叉关注模式（Cross-Cutting Concern Patterns）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;交叉关注模式cross-cutting-concern-patterns&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%a4%e5%8f%89%e5%85%b3%e6%b3%a8%e6%a8%a1%e5%bc%8fcross-cutting-concern-patterns&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;&lt;strong&gt;外部配置（External Configuration）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;外部配置external-configuration&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%a4%96%e9%83%a8%e9%85%8d%e7%bd%aeexternal-configuration&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一个服务通常还会调用其他服务和数据库，对于每一个环境，例如 dev, QA, UAT, prod，这些环境的端点 URL 或某些配置属性可能不同，这些属性中的任何一项更改都可能需要重新构建或重新部署服务。&lt;/p&gt;
&lt;p&gt;为了避免代码修改，可以使用配置，将所有的配置信息都外部化，包括端点 URL 和认证信息。应用程序应该在启动时或运行时加载这些配置。这些配置可以在应用启动的时候访问到，或者这些配置在不需要重启服务的情况下就可以更新。&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;服务发现模式（Service Discovery Pattern）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;服务发现模式service-discovery-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%9c%8d%e5%8a%a1%e5%8f%91%e7%8e%b0%e6%a8%a1%e5%bc%8fservice-discovery-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;当遇见如图所示的微服务架构时，在微服务调用上我们要关注这样一些问题。&lt;/p&gt;
&lt;p&gt;因为使用了容器技术，IP 地址会动态分配给每个微服务实例， 每次地址更改时，消费服务的调用都会中断，需要手动更改才能恢复。&lt;/p&gt;
&lt;p&gt;消费者必须记住每个服务 URL，并使其紧密耦合。&lt;/p&gt;
&lt;p&gt;因此需要有注册服务，该注册服务将保存每个生产型服务的元数据和每个服务的使用规范。服务实例在启动时应注册到注册中心，而在实例关闭时应注销。服务发现有两种类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;客户端，例如：Netflix Eureka&lt;/li&gt;
&lt;li&gt;服务端：例如： AWS ALB&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;blog/2022/microservices-design-patterns/imgs/5.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
服务发现 [9]&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;断路器模式（Circuit Breaker Pattern）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;断路器模式circuit-breaker-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%96%ad%e8%b7%af%e5%99%a8%e6%a8%a1%e5%bc%8fcircuit-breaker-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一个服务通常会调用其他服务来查询数据，有一种可能性是下游的服务会关闭，这将会带来两个问题：1）上游服务继续请求关闭的服务，直到耗尽网络资源，并且降低系统性能。2）用户体验将会很糟糕且不可预测的。&lt;/p&gt;
&lt;p&gt;消费者应通过代理来调用远程服务，该代理的行为类似于电路中的断路器。当连续的请求失败的次数超过阈值时，断路器将跳闸一段时间，并且在跳闸的这段时间内，所有远程服务调用的尝试都将立即失败。当超过了断路器跳闸时间之后，断路器将允许有限数量的测试请求通过。如果这些请求成功，则断路器将恢复正常操作。否则，如果有一个请求失败，则断路器再次跳闸。对于一个应用试图尝试调用另一个远程服务或者获取共享资源，并且该操作很容易的失败的情况来说， 这个模式非常适用。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;blog/2022/microservices-design-patterns/imgs/6.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;断路器模式Circuit Breaker Pattern [10]&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;蓝绿发布模式（Blue-Green Deployment Pattern）&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;蓝绿发布模式blue-green-deployment-pattern&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%93%9d%e7%bb%bf%e5%8f%91%e5%b8%83%e6%a8%a1%e5%bc%8fblue-green-deployment-pattern&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在微服务架构中，一个应用程序可以有许多个微服务。 如果我们在停止所有服务之后然后部署增强版本，则停机时间将是巨大的，并且可能影响业务。同样，回滚将是一场噩梦。蓝绿发布模式可以避免这种情况。&lt;/p&gt;
&lt;p&gt;蓝绿发布模式可以减少或消除停机时间，它的做法是通过运行切换两个相同的生产环境：Blue 和 Green。这里我们假设 Green 是已存在的工作实例，Blue 是该应用程序的新版本。在任何时候，只有一个环境处于服务状态，该服务环境为所有生产流量提供服务。 所有云平台均提供了用于实施蓝绿色部署的选项。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;blog/2022/microservices-design-patterns/imgs/7.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
蓝绿发布模式Blue-Green Deployment Pattern&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;br&gt;
[1] “Microservice Architecture: Aligning Principles, Practices, and Culture” Book by Irakli Nadareishvili, Matt McLarty, and Michael Amundsen&lt;/p&gt;
&lt;p&gt;[2] &lt;a href=&#34;https://microservices.io/patterns/decomposition/decompose-by-business-capability.html&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://microservices.io/patterns/decomposition/decompose-by-business-capability.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[3] &lt;a href=&#34;https://www.baeldung.com/transactions-across-microservices&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://www.baeldung.com/transactions-across-microservices&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[4] &lt;a href=&#34;https://developer.ibm.com/articles/cl-strangler-application-pattern-microservices-apps-trs/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://developer.ibm.com/articles/cl-strangler-application-pattern-microservices-apps-trs/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[5] &lt;a href=&#34;https://docs.microsoft.com/en-us/azure/architecture/patterns/bulkhead&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://docs.microsoft.com/en-us/azure/architecture/patterns/bulkhead&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[6] &lt;a href=&#34;https://dzone.com/articles/design-patterns-for-microservices&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://dzone.com/articles/design-patterns-for-microservices&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[7] &lt;a href=&#34;https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs#event-sourcing-and-cqrs&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs#event-sourcing-and-cqrs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[8] &lt;a href=&#34;https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[9] &lt;a href=&#34;https://www.dineshonjava.com/microservices-with-spring-boot/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://www.dineshonjava.com/microservices-with-spring-boot/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[10] &lt;a href=&#34;https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>Kubernetes 的 API 流量查看器 - Kubeshark</title>
      <link>https://www.helight.info/blog/2022/kubeshark/</link>
      <pubDate>Sat, 26 Nov 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/kubeshark/</guid>
      <description>
        
        
        &lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;上周公司同事在内部分享了 Kubeshark 这个组件，感觉还是挺有意思，所以这里整理了他收集的一些资料，再结合网上的其他资料，总结了解了一下这个组件。&lt;/p&gt;
&lt;h2&gt;一、Kubeshark 是什么？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一kubeshark-是什么&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80kubeshark-%e6%98%af%e4%bb%80%e4%b9%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Kubeshark 由 2021 年 UP9 公司开源的 K8s API 流量查看器 Mizu 发展而来，试图成为一款 K8s 全过程流量监控工具。&lt;/p&gt;
&lt;p&gt;Kubeshark 被叫做 kubernetes 的 API 流量查看器，它提供对进出 Kubernetes 集群内容器和 pod 的所有 API 流量和负载的深度可见性和监控。 类似于针对 Kubernetes 而重新发明的 TCPDump 和 Wireshark。
地址：&lt;a href=&#34;https://github.com/kubeshark/kubeshark&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://github.com/kubeshark/kubeshark&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../kubeshark/imgs/1.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Kubeshark 也被叫做 Kubernetes 的可观测性工具，可以对微服务进行动态分析，检测异常并在运行时出现某些模式时触发功能。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;可以将 Kubeshark 视为 Wireshark、BPF 编译器集合 (BCC) 工具等的 Kubernetes 感知组合。&lt;/li&gt;
&lt;li&gt;Kubeshark 可以嗅探集群中的部分或所有 TCP 流量，将其记录到 PCAP 文件中并剖析。&lt;/li&gt;
&lt;li&gt;Kubeshark 使用 eBPF 来跟踪内核空间和用户空间中的函数调用。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;../blog/2022/kubeshark/imgs/2.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;二、Kubeshark 架构&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;二kubeshark-架构&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%8ckubeshark-%e6%9e%b6%e6%9e%84&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Kubeshark 由三个不同的软件组成，它们可以协同工作：CLI、Hub 和 Worker。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;CLI，它是客户端的 二进制文件，通过 K8s API 与集群通信。&lt;/li&gt;
&lt;li&gt;Hub，它协调 worker 部署，接收来自每个 worker 的嗅探和剖析，并收集到一个中心位置。它还提供一个Web界面，用于在浏览器上显示收集到的流量。&lt;/li&gt;
&lt;li&gt;Work，作为 DaemonSet 部署到集群中，以确保集群中的每个节点都被 Kubeshark 覆盖。
&lt;img src=&#34;../blog/2022/kubeshark/imgs/3.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;三、Kubeshark 功能&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;三kubeshark-功能&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%89kubeshark-%e5%8a%9f%e8%83%bd&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;1）Kubeshark 功能 - 网络嗅探&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1kubeshark-功能---网络嗅探&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1kubeshark-%e5%8a%9f%e8%83%bd---%e7%bd%91%e7%bb%9c%e5%97%85%e6%8e%a2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Kubeshark 可以使用 Linux 内核中内置的各种方法和 API 嗅探集群中的加密和未加密流量。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;直接抓包，直接使用 libpcap、AF_PACKET 和 PF_RING 嗅探集群中的 TCP 流量，并将其记录到 PCAP 文件中。例如在使用服务网格的场景中，Kubeshark 会自动检测任何 Envoy Proxy并将其包含到其 TCP 数据包捕获源列表中。&lt;/li&gt;
&lt;li&gt;基于 eBPF 抓包，基于 eBPF 的数据包捕获使用 eBPF 嗅探集群中的加密流量 (TLS)，而无需实际进行解密。事实上，它挂钩到 OpenSSL 库和 Go 的 crypto/tls 包中某些函数的入口点和出口点。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;2）Kubeshark 功能 – 查询&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2kubeshark-功能--查询&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2kubeshark-%e5%8a%9f%e8%83%bd--%e6%9f%a5%e8%af%a2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;img src=&#34;../blog/2022/kubeshark/imgs/4.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;3）Kubeshark 功能 – 内核跟踪&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3kubeshark-功能--内核跟踪&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3kubeshark-%e5%8a%9f%e8%83%bd--%e5%86%85%e6%a0%b8%e8%b7%9f%e8%b8%aa&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Kubeshark 使用 🐝 eBPF（扩展伯克利数据包过滤器）提供跟踪内核空间和用户空间功能。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 捕获加密的 TLS 流量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;kubeshark tap --tls -n harbor&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src=&#34;../blog/2022/kubeshark/imgs/5.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;3）Kubeshark 功能 – 流量校验&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3kubeshark-功能--流量校验&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3kubeshark-%e5%8a%9f%e8%83%bd--%e6%b5%81%e9%87%8f%e6%a0%a1%e9%aa%8c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Kubeshark 具有流量验证功能，可与网络嗅探器功能结合使用。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;rules&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Catalogue-Latency-SLO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;#catalogue&amp;#39;s service &amp;#34;/catalogue&amp;#34; response time &amp;lt; 300&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;latency&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;/catalogue&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;latency&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;300&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;service&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;catalogue.*&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;FECatalogue-Latency-SLO&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;#front-end&amp;#39;s service &amp;#34;/catalogue&amp;#34; response time &amp;lt; 600m&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;latency&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;/catalogue&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;latency&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;600&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;service&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;front-end.*&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;4）Kubeshark 功能 – 服务地图&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;4kubeshark-功能--服务地图&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#4kubeshark-%e5%8a%9f%e8%83%bd--%e6%9c%8d%e5%8a%a1%e5%9c%b0%e5%9b%be&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;部署完成后，Kubeshark CLI 将在 http://localhost:8899 打开 UI 单击右上角名为 Service Map 的按钮打开服务依赖关系图。该图根据网络流量显示 Pod 以及它们之间的关系。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../blog/2022/kubeshark/imgs/6.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;5）Kubeshark 功能 – 数据脱敏&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;5kubeshark-功能--数据脱敏&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#5kubeshark-%e5%8a%9f%e8%83%bd--%e6%95%b0%e6%8d%ae%e8%84%b1%e6%95%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Kubeshark 捕获的流量包含敏感信息。用户可以配置 Kubeshark 以隐藏某些关键字或数据片段将在 UI 中显示为 [REDACTED]。&lt;/p&gt;
&lt;p&gt;默认的脱敏字段
&amp;ldquo;token&amp;rdquo;, &amp;ldquo;authorization&amp;rdquo;, &amp;ldquo;authentication&amp;rdquo;, &amp;ldquo;cookie&amp;rdquo;, &amp;ldquo;userid&amp;rdquo;, &amp;ldquo;password&amp;rdquo;, &amp;ldquo;username&amp;rdquo;,&lt;/p&gt;
&lt;p&gt;&amp;ldquo;user&amp;rdquo;, &amp;ldquo;key&amp;rdquo;, &amp;ldquo;passcode&amp;rdquo;, &amp;ldquo;pass&amp;rdquo;, &amp;ldquo;auth&amp;rdquo;, &amp;ldquo;authtoken&amp;rdquo;, &amp;ldquo;jwt&amp;rdquo;, &amp;ldquo;bearer&amp;rdquo;, &amp;ldquo;clientid&amp;rdquo;,&lt;/p&gt;
&lt;p&gt;&amp;ldquo;clientsecret&amp;rdquo;, &amp;ldquo;redirecturi&amp;rdquo;, &amp;ldquo;phonenumber&amp;rdquo;, &amp;ldquo;zip&amp;rdquo;, &amp;ldquo;zipcode&amp;rdquo;, &amp;ldquo;address&amp;rdquo;, &amp;ldquo;country&amp;rdquo;,&lt;/p&gt;
&lt;p&gt;&amp;ldquo;firstname&amp;rdquo;, &amp;ldquo;lastname&amp;rdquo;, &amp;ldquo;middlename&amp;rdquo;, &amp;ldquo;fname&amp;rdquo;, &amp;ldquo;lname&amp;rdquo;, &amp;ldquo;birthdate&amp;rdquo;&lt;/p&gt;
&lt;h2&gt;四、一些使用场景和用法&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;四一些使用场景和用法&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9b%e4%b8%80%e4%ba%9b%e4%bd%bf%e7%94%a8%e5%9c%ba%e6%99%af%e5%92%8c%e7%94%a8%e6%b3%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;可以直接在其 github 站点上看到这些基本使用场景。&lt;/p&gt;
&lt;h3&gt;1）监控指定的 Pod&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1监控指定的-pod&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1%e7%9b%91%e6%8e%a7%e6%8c%87%e5%ae%9a%e7%9a%84-pod&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;kubeshark tap catalogue-b87b45784-sxc8q&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;2）使用正则表达式监控一组 Pod&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2使用正则表达式监控一组-pod&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9b%91%e6%8e%a7%e4%b8%80%e7%bb%84-pod&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;kubeshark tap &lt;span class=&#34;s2&#34;&gt;&amp;#34;(catalo*|front-end*)&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;3）指定监控的 Namespace&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3指定监控的-namespace&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3%e6%8c%87%e5%ae%9a%e7%9b%91%e6%8e%a7%e7%9a%84-namespace&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;默认情况下，Kubeshark 部署在 &lt;code&gt;default&lt;/code&gt; namespace 中，也是监听这个 namespace，可以使用下面的命令指定到一个不同的 namespace 中&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;kubeshark tap -n sock-shop&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;4）指定所有 Namespaces&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;4指定所有-namespaces&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#4%e6%8c%87%e5%ae%9a%e6%89%80%e6%9c%89-namespaces&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;kubeshark tap -A&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;五、总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;五总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%94%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;该工具底层基于 ePBF、Linux 内核网络 API，并且解决了流量数据加解密问题，整体上看是一款能够满足对 K8s 全过程流量监控与管理的工具。&lt;/p&gt;
&lt;p&gt;但目前的实现还只是一个功能原型，在数据存储、网络访问、单机瓶颈等方面仍然存在问题，也不具备模拟流量仿真能力。优势在于提供了流量查询语言 KFL 和微服务流量关联的知识图谱展示。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>Gartner2023年十大战略技术趋势</title>
      <link>https://www.helight.info/blog/2022/gartner-2023-top-10-tech/</link>
      <pubDate>Tue, 15 Nov 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/gartner-2023-top-10-tech/</guid>
      <description>
        
        
        &lt;h2&gt;回顾 2022&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;回顾-2022&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9b%9e%e9%a1%be-2022&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这张图是 Gartner 在 2022 年的技术趋势预测。
&lt;img src=&#34;../gartner-2023-top-10-tech/imgs/1.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Gartner发布了《2023年十大战略技 术趋势》报告。该报告可以帮助组织领导者、技术人员等，在未来 36 个月掌握最新技术的发展趋势。技术趋势 划分为优化、开拓、扩展三大主题:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ø 优化
&lt;ol&gt;
&lt;li&gt;① 数字免疫系统&lt;/li&gt;
&lt;li&gt;② 应用可观测性&lt;/li&gt;
&lt;li&gt;③ AI信任,风险和安全管理&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Ø 扩展
&lt;ol&gt;
&lt;li&gt;④ 行业云平台&lt;/li&gt;
&lt;li&gt;⑤ 平台工程&lt;/li&gt;
&lt;li&gt;⑥ 无线价值实现&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Ø 开拓
&lt;ol&gt;
&lt;li&gt;⑦ 超级应用&lt;/li&gt;
&lt;li&gt;⑧ 自适应AI&lt;/li&gt;
&lt;li&gt;⑨ 元宇宙&lt;/li&gt;
&lt;li&gt;⑩ 可持续技术&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;../gartner-2023-top-10-tech/imgs/2.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;数字免疫系统(Digital Immune System)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;数字免疫系统digital-immune-system&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%95%b0%e5%ad%97%e5%85%8d%e7%96%ab%e7%b3%bb%e7%bb%9fdigital-immune-system&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;数字免疫系统 (DIS) 结合了可观测性、人工智能 (AI) 增强测试、混沌工程、自动修复、站点可靠性(SRE)和供应链安全等实践和技术，以提高产品、服务和系统的弹性。&lt;/p&gt;
&lt;h3&gt;• 实践案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-实践案例&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;美国航空公司使用站点可靠性工程、混沌工 程实践和“测试优先”方法来更好地处理系 统复杂性并解决未知的漏洞和弱点。 Gartner 表示，这增加了其系统知识并揭示 了一个巨大的弹性漏洞。&lt;/p&gt;
&lt;h3&gt;• Gartner预测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-gartner预测&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-gartner%e9%a2%84%e6%b5%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;到 2025 年，投资建设数字免疫系统的企业机构将能够减少多达 80% 的系统宕机时间，所减少的损失将直接转化为更高的收入。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../gartner-2023-top-10-tech/imgs/3.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;应用可观测性(Applied Observability)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;应用可观测性applied-observability&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%ba%94%e7%94%a8%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7applied-observability&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;应用可观测性是在跨业务功能、应用程序、基础设施、运营 (I&amp;amp;O) 团队高度协调和集成可观测数据的方法，实现从行动到反馈、主动规划业务决策的最短延迟。&lt;/p&gt;
&lt;h3&gt;• 实践案例1&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-实践案例1&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;特斯拉是一个使用应用可观测性的典型案例。
该技术通过实时观察特斯拉车主的驾驶行为，在美国几个州为他们提供车辆保险。特斯拉 汽车使用传感器和 Autopilot 软件“观察” 和测量驾驶行为，以生成每月安全评分。特斯拉表示，那些通过安全评分的司机可以节省 20% 到 40% 的保费，而那些安全分数最高 的司机可以节省 40% 到 60% 费用。&lt;/p&gt;
&lt;h3&gt;• Gartner预测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-gartner预测-1&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-gartner%e9%a2%84%e6%b5%8b-1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;到 2026 年，70% 成功应用可观测性的组织将实现更短 的决策延迟，从而为业务目标或IT流程带来竞争优势。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../gartner-2023-top-10-tech/imgs/4.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;人工智能信任、风险和安全管理(AI Trust, Risk and Security Management，简称AI TRiSM)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;人工智能信任风险和安全管理ai-trust-risk-and-security-management简称ai-trism&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%ba%e5%b7%a5%e6%99%ba%e8%83%bd%e4%bf%a1%e4%bb%bb%e9%a3%8e%e9%99%a9%e5%92%8c%e5%ae%89%e5%85%a8%e7%ae%a1%e7%90%86ai-trust-risk-and-security-management%e7%ae%80%e7%a7%b0ai-trism&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;人工智能需要传统控制无法提供的新形式的信任、风险和安全管理。新的AI TRiSM功能可确保模型的可靠性、可信度、安全性和隐私性，并在AI应用、实现业务目标和用户接受度方面取得了更好的成果。&lt;/p&gt;
&lt;h3&gt;• 实践案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-实践案例-1&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b-1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;丹麦商业管理局 (DBA) 开发了一种将高级道德原则应用于其 AI 模型的方法。DBA 将其 道德原则与具体行动联系起来，根据公平测试、检查模型、预测并建立模型监控框架。 DBA 的方法帮助其快速部署和管理 16 个 AI 模 型，用于监控价值数十亿欧元的金融交易。&lt;/p&gt;
&lt;h3&gt;• Gartner预测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-gartner预测-2&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-gartner%e9%a2%84%e6%b5%8b-2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;到 2026 年，实施人工智能信任、风险和安全管理的组织，将看到他们的AI 模型在采用、业务目标和用户接 受度方面实现 50% 的结果改进。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../gartner-2023-top-10-tech/imgs/5.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;行业云平台(Industry Cloud Platforms)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;行业云平台industry-cloud-platforms&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%a1%8c%e4%b8%9a%e4%ba%91%e5%b9%b3%e5%8f%b0industry-cloud-platforms&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;行业云平台通过组合 SaaS、平台即服务(PaaS)和基础设施即服务(IaaS)提供支持行业应用 场景的行业模块化能力。企业可以将行业云平台的打包功能作为基础模块，组合成独特、差异化的数字业务项目，在提高敏捷性、推动创新和缩短产品上市时间的同时避免单一厂商锁定。&lt;/p&gt;
&lt;h3&gt;• 实践案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-实践案例-2&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b-2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;杭州是中国人口最多的城市之一，通过与阿 里巴巴的技术合作建立了“智慧城市大脑” 平台，来管理拥堵并简化日常城市运营。该平台结合了数字化基础设施、中央数据平台和海量应用。实施后，该市的拥堵排名大幅下降，从中国第五大拥堵城市跌至前 50 名。&lt;/p&gt;
&lt;h3&gt;• Gartner预测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-gartner预测-3&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-gartner%e9%a2%84%e6%b5%8b-3&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;到 2027 年，超过 50% 的企业将使用行业云平台来加速 他们的业务项目。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../gartner-2023-top-10-tech/imgs/6.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;平台工程(Platform Engineering)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;平台工程platform-engineering&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%b9%b3%e5%8f%b0%e5%b7%a5%e7%a8%8bplatform-engineering&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;平台工程是一套用来构建和运营支持软件交付和生命周期管理的自助式内部开发者平台的机制和架构。平台工程的目标是优化开发者体验并加快产品团队为客户创造价值的速度。&lt;/p&gt;
&lt;h3&gt;• 实践案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-实践案例-3&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b-3&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;耐克建立了“可组合平台”，将战略相关的全球业务能力结合起来，这些能力由通过 API 公开的模块化和可组合技术实现。耐克发现 该平台使其能够更快地响应变化，加快产品上市时间，提高可扩展性并降低运营成本。&lt;/p&gt;
&lt;h3&gt;• Gartner预测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-gartner预测-4&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-gartner%e9%a2%84%e6%b5%8b-4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;到 2026 年，80% 的软件工程组织将建立平台团队，其中 75% 将包含开发者自助服务门户。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../blog/2022/gartner-2023-top-10-tech/imgs/7.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;无线价值实现(Wireless Value Realization)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;无线价值实现wireless-value-realization&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%97%a0%e7%ba%bf%e4%bb%b7%e5%80%bc%e5%ae%9e%e7%8e%b0wireless-value-realization&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;无线价值实现了从传统终端用户计算，到支持边缘设备再到数字标签解决方案的方方面面。所有这些都需要连接才能运行，并且需要一系列无线解决方案来满足所有环境的需求。&lt;/p&gt;
&lt;h3&gt;• 实践案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-实践案例-4&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b-4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;以色列零售商 Shufersal 正在使用来自网 络的电力来为商品贴上低能耗物联网芯片的标签。它使用这些直接跟踪从农场到商 店货架的蔬菜，提供供应链可见性、库存 管理和来源信息。&lt;/p&gt;
&lt;h3&gt;• Gartner预测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-gartner预测-5&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-gartner%e9%a2%84%e6%b5%8b-5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;到 2025 年，50% 的企业无线端点将使用网络服务，提供通信以外的其他功能，而这一比例低于 15%。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../blog/2022/gartner-2023-top-10-tech/imgs/8.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;超级应用(Superapps)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;超级应用superapps&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%b6%85%e7%ba%a7%e5%ba%94%e7%94%a8superapps&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;超级应用是为最终用户(例如，客户、合作伙伴或员工)提供一组核心功能，以及访问独立创建小应用(mini apps)的应用。超级应用程序被构建为一个平台，可提供一致和个性化的应用程序体验。&lt;/p&gt;
&lt;h3&gt;• 实践案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-实践案例-5&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b-5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;PayPay 是一家日本支付提供商，拥有近 5000 万用户。其增长战略的一个关键部分是将第三方产品和服务的购买，整合到其超级应用程序中，它已经提供了用于购 买电影票、订购外卖和自行车共享的第三方小应用程序，以及自己的财务管理应用 程序服务和零售购物等。&lt;/p&gt;
&lt;h3&gt;• Gartner预测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-gartner预测-6&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-gartner%e9%a2%84%e6%b5%8b-6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;到 2027 年，全球超过 50% 的人口将成为多个超级应用的日活跃用户。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../blog/2022/gartner-2023-top-10-tech/imgs/9.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;自适应人工智能(Adaptive AI)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;自适应人工智能adaptive-ai&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%87%aa%e9%80%82%e5%ba%94%e4%ba%ba%e5%b7%a5%e6%99%ba%e8%83%bdadaptive-ai&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;自适应人工智能系统不断地重新训练模型并根据新数据在运行时和开发环境中学习，以快速适应初始 开发期间未预见或不可用的环境变化。&lt;/p&gt;
&lt;h3&gt;• 实践案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-实践案例-6&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b-6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;美国化学和材料制造商陶氏公司部署了自适应人工智能系统，利用对使用模式和业务价值优化的反馈来增强企业分析。它使分析平台产生的价值增加了 320%。&lt;/p&gt;
&lt;h3&gt;• Gartner预测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-gartner预测-7&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-gartner%e9%a2%84%e6%b5%8b-7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;到 2026年，采用AI工程实践来构建和管理自适应 AI 系统的企业，将在AI模型的可操作性方面优于同行至少 25%。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../blog/2022/gartner-2023-top-10-tech/imgs/10.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;元宇宙(Metaverse)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;元宇宙metaverse&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%85%83%e5%ae%87%e5%ae%99metaverse&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;元宇宙是定义为一个集体虚拟 3D 共享空间，由虚拟增强的物理和数字现实的融合创建，是持久的， 提供增强的沉浸式体验。&lt;/p&gt;
&lt;h3&gt;• 实践案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-实践案例-7&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b-7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;印度虚拟现实初创公司 OneRare 正在为美 食爱好者打造身临其境的游戏化体验，让食品品牌进入全球市场，通过提供食品吸引游戏玩家，并在虚拟和实体商店中使用。&lt;/p&gt;
&lt;h3&gt;• Gartner预测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-gartner预测-8&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-gartner%e9%a2%84%e6%b5%8b-8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;到 2027 年，全球超过 40% 的大型企业机构将在基于元 宇宙的项目中使用Web3、增强现实(AR)云和数字 孪生的组合来增加收入。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../blog/2022/gartner-2023-top-10-tech/imgs/11.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;可持续技术(Sustainability)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可持续技术sustainability&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e6%8c%81%e7%bb%ad%e6%8a%80%e6%9c%afsustainability&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;可持续技术是一种解决方案框架，可提高 IT服务的能源和效率;通过可追溯性、分析、可再生能源等技术实现企业可持续发展;并通过应用程序、软件、市场等帮助客户变得更具可持续性。&lt;/p&gt;
&lt;h3&gt;• 实践案例&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-实践案例-8&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e5%ae%9e%e8%b7%b5%e6%a1%88%e4%be%8b-8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;迪拜电力和水务局 (DEWA) 等公用事业部门，使用物联网和数字孪生创建智能建筑 管理解决方案，用水量减少 50%。&lt;/p&gt;
&lt;h3&gt;• Gartner预测&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-gartner预测-9&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-gartner%e9%a2%84%e6%b5%8b-9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;到 2025 年，50% 的 CIO 将拥有与 IT 组织的可持续性相 关的绩效指标。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../blog/2022/gartner-2023-top-10-tech/imgs/12.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;完整报告地址： &lt;a href=&#34;https://www.gartner.com/en/articles/gartner-top-10-strategic-technology-trends-for-2023&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://www.gartner.com/en/articles/gartner-top-10-strategic-technology-trends-for-2023&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>【译】Linux Conntrack：为什么它会崩溃，如何避免这个问题</title>
      <link>https://www.helight.info/blog/2022/linux-conntrack/</link>
      <pubDate>Tue, 01 Nov 2022 09:47:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/linux-conntrack/</guid>
      <description>
        
        
        &lt;p&gt;Conntrack 这个话题也是非常复杂且重要的，文章中的案例在我们实际场景中确实遇到过，这篇文章总结的挺到位，但是没有进一步从原理解释如何实现 doNotTrack 及其原理。&lt;/p&gt;
&lt;p&gt;原文地址：&lt;a href=&#34;https://www.tigera.io/blog/when-linux-conntrack-is-no-longer-your-friend/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://www.tigera.io/blog/when-linux-conntrack-is-no-longer-your-friend/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;连接跟踪（“conntrack”）是 Linux 内核网络栈的核心特性。它允许内核跟踪所有的逻辑网络连接或数据包流，从而识别组成每个流的所有数据包，以便能够统一的处理它们。&lt;/p&gt;
&lt;p&gt;Conntrack 是一个重要的内核特性，它支撑了一些关键的很重要的应用场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NAT 根据于连接跟踪信息，可以以相同的方式转换这个流中的所有数据包。例如，当一个 pod 访问 Kubernetes 服务时，kube-proxy 的负载平衡使用 NAT 将连接重定向到一个特定的后端 pod。这个连接就是记录到 conntrack 表中，到服务 IP 的数据包应该都发送到相同的后端 pod，从后端 pod 返回的数据包应该做反向 NAT 才能返回到源 pod。&lt;/li&gt;
&lt;li&gt;有状态防火墙，例如 Calico，根据连接跟踪信息来精确地将“响应”流量列入白名单。你可以编写一个网络策略，如“允许我的 pod 连接到任何远程 IP”，而不是编写策略显式地允许响应流量。(如果没有这一点，你就需要添加更不安全的规则如“允许数据包从任何 IP 进入我的 pod”。)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;此外，conntrack 通常可以提高性能(减少 CPU 和数据包延迟)，因为只有数据流中的第一个数据包需要经过完整的网络堆栈处理，通过第一个包的处理确定后续包怎么处理。请参阅“&lt;a href=&#34;http://www.helight.cn/blog/2021/kube-proxy-modes-iptables-or-ipvs/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;compare kube-proxy-modes&lt;/a&gt;”博客，可以进一步深入理解。&lt;/p&gt;
&lt;p&gt;但是，conntrack 也是有局限性的。。。&lt;/p&gt;
&lt;h2&gt;那它会在哪里出问题呢？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;那它会在哪里出问题呢&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%82%a3%e5%ae%83%e4%bc%9a%e5%9c%a8%e5%93%aa%e9%87%8c%e5%87%ba%e9%97%ae%e9%a2%98%e5%91%a2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;conntrack 表有一个可配置的最大值，如果 conntrack 表被添加到了最大值，连接通常会开始被拒绝或丢弃。对于大多数工作负载来说，conntrack 表的大小是没问题的，也永远都不是问题。然而，在一些情况下，conntrack 表需要多注：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最明显的情况是如果你的服务同时处理大量的活动连接。例如，如果你的 conntrack 表配置为128k 的大小，但您有&amp;gt;128k 的并发连接，那么肯定会遇到问题！&lt;/li&gt;
&lt;li&gt;另外一种不太明显的情况是，如果服务每秒钟处理非常高的连接数。即使是短连接，Linux 也会持续跟踪一段时间的（默认为120秒）连接。例如，如果 conntrack 表被配置为128k 大小，并且想每秒处理 1100 个连接，那么即使是短连接，这也将超过conntrack表的大小（128k / 120s = 1092个连接/秒）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;有一些小众的工作负载类型就属于这些类别。此外，如果处于一个敌对的环境中，用大量半开的连冲击没你的服务就可以被用作拒绝服务攻击。在这两种情况下，conntrack 都可能成为系统中的瓶颈。对于某些场景，通过增加 conntrack 表大小或减少 conntrack 超时时间来调优 conntrack 可能足以满足你的需求（但如果调优错误，可能会带来很多麻烦）。对于其他场景，你要让违规流量绕过 conntrack。&lt;/p&gt;
&lt;h2&gt;一个真实的例子&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;一个真实的例子&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%80%e4%b8%aa%e7%9c%9f%e5%ae%9e%e7%9a%84%e4%be%8b%e5%ad%90&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;举一个具体的例子，我们合作过的一个大型 SaaS 提供商有一组 memcached 服务运行在裸服务器上（未虚拟化或容器化），每台服务器每秒处理 50k+ 短连接。实际上这远远超出了标准 Linux 配置所能处理的范围。&lt;/p&gt;
&lt;p&gt;他们已经尝试通过调优 conntrack 配置来增加表的大小和减少超时时间，但是这种场景下这样的调优并不是最佳办法，最大的问题就是增加了内存的使用(大概是 GBytes!)，而且是短连接的情况下， conntrack 没有提供通常的性能优势(减少 CPU 使用或是包延迟)。&lt;/p&gt;
&lt;p&gt;相反，他们使用了 Calico。Calico 的网络策略允许特定的流量绕开conntrack（使用 doNotTrack 标志）。这为他们提供了所需的性能，以及 Calico 带来的额外安全好处。&lt;/p&gt;
&lt;h2&gt;绕开 conntrack 有什么好处?&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;绕开-conntrack-有什么好处&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%bb%95%e5%bc%80-conntrack-%e6%9c%89%e4%bb%80%e4%b9%88%e5%a5%bd%e5%a4%84&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;不跟踪网络策略通常必须是对称的。在 saas 提供者的那个案例中，他们的工作负载是内部的，因此使用网络策略，他们可以小范围地将所有允许访问 memcached 服务的工作负载的流量列入白名单。&lt;/li&gt;
&lt;li&gt;不跟踪策略不关注连接的方向。因此，如果一个 memcached 服务被破坏，理论上只要它使用了正确的源端口，它就可以尝试连接到任何一个 memcached 客户端。但是，假设你为 memcached 客户端定义了正确的网络策略，那么这些连接尝试仍然会在客户端被拒绝。&lt;/li&gt;
&lt;li&gt;不跟踪网络策略应用于每个包，而正常网络策略只应用于流中的第一个包。这可能会增加每个包的 CPU 成本，因为每个包都需要由网络策略处理。但是对于短连接，这种额外的处理开销被不使用 conntrack 的优化所抵消。例如，在SaaS提供商的案例中，每个连接中的数据包数量非常少，因此对每个数据包应用策略的额外开销是合理的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;真实测试&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;真实测试&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%9c%9f%e5%ae%9e%e6%b5%8b%e8%af%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我们测试了单个 memcached 服务 pod 和许多运行在远程节点上的客户端 pod，因此我们可以每秒发动非常多的连接。memcached 服务 pod 主机是 8 核的和一个 512k 配置的 conntrack 表（主机大小的标准设置）。我们测量了以下几种情况下的性能差异：无网络策略；Calico 正常网络策略和 Calico 不跟踪网络策略。&lt;/p&gt;
&lt;p&gt;在第一个测试中，我们将每秒的连接限制在 4000 个，这样我们就可以关注 CPU 的差异。无策略和正常策略在性能上没有可测量的差异，但不跟踪策略的 CPU 负载减少了大约 20%。&lt;/p&gt;
&lt;p&gt;[&lt;img src=&#34;../Linux-Conntrack/imgs/1.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;在第二个测试中，我们推送了尽可能多的客户端连接，并测量了 memcached 服务器每秒能够处理的最大连接数。正如预期的那样，没有策略和正常策略都达到了 conntrack 表限制，即略高于每秒 4,000 个连接（512k / 120s = 4,369个连接/秒）。在不跟踪政策实施的情况下，我们的客户每秒推送了 60,000 个连接，而没有遇到任何问题。我们很有信心，我们可以通过增加更多的客户来超越这一点，但感觉数字已经足够说明这篇博客的要点!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../Linux-Conntrack/imgs/2.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;结论&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;结论&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%bb%93%e8%ae%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Conntrack 是一个重要的内核特性。它很擅长自己的工作场景。许多主要的使用场景都依赖于它。然而，对于一些小众场景，conntrack 的开销超过了它所带来的正常好处。在这些场景中，可以使用 Calico 网络策略选择性地绕过 conntrack，同时仍可以加强网络安全性。对于所有其他流量，conntrack 仍然是你的好朋友!&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>何时（以及何时不）使用 eBPF</title>
      <link>https://www.helight.info/blog/2022/ebpf-when-to-use-it/</link>
      <pubDate>Mon, 31 Oct 2022 08:47:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/ebpf-when-to-use-it/</guid>
      <description>
        
        
        &lt;p&gt;原文地址：https://www.tigera.io/blog/ebpf-when-and-when-not-to-use-it/&lt;/p&gt;
&lt;p&gt;本文介绍了 eBPF 的一些基本应用场景，主要和内核函数，iptables 对比，让大家能理解 eBPF 应该在那些场景下使用，那些场景下不建议使用。我认为可以作为入门 eBPF 的必修课，学习一个技术，必须知道这个技术擅长那些场景，不擅长那些场景，在学习和使用上才不至于走弯路。&lt;/p&gt;
&lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;扩展伯克利包过滤器 (&lt;a href=&#34;https://www.tigera.io/learn/guides/ebpf&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;eBPF&lt;/a&gt;) 是 Linux 内核的一个相对较新的特性，这个特性让许多 DevOps、SRE 和工程师感到眼前一亮。但是它是满足所有 Linux 内核需求的一站式解决方案吗？所以本文中我们要分析看看 eBPF 在哪些方面做得很好，以及它与标准 Linux iptables 的对比如何。&lt;/p&gt;
&lt;h2&gt;eBPF 是什么?&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;ebpf-是什么&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#ebpf-%e6%98%af%e4%bb%80%e4%b9%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;eBPF 是 Linux 内核中一个已经可用的特性，它允许在内核中运行一个虚拟机。这个虚拟机可以让你安全地将程序加载到内核中并执行，这样就可以灵活的在用户层定义各种内核中的操作了。那为什么这很重要呢?&lt;/p&gt;
&lt;p&gt;在过去，对内核进行功能更改是非常困难的：可以调用一些内核 api 来获取数据，但不能影响内核内部的内容或执行代码。如果要这样做，那你需要向 Linux 社区提交一个补丁，然后等待它被批准。而使用 eBPF，可以将程序加载到内核中，并让内核在一些情况下执行你的程序，比如收到一个数据包或者其他的事件发生。&lt;/p&gt;
&lt;p&gt;有了 eBPF，内核及其行为变得高度可定制，不再是固定的了。如果在合适的情况下使用这种能力，将是非常有价值的。&lt;/p&gt;
&lt;h2&gt;如何使用 eBPF？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;如何使用-ebpf&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8-ebpf&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;eBPF 有几个使用场景，包括流量控制、创建网络策略、连接时长负载平衡和可观察性。&lt;/p&gt;
&lt;h3&gt;流量控制&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;流量控制&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%b5%81%e9%87%8f%e6%8e%a7%e5%88%b6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;如果没有 eBPF，数据包使用标准的 Linux 网络路径到达最终目的地。如果一个数据包出现在 A 点，并且你知道这个数据包需要到达 B 点，那么你可以通过优化 Linux 内核中的网络路径将数据包直接发送到 B 点来。使用 eBPF，你就可以利用额外的上下文在内核中进行这些更改，这样数据包就可以绕过复杂的路由，直接到达最终目的地。&lt;/p&gt;
&lt;p&gt;这在 Kubernetes 容器环境中尤其有用，因为其中有许多网络。（除了主机网络堆栈，每个容器都有自己的迷你网络堆栈）当流量进来时，它通常被路由到一个容器堆栈，并且在从主机堆栈到达那里的过程中必须经过一个复杂的路径。可以使用 eBPF 绕过此复杂的路由。&lt;/p&gt;
&lt;h3&gt;创建网络策略&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;创建网络策略&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%88%9b%e5%bb%ba%e7%bd%91%e7%bb%9c%e7%ad%96%e7%95%a5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在创建网络策略时，有两种情况可以使用 eBPF：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;eXpress 数据路径(&lt;a href=&#34;https://www.tigera.io/learn/guides/ebpf-xdp/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;XDP&lt;/a&gt;)&lt;/strong&gt; - 当一个原始数据包缓冲区进入系统时，eBPF 为你提供了一种有效的方法来检查该缓冲区并快速决定如何处理它。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;网络策略&lt;/strong&gt; -  eBPF 允许高效地检查数据包和实施网络策略，无论是 pod 和主机。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;连接时长负载平衡&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;连接时长负载平衡&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%bf%9e%e6%8e%a5%e6%97%b6%e9%95%bf%e8%b4%9f%e8%bd%bd%e5%b9%b3%e8%a1%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;在 Kubernetes 中进行负载均衡服务连接时，一个端口需要与服务进行通信，因此需要进行 NAT 转换。一个数据包被发送到一个虚拟 IP，该虚拟 IP 将其转换为目的 IP 是支持该服务的 pod 上；然后pod 响应虚拟 IP，返回的数据包被转发回源地址。&lt;/p&gt;
&lt;p&gt;通过使用 eBPF，可以使用已加载到内核的 eBPF 程序在连接开始处理的地方进行负载平衡，从而避免这种包转换。由于目的网络地址转换（DNAT）不需要在包处理路径上做处理，因此所有来自服务连接的 NAT 开销都被优化掉了。&lt;/p&gt;
&lt;h3&gt;可观察性&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可观察性&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e8%a7%82%e5%af%9f%e6%80%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;使用 eBPF 实现可观察性的两种有用方法：收集统计信息和深入调试内核。eBPF 程序可以附加到内核中许多不同的函数上，可以访问这些函数正在处理的数据，也允许修改这些数据。例如，使用 eBPF，如果建立了网络连接，则可以在创建套接字时触发一个调用。为什么将套接字调用作为事件接收很重要？因为 eBPF 在打开套接字的程序的上下文中提供了这些函数调用，因此可以获得关于哪个进程打开了它，以及套接字发生了什么事情。&lt;/p&gt;
&lt;h2&gt;性能的代价&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;性能的代价&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%80%a7%e8%83%bd%e7%9a%84%e4%bb%a3%e4%bb%b7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;那么 eBPF 比标准的 Linux iptables 更有效吗？简单来说：要分情况来看。&lt;/p&gt;
&lt;p&gt;如果要对 iptables 在大量 IP 地址(即 ipset)的进行网络策略时的工作方式进行微基准测试，iptables 在很多情况下比 eBPF 更好。但是如果想在 Linux 内核中做一些事情，比如需要更改内核中的数据包流向，那么 eBPF 将是更好的选择。标准的 Linux iptables 是一个复杂的系统，当然有它的局限性，但同时它提供了操控流量的能力；如果你知道如何编写 iptables 规则，那么你可以做很多事情。eBPF 允许将自己的程序加载到内核中，并可以根据你的需要定制影响内核中的行为，因此它比 iptables 更灵活，因为它不局限于是一组规则。&lt;/p&gt;
&lt;p&gt;另外需要考虑的是，虽然 eBPF 允许运行程序、添加逻辑、重定向流向和绕过处理(这是肯定的优势)，但它是一个虚拟机，因此必须转换为字节码运行。相比之下，Linux 内核的 iptables 运行的是已经编译好的代码。&lt;/p&gt;
&lt;p&gt;正如你所看到的，eBPF 和 iptables 并不是一个直接的比较。我们需要评估的是性能，这里需要关注的两个关键因素是延迟（速度）和消耗。如果 eBPF 非常快，但占用了 80% 的资源，那么它就像兰博基尼——一辆昂贵的跑车。如果这对你有用，那太好了(也许你真的喜欢昂贵的跑车)。只要记住，更多的 CPU 使用就意味着你要在云提供商这里花更多的钱。因此，虽然兰博基尼可能比很多其他汽车都快，但如果你需要遵守日常通勤的速度限制，它可能不是最好的花钱方式。&lt;/p&gt;
&lt;h2&gt;何时使用 eBPF（何时不使用）&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;何时使用-ebpf何时不使用&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bd%95%e6%97%b6%e4%bd%bf%e7%94%a8-ebpf%e4%bd%95%e6%97%b6%e4%b8%8d%e4%bd%bf%e7%94%a8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;使用 eBPF，你可以获得性能——但这是有代价的。你需要通过计算性能的代价，并从 eBPF 的功能角度决定你是否接受，要从而找到两者之间的平衡。&lt;/p&gt;
&lt;p&gt;来看一些使用 eBPF 有意义的具体情况，以及一些不建议使用 eBPF 的情况。&lt;/p&gt;
&lt;h5&gt;✘ 何时不用 eBPF&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-何时不用-ebpf&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-%e4%bd%95%e6%97%b6%e4%b8%8d%e7%94%a8-ebpf&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;实现应用层策略&lt;/strong&gt; - 由于价格与性能的权衡，使用 eBPF 执行深度协议检查和实现应用层策略的效率不是很高。你可以利用 Linux 内核的连接跟踪器（ connection tracker）来实现策略，对每个流应用一次策略（无论流有 5 个包还是5000 个包），并在 Linux conntrack 表中将其标记为允许或拒绝。不需要不断检查流中的每个包。如果要使用 eBPF 实现策略，它允许在单个 TCP 连接上有多个 HTTP 事务，为了检测这些事务需要检查每个包，并且要实现第 7 层控制。要做到这一点，需要执行 CPU 周期，这个代价非常大。一种更有效的方法是使用像 Envoy 这样的代理，并使用eBPF 优化到 Envoy 的流量，同时让 Envoy 为来翻译应用程序协议。Iptables + Envoy 这样的代理是更好的设计，在这种情况下也是更好的选择。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;构建服务网格控制平面&lt;/strong&gt; - 类似地，服务网格依赖于像 Envoy 这样的代理。多年来，我们在设计这一过程上花了很多心思。这样做的主要原因是，在许多情况下，对于像 HTTP 这样的应用协议，在集群内高速进行内置处理是不可行的。因此，应该考虑使用 eBPF 以一种有效的方式将通信路由到像 Envoy 这样的代理，而不是使用它替换代理本身。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;逐包处理&lt;/strong&gt; — 使用 eBPF 执行 CPU 密集型或逐包处理，例如对加密流进行解密和重新加密，并不高效，因为需要构建一个结构并对每个包进行查找，代价非常大。&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;✔ When to use eBPF&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;-when-to-use-ebpf&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#-when-to-use-ebpf&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h5&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;XDP&lt;/strong&gt; -  eBPF 在原始数据包进入系统时提供了一种有效的处理方法，允许快速决定如何处理数据包。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;连接时间负载平衡&lt;/strong&gt; - 使用 eBPF 可以在源端使用加载到内核的程序进行负载平衡，而不是使用虚拟 IP。由于 DNAT  不需要发生在包处理路径上，所有来自业务连接的 NAT 开销就都被优化了。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可观察性&lt;/strong&gt; - epf程序是在Linux内核中添加探测器作为传感器的极好方法，以获得上下文丰富的数据。这是一个巨大的好处，因为不需要更改内核来支持跟踪和分析。您可以很容易地在打开套接字的程序的上下文中接收套接字调用，或者添加程序来跟踪内核中的系统调用。在我们看来，可观察性是eBPF最有用的用例。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;eBPF 是 iptables 的替代品吗？我想不完全是。很难想象所有东西在 eBPF 中都能像在 iptables 中一样高效地工作。目前，这两种功能是共存的，取决于用户如何权衡代价和性能，并根据他们的特定需求决定何时使用哪个功能。&lt;/p&gt;
&lt;p&gt;我们相信正确的解决方案是利用 eBPF 加上 Linux 内核中的现有机制来实现你想要的结果。既然我们已经确定 eBPF 和 iptables 都是有用的，那么在我们看来，唯一符合逻辑的事情就是同时支持两者。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>【译】使用 SO_REUSEPORT 套接字选项提升服务性能</title>
      <link>https://www.helight.info/blog/2022/linux-tcp-so-reuseport/</link>
      <pubDate>Sat, 29 Oct 2022 09:47:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/linux-tcp-so-reuseport/</guid>
      <description>
        
        
        &lt;p&gt;原文地址：&lt;a href=&#34;https://blog.flipkart.tech/linux-tcp-so-reuseport-usage-and-implementation-6bfbf642885a&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://blog.flipkart.tech/linux-tcp-so-reuseport-usage-and-implementation-6bfbf642885a&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Linux 网络栈中有一个相对较新的特性——SO_REUSEPORT 套接字选项，可以使用它来提升你的服务性能。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/1.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;图 1: 上面的服务是使用并行监听器来避免请求连接瓶颈，而下面的服务只使用一个监听器来接收连接&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;概要&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;HAProxy 和 NGINX 是少数几个使用 Linux 网络栈中 TCP 的 SO_REUSEPORT 套接字选项[1]的应用程序。这个选项最初是在 4.4 BSD 中引入的，帮助在现在大型多核系统中实现高性能服务。本文的前几节将解释 TCP/IP 套接字的一些基本概念，其余部分将使用这些知识描述 SO_REUSEPORT 套接字选项的基本原理、用法和实现。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题陈述&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当运行在多核系统上时，高性能服务采用的传统方法是使用单个监听器进程接受连接，并将这些连接传递给工作进程进行处理。但在高连接负载下，监听过程成为瓶颈。服务经常使用的另一种方法是打开一个监听套接字，然后分多个进程，每个进程调用 accept() 来处理套接字上的接入的连接，同时自己执行工作。这种方法的问题是，开始拾取连接的过程往往会获得高度倾斜的连接。在本文中，我们将讨论第三种替代方法——打开多个监听套接字，使用SO_REUSEPORT 处理传入的连接，这既解决了单个进程瓶颈问题，也解决了进程之间的连接倾斜问题。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TCP 连接基础&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一个 TCP 连接是由唯一的一个 5 元组来定义描述 &lt;strong&gt;[2]&lt;/strong&gt;:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;&lt;em&gt;[ Protocol, Source IP address, Source Port, Destination IP address, Destination Port ]&lt;/em&gt;&lt;/strong&gt;&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;ul&gt;
&lt;li&gt;&lt;strong&gt;Protocol&lt;/strong&gt;：该字段在根据应用程序提供的参数在创建套接字时初始化。在本文中，协议始终是 TCP。例如,
socket(AF_INET SOCK_STREAM 0); /* 创建TCP套接字 */&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;源 IP 地址和端口&lt;/strong&gt;：这些通常在应用程序调用 connect() 时由内核设置，而无需事先调用 bind()。内核为会选择一个合适的IP地址与目标服务通信，并从临时端口范围 (&lt;em&gt;sysctl net.ipv4.ip_local_port_range&lt;/em&gt;) 中选择一个源端口。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;目的 IP 地址和端口&lt;/strong&gt;：由应用程序通过调用 connect() 设置。例如:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AF_INET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_port&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;htons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SERVER_PORT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;bcopy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server_ent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server_ent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h_length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;/* Connect to server, and set the socket&amp;#39;s destination IP address and port#
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;* based on above parameters. Also, request the kernel to automatically set
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;* the Source IP and port# if the application did not call bind() prior to connect().
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sockaddr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;服务端应用&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;协议&lt;/strong&gt;：初始化方式与客户端应用相同。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;源 IP 地址和端口&lt;/strong&gt;：由应用程序调用 bind() 时设置，例如:&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;srv_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AF_INET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;srv_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s_addr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;INADDR_ANY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;srv_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_port&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;htons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SERVER_PORT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;srv_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;srv_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;目的 IP 地址及端口&lt;/strong&gt;：客户端通过 TCP 三次握手连接服务端[3]。服务端的 TCP/IP 协议栈创建一个新的套接字来跟踪管理客户端连接，并从传入的客户端连接参数设置它的源 IP:port 和目的 IP:port。新的套接字的状态被转换为 ESTABLISHED 状态，而服务端的 LISTEN 套接字则保持不变。此时，服务端应用程序对 LISTEN 套接字上的 &lt;em&gt;accept()&lt;/em&gt; 的调用返回对新建立的套接字的引用。有关客户端和服务端应用程序的示例实现，请参阅本文末尾的源代码清单。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TIME-WAIT 套接字&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;一个 TIME-WAIT [4]套接字是在应用程序首先关闭它的 TCP 连接时创建的。这导致 TCP 4 次握手的启动，在此过程中，套接字状态从 ESTABLISHED 变为 FIN-WAIT1、FIN-WAIT2 到 TIME-WAIT，然后套接字被关闭。由于协议原因，TIME-WAIT 状态是一种延迟状态。应用程序可以通过发送 TCP RST 包来指示 TCP/IP 栈不让连接延迟。这样一来，连接就会立即终止，而不需要经过TCP 4 次握手。下面的代码片段通过指定套接字逗留时间为 0 秒来实现连接的重置：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linger&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;opt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l_onoff&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l_linger&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;setsockopt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SOL_SOCKET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SO_LINGER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;opt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;opt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;理解服务器套接字的不同状态&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;服务端通常在启动时执行以下系统调用：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mf&#34;&gt;1.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Create&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;socket&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;server_fd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;socket&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mf&#34;&gt;2.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Bind&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;well&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;known&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IP&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;address&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server_fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;...);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mf&#34;&gt;3.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Mark&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;the&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;socket&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;passive&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;changing&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;it&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;state&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;LISTEN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;listen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server_fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;...);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;mf&#34;&gt;4.&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Wait&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reference&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;descriptor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;client_fd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;accept&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server_fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;...);&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;任何通过 &lt;em&gt;socket()&lt;/em&gt; 或 &lt;em&gt;accept()&lt;/em&gt; 系统调用创建的新套接字，都会在内核中使用 &lt;code&gt;struct sock&lt;/code&gt; 结构[5]进行跟踪管理。在上面的代码片段中，在步骤 1 中创建了一个套接字，并在步骤 2 中绑定了一个明确的地址。这个套接字在步骤 3 中被转换为 LISTEN 状态。步骤 4 中调用 &lt;em&gt;accept()&lt;/em&gt;，阻塞直到有客户端连接到这个 &lt;em&gt;IP:port&lt;/em&gt;。客户端完成TCP 3 次握手后，内核创建一个套接字，并返回对该套接字的引用。新套接字的状态设置为 ESTABLISHED，而 &lt;em&gt;server_fd&lt;/em&gt; 套接字保持 LISTEN 状态。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SO_REUSEADDR 套接字选项&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;TCP 套接字的 SO_REUSEADDR 选项可以从以下两个用例中更好地理解:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;案例 #1.&lt;/strong&gt; 服务端应用程序重新启动分为两个步骤—退出之后再启动。在退出期间，服务端的 LISTEN 套接字立即关闭。让我们看看因为服务端的存在连接而可能出现的两种情况。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;所有已建立的连接都被这个濒死的服务端进程关闭，并且那些套接字转换到 TIME-WAIT 状态。&lt;/li&gt;
&lt;li&gt;所有已建立连接将被移交给子进程，并继续保持 ESTABLISHED 状态。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;当服务端随后启动时，它尝试使用 EADDRINUSE 参数绑定到它监听端口时会失败，因为系统上的一些套接字已经绑定到这个 &lt;em&gt;IP:port&lt;/em&gt; 组合(例如，处于 TIME-WAIT 或 ESTABLISHED 状态的套接字)。这个问题的演示如下:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Server is listening on port #45000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ss -tan &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep :45000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;LISTEN &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; 10.20.1.1:45000 *:*
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# A client connects to the server using it&amp;#39;s source port 54762. A new&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# socket is created and is seen in ESTABLISHED state, along with the&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# earlier LISTEN socket.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ss -tan &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep :45000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;LISTEN &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; 10.20.1.1:45000 *:*
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ESTAB &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; 10.20.1.1:45000 10.20.1.100:54762
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Kill the server application.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ pkill -9 my_server
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Restart the server application.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ./my_server &lt;span class=&#34;m&#34;&gt;45000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bind: Address already in use
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Find out why&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ss -tan &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep :45000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;TIME-WAIT &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; 10.20.1.1:45000 10.20.1.100:54762&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;此清单显示前面已经是 ESTABLISHED 状态的套接字与现在在 TIME-WAIT 状态下的套接字相同。由于这个绑定到本地地址- 10.20.1.1:45000 的套接字的存在，阻止了接下来服务为它的 LISTEN 套接字 &lt;em&gt;bind()&lt;/em&gt; 到相同的 &lt;em&gt;IP:port&lt;/em&gt; 组合。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;用例 # 2&lt;/strong&gt; 如果两个进程试图 &lt;em&gt;bind()&lt;/em&gt; 到相同的 &lt;em&gt;IP:port&lt;/em&gt; 组合，先执行 &lt;em&gt;bind()&lt;/em&gt; 的进程会成功，而后执行 &lt;em&gt;bind()&lt;/em&gt; 的进程会由于EADDRINUSE 而失败。此用例的另一个实例涉及到一个绑定到特定 &lt;em&gt;IP:port&lt;/em&gt; (例如，192.168.100.1:80)的应用程序，以及另一个试图绑定到具有相同端口号的通配符 IP 地址的应用程序(例如，0.0.0.0:80)；同样，后一个 &lt;em&gt;bind()&lt;/em&gt; 调用失败，因为它试图绑定到使用与第一个进程使用的相同端口号的所有地址。如果两个进程都在它们的套接字上设置了 SO_REUSEADDR 选项，那么两个套接字都可以成功绑定。但是，请注意一点——如果第一个进程调用了 &lt;em&gt;bind()&lt;/em&gt; 和 &lt;em&gt;listen()&lt;/em&gt; ，第二个进程仍然无法成功执行 &lt;em&gt;bind()&lt;/em&gt; ，因为第一个套接字处于 LISTEN 状态。因此，这个用例的实现通常用于那些想在连接到不同服务之前绑定到特定 IP:port 的客户端。&lt;/p&gt;
&lt;p&gt;SO_REUSEADDR 如何帮助解决这个问题的呢？当服务重新启动并在设置了 SO_REUSEADDR 的套接字上调用 &lt;em&gt;bind()&lt;/em&gt; 时，内核忽略所有绑定到相同 &lt;em&gt;IP:port&lt;/em&gt; 组合的非 LISTEN 套接字。Richard Stevens 在他的**《Unix网络编程[6]》** 一书 中这样描述这个特性：“ SO_REUSEADDR 允许监听服务启动并绑定它的已知端口，即使创建的这个链接之前已经把这个端口作为它的本地端口”。&lt;/p&gt;
&lt;p&gt;但是，我们需要 SO_REUSEPORT 选项来让两个或多个进程成功地在同一个端口上调用 &lt;em&gt;listen()&lt;/em&gt; 。这个选项将在后面的部分中进行更详细的说明。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SO_REUSEPORT 套接字选项&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当现有的套接字在 ESTABLISHED 或 TIME-WAIT 状态时，SO_REUSEADDR 选项允许套接字 &lt;em&gt;bind()&lt;/em&gt; 到相同的 &lt;em&gt;IP:port&lt;/em&gt; 组合，而当现有的套接字在 LISTEN 状态时 SO_REUSEPORT 选项允许绑定到相同的 &lt;em&gt;IP:port&lt;/em&gt; 。当应用程序在启用SO_REUSEPORT 的套接字上调用 &lt;em&gt;bind()&lt;/em&gt; 或 &lt;em&gt;listen()&lt;/em&gt; 时，内核会忽略所有套接字，包括处于 LISTEN 状态的套接字。这允许多次调用服务进程，允许多个进程监听连接。下一节我们来研究一下内核怎么实现 SO_REUSEPORT 的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;如何在多个监听器之间分配连接?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;当多个套接字处于 LISTEN 状态时，内核如何决定哪个套接字——以及哪个应用程序进程——接收传入连接？还是使用了轮训、最少连接、随机或者其他方法决定的？我们来更深入地研究一下 TCP/IP 代码，以理解套接字选择是如何执行的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;为了清晰起见，本节中的数据结构和代码片段进行了大量简化——删除了一些结构体元素、函数参数、变量和不必要的代码——但又不失正确性。为了更好地理解，清单的某些部分是伪代码。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sk&lt;/strong&gt; 表示 “&lt;em&gt;struct sock&lt;/em&gt;” 类型的内核套接字数据结构。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;skb&lt;/strong&gt;，即套接字缓冲区，表示 “&lt;em&gt;struct sk_buff&lt;/em&gt;” 类型的网络包。&lt;/li&gt;
&lt;li&gt;&lt;em&gt;src_addr、src_port&lt;/em&gt; 和 &lt;em&gt;dst_addr, dst_port&lt;/em&gt; 分别表示：源IP:端口和目的IP:端口。&lt;/li&gt;
&lt;li&gt;如果需要，读者可以将代码片段与实际内核源代码[5]关联起来一起看。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;当传入网络数据包 &lt;strong&gt;skb&lt;/strong&gt; 在提交到 TCP/IP 协议栈中时，IP 子系统就会调用 TCP 的数据包接收处理函数 &lt;em&gt;tcp_v4_rcv()&lt;/em&gt;，并提供 &lt;strong&gt;skb&lt;/strong&gt; 作为参数。&lt;em&gt;tcp_v4_rcv()&lt;/em&gt; 会尝试寻找与此 skb 相关的套接字:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;_sk&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;__inet_lookup_skb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tcp_hashinfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;skb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;tcp_hashinfo&lt;/em&gt; 是一个类型为 “&lt;em&gt;struct inet_hashinfo&lt;/em&gt;” 的全局变量，其中包含了 ESTABLISHED 和 LISTEN 套接字的两个哈希表。LISTEN 哈希表的大小为 32 个桶，如下所示:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define LHTABLE_SIZE 32 &lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* Yes, really, this is all you need */&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inet_hashinfo&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* Hash table for fully established sockets 已经建立好的套接字 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inet_ehash_bucket&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ehash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* Hash table for LISTEN sockets 处在 LISTEN 状态的套接字 */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inet_listen_hashbucket&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;listening_hash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LHTABLE_SIZE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inet_hashinfo&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tcp_hashinfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;__inet_lookup_skb() 从传入的 &lt;strong&gt;skb&lt;/strong&gt; 中提取&lt;strong&gt;源和目的 IP 地址&lt;/strong&gt;，并将这些地址与源和目的端口一起传递给__inet_lookup() 以查找相关的 ESTABLISHED 或 LISTEN 状态的套接字，如下所示:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;__inet_lookup_skb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tcp_hashinfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;skb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* Get the IPv4 header to know the source and destination IP&amp;#39;s */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iphdr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iph&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ip_hdr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;skb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	* Look up the incoming skb in tcp_hashinfo using the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	* [ Source-IP:Port, Destination-IP:Port ] tuple.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;__inet_lookup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tcp_hashinfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;skb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iph&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;saddr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iph&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;daddr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;__inet_lookup()_ looks in &lt;em&gt;tcp_hashinfo-&amp;gt;ehash&lt;/em&gt; hash-table for an already established socket matching the client 4-tuple parameters. In the absence of an established socket, it looks in &lt;em&gt;tcp_hashinfo-&amp;gt;listening_hash&lt;/em&gt; hash-table for a LISTEN socket.
__inet_lookup() 在 &lt;em&gt;tcp_hashinfo-&amp;gt;ehash&lt;/em&gt; 哈希表中查找已经建立成功的套接字，匹配客户端4元组参数。如果没有找到，它将在 &lt;em&gt;tcp_hashinfo-&amp;gt;listening_hash&lt;/em&gt; 哈希表中查找 LISTEN 套接字。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;__inet_lookup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tcp_hashinfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;skb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* Convert dest_port# from network to host byte order */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;u16&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hnum&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ntohs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* First look for an established socket ... */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;__inet_lookup_established&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tcp_hashinfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hnum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* failing which, look for a LISTEN socket */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;__inet_lookup_listener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tcp_hashinfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;skb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hnum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;__inet_lookup_listener() 函数进行已经存在的 LISTEN 套接字的选择：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;__inet_lookup_listener&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tcp_hashinfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;skb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	* Use the destination port# to calculate a hash table slot# of the listen socket.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	* inet_lhashfn() returns a number between 0 and INET_LHTABLE_SIZE-1 (both
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	* inclusive).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kt&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hash&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;inet_lhashfn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* Use this hash slot# to index the global LISTEN hash table */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;inet_listen_hashbucket&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ilb&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tcp_hashinfo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;listening_hash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* Keep track of the best matching LISTEN socket thus far, and it’s “score” */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi_score&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;each&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;socket&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;‘&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;’&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;the&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;selected&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hash&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bucket&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;err&#34;&gt;‘&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ilb&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;’&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;cm&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		* Calculate the “score” of this LISTEN socket (sk) against the incoming skb.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		* Score is computed on some parameters, such as, exact destination port#,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		* destination IP address closest match (as against matching INADDR_ANY,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		* for example), with each criteria getting a different weight.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;n&#34;&gt;score&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;compute_score&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;score&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hi_score&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;cm&#34;&gt;/* Highest score - best matched socket till now */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk_reuseport&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;cm&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;			* sk has SO_REUSEPORT feature enabled. Call inet_ehashfn()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;			* with dest_addr, dest_port, src_addr and src_port to compute a
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;			* 2nd hash - phash.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;			*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;n&#34;&gt;phash&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;inet_ehashfn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;cm&#34;&gt;/* Select socket from sk’s SO_REUSEPORT group using phash.*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;reuseport_select_sock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;phash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;cm&#34;&gt;/* Update new best socket and it’s score */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;n&#34;&gt;hi_score&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;score&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;由 &lt;em&gt;reuseport_select_sock()&lt;/em&gt; 负责从 SO_REUSEPORT 组中选择套接字：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;reuseport_select_sock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;phash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* Get control block of sockets in this SO_REUSEPORT group */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock_reuseport&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reuse&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk_reuseport_cb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* Get count of sockets in the group */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_socks&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reuse&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;num_socks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* Calculate value between 0 and &amp;#39;num_socks-1&amp;#39; (both inclusive) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kt&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;index&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;reciprocal_scale&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;phash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_socks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* Index into the SO_REUSEPORT group using this index, and return that socket */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reuse&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;socks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们需要退一步来理解这是如何实现的。当第一个进程在启用了 SO_REUSEPORT 的套接字上调用 &lt;em&gt;listen()&lt;/em&gt; 时，会分配它的 “&lt;em&gt;struct sock&lt;/em&gt;” 结构中的指针- &lt;em&gt;sk_reuseport_cb&lt;/em&gt;。该结构定义为:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock_reuseport&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;u16&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;max_socks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* Allocated size of socks[] array */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;u16&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_socks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* #Elements in socks[] */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;socks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* All sockets added to this group */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;该结构的最后一个元素是“灵活数组成员”[7]。整个结构是这样分配的：&lt;em&gt;socks[]&lt;/em&gt; 数组有128个类型为“&lt;em&gt;struct sock *&lt;/em&gt;”的元素。注意，当监听器的数量超过 128 时，这个结构会被重新分配，这个 &lt;em&gt;socks[]&lt;/em&gt; 数组的大小就会翻倍。&lt;/p&gt;
&lt;p&gt;调用 &lt;em&gt;listen()&lt;/em&gt; 的第一个套接字 sk1 会被缓存在它自己的 &lt;em&gt;socks[]&lt;/em&gt; 数组的第一个槽位中，例如： &lt;em&gt;sk1-&amp;gt;sk_reuseport_cb-&amp;gt;socks[0] = sk1;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;当随后在绑定到相同 &lt;em&gt;IP:port&lt;/em&gt; 的其他套接字(sk2，…)上调用 &lt;em&gt;listen()&lt;/em&gt; 时，会执行两个操作:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;新套接字(sk2，…)的地址被附加到第一个套接字(sk1)的 &lt;em&gt;sk_reuseport_cb-&amp;gt;socks[]&lt;/em&gt; 。&lt;/li&gt;
&lt;li&gt;新套接字的 &lt;em&gt;sk_reuseport_cb&lt;/em&gt; 指针指向第一个套接字的 &lt;em&gt;sk_reuseport_cb&lt;/em&gt; 指针。这确保同一组的所有 LISTEN 套接字引用相同的 &lt;em&gt;sk_reuseport_cb&lt;/em&gt; 指针。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这两个步骤的执行如下图所示&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/2.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;图 2: LISTEN 套接字的 SO_REUSEPORT组&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在此图中，sk1 是第一个 LISTEN 套接字，而 sk2 和sk3 是随后调用 &lt;em&gt;listen()&lt;/em&gt; 的套接字。上面描述的两个步骤在下面的代码片段中执行，并通过 &lt;em&gt;listen()&lt;/em&gt; 调用链执行:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;inet_reuseport_add_sock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new_sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* First check if another identical LISTEN socket, prev_sk,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	* exists. ... Then do the following:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prev_sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;cm&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		* Not the first listener - do the following:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		* - Grow prev_sk-&amp;gt;sk_reuseport_cb structure if required.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		* - Save new_sk socket pointer in prev_sk&amp;#39;s socks[].
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		* - prev_sk-&amp;gt;sk_reuseport_cb-&amp;gt;socks[num_socks] = new_sk;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		* - prev_sk-&amp;gt;sk_reuseport_cb-&amp;gt;num_socks++;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		* - Pointer assignment of the control block:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		* new_sk-&amp;gt;sk_reuseport_cb = prev_sk-&amp;gt;sk_reuseport_cb;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;		*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;reuseport_add_sock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new_sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;prev_sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	* First listener - do the following:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	* - allocate new_sk-&amp;gt;sk_reuseport_cb to contain 128 socks[]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	* - new_sk-&amp;gt;sk_reuseport_cb-&amp;gt;max_socks = 128;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	* - new_sk-&amp;gt;sk_reuseport_cb-&amp;gt;socks[0] = new_sk;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	* - new_sk-&amp;gt;sk_reuseport_cb-&amp;gt;numsocks = 1;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;	*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;reuseport_alloc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new_sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;现在让我们了解 &lt;em&gt;reuseport_select_sock()&lt;/em&gt; 如何选择 LISTEN 套接字。&lt;em&gt;reuseport_select_sock()&lt;/em&gt; 通过调用_reciprocal_scale()_ 简单地索引到 &amp;rsquo; &lt;em&gt;socks[]&lt;/em&gt; &amp;rsquo; 数组中，如下所示：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;unsigned&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;index&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;reciprocal_scale&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;phash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_socks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reuse&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;socks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;index&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;reciprocal_scale()&lt;/em&gt; [8] 是一个优化的函数，它使用乘法和移位操作实现伪模运算&lt;/p&gt;
&lt;p&gt;如前面所看到的， &lt;em&gt;‘phash’&lt;/em&gt; 是在 __inet_lookup_listener() 函数中计算,&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;phash&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;inet_ehashfn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dst_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dst_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;src_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;&amp;rsquo; num_socks &amp;lsquo;&lt;/em&gt; 是 socks[] 数组中的套接字个数。函数 &lt;em&gt;reciprocal_scale(phash, num_socks)&lt;/em&gt; 计算一个索引，索引&amp;gt;= 0，但是 &amp;lt; num_socks。该索引用于从 SO_REUSEPOR T套接字组中获取套接字。因此，我们看到内核通过对客户 &lt;em&gt;IP:port&lt;/em&gt; 和服务 &lt;em&gt;IP:port&lt;/em&gt; 计算哈希值来选择套接字。该方法对不同的 LISTEN 套接字上的连接可以做到较好的分配。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;来看如何实际使用 SO_REUSEPORT 选项&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;让我们通过两个测试来看看 SO_REUSEPORT 的影响&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;一个应用程序打开一个套接字用于监听，并创建两个进程。应用程序代码路径： &lt;em&gt;socket(); bind (); listen(); fork ()&lt;/em&gt;；&lt;/li&gt;
&lt;li&gt;一个应用程序创建两个进程，每个进程在设置 SO_REUSEPORT 后创建一个 LISTEN 套接字。应用程序代码路径:&lt;em&gt;fork();socket();setsockopt (SO_REUSEPORT);bind ();listen()&lt;/em&gt;；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;先看看没有 SO_REUSEPORT 的套接字状态：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ss -tlnpe &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep :45000LISTEN &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;128&lt;/span&gt; *:45000 *:* users:&lt;span class=&#34;o&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;my_server&amp;#34;&lt;/span&gt;,pid&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;3020,fd&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;3&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;,&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;my_server&amp;#34;&lt;/span&gt;,pid&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;3019,fd&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;3&lt;span class=&#34;o&#34;&gt;))&lt;/span&gt; ino:3854904087 sk:37d5a0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;字符串 “&lt;em&gt;ino:3854904087 sk:37d5a0&lt;/em&gt;” 就描述一个内核套接字。&lt;/p&gt;
&lt;p&gt;再来看看有 SO_REUSEPORT 的套接字状态：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ ss -tlnpe &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep :45000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;LISTEN &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;128&lt;/span&gt; *:45000 *:* users:&lt;span class=&#34;o&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;my_server&amp;#34;&lt;/span&gt;,pid&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;1975,fd&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;3&lt;span class=&#34;o&#34;&gt;))&lt;/span&gt; ino:3854935788 sk:37d59c
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;LISTEN &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;128&lt;/span&gt; *:45000 *:* users:&lt;span class=&#34;o&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;my_server&amp;#34;&lt;/span&gt;,pid&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;1974,fd&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;3&lt;span class=&#34;o&#34;&gt;))&lt;/span&gt; ino:3854935786 sk:37d59d&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;现在我们看到了两个不同的内核套接字——注意不同的 inode 号。&lt;/p&gt;
&lt;p&gt;使用多个进程接受单个 LISTEN 套接字上的连接的应用程序可能会遇到严重的性能问题，因为每个进程在 &lt;em&gt;accept()&lt;/em&gt; 中争夺相同的套接字锁，如下面的简化伪代码所示:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;inet_csk_accept&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;newsk&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* client socket */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;cm&#34;&gt;/* Make sure that this socket is listening, and that it has something pending. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nf&#34;&gt;lock_sock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk_state&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TCP_LISTEN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;there are completed connections waiting to be accepted&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;n&#34;&gt;newsk&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_first_connection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nf&#34;&gt;release_sock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;newsk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;lock_sock()&lt;/em&gt; 和 &lt;em&gt;release_sock()&lt;/em&gt; 都在内部获取并释放嵌入在&amp;rsquo; sk &amp;lsquo;中的自旋锁。参见本文后面的&lt;strong&gt;图4&lt;/strong&gt;观察自旋锁竞争用造成的开销。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Benchmarking SO_REUSEPORT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;以下设置用于测量 SO_REUSEPORT 性能：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;内核版本：4.17.13。&lt;/li&gt;
&lt;li&gt;客户端和服务端系统都有 48 个超线程核心，并通过交换机使用一个 40g NIC 相互连接。&lt;/li&gt;
&lt;li&gt;服务端有以下两种启动方式：&lt;/li&gt;
&lt;li&gt;创建一个 LISTEN 套接字和 fork 48 次;或&lt;/li&gt;
&lt;li&gt;Fork 48 次，每个子进程在启用 SO_REUSEPORT 后创建一个 LISTEN 套接字。&lt;/li&gt;
&lt;li&gt;客户端创建 48 个进程。每个进程依次连接和断开与服务器的连接 100 万次。&lt;/li&gt;
&lt;li&gt;客户端和服务端应用程序的源代码在本文的末尾。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;With fork of the LISTEN socket
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;server-system-$ ./my_server &lt;span class=&#34;m&#34;&gt;45000&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;48&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# 0 indicates fork() of a LISTEN socket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;client-system-$ &lt;span class=&#34;nb&#34;&gt;time&lt;/span&gt; ./my_client &amp;lt;server-ip&amp;gt; &lt;span class=&#34;m&#34;&gt;45000&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;48&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;real 4m45.471s
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;With SO_REUSEPORT
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;server-system-$ ./my_server &lt;span class=&#34;m&#34;&gt;45000&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;48&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# 1 indicates SO_REUSEPORT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;client-system-$ &lt;span class=&#34;nb&#34;&gt;time&lt;/span&gt; ./my_client &amp;lt;server-ip&amp;gt; &lt;span class=&#34;m&#34;&gt;45000&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;48&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;real 1m36.766s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;SO_REUSEPORT 的性能分析&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;让我们使用 &lt;strong&gt;perf&lt;/strong&gt; [9] 工具查看以上两个测试的性能数据。图 3 和图 4 显示了在不使用 SO_REUSEPORT 的情况下进行上述测试的硬件性能统计和内核性能。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/3.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;图 3. 没有设置 SO_REUSEPORT 时硬件性能统计&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/4.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;图 4. 没有设置 SO_REUSEPORT 时 top 25 个函数的性能数据&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;图 5 和图 6 显示了使用 SO_REUSEPORT 进行上述测试的硬件性能统计和内核性能。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/5.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;图 5. 设置了  SO_REUSEPORT 时硬件性能统计&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/6.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;图 6. 设置了 SO_REUSEPORT 时的 top 25 函数性能&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;客户端和服务端应用程序的源代码：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;下面实现了一个用于 SO_REUSEPORT 性能测试的服务端和客户端应用程序。&lt;/p&gt;
&lt;p&gt;服务端程序:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;sys/wait.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;netdb.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;create_children&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nprocs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent_pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nprocs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;getpid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent_pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fork&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nf&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reuse_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cfd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nprocs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;opt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent_pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getpid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sockaddr_in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nf&#34;&gt;fprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Port# #Procs {0-&amp;gt;fork, or 1-&amp;gt;SO_REUSEPORT}&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;nprocs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;atoi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;reuse_port&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;atoi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reuse_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* proper SO_REUSEPORT */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nf&#34;&gt;create_children&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nprocs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent_pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;socket&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AF_INET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SOCK_STREAM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nf&#34;&gt;perror&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;socket&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reuse_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nf&#34;&gt;setsockopt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SOL_SOCKET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SO_REUSEPORT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;opt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;opt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AF_INET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s_addr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;INADDR_ANY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_port&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;htons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;atoi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;bind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sockaddr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nf&#34;&gt;perror&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;bind&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reuse_port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* simple fork instead of SO_REUSEPORT */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nf&#34;&gt;create_children&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nprocs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent_pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;parent_pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getpid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;cm&#34;&gt;/* wait for all children */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nf&#34;&gt;listen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SOMAXCONN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cfd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;accept&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;nf&#34;&gt;perror&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;accept&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nf&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cfd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;客户端程序&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;strings.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;sys/wait.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;netdb.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;create_children&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nprocs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent_pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nprocs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;getpid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent_pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;fork&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nf&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nprocs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent_pid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getpid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sockaddr_in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hostent&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server_ent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linger&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nolinger&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l_onoff&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;l_linger&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nf&#34;&gt;fprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;stderr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Server-IP Port# #Processes #Conns_per_Proc&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;nprocs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;atoi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;atoi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server_ent&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gethostbyname&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;nf&#34;&gt;perror&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;gethostbyname&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nf&#34;&gt;bzero&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AF_INET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_port&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;htons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;atoi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nf&#34;&gt;bcopy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server_ent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server_ent&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h_length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;nf&#34;&gt;create_children&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nprocs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent_pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;getpid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parent_pid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;cm&#34;&gt;/* Parent does nothing other than wait for children */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;wait&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;cm&#34;&gt;/* while the children connect() ‘count’ times to the server */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;--&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;socket&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AF_INET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SOCK_STREAM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;nf&#34;&gt;perror&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;socket&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;connect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sockaddr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;nf&#34;&gt;perror&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;connect&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;				&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;cm&#34;&gt;/* Reset connection to avoid TIME-WAIT state */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nf&#34;&gt;setsockopt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SOL_SOCKET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SO_LINGER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nolinger&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nolinger&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;			&lt;span class=&#34;nf&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;		&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;引用&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;[1] &lt;a href=&#34;https://lwn.net/Articles/542629/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://lwn.net/Articles/542629/&lt;/a&gt;&lt;br&gt;
[2] &lt;a href=&#34;https://en.wikipedia.org/wiki/Network_socket&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://en.wikipedia.org/wiki/Network_socket&lt;/a&gt;&lt;br&gt;
[3] &lt;a href=&#34;https://en.wikipedia.org/wiki/Transmission_Control_Protocol&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://en.wikipedia.org/wiki/Transmission_Control_Protocol&lt;/a&gt;&lt;br&gt;
[4] TCP State Transition diagram: &lt;a href=&#34;https://en.wikipedia.org/wiki/File:Tcp_state_diagram.png&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://en.wikipedia.org/wiki/File:Tcp_state_diagram.png&lt;/a&gt;&lt;br&gt;
[5] Kernel source code: &lt;a href=&#34;https://elixir.bootlin.com/linux/v4.17.13/source&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://elixir.bootlin.com/linux/v4.17.13/source&lt;/a&gt;&lt;br&gt;
[6] &lt;a href=&#34;https://www.amazon.com/Unix-Network-Programming-Sockets-Networking/dp/0131411551/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://www.amazon.com/Unix-Network-Programming-Sockets-Networking/dp/0131411551/&lt;/a&gt;&lt;br&gt;
[7] &lt;a href=&#34;https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html&lt;/a&gt;&lt;br&gt;
[8] &lt;a href=&#34;http://homepage.cs.uiowa.edu/~jones/bcd/divide.html&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;http://homepage.cs.uiowa.edu/~jones/bcd/divide.html&lt;/a&gt;&lt;br&gt;
[9] &lt;a href=&#34;https://perf.wiki.kernel.org/index.php/Tutorial&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://perf.wiki.kernel.org/index.php/Tutorial&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>如何在生产环境跟踪 Go 函数的参数</title>
      <link>https://www.helight.info/blog/2022/ebpf-function-tracing/</link>
      <pubDate>Wed, 26 Oct 2022 08:47:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/ebpf-function-tracing/</guid>
      <description>
        
        
        &lt;p&gt;原文地址：https://blog.px.dev/ebpf-function-tracing/&lt;/p&gt;
&lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这是一系列文章中的第一篇，这个系列的文字是分析记录我们如何在生产环境中使用 eBPF 调试应用程序，而不需要重新编译/重新部署。这篇文章描述了如何使用 &lt;a href=&#34;https://github.com/iovisor/gobpf&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;gobpf&lt;/a&gt; 和 uprobes 为 Go 应用程序构建函数参数跟踪器。该技术也可扩展到其他编译语言，如 C++、Rust 等。本系列的下一篇文章将讨论使用 eBPF 跟踪 HTTP/gRPC 数据、SSL等。&lt;/p&gt;
&lt;p&gt;在调试时，我们通常对捕获程序的状态比较感兴趣。这可以让我们检查应用程序正在做什么，并确定 bug 在代码中的位置。观察状态的一种简单方法是使用调试器捕获函数参数。对于 Go 应用程序，我们通常使用 Delve 或 gdb。&lt;/p&gt;
&lt;p&gt;Delve 和 gdb 可以很好地用于开发环境中的调试，但它们不经常用于生产环境中。使这些调试器强大的特性也会使它们不适合在生产系统中使用。调试器可能对程序造成严重的中断，甚至允许状态突变，从而可能导致生产软件的意外故障。&lt;/p&gt;
&lt;h2&gt;eBPF&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;ebpf&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#ebpf&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;为了更清晰地捕获函数参数，我们将探索使用增强的 BPF (&lt;a href=&#34;https://ebpf.io/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;eBPF&lt;/a&gt;)，它可以在在 Linux 4 以上的内核系统中可用，以及探索使用更高级别的 Go 库 &lt;a href=&#34;https://github.com/iovisor/gobpf&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;gobpf&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;扩展 BPF (eBPF)是 Linux 4.x+ 中出现的一项内核技术。你可以将它看作是一个轻量级的沙盒 VM，它运行在 Linux 内核内部，可以在经过验证的的前提下提供对内核内存的访问。&lt;/p&gt;
&lt;p&gt;如下面的概述所示，eBPF 允许内核运行 BPF 字节码。虽然使用的前端语言可能不同，但它通常是 C 语言的受限子集。通常，C 代码首先使用Clang 编译为 BPF 字节码，然后对字节码进行验证，以确保它可以安全执行。这些严格的验证保证了机器代码不会有意或无意地破坏 Linux 内核，并且在每次触发 BPF 探测时，它将在有限数量的指令中执行。这些保证使 eBPF 能够用于性能关键的工作负载，如包过滤、网络监视等。&lt;/p&gt;
&lt;p&gt;从功能上讲，eBPF 允许你在某些事件触发下运行受限制的C代码（比如：定时器、网络事件或函数调用)。当在函数调用中被触发时，我们将这些函数称为探针，它们可以用于运行内核中的函数调用（kprobes），或者运行用户空间程序中的函数调用（uprobe）。这篇文章的重点是使用uprobes 来进行动态函数参数的跟踪。&lt;/p&gt;
&lt;h2&gt;Uprobes&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;uprobes&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#uprobes&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Uprobe 允许你通过插入一个触发软中断的调试指令（x86上是 &lt;code&gt;int3&lt;/code&gt;）来拦截用户空间程序。这也是 &lt;a href=&#34;https://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;调试器的工作原理&lt;/a&gt;。uprobe 的执行流程本质上与任何其他 BPF 程序相同，并在下面的图表中进行了总结。编译和验证的 BPF 程序作为 uprobe 的一部分被执行，结果可以被写入缓冲区。&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
    &lt;img src=&#34;../imgs/bpf-tracing.jpeg&#34; title=&#34;BPF for tracing (from Brendan Gregg)&#34; alt=&#34;BPF for tracing (from Brendan Gregg)&#34;  loading=&#34;lazy&#34; /&gt;
    &lt;figcaption&gt;BPF for tracing (from Brendan Gregg)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/p&gt;
&lt;p&gt;BPF  (来自 Brendan Gregg)&lt;/p&gt;
&lt;p&gt;我们看看 uprobe 实际上是怎么工作的。为了部署 uprobe 并捕获函数参数，我们将使用&lt;a href=&#34;https://github.com/pixie-io/pixie-demos/blob/main/simple-gotracing/app/app.go&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;这个&lt;/a&gt;简单的演示应用程序。这个 Go 程序的相关部分如下所示。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;main()&lt;/code&gt; 是一个简单的 HTTP 服务器，它在 &lt;em&gt;/e&lt;/em&gt; 上公开一个 &lt;em&gt;GET&lt;/em&gt; 端点，它使用迭代逼近计算欧拉数(&lt;strong&gt;e&lt;/strong&gt;)。&lt;code&gt;computeE&lt;/code&gt; 接受单个查询参数（&lt;em&gt;iters&lt;/em&gt;），该参数指定为近似运算而运行的迭代次数。迭代次数越多，以计算周期为代价的结果近似就越准确。理解函数背后的数学原理并不重要。我们只对跟踪&lt;code&gt;computeE&lt;/code&gt; 的任何调用的参数感兴趣。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// computeE 通过一个指定的运行数值来计算 e 的近似值&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;computeE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;iterations&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;float64&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fact&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;iterations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fact&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;float64&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fact&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;HandleFunc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;/e&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;w&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ResponseWriter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;http&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 从 get 请求的参数重解析初 iters 参数，如果没有则使用默认值。&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// ... 代码暂时删除 ...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;w&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([]&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;e = %0.4f\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;computeE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;iters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// 启动服务...&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;为了理解 uprobe 是如何工作的，让我们看看如何在二进制文件中跟踪符号。因为 uprobe 是通过插入调试陷阱指令来工作的，所以我们需要获取函数所在的地址。Linux 上的 Go 二进制文件使用 ELF 存储调试信息。此信息是可以用的，即使在优化的二进制文件中也是可以读取使用，除非已经剥离了调试数据（如使用 strip 命令）。我们可以使用 &lt;code&gt;objdump&lt;/code&gt; 命令来检查二进制文件中的符号:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;0&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; % objdump --syms app&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;grep computeE
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000006609a0 g     F .text    000000000000004b              main.computeE&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;从输出中，我们知道函数 &lt;code&gt;computeE&lt;/code&gt;  位于地址 &lt;code&gt;0x6609a0&lt;/code&gt;。为了查看它周围的指令，我们可以使用 &lt;code&gt;objdump&lt;/code&gt; 将其分解为二进制文件(通过添加 &lt;code&gt;-d&lt;/code&gt; 来完成)。解析后的代码如下：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;0&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; % objdump -d app &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; less
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000006609a0 &amp;lt;main.computeE&amp;gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  6609a0:       &lt;span class=&#34;m&#34;&gt;48&lt;/span&gt; 8b &lt;span class=&#34;m&#34;&gt;44&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;24&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;08&lt;/span&gt;          mov    0x8&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;%rsp&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;,%rax
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  6609a5:       b9 &lt;span class=&#34;m&#34;&gt;02&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;00&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;00&lt;/span&gt;          mov    &lt;span class=&#34;nv&#34;&gt;$0&lt;/span&gt;x2,%ecx
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  6609aa:       f2 0f &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;05&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;16&lt;/span&gt; a6 0f    movsd  0xfa616&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;%rip&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;,%xmm0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  6609b1:       &lt;span class=&#34;m&#34;&gt;00&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  6609b2:       f2 0f &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; 0d &lt;span class=&#34;m&#34;&gt;36&lt;/span&gt; a6 0f    movsd  0xfa636&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;%rip&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;,%xmm1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;从这里我们可以看到 &lt;code&gt;computeE&lt;/code&gt; 被调用时会发生什么。第一条指令是 &lt;code&gt;mov 0x8(%rsp)，%rax&lt;/code&gt;。这 从 &lt;code&gt;rsp&lt;/code&gt; 寄存器偏移 &lt;code&gt;0x8&lt;/code&gt; 再移动到 &lt;code&gt;rax&lt;/code&gt; 寄存器。这实际上是上面的输入参数 &lt;code&gt;iterations&lt;/code&gt;；Go 的参数在堆栈上传递。&lt;/p&gt;
&lt;p&gt;有了这些信息，我们现在可以深入研究并编写代码来跟踪 &lt;code&gt;computeE&lt;/code&gt; 的参数。&lt;/p&gt;
&lt;p&gt;为了捕获事件，我们需要注册一个 uprobe 函数，并写一个可以读取输出的用户空间函数。如下图所示。我们将编写一个名为 &lt;code&gt;tracer&lt;/code&gt; 的二进制程序，它负责注册 BPF 代码并读取 BPF 代码的结果。如图，uprobe 将简单地写入 perf buffer，这是用于 perf 事件的 linux 内核数据结构。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/app-tracer.svg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;显示 Tracer 二进制程序跟踪从应用程序生成的 perf 事件&lt;/p&gt;
&lt;p&gt;现在我们了解了所涉及的部分，让我们看看添加 uprobe 时发生的详细情况。下图显示了 Linux 内核如何使用 uprobe 修改二进制文件。软中断指令(&lt;code&gt;int3&lt;/code&gt;)作为 &lt;code&gt;main.computeE&lt;/code&gt; 中的第一个指令插入。这会导致一个软中断，允许 Linux 内核执行我们的 BPF 函数。然后将参数写入 perf-buffer 缓冲区，再由跟踪程序 &lt;code&gt;tracer&lt;/code&gt; 异步读取。
&lt;img src=&#34;../imgs/app-trace.svg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;如何使用调试陷阱指令调用 BPF 程序的详细信息&lt;/p&gt;
&lt;p&gt;这种 BPF 函数相对简单；C 代码如下所示。我们注册这个函数，以便每次 &lt;code&gt;main.computee&lt;/code&gt; 被调用时它都会被调用。一旦调用了它，我们只需读取函数参数并将其写入 perf buffer 缓冲区。设置缓冲区需要许多的配置信息，可以参考这个&lt;a href=&#34;https://github.com/pixie-io/pixie-demos/blob/main/simple-gotracing/trace_example/trace.go&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;完整示例&lt;/a&gt;。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;uapi/linux/ptrace.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;BPF_PERF_OUTPUT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;trace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;inline&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;computeECalled&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pt_regs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// 输入参数存储在 ax 中
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;val&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;trace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;perf_submit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;现在我们有了一个功能完备的 &lt;code&gt;main.computeE&lt;/code&gt; 函数的端到端参数跟踪器！结果如下面的视频剪辑所示。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/e2e-demo.gif&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;示例&lt;/p&gt;
&lt;p&gt;其中很酷的一件事情是，我们实际上可以使用 GDB 查看对二进制文件所做的修改。在运行跟踪程序二进制之前，我们解析初在 &lt;code&gt;0x6609a0 &lt;/code&gt;地址的指令。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;gdb&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; display /4i 0x6609a0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;10: x/4i 0x6609a0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   0x6609a0 &amp;lt;main.computeE&amp;gt;:    mov    0x8&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;%rsp&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;,%rax
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   0x6609a5 &amp;lt;main.computeE+5&amp;gt;:  mov    &lt;span class=&#34;nv&#34;&gt;$0&lt;/span&gt;x2,%ecx
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   0x6609aa &amp;lt;main.computeE+10&amp;gt;: movsd  0xfa616&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;%rip&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;,%xmm0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   0x6609b2 &amp;lt;main.computeE+18&amp;gt;: movsd  0xfa636&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;%rip&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;,%xmm1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;下面是运行 tracer 二进制跟踪程序后的结果。我们可以清楚地看到，第一条指令现在是 &lt;code&gt;int3 &lt;/code&gt;。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;gdb&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; display /4i 0x6609a0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;7: x/4i 0x6609a0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   0x6609a0 &amp;lt;main.computeE&amp;gt;:    int3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   0x6609a1 &amp;lt;main.computeE+1&amp;gt;:  mov    0x8&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;%rsp&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;,%eax
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   0x6609a5 &amp;lt;main.computeE+5&amp;gt;:  mov    &lt;span class=&#34;nv&#34;&gt;$0&lt;/span&gt;x2,%ecx
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   0x6609aa &amp;lt;main.computeE+10&amp;gt;: movsd  0xfa616&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;%rip&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;,%xmm0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;尽管我们为这个特定的示例硬编码了跟踪程序 tracer，但也是可以让这个过程通用化的。Go 的许多方面，如嵌套指针、接口、通道等，使这个过程很有挑战性，但是，要解决这些问题，需要另一种现有系统中无法使用的检测模式。此外，由于这个过程在二进制级别上工作，它可以用于其他语言(C++、Rust等)的本机编译二进制文件。我们只需要考虑它们各自 ABI 的差异。&lt;/p&gt;
&lt;p&gt;使用 uprobe 跟踪 BPF 有它自己的优点和缺点。当我们要对二进制状态进行可观察时，BPF 是不错的选择，即使是在附加调试器会有问题或有害的环境中运行(例如生产二进制)。最大的缺点是即使是要观察很小的应用程序状态也需要代码。虽然 BPF 代码相对容易访问，但编写和维护起来比较复杂。如果没有大量的高级工具，就不太可能将其用于通用的调试中。&lt;/p&gt;
&lt;p&gt;我们在 Pixie 目前就在做跟踪 Go 动态日志记录的事情。可以查看&lt;a href=&#34;https://docs.px.dev/tutorials/simple-go-tracing/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;这个项目&lt;/a&gt;来查看 Pixie 如何跟踪在 K8s 集群上运行的 Go 应用程序。&lt;/p&gt;
&lt;h2&gt;参考文献&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;参考文献&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%82%e8%80%83%e6%96%87%e7%8c%ae&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/iovisor/gobpf&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;iovisor/gobpf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/iovisor/bcc&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;iovisor/bcc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>如何使用 eBPF 检测分析用户态程序</title>
      <link>https://www.helight.info/blog/2022/instrument-userland-apps-with-ebpf/</link>
      <pubDate>Tue, 25 Oct 2022 08:47:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/instrument-userland-apps-with-ebpf/</guid>
      <description>
        
        
        &lt;p&gt;eBPF 彻底改变了 Linux 内核中的可观察性。在我之前的系列文章中，我介绍了&lt;a href=&#34;http://www.helight.cn/blog/2020/linux-kernel-observability-ebpf/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;eBPF 生态系统的基本构建模块&lt;/a&gt;，简要介绍了&lt;a href=&#34;https://sematext.com/blog/ebpf-and-xdp-for-processing-packets-at-bare-metal-speed/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;XDP&lt;/a&gt;，并展示了它与 eBPF 基础设施如何密切合作，以便在网络堆栈中引入一个快速处理的数据路径。&lt;/p&gt;
&lt;p&gt;然而，eBPF 并不只是用在内核空间跟踪。如果我们可以在生产环境中运行的应用程序上也能享受 eBPF 驱动的跟踪的，这是不是很好呢?&lt;/p&gt;
&lt;p&gt;这就是 &lt;em&gt;uprobes&lt;/em&gt; 发挥作用的地方。可以将它们看作是一种 &lt;em&gt;kprobes&lt;/em&gt; ，它加载到了用户空间跟踪点而不是内核符号。多语言运行时、数据库系统和其他软件栈都包含了可以被 &lt;a href=&#34;https://github.com/iovisor/bcc/blob/master/tools/lib/ustat.py&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;BCC&lt;/a&gt; 工具使用的钩子。具体地说，&lt;em&gt;ustat&lt;/em&gt; 工具收集了大量有用事件，如垃圾收集事件、对象创建统计信息、方法调用等。&lt;/p&gt;
&lt;p&gt;但是“官方”语言运行时的版本，如 Node.js 和 Python，不带 DTrace 支持，这就需要你必须从源代码构建，将 &amp;ndash;with-dtrace_ 标志传递给编译器。这不是说必须一定要本机编译语言。只要符号表可用，就可以对二进制文本段中出现的任何符号应用动态跟踪。在运行的二进制文件上检测 Go 或 Rust stdlib 函数调用就是通过这种方式完成的。&lt;/p&gt;
&lt;h2&gt;可用于检测分析应用程序的 eBPF 技术&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可用于检测分析应用程序的-ebpf-技术&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e7%94%a8%e4%ba%8e%e6%a3%80%e6%b5%8b%e5%88%86%e6%9e%90%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e7%9a%84-ebpf-%e6%8a%80%e6%9c%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;跟踪用户空间进程有多种方法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;静态声明的 USDT&lt;/li&gt;
&lt;li&gt;动态声明的 USDT&lt;/li&gt;
&lt;li&gt;使用 uprobes 进行动态跟踪&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;静态声明的 USDT&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;静态声明的-usdt&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%9d%99%e6%80%81%e5%a3%b0%e6%98%8e%e7%9a%84-usdt&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;USDT (Userland Statically Defined Tracing)  的做法是直接在用户代码中嵌入探测。该技术的起源可以追溯到 Solaris/BSD DTrace 时代，包括使用 &lt;em&gt;DTRACE_PROBE()&lt;/em&gt; 宏在重要代码位置上声明跟踪点。与常规符号不同，USDT 钩子保证即使代码被重构也能保持稳定。下图描述了在用户代码中声明 USDT 跟踪点的过程，直到在内核中执行为止。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../Instrument-UserLand-Apps-with-eBPF/imgs/1.png&#34; alt=&#34;uprobe&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;开发人员可以先通过 &lt;em&gt;DTRACE_PROBE&lt;/em&gt; 和 &lt;em&gt;DTRACE_PROBE1&lt;/em&gt; 宏来在需要的代码块中植入跟踪点。两个宏都接受两个强制参数，如提供者/探测名称，后面跟着你希望从跟踪点查询的任何值。编译器将把USDT 跟踪点塞进目标二进制文件 ELF 段中 。编译器和跟踪工具之间规定了 USDT 元数据所在的位置必须存在 &lt;em&gt;.note.stapstd&lt;/em&gt; 段。&lt;/p&gt;
&lt;p&gt;USDT 跟踪工具检查 ELF 段，并在被转为 &lt;em&gt;int3&lt;/em&gt; 中断的跟踪点位置上放置一个断点。每当在跟踪点的标记处执行时，就会触发中断处理程序，并在内核中调用与 &lt;em&gt;uprobe&lt;/em&gt; 关联的程序来处理事件并将它们广播到用户空间，执行映射聚合等等。&lt;/p&gt;
&lt;h3&gt;动态声明的 USDT&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;动态声明的-usdt&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8a%a8%e6%80%81%e5%a3%b0%e6%98%8e%e7%9a%84-usdt&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;由于 USDT 被加入静态生成的 ELF 段，所以USDT不能运行在解释性语言或基于 jit 的语言上的软件上。幸运的是，可以通过 &lt;em&gt;libstapsdt&lt;/em&gt; 在运行时中定义跟踪点。它生成一个带有 USDT 信息的小型共享对象，该共享对象被映射到进程的地址空间，因此跟踪工具可以附加到目标跟踪点上。在许多语言中都有 &lt;em&gt;libstapsdt&lt;/em&gt; 。要了解如何在 Node.js 中安装 USDT 探测可以参考这个 &lt;a href=&#34;https://github.com/sthima/node-usdt#example&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;example&lt;/a&gt;。&lt;/p&gt;
&lt;h3&gt;使用 uprobes 进行动态跟踪&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;使用-uprobes-进行动态跟踪&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bd%bf%e7%94%a8-uprobes-%e8%bf%9b%e8%a1%8c%e5%8a%a8%e6%80%81%e8%b7%9f%e8%b8%aa&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这种类型的跟踪机制不需要目标进程提供任何额外的功能，只需要它的符号表是可访问的。这是最通用和最强大的插装方法，因为它允许在任意指令上注入断点，甚至不需要重启运行的进程。&lt;/p&gt;
&lt;h3&gt;跟踪例子&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;跟踪例子&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%b7%9f%e8%b8%aa%e4%be%8b%e5%ad%90&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;After a brief theoretical introduction, let’s see some concrete examples on how to instrument real-world apps crafted in diverse languages.
在简单的理论介绍之后，我们来看一些具体的例子，看看如何用跟踪分析不同的语言的应用程序。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;C 语言&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Redis is a popular key-value data structures server built in C. Taking a sneak peek into the Redis symbol table reveals a vast number of functions that are candidates for capturing via uprobes.
Redis 是一个用 C 语言开发的非常流行的 k-v 数据库服务，仔细看一下 Redis 符号表，就会发现大量可以通过 uprobes 捕获的函数。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ objdump -tT /usr/bin/redis-server
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;…
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;000000000004c160 g    DF .text  00000000000000cc  Base 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;addReplyDouble
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;0000000000090940&lt;/span&gt; g    DF .text  00000000000000b0  Base        sha1hex
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000000586e0 g    DF .text  000000000000007c  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;replicationSetMaster
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000001b39e0 g    DO .data  &lt;span class=&#34;m&#34;&gt;0000000000000030&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;dbDictType
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000000ace20 g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000030&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;RM_DictGetC
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0000000000041bc0 g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000073&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sdsull2str
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000000bba00 g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000871&lt;/span&gt;  Base        raxSeek
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000000ac8c0 g    DF .text  000000000000000c  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;RM_ThreadSafeContextUnlock
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000000e3900 g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000059&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mp_encode_lua_string
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000001cef60 g    DO .bss   &lt;span class=&#34;m&#34;&gt;0000000000000438&lt;/span&gt;  Base        rdbstate
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;0000000000047110&lt;/span&gt; g    DF .text  00000000000000b5  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;zipSaveInteger
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;000000000009f5a0 g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000055&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;addReplyDictOfRedisInstances
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;0000000000069200&lt;/span&gt; g    DF .text  000000000000004a  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;zzlDelete
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0000000000041e90 g    DF .text  00000000000008ba  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sdscatfmt
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;000000000009ac40 g    DF .text  000000000000003a  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sentinelLinkEstablishedCallback
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000000619d0 g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000045&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;psetexCommand
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000000d92f0 g    DF .text  00000000000000fc  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;luaL_argerror
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000000bc360 g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000328&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;raxRandomWalk
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0000000000096a00 g    DF .text  00000000000000c3  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rioInitWithFdset
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;000000000003d160 g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000882&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;serverCron
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;0000000000032907&lt;/span&gt; g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000000&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;je_prof_thread_name_set
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;0000000000043960&lt;/span&gt; g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000031&lt;/span&gt;  Base        zfree
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000000a2a40 g    DF .text  00000000000001ab  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sentinelFailoverDetectEnd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000001b8500 g    DO .data  &lt;span class=&#34;m&#34;&gt;0000000000000028&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;je_percpu_arena_mode_names
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000000b5f90 g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000018&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;geohashEstimateStepsByRadius
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000000000d95e0 g    DF .text  &lt;span class=&#34;m&#34;&gt;0000000000000039&lt;/span&gt;  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;luaL_checkany
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;0000000000048850&lt;/span&gt; g    DF .text  00000000000002d4  Base        
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;createClient
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;有一个有趣的 &lt;em&gt;createStringObject&lt;/em&gt; 函数，Redis 内部利用它来分配围绕 &lt;em&gt;robj&lt;/em&gt; 结构建模的字符串。Redis 命令通过 &lt;em&gt;createStringObject&lt;/em&gt; 调用来执行。通过跟踪这个函数，我们可以监视发送到 Redis 服务器的任何命令。为此，我将使用 BCC 工具包中的 &lt;em&gt;trace&lt;/em&gt; 功能。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ /usr/share/bcc/tools/trace &lt;span class=&#34;s1&#34;&gt;&amp;#39;/usr/bin/redis-server:createStringObject &amp;#34;%s&amp;#34; arg1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PID     TID     COMM            FUNC             -
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    &lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    redis-server    createStringObject b&lt;span class=&#34;s1&#34;&gt;&amp;#39;COMMANDrn&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    &lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    redis-server    createStringObject 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;b&lt;span class=&#34;s1&#34;&gt;&amp;#39;setrn$4rnoctirn$4rnfestrn&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    &lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    redis-server    createStringObject b&lt;span class=&#34;s1&#34;&gt;&amp;#39;octirn$4rnfestrn&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    &lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    redis-server    createStringObject b&lt;span class=&#34;s1&#34;&gt;&amp;#39;festrn&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    &lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    redis-server    createStringObject b&lt;span class=&#34;s1&#34;&gt;&amp;#39;getrn$4rnoctirn&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    &lt;span class=&#34;m&#34;&gt;8984&lt;/span&gt;    redis-server    createStringObject b&lt;span class=&#34;s1&#34;&gt;&amp;#39;octirn&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以上是在 Redis CLI 客户端执行 &amp;ldquo;set octi fest&amp;rdquo; 和 &amp;ldquo;get octi&amp;rdquo; 的输出结果。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Java语言&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;现代 JVM 版本自带对 USDT 的内置支持。所有探针都是用 &lt;em&gt;libjvm&lt;/em&gt; 共享对象带来的。我们可以在 ELF 段中到可用的追踪点。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ readelf -n /usr/lib/jvm/jdk-11-oracle/lib/server/libjvm.so
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;stapsdt              0x00000037       NT_STAPSDT &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;SystemTap probe 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;descriptors&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Provider: hs_private
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Name: cms__initmark__end
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Location: 0x0000000000e2420c, Base: 0x0000000000f725b4, Semaphore: 0x0000000000000000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Arguments:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;stapsdt              0x00000037       NT_STAPSDT &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;SystemTap probe descriptors&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Provider: hs_private
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Name: cms__remark__begin
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Location: 0x0000000000e24334, Base: 0x0000000000f725b4, Semaphore: 0x0000000000000000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Arguments:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;stapsdt              0x00000035       NT_STAPSDT &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;SystemTap probe descriptors&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Provider: hs_private
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Name: cms__remark__end
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Location: 0x0000000000e24418, Base: 0x0000000000f725b4, Semaphore: 0x0000000000000000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Arguments:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;stapsdt              0x0000002f       NT_STAPSDT &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;SystemTap probe descriptors&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Provider: hotspot
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Name: gc__begin
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Location: 0x0000000000e2b262, Base: 0x0000000000f725b4, Semaphore: 0x0000000000000000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Arguments: 1@&lt;span class=&#34;nv&#34;&gt;$1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;stapsdt              0x00000029       NT_STAPSDT &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;SystemTap probe descriptors&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Provider: hotspot
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Name: gc__end
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Location: 0x0000000000e2b31a, Base: 0x0000000000f725b4, Semaphore: 0x0000000000000000
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  Arguments:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;为了捕获所有的类加载事件，我们可以使用以下命令：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ /usr/share/bcc/tools/trace 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;u:/usr/lib/jvm/jdk-11-oracle/lib/server/libjvm.so:class__loaded &amp;#34;%s&amp;#34;, arg1&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;类似的，我们可以观察线程创建事件：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ /usr/share/bcc/tools/trace 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;u:/usr/lib/jvm/jdk-11-oracle/lib/server/libjvm.so:thread__start &amp;#34;%s&amp;#34;, arg1&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PID     TID     COMM            FUNC
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;27390&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27398&lt;/span&gt;   java            thread__start    b&lt;span class=&#34;s1&#34;&gt;&amp;#39;Reference Handler&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;27390&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27399&lt;/span&gt;   java            thread__start    b&lt;span class=&#34;s1&#34;&gt;&amp;#39;Finalizer&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;27390&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27400&lt;/span&gt;   java            thread__start    b&lt;span class=&#34;s1&#34;&gt;&amp;#39;Signal Dispatcher&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;27390&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27401&lt;/span&gt;   java            thread__start    b&lt;span class=&#34;s1&#34;&gt;&amp;#39;C2 CompilerThread0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;27390&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27402&lt;/span&gt;   java            thread__start    b&lt;span class=&#34;s1&#34;&gt;&amp;#39;C1 CompilerThread0&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;27390&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27403&lt;/span&gt;   java            thread__start    b&lt;span class=&#34;s1&#34;&gt;&amp;#39;Sweeper thread&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;27390&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27404&lt;/span&gt;   java            thread__start    b&lt;span class=&#34;s1&#34;&gt;&amp;#39;Service Thread&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;当扩展探测通过 &lt;em&gt;-XX:+ExtendedDTraceProbes&lt;/em&gt; 属性启用时，&lt;em&gt;uflow 工具&lt;/em&gt; 能够实时跟踪和绘制所有方法执行的图形。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ /usr/share/bcc/tools/lib/uflow -l java &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Tracing method calls in java process 27965... Ctrl-C to quit.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CPU PID    TID    TIME&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;us&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; METHOD
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;27991&lt;/span&gt;  0.736    &amp;lt;- jdk/internal/misc/Unsafe.park
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;27991&lt;/span&gt;  0.736    -&amp;gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;java/util/concurrent/locks/LockSupport.setBlocker&lt;span class=&#34;s1&#34;&gt;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;5   27965  27991  0.736      -&amp;gt; jdk/internal/misc/Unsafe.putObject
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;5   27965  27991  0.736      &amp;lt;- jdk/internal/misc/Unsafe.putObject
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;5   27965  27991  0.736    &amp;lt;- 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;java/util/concurrent/locks/LockSupport.setBlocker&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;27991&lt;/span&gt;  0.736    &amp;lt;- 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;java/util/concurrent/locks/LockSupport.parkNanos
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;27991&lt;/span&gt;  0.736    -&amp;gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;java/util/concurrent/locks/AbstractQueuedSynchronizer&lt;span class=&#34;nv&#34;&gt;$ConditionObject&lt;/span&gt;.checkInterruptWhileWaiting
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;27991&lt;/span&gt;  0.737      -&amp;gt; java/lang/Thread.interrupted
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;27991&lt;/span&gt;  0.737        -&amp;gt; java/lang/Thread.isInterrupted
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;27991&lt;/span&gt;  0.737        &amp;lt;- java/lang/Thread.isInterrupted
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;27991&lt;/span&gt;  0.737      &amp;lt;- java/lang/Thread.interrupted
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;27991&lt;/span&gt;  0.737    &amp;lt;- 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;java/util/concurrent/locks/AbstractQueuedSynchronizer&lt;span class=&#34;nv&#34;&gt;$ConditionObject&lt;/span&gt;.checkInterruptWhileWaiting
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;27991&lt;/span&gt;  0.737    -&amp;gt; java/lang/System.nanoTime
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;27965&lt;/span&gt;  &lt;span class=&#34;m&#34;&gt;27991&lt;/span&gt;  0.737    &amp;lt;- java/lang/System.nanoTime&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;但是，就扩展探针所产生的开销而言，这往往非常昂贵，因此不适合在生产环境中调试。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Go语言&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我将用一个 Go 中的例子来结束跟踪技术的演示。因为 Go 是一种原生编译语言，所以使用跟踪工具将 &lt;em&gt;uprobe&lt;/em&gt; 程序附加到目标符号上是尝试性的。你可以用下面这个简单的代码片段自己尝试一下:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;package&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ go build -o hi build.go
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$/usr/share/bcc/tools/trace &lt;span class=&#34;s1&#34;&gt;&amp;#39;/tmp/hi:fmt.Println &amp;#34;%s&amp;#34; arg1&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PID     TID     COMM            FUNC             -
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;31545&lt;/span&gt;   &lt;span class=&#34;m&#34;&gt;31545&lt;/span&gt;   hi              fmt.Println      b&lt;span class=&#34;s1&#34;&gt;&amp;#39;xd6x8dK&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;除了打印这里的 &amp;quot; Hi &amp;ldquo;字符串，我们在参数列中看到打印了一些随机的垃圾信息。这在一定程度上是由于 trace 不能处理 Println 可变参数造成的，但也可能和 ABI 调用约定的参数使用的错误假设有关。在 C/C++ 中，传递参数的首选方式是在常规寄存器中，而 Go 在堆栈上传递参数。&lt;/p&gt;
&lt;p&gt;由于我们不能依赖 trace 工具来来演示如何跟踪 Go 代码，所以我将构建一个简单的工具来跟踪由  &lt;em&gt;http.Get&lt;/em&gt; 函数发出的所有 HTTP GET 请求。 你可以很容易地修改它来捕获其他 HTTP 请求动词，大家可以参与贡献。完整的源代码可以在这个 &lt;a href=&#34;https://github.com/sematext/uprobe-http-tracer&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;repo&lt;/a&gt; 中找到。&lt;/p&gt;
&lt;p&gt;我不会详细介绍 &lt;em&gt;uprobe&lt;/em&gt; 附加/加载过程，因为我们正在使用 Go 绑定 来 帮 &lt;em&gt;libbcc&lt;/em&gt; 完成复杂的工作。让我们分析一下实际的 &lt;em&gt;uprobe&lt;/em&gt; 程序。&lt;/p&gt;
&lt;p&gt;在必需的 include 语句之后，有宏的定义，该宏通过偏移量处理的方式负责从堆栈中获取参数。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SP_OFFSET(offset) (void *)PT_REGS_SP(ctx) + offset * 8&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;接下来，我们声明数据结构用于封装通过 &lt;em&gt;reqs&lt;/em&gt; map流传递的事件。map 用 &lt;em&gt;BPF_PERF_OUTPUT&lt;/em&gt; 宏来定义。我们程序的核心是__uprobe_http_get 函数。当 &lt;em&gt;http.Get&lt;/em&gt; 被调用，则在内核空间中触发前面的函数。我们知道 &lt;a href=&#34;https://golang.org/pkg/net/http/#Client.Get&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;HTTP . get&lt;/a&gt; 只有一个参数，表示 HTTP 请求被发送到的 URL。C 语言和 Go 语言的另一个区别是字符串内存中布局处理。&lt;/p&gt;
&lt;p&gt;C 字符串是以空结束的序列串，而 Go 用 2 个值来描述：指向内存缓冲区的指针和字符串长度。这就解释了我们需要对 bpf_probe_read 进行两个调用——一个用于读取字符串，另一个用于提取字符串的长度。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;bpf_probe_read&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SP_OFFSET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;bpf_probe_read&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;req&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;req&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SP_OFFSET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;稍后在用户空间中，URL 将从字节片裁剪到相应的长度。作为一个附加说明，我想提到的是，该工具的草案版本能够通过注入 &lt;em&gt;uretprobe&lt;/em&gt; 来检测出每个 &lt;em&gt;HTTP GET&lt;/em&gt; 请求的延迟。然而，每次 Go 运行时决定收缩/增长堆栈就会有一个灾难性的影响，因为 &lt;em&gt;uretprobes&lt;/em&gt; 补丁的返回地址是在堆栈上的跳转函数，它在 eBPF VM 的上下文中执行。在退出 &lt;em&gt;uretprobe&lt;/em&gt; 函数时，指令指针被恢复到原始的返回地址，该地址可能指向一个无效的位置，打乱堆栈并导致进程崩溃。有一些&lt;a href=&#34;https://github.com/iovisor/bcc/issues/1320#issuecomment-407927542&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;建议&lt;/a&gt;来解决这个问题。&lt;/p&gt;
&lt;h2&gt;结论&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;结论&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%bb%93%e8%ae%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我们的 eBPF 之旅已经走到了终点。在这最后一篇文章中，我们介绍了一些 eBPF 特性用于用户空间进程插装 。通过几个实用案例，我们展示了 BCC 框架在捕获可观察性信号方面的多功能性。最后，我们亲自动手建立了一个小工具，用于跟踪实时 Go 应用程序上的 HTTP 请求。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人，关注「黑光技术」，关注技术分享。
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;

      </description>
    </item>
    
    <item>
      <title>API 网关做哪些事情呢？</title>
      <link>https://www.helight.info/blog/2022/what-does-api-gateway-do/</link>
      <pubDate>Sat, 24 Sep 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/what-does-api-gateway-do/</guid>
      <description>
        
        
        &lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;一个互联网技术玩家，一个爱聊技术的家伙。在工作和学习中不断思考，把这些思考总结出来，并分享，和大家一起交流进步。&lt;/p&gt;
&lt;p&gt;合理化的图文组织，让大家可以更容易学习一个技术。&lt;/p&gt;
&lt;p&gt;今天分享的是在 推 上看到的一个对 API Gateway 解析的图，感觉不错，比较清晰的指出 API Gateway 一般会做哪些事情。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/api.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;解说&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;解说&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%a7%a3%e8%af%b4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这图还是比较清晰的说明了 API Gateway 在一个服务中到底会做哪些事情。我在公司内也在建设内部的一个 API Gateway。一个常见的 API Gateway 就应该这么建设和这么使用。&lt;/p&gt;
&lt;p&gt;下面看看我在做的 API Gateway 的一个思路，大同小异，但是我是希望这个东西能能系统化，系统化的解决 API 的问题。
&lt;img src=&#34;../imgs/api2.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;我们在做的这个 API Gateway 有这样一些特点。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;基于开源项目 Envoy 研发，随时可以更新开源社区的新功能。&lt;/li&gt;
&lt;li&gt;业务插件和能力扩展：已经积累了 30 多种业务插件，接管或者卸载一部分业务服务要做的通用能力到 Gateway，让业务更加轻松方便使用。&lt;/li&gt;
&lt;li&gt;完善的内网外部接入能力：外网支持北极星，CLB的完整接入，内网支持北极星，service，ip，域名等多种方式。&lt;/li&gt;
&lt;li&gt;可观测性和监控：基于 K8S 的容器后监控能力，cpu 负载，内存等等；还有访问日志监控体系，还有可以轻松检索你的每一条请求，并且可以基于状态码和关键字进行告警。&lt;/li&gt;
&lt;li&gt;强大的路由管理能力：支持header头，url等多种匹配和多种路由算法。&lt;/li&gt;
&lt;li&gt;服务契约管理：具有配套的API契约管理能力，基于PB和OpenAPI轻松管理你服务的API。结合 PB 生成 swager 的 API 管理文档，并且结合 OpenAPI 也可以很好的管理，还有导出导出文档。在线简单测试，测试用例管理，测试历史以及 API 的 mock 能力都有。&lt;/li&gt;
&lt;/ol&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>程序在我机器上是跑的好好的</title>
      <link>https://www.helight.info/blog/2022/docker-works/</link>
      <pubDate>Sat, 17 Sep 2022 08:47:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/docker-works/</guid>
      <description>
        
        
        &lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;一个互联网技术玩家，一个爱聊技术的家伙。在工作和学习中不断思考，把这些思考总结出来，并分享，和大家一起交流进步。&lt;/p&gt;
&lt;p&gt;合理化的图文组织，让大家可以更容易学习一个技术。&lt;/p&gt;
&lt;p&gt;今天分享的是在 facebook 上看到的一个对 sre 学习的图，感觉不错，比较清晰的指出 sre 应该怎么做。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/docker-works.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;说说&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;说说&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%af%b4%e8%af%b4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;有意思的一张图片，感觉就是这样的，哈哈哈。&lt;/p&gt;
&lt;p&gt;在你机器上跑的好好的，那就把你的机器拿过来吧，让他在我这里跑。&lt;/p&gt;
&lt;p&gt;让程序所有的运行环境都不发生变化的情况下运行。docker 就是这么做的。&lt;/p&gt;
&lt;p&gt;感受到痛之后才能改变。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>站点可靠性工程（SRE）最佳实践</title>
      <link>https://www.helight.info/blog/2022/sre/</link>
      <pubDate>Sat, 17 Sep 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/sre/</guid>
      <description>
        
        
        &lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;一个互联网技术玩家，一个爱聊技术的家伙。在工作和学习中不断思考，把这些思考总结出来，并分享，和大家一起交流进步。&lt;/p&gt;
&lt;p&gt;合理化的图文组织，让大家可以更容易学习一个技术。&lt;/p&gt;
&lt;p&gt;今天分享的是在 facebook 上看到的一个对 sre 学习的图，感觉不错，比较清晰的指出 sre 应该怎么做。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/sre.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;解说&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;解说&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%a7%a3%e8%af%b4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;改进事件管理：为了预防或快速解决事件，企业必须建立适当的 SRE 事件管理流程。这将帮助SRE 团队根据紧急程度和影响对事件进行识别、记录和分类，然后相应地确定事件的优先级。一旦事件得到解决，团队就可以关闭它并更新状态。在理想情况下，SRE 团队还将对事件进行事后分析，以确定需要改进的地方，并帮助确保系统的弹性和有效的事件管理。&lt;/li&gt;
&lt;li&gt;在运营中纳入嵌入式 SRE：有时，日常工单的数量非常多，以至于运营任务占用了他们的大部分时间，从而减缓了进度。将 SRE 嵌入到运营中可以解决这个问题。SRE 将观察团队的日常任务，并推荐改进过程和结果的解决方案，并提供工程最佳实践，以在整个项目生命周期中保持可靠性和可扩展性。&lt;/li&gt;
&lt;li&gt;定制单体环境与分布式环境的监控：监控单体环境的可靠性不同于监控分布式环境。例如，单体式应用程序将所有日志和指标存储在单个日志文件中，而分布式应用程序具有不同的数据源。但是，分布式应用程序的风险较小；例如，重新部署分布式应用程序比整体式应用程序更容易、更快。为使其有效，SRE 团队应相应地调整其监控方法。&lt;/li&gt;
&lt;li&gt;在托管云环境中应用详尽的规则：随着越来越多的关键应用程序迁移到云，企业必须确保系统具有弹性。要使 SRE 团队能够高效地管理云环境，需要大量的规则。这些规则应该能够在事故发生期间提醒团队，并识别出未检测到的情况是否是紧急的和可操作的。通过提供即将发生的故障的清晰画面，SRE 团队将能够几乎实时地采取适当的行动。&lt;/li&gt;
&lt;/ol&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>DevOps Roadmap 2022</title>
      <link>https://www.helight.info/blog/2022/devops_roadmap/</link>
      <pubDate>Fri, 16 Sep 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/devops_roadmap/</guid>
      <description>
        
        
        &lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;一个互联网技术玩家，一个爱聊技术的家伙。在工作和学习中不断思考，把这些思考总结出来，并分享，和大家一起交流进步。&lt;/p&gt;
&lt;p&gt;合理化的图文组织，让大家可以更容易学习一个技术。&lt;/p&gt;
&lt;p&gt;今天分享的是 一个外国小哥整理的 DevOps Roadmap，原地址在&lt;a href=&#34;https://github.com/Vrashabh-Sontakke/Complete_DevOps_Roadmap_2022&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;这里&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/devopsroadmap.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;说说&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;说说&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e8%af%b4%e8%af%b4&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这个图垒起来了非常全面的技术和技术组件，从内容介绍上来说非常全面，而且也做了较为明确的分层。对于要全面学习的同学来说这个就非常合适了，可以从较为高的一个视角去看DevOps所涉及的技术和技术组件。&lt;/p&gt;
&lt;p&gt;但是，也有一些缺点，对于初学者非常不友好，无处下手，不知道该从里开始。但是学习到后面还是需要有全面的了解。&lt;/p&gt;
&lt;p&gt;另外好像也是一种梳理知识体系的方法，大家可以学习一下，把自己在某个领域的知识以这种层级方式不断梳理细化，成为自己的领域知识地图。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>技术人的转身思考：project 到 product 的转化</title>
      <link>https://www.helight.info/blog/2022/project-to-product/</link>
      <pubDate>Fri, 20 May 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/project-to-product/</guid>
      <description>
        
        
        &lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;前几天看到了一篇 Gartner 的报告，感觉非常有意思，这里梳理记录一下我的一下思考。给团队的同学我也分享了一下我的思考。&lt;/p&gt;
&lt;p&gt;这篇文章的题目是《How to shift from Project to Product》，看情况这是一个系列文章，这篇是一个开头或者是大纲，后面应该还有更详细的内容。&lt;/p&gt;
&lt;p&gt;但是就从我的角度来说这篇大纲给我的触动也是挺大的，我认为这是一个技术人的必修课。&lt;/p&gt;
&lt;h2&gt;大家理解的 Project 是什么&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;大家理解的-project-是什么&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%a4%a7%e5%ae%b6%e7%90%86%e8%a7%a3%e7%9a%84-project-%e6%98%af%e4%bb%80%e4%b9%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;以前对这个词的理解也就那样，没有多想和 Product 的区别。比如大学的时候老师留的大作业一般我们都叫做 Project，那时候我们做的项目都是叫做 Project，甚至工作了一段时间我们还是在做 leader 交给我们的 Project。还有我们程序员在 IDE 中创建的也叫做 Project。&lt;/p&gt;
&lt;p&gt;所以在一段时间内我们认为程序员就是做 Project 的，而且做 Project 就是正业、就是理所应当和很厉害的了。不知道大家有没有这样的感觉？&lt;/p&gt;
&lt;p&gt;我理解的 Project 是什么？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;完成特定功能的一个工程或者小系统。&lt;/li&gt;
&lt;li&gt;有一定的核心技术，而且重点在技术。&lt;/li&gt;
&lt;li&gt;在一定程度上只要重视技术就可以了完成这个 Project。&lt;/li&gt;
&lt;li&gt;所以主要是技术人员，关注技术研发和项目管理。&lt;/li&gt;
&lt;li&gt;有很多 Project 的目的并不是为了使用，而是验证、研究、测试。&lt;/li&gt;
&lt;li&gt;大多数的 Project 是一次交付的，缺乏后期的运营管理迭代提升。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这是我的理解，如果你有其他的想法也希望能发给我。&lt;/p&gt;
&lt;p&gt;虽然我在团队内一直也是前调我们是做平台的、或是一个完整系统的。不断在推动团队成员再往更深或者叫做更高的方向思考。&lt;/p&gt;
&lt;p&gt;我一直是在思考技术价值，怎么把技术的价值才能体现出来，所以在团队内我以我笨拙的语言给大家说：核心技术一定要有，但是核心技术并不能可靠的提供服务，核心技术一定要配合很多外围配套的设施才能提供可靠稳定高效的服务。&lt;/p&gt;
&lt;p&gt;大家也能看到这里的不完整性和不确定性，大家似乎理解了，但是可能还是不知道还要做哪些事情。&lt;/p&gt;
&lt;h2&gt;大家理解的 Product 是什么&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;大家理解的-product-是什么&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%a4%a7%e5%ae%b6%e7%90%86%e8%a7%a3%e7%9a%84-product-%e6%98%af%e4%bb%80%e4%b9%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Product 是什么？中文翻译是产品，就是说啥是产品？怎么做一个产品？&lt;/p&gt;
&lt;p&gt;我对 Product 的理解：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;目标是解决一个或者一系列使用问题而创造的一个东西。&lt;/li&gt;
&lt;li&gt;可以给到很多人方便的使用（当然也有使用体验差的产品）。&lt;/li&gt;
&lt;li&gt;除了核心技术外还有一系列的外围支持。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;因为我是做技术的，那么我认为我们研发的一定是技术产品（系统，平台或者小工具）。&lt;/p&gt;
&lt;p&gt;根据上面的大概描述，我想应该是可以分清楚这两个词的区别了。&lt;/p&gt;
&lt;h2&gt;在技术公司如何选择？Project or Product&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;在技术公司如何选择project-or-product&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9c%a8%e6%8a%80%e6%9c%af%e5%85%ac%e5%8f%b8%e5%a6%82%e4%bd%95%e9%80%89%e6%8b%a9project-or-product&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;当然这里面没有优劣之分，这里论述并不是说 Product 一定是比 Project 好的，只是他们的目标和方向以及实用场景不同。&lt;/p&gt;
&lt;p&gt;在一个技术公司两者也不可缺失，但是作为公司来说一定是通过产品来做到价值体现的。&lt;/p&gt;
&lt;p&gt;但是在产品的研发过程中都是要通过各个小的 Project 来逐步把产品形成的。&lt;/p&gt;
&lt;p&gt;我想作为一个技术人员，首先对于 Project 是一定要比较拿手的，在系统的架构设计，研发项目管理上，大家在工作的前几年中都要学习掌握扎实。
尤其在在核心技术的钻研和突破上也要总结出适合自己的一些方法论。&lt;/p&gt;
&lt;p&gt;其次，作为公司能够产生长远或者说是核心价值的一定是产品，所以在有了核心技术自后就要考虑如何产品化，通过做好一个好的产品结合好的产品营销运营来让技术和人的价值放大。&lt;/p&gt;
&lt;p&gt;那么产品化就是公司非常重要的一环，我这几年在公司一直在做平台类的产品，也是一直在想各种方法和思路让团队做出的平台让更多的人能更好的来使用，并且我们自己还要负责推广运营后勤。所以看到这个报告有一种情切感。思路上更加印证了这几年在积累的一些思路和方法。尤其今年上半年我搞的技术人员的服务经理制，就是在想办法让自己团队的技术 Project 经过转型升级为真正的 Product。当然我们都还在路上。&lt;/p&gt;
&lt;h2&gt;从 Project 到 Product 需要什么？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;从-project-到-product-需要什么&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%8e-project-%e5%88%b0-product-%e9%9c%80%e8%a6%81%e4%bb%80%e4%b9%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;做了上面这么多的铺垫其实也就是下面这些思考了，就是如果做到一个 Project 转化为 Product。&lt;/p&gt;
&lt;p&gt;首先这份报告给出了一个技术 Project 到 技术 Product 需要的能力项，或者是需要做的事情。&lt;/p&gt;
&lt;p&gt;其次这份报告给出了一个产品在研发和到市场运营的大致过程，包括了没个过程中需要关注的内容。&lt;/p&gt;
&lt;h3&gt;技术 Project 到 技术 Product 需要的能力项&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;技术-project-到-技术-product-需要的能力项&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%8a%80%e6%9c%af-project-%e5%88%b0-%e6%8a%80%e6%9c%af-product-%e9%9c%80%e8%a6%81%e7%9a%84%e8%83%bd%e5%8a%9b%e9%a1%b9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;先看看报告中这张图，这里介绍的是如果要做到产品化，就需要有一个产品化的组织架构，通过这个组织架构对产品进行不同角度的思考，最终才能做出一个有可能成功的产品。
从角色上来看有&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;CIO： 解决技术层的问题，从研发管理，数据分析、优化和项目管理。&lt;/li&gt;
&lt;li&gt;CFO：从成本的角度来考虑产品化的阶段和投入，还有价值利润的获取。&lt;/li&gt;
&lt;li&gt;Business Leader：产品交付，价值利润的实现。&lt;/li&gt;
&lt;li&gt;Team：从整体来考虑各个角度和优化和对变化的快速响应。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/1.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;技术 Project 到 技术 Product 的路线图&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;技术-project-到-技术-product-的路线图&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%8a%80%e6%9c%af-project-%e5%88%b0-%e6%8a%80%e6%9c%af-product-%e7%9a%84%e8%b7%af%e7%ba%bf%e5%9b%be&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这张图也是这个报告的核心，主要是路线节点，以及各个节点需要的大致准备时间。这个时间作为一般互联网产品研发和运营周期，我认为是比较合理的。&lt;/p&gt;
&lt;p&gt;可以看出来，一般是分三步走：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;准备：大概需要3个月左右
&lt;ol&gt;
&lt;li&gt;组建团队&lt;/li&gt;
&lt;li&gt;验证核心逻辑是不是ok&lt;/li&gt;
&lt;li&gt;对未来的运营模型预测设计&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;起飞：大概1年时间
&lt;ol&gt;
&lt;li&gt;设计实现初步可用版本&lt;/li&gt;
&lt;li&gt;做基本交付实用和实际验证&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;扩张：2年左右
&lt;ol&gt;
&lt;li&gt;扩张用户&lt;/li&gt;
&lt;li&gt;根据用户规模进行团队调整&lt;/li&gt;
&lt;li&gt;价值实现和利润实现&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/2.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;技术 Project 到 技术 Product 的关键阶段&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;技术-project-到-技术-product-的关键阶段&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%8a%80%e6%9c%af-project-%e5%88%b0-%e6%8a%80%e6%9c%af-product-%e7%9a%84%e5%85%b3%e9%94%ae%e9%98%b6%e6%ae%b5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这里其实从另外一个角度，对操作阶段进行了划分。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;基本的团队组建阶段：这个阶段首先是有一个大致的点子，要做去，开始考虑团队的组建，一些验证工作&lt;/li&gt;
&lt;li&gt;成熟度评估：评估产品竞争能力，评估市场，根据产品进行团队优化&lt;/li&gt;
&lt;li&gt;产品研发：根据市场需求进行产品研发和优化&lt;/li&gt;
&lt;li&gt;起飞阶段：作为产品试飞阶段，要分析产品的各项线上运营数据，不断优化产品&lt;/li&gt;
&lt;li&gt;产品到成熟期并进行RIO的考核
&lt;img src=&#34;../imgs/3.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;整体报告不是很详细，只是把大致思路梳理了出来，其实我感觉这就够了，因为不同的产品，团队和公司内外的环境也会对真实的实现过程产生严重的影响的。有思路但是真正具体实践还是要我们自己根据实际情况来走。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>开发了一个技术文章订阅器：TechNews</title>
      <link>https://www.helight.info/blog/2022/technews/</link>
      <pubDate>Tue, 05 Apr 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/technews/</guid>
      <description>
        
        
        &lt;h2&gt;TechNews 为什么会出现？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;technews-为什么会出现&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#technews-%e4%b8%ba%e4%bb%80%e4%b9%88%e4%bc%9a%e5%87%ba%e7%8e%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这几年学习技术基本上都是从国外一些网站找资料，直接看或者翻译一下。找这些资料其实还是比较繁琐。&lt;/p&gt;
&lt;p&gt;所以一直在想有一个合适的收集工具可以把多个地方的东西收集起来，再以一种较为方便的方式可以浏览学习，看到好的可以就记录下来翻译深入学习。&lt;/p&gt;
&lt;p&gt;本来想可以使用 rss 订阅，但是一是手机上没有特别好的 rss 订阅工具；另外现在软件设计必然要考虑商业化，必然会有很多我不用的功能，不够纯粹；还有就是不想安装这么多软件。&lt;/p&gt;
&lt;p&gt;所以这几天用 golang 开发了这个小程序，可以定时拉取配置列表中站点上的文章。拉取之后从新组织输出为静态网页，直接在手机中就可以浏览了。&lt;/p&gt;
&lt;p&gt;目前还做了一个信息网站 API 的直接抓取，还是挺有意思的，目前大多数的网站是允许以摘要的形式被抓取的。因为要阅读详细内容，还是要转到他们的网站。&lt;/p&gt;
&lt;p&gt;其实想的是可以直接从微信中看，因为目前这个号没有认证，只能从已经发布的一篇文章中点击原文链接过去。&lt;/p&gt;
&lt;h2&gt;目前的使用过程&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;目前的使用过程&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%9b%ae%e5%89%8d%e7%9a%84%e4%bd%bf%e7%94%a8%e8%bf%87%e7%a8%8b&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;在公众号的这里点击访问介绍 TechNews 的文章。
&lt;img src=&#34;../imgs/1.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;点击阅读原文，在这里直接转到 TechNews 首页
&lt;img src=&#34;../imgs/2.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;首页是这样的，会有一个列表，每次抓取生成一条
&lt;img src=&#34;../imgs/3.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;点击其中一条之后进入这里，就可以看文章了，目前主要是文章标题时间和摘要。
&lt;img src=&#34;../imgs/4.jpeg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在电脑上看是这样的
&lt;img src=&#34;../imgs/technews.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;目前 TechNews 的主要功能：&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;目前-technews-的主要功能&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%9b%ae%e5%89%8d-technews-%e7%9a%84%e4%b8%bb%e8%a6%81%e5%8a%9f%e8%83%bd&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;每周定时抓取指定网站的技术相关文章到这个页面，可以直接快速浏览文章信息。&lt;/li&gt;
&lt;li&gt;编译生成静态文件进行浏览，会有更快速的访问。&lt;/li&gt;
&lt;li&gt;抓取站点可以按需进行配置增加。&lt;/li&gt;
&lt;li&gt;使用bloomfilter进行重复链接过滤，避免有重复展示相同文章。&lt;/li&gt;
&lt;li&gt;可以使用微信公众号即可在手机上进行浏览，不需要安装新app。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;TechNews 使用的主要技术&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;technews-使用的主要技术&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#technews-%e4%bd%bf%e7%94%a8%e7%9a%84%e4%b8%bb%e8%a6%81%e6%8a%80%e6%9c%af&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;项目主要开发语言： golang&lt;/li&gt;
&lt;li&gt;rss 抓取使用：github.com/zhshch2002/goreq 这个库使用相对简单，比较好用&lt;/li&gt;
&lt;li&gt;rss 解析使用：github.com/mmcdole/gofeed&lt;/li&gt;
&lt;li&gt;内容过滤使用了 2 个库
&lt;ol&gt;
&lt;li&gt;bloomfilter：github.com/tylertreat/BoomFilters 做 url 去重&lt;/li&gt;
&lt;li&gt;Damerau-Levenshtein： github.com/lmas/Damerau-Levenshtein  计算标题的编辑距离，做标题去重&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;配置文件加载：github.com/BurntSushi/toml&lt;/li&gt;
&lt;li&gt;信息存储使用了：sqlite&lt;/li&gt;
&lt;li&gt;dborm 使用：gorm.io/gorm&lt;/li&gt;
&lt;li&gt;页面渲染到静态文件：html/template&lt;/li&gt;
&lt;li&gt;另外还有一些页面解析使用了：github.com/PuerkitoBio/goquery&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;目前已经订阅的站点&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;目前已经订阅的站点&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%9b%ae%e5%89%8d%e5%b7%b2%e7%bb%8f%e8%ae%a2%e9%98%85%e7%9a%84%e7%ab%99%e7%82%b9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;独立 tab 展示的&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;独立-tab-展示的&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%8b%ac%e7%ab%8b-tab-%e5%b1%95%e7%a4%ba%e7%9a%84&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Ubuntu = &amp;ldquo;&lt;a href=&#34;https://ubuntu.com/blog/feed%22&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://ubuntu.com/blog/feed&#34;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenSource = &amp;ldquo;&lt;a href=&#34;https://opensource.com/feed%22&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://opensource.com/feed&#34;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;CloudFlare = &amp;ldquo;&lt;a href=&#34;https://blog.cloudflare.com/rss/%22&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://blog.cloudflare.com/rss/&#34;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;RedHat = &amp;ldquo;&lt;a href=&#34;https://www.redhat.com/en/rss/blog/channel/red-hat-summit%22&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://www.redhat.com/en/rss/blog/channel/red-hat-summit&#34;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;在 AllInOne 这个 tab&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;在-allinone-这个-tab&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9c%a8-allinone-%e8%bf%99%e4%b8%aa-tab&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这些内容大多可以是 blog 等这类更新低频的站点，一般一周估计没有太多更新，所以把多个站点的内容都放到这里统一抓取。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;theagileadmin = &amp;ldquo;&lt;a href=&#34;https://theagileadmin.com/feed%22&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://theagileadmin.com/feed&#34;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;skynews = &amp;ldquo;&lt;a href=&#34;https://feeds.skynews.com/feeds/rss/technology.xml%22&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://feeds.skynews.com/feeds/rss/technology.xml&#34;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;后记&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;后记&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%90%8e%e8%ae%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;技术就是这样，可以自己折腾玩，还是比较有意思的。这个项目基本上也就 2 天时间搞定，后面再看有什么想做的可以继续加入。&lt;/p&gt;
&lt;p&gt;另外这里推到公众号上也是希望有更多的人可以给我提点意见，或者有人可以一起来玩。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>可观测性:不是你想的那样</title>
      <link>https://www.helight.info/blog/2022/what-is-observability/</link>
      <pubDate>Sat, 26 Mar 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/what-is-observability/</guid>
      <description>
        
        
        &lt;p&gt;本文译自 &lt;a href=&#34;https://www.splunk.com/en_us/blog/devops/observability-it-s-not-what-you-think.html&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;可观测性:不是你想的那样&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;译者：&lt;a href=&#34;http://helight.cn/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;helight&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;原文地址：https://www.splunk.com/en_us/blog/devops/observability-it-s-not-what-you-think.html&lt;/p&gt;
&lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;可观测性很多人估计会有一种疑惑：啥是可观测性，和我们之前的监控系统有啥区别，怎么老搞一些新名词出来，学不动了呀。。。。&lt;/p&gt;
&lt;p&gt;所以这篇文章从理论的角度出发，为可观测性进行“强行”正名，更重要的是我也想看看整这些名词的外国人是怎么想的。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/observability.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;可观测性是什么？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可观测性是什么&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7%e6%98%af%e4%bb%80%e4%b9%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;可观测性是一种思维方式，通过收集和分析你整个业务的数据让你可以知道你业务的任何问题。如果你问其他人，可观测性就是“通过查看系统的输出来监视系统的内部状态”的干巴巴的控制理论定义，或者是“度量指标、跟踪和日志”的非常专业名词。虽然这些说法也是对的，但是可观测性不仅仅是一个你要实现的东西，然后可以自豪的说“现在这个系统有了可观测性了”。将可观测性构建到你的业务中，可以让你看清楚有关业务的问题。&lt;/p&gt;
&lt;h2&gt;有什么样的问题？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;有什么样的问题&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%9c%89%e4%bb%80%e4%b9%88%e6%a0%b7%e7%9a%84%e9%97%ae%e9%a2%98&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;当然，“当错误数上升时我们的应用中发生了什么”这样的基础问题就可以用可观测性工具来回答，但这仅仅触及了可观测性的表面。&lt;/p&gt;
&lt;p&gt;可观测性思想能让你能够做的是找出为什么错误数会飙升。如果你非常熟悉你的应用程序及其所有依赖项，那么你可能会从监控系统中就看出问题所在了，但随着现代应用程序变得越来越复杂，你自己可以根据监控系统中的信息就可以分析出来问题所在会变的越来越困难。&lt;/p&gt;
&lt;p&gt;业务需求、特性发布、A/B 测试、重构成为微服务。。。。。。诸如此类的事情结合在一起创造了不断增加的熵，因此在没有帮助的情况下了解系统的一切变得越来越困难。&lt;/p&gt;
&lt;p&gt;可观测性还允许你探究错误是如何(或者是否!)影响用户体验的。你可以查看 RUM 数据、购买量、一般业务指标、营销活动、客户支持票据、社交媒体情绪，等等——这些数据将可观测性系统从只有少数人使用的东西，变成了整个公司都能从中探究业务的东西。这些数据不仅能让你回答“是什么”，还能让你回答“为什么”和“如何”。一个真正的可观测性套件可以让你回答所有这些问题：&lt;/p&gt;
&lt;p&gt;“是什么导致了这一突破?”
“这个广告有多有效?”
“这个新的前端设计推动了购买吗?”
“这次服务中断让我们的用户生气了吗?”&lt;/p&gt;
&lt;h2&gt;你为什么应该关心可观测性？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;你为什么应该关心可观测性&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bd%a0%e4%b8%ba%e4%bb%80%e4%b9%88%e5%ba%94%e8%af%a5%e5%85%b3%e5%bf%83%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;将这种类型的数据集成到你的系统中，你就可以发现你给最好的客户发送的营销活动中，有一个错误的动作 URL，该 URL 指向了一个 404 页面。如果没有将数据完全集成到你的可观测性解决方案中，你当然可以看到 4xx 的速率增加了。但是，你不知道为什么 4xx 的比率上升了，只知道 4xx 的比率上升了。&lt;/p&gt;
&lt;p&gt;想象一下，如果除了“前端服务 4xx 高于阈值”之外，你还看到了同时发生的“营销活动失效开始”的事件，那么你可以多快地解决一个问题。你不仅会知道哪里出了问题，还会很好地猜测出问题的原因，你还会有一个很好的跳板来调查这个错误给你带来的收入影响，或负面影响。&lt;/p&gt;
&lt;h2&gt;为什么说这不是监控？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;为什么说这不是监控&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%af%b4%e8%bf%99%e4%b8%8d%e6%98%af%e7%9b%91%e6%8e%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;正如我所说的，监控会告诉你某些地方出了问题，但它不会告诉你为什么会出问题。监控设置也只能监控你认为可能有问题的东西（你的”已知“）。如果你没有想到预先对相关组件进行检测，则无法对其进行监控。更糟糕的是，如果出现问题并决定给它添加监视，你是仍然没有关于组件执行的历史数据。&lt;/p&gt;
&lt;p&gt;此外，在你知道可能发生什么问题之前，监视需要特别的关注点——你必须专门检测指定的东西，并针对它们设置特定的告警。这需要时间来做并且容易出错。&lt;/p&gt;
&lt;p&gt;而且，无论你的监控解决方案有多好，它仍然不足以探测你的业务。传统的监控系统不可能查看“未知的事情”，因为数据根本不存在，无法进行评估。&lt;/p&gt;
&lt;p&gt;在传统的监控中，通常不支持添加业务指标，或者支持得很差。实时用户数据几乎从未包含在监控系统中，这是荒谬的，因为我们在 web 应用程序中所做的一切都是为了传递用户体验!&lt;/p&gt;
&lt;h2&gt;可观测性“三大支柱”如何协同工作？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可观测性三大支柱如何协同工作&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7%e4%b8%89%e5%a4%a7%e6%94%af%e6%9f%b1%e5%a6%82%e4%bd%95%e5%8d%8f%e5%90%8c%e5%b7%a5%e4%bd%9c&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;度量指标、跟踪和日志是可观测性的“三大支柱”，它们是必要的，但不足以真正理解什么是可观测性，并深入了解你的应用程序和业务。&lt;/p&gt;
&lt;p&gt;度量指标可以用来告诉你哪里出了问题。&lt;/p&gt;
&lt;p&gt;跟踪可以告诉你是怎么错的——例如，哪些特定的调用不起作用。&lt;/p&gt;
&lt;p&gt;日志告诉你为什么它是错误的，让你深入到一个特定的度量指标/跟踪，以找出它为什么以你看到的方式运行。&lt;/p&gt;
&lt;p&gt;收集这些数据是形成可观测性思维的开始，但这仅仅是个开始。&lt;/p&gt;
&lt;h2&gt;为什么你需要每一块数据？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;为什么你需要每一块数据&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%b8%ba%e4%bb%80%e4%b9%88%e4%bd%a0%e9%9c%80%e8%a6%81%e6%af%8f%e4%b8%80%e5%9d%97%e6%95%b0%e6%8d%ae&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;从简单的角度来看，可观测性的一个大问题是需要收集和保留太多的数据。“实际上，你不可能将现代服务产生的输出量存储在一个地方。&lt;/p&gt;
&lt;p&gt;”大多数供应商提出的解决方案叫所谓的抽样，但我更喜欢称之为“丢弃数据”。被丢弃的数据可能是你最关键的客户的交易。这可能是一个特殊的用例，它会导致一些奇怪的错误，并使你的数据库服务崩溃。&lt;/p&gt;
&lt;p&gt;更糟糕的是，许多供应商会宣传这是一种“为你省钱”的功能。我将在另一篇博文中更详细地介绍抽样的隐性成本。&lt;/p&gt;
&lt;p&gt;在一个经典的控制理论世界中，你有一堆仪表来监控关键的基础设施，你会因为“30% 就足够了”而抛弃 70% 的观察结果吗？当然，你不会这么做，但这正是许多供应商建议你必须对可观测性做的事情，因为问题数据的性质。事实并非如此。成熟的平台可以处理与你的业务有关的所有数据，不会丢弃任何数据。&lt;/p&gt;
&lt;h2&gt;可观测性不是一种实际操作，而是一种观念&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可观测性不是一种实际操作而是一种观念&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7%e4%b8%8d%e6%98%af%e4%b8%80%e7%a7%8d%e5%ae%9e%e9%99%85%e6%93%8d%e4%bd%9c%e8%80%8c%e6%98%af%e4%b8%80%e7%a7%8d%e8%a7%82%e5%bf%b5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;虽然本文讨论了一些关于可观测性的实现细节，但可观测性真正的含义并不是“收集和存储度量指标、跟踪和日志”。&lt;/p&gt;
&lt;p&gt;这是一种“我们应该收集什么样的数据，才能有助于解决我们想要了解的业务问题”的思维。&lt;/p&gt;
&lt;p&gt;可观测性不仅仅是应用程序性能监控或基础设施监控(尽管这些是它的一部分)。&lt;/p&gt;
&lt;p&gt;它是关于理解摄取一切信息的需要。真实用户体验指标。营销活动。流量的季节性变化。你仓库的人请病假了。&lt;/p&gt;
&lt;p&gt;可观测性是一种思维模式，它要求所有人(开发者、运营人员、产品、首席执行官等)使用的关于你的业务和应用程序的数据都必须有一个真实的单一来源。&lt;/p&gt;
&lt;p&gt;数以百万计的数据点组成了你的业务，而可观测性是在一个系统中捕获所有的数据，然后使用这些数据来回答问题，而不仅仅是你的业务运行的技术应用程序。&lt;/p&gt;
&lt;p&gt;要充分利用可观测性，你需要一个专门构建的流架构，它可以任意伸缩，并让你持续收到你的更改如何影响用户和业务的相关反馈。你需要一个将许多工具集成为一个共同的真理来源的系统，并从这些工具中提供见解。&lt;/p&gt;
&lt;h2&gt;后记&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;后记&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%90%8e%e8%ae%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;整个文章说的还是比较玄乎的，反正我在真实的业务场景中是无法做到收集那么多信息。虽然本文一再说可观测性是一种思维，整个我不否认，确实感觉应该是一个全面的分析认识。但是到底如何实施，收集哪些必要的信息，如何全面的收集到一起都是有很大挑战难度的。&lt;/p&gt;
&lt;p&gt;在我看来还是那种思维：大数据小做。无论再大的山也是要一点点干到的。除非存储和算力有非常大的提升，但是我在想提升算力的同时，需要观测的数据也会更多，因为我们要解决的问题也会越来越大呀。&lt;/p&gt;
&lt;p&gt;翻译完了之后，感觉还是有点收获的，不是一点都没有。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>什么是 PaaS？ PaaS 类型介绍</title>
      <link>https://www.helight.info/blog/2022/what-is-paas-type/</link>
      <pubDate>Sun, 20 Mar 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/what-is-paas-type/</guid>
      <description>
        
        
        &lt;p&gt;本文译自 &lt;a href=&#34;https://jelastic.com/blog/what-is-paas-platform-as-a-service-types-explained/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;什么是 PaaS？ PaaS 类型介绍&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;译者：&lt;a href=&#34;http://helight.cn/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;helight&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;原文地址：https://jelastic.com/blog/what-is-paas-platform-as-a-service-types-explained/&lt;/p&gt;
&lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这篇文章是对 PaaS 的划分介绍，没有从基础介绍开始，这里默认大家就是知道什么是 PaaS，PaaS 要解决什么问题的。&lt;/p&gt;
&lt;p&gt;这里的分层对具体的 PaaS 建设我认为有比较好的指导意义，至少明白没有万能的 PaaS，只有适合业务场景的 PaaS。&lt;/p&gt;
&lt;p&gt;那么大概有哪些类别的 PaaS？你的业务场景需要建设怎样的 PaaS 才能对业务有帮助？抽象到那一层是比较合适的？&lt;/p&gt;
&lt;p&gt;一起来看看。&lt;/p&gt;
&lt;h2&gt;介绍&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;介绍&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%8b%e7%bb%8d&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;没有说一个 PaaS 可以适合所有人的。现在甚至云计算服务模型的定义也是相当模糊的。 一般情况下，它被描述为一种云托管平台，这个平台上具有一组部署服务并能自动扩展，有应用程序管理和 DevOps 工具，可以在共享基础设施或内部设施。同时，PaaS 屏蔽了构建和维护基础设施的复杂性。 让我们看看 PaaS 在其用例和支持的技术方面有何不同，以及如何确定哪种将满足特定的需求。&lt;/p&gt;
&lt;p&gt;让我们从多个角度进一步研究和分析 PaaS 解决方案：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;PaaS 的目标&lt;/li&gt;
&lt;li&gt;PaaS 抽象能力&lt;/li&gt;
&lt;li&gt;PaaS 功能&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/what-is-paas.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;目标驱动的 PaaS 分类&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;目标驱动的-paas-分类&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%9b%ae%e6%a0%87%e9%a9%b1%e5%8a%a8%e7%9a%84-paas-%e5%88%86%e7%b1%bb&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;今天的 PaaS 供应商通过提供专门为特定服务构建的各种工具，在云上为应用程序开发及其托管提供了创新实现。考虑到 PaaS 解决方案中托管的用例，我们可以将 PaaS 产品分为三大类：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;通用型 PaaS&lt;/li&gt;
&lt;li&gt;新兴 PaaS&lt;/li&gt;
&lt;li&gt;专用 PaaS&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;通用&lt;/strong&gt;的平台被广泛选择用于传统的有状态 Web 和分层应用程序，从而为迁移现有工作负载提供了“提升和转变”的方法。 此外，这种 PaaS 类型会随着现代技术而及时扩展，以满足无状态云原生应用程序和微服务的需求，并有助于开发新的可扩展和容错服务。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新兴的 PaaS&lt;/strong&gt; 为市场带来了新的实现。它们通常使用在开发基于新兴技术（例如无服务器，分布式事件处理，机器学习框架等等）的独立服务。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;专业平台&lt;/strong&gt;专注于较小的一些应用场景，但市场需求很高。实时证明此类产品在不同方向领域上都非常有价值，包括电子商务，大数据处理和商业应用等场景。 通常，这些平台会转变为 PaaS 的子类别，例如 CMSaaS，电子商务即服务，DBaaS，BPaS等等。&lt;/p&gt;
&lt;h2&gt;PaaS 的抽象级别&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;paas-的抽象级别&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#paas-%e7%9a%84%e6%8a%bd%e8%b1%a1%e7%ba%a7%e5%88%ab&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;PaaS 解决方案越来越关注于应用程序部署和交付过程的全周期自动化。这有助于开发人员将更多的精力放在应用程序设计及其实现上，而不是耗时的例行任务或复杂的任务，例如服务器和存储配置，应用程序和基础设施的安全性，自动扩展，负载平衡等等。&lt;/p&gt;
&lt;p&gt;PaaS 的抽象级别可以分为 3 中：低，中和高。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;低抽象级别的平台&lt;/strong&gt;，尤其是容器即服务（CaaS）解决方案，为 DevOps 团队提供了对基础设施配置的底层访问，以及对容器和各种平台服务的精细控制（例如服务发现，日志记录，安全性和负载平衡）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;中间抽象&lt;/strong&gt;的主要目的是使开发人员编码时无需担心基础设施的配置和管理。这些平台让开发人员可以访问从 CaaS 和 IaaS 部署属性中完全抽象出来的各种可集成和优化过的开发框架，中间件软件堆栈，API 和服务。此类 PaaS 解决方案通常提供开箱即用的自动扩展 ，负载平衡，高可用性，备份，灾难恢复，CI/CD 和其他应用程序生命周期管理功能。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;高度抽象&lt;/strong&gt;的解决方案目标是对甚至编码过程进行抽象，以提高应用程序交付速度并降低创新成本。在这种情况下，开发人员可以获得整个技术堆栈，但具有应用程序，平台和基础设施级别的完整抽象。它有助于提高团队成员的绩效并降低其技术技能的要求。&lt;/p&gt;
&lt;h2&gt;集成到 PaaS 的功能和服务&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;集成到-paas-的功能和服务&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%9b%86%e6%88%90%e5%88%b0-paas-%e7%9a%84%e5%8a%9f%e8%83%bd%e5%92%8c%e6%9c%8d%e5%8a%a1&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;为了使应用程序生命周期管理过程自动化，PaaS 代表了一系列配置工具，持续集成和交付服务，流行的 IDE 的连接器和插件。
我们可以重点介绍这一类别中的三种主要方法：&lt;/p&gt;
&lt;h3&gt;部署自动化&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;部署自动化&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%83%a8%e7%bd%b2%e8%87%aa%e5%8a%a8%e5%8c%96&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;PaaS 专注于为自动化部署提供工具和服务，提供 “一键式” 或 “git-push” 的功能，以及用于代码构建，持续集成和项目管理工具的预配置环境。&lt;/p&gt;
&lt;h3&gt;基础设施管理&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;基础设施管理&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%9f%ba%e7%a1%80%e8%ae%be%e6%96%bd%e7%ae%a1%e7%90%86&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;云平台聚焦于基础设施配置，健康和可用性监视，安全和性能检查，成本优化，以及提供与升级和维护相关的自动化和服务。&lt;/p&gt;
&lt;h3&gt;容器编排&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;容器编排&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%ae%b9%e5%99%a8%e7%bc%96%e6%8e%92&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;容器管理平台提供的功能可以解决容器化过程的挑战，以及对现有或新应用程序进行云原生化的挑战。 现在，许多 PaaS 供应商都将 CaaS 作为其产品的组成部分，从而进一步增强了 PaaS 作为各种 DevOps 工具集合的观点。&lt;/p&gt;
&lt;h2&gt;如何选择 PaaS&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;如何选择-paas&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%a6%82%e4%bd%95%e9%80%89%e6%8b%a9-paas&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在为公司选择 PaaS 之前，要考虑几个要点。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;最重要的是要分析所选的 PaaS 是否支持目前开发团队使用或计划在未来使用的技术，中间件堆栈和编程语言。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;接下来要考虑的是供应商和数据绑定。 尽管有一些 PaaS 提供了好处，但是由于平台上的工具和服务的专有设计，对应用程序本身和使用的中间件堆栈的访问可能非常有限。这会影响应用程序的可移植性。因此，迁移到任何其他云或实现多云互操作性方法成为一个非常大的挑战。同样的问题也适用于存储的数据。 确保 PaaS 提供者允许轻松导入/导出数据，没有任何绑定。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;没有适用于所有项目的“一刀切”的技术，但是在现代云世界中，所有可用的集成和互连功能使特定产品之间的界限变得模糊。当涉及到云服务，DevOps 工具和容器管理系统时，Jelastic 多云 PaaS 提供了所需的选择自由。尝试以最小的投资来极大地提高开发生产力和应用程序交付过程。&lt;/p&gt;
&lt;h2&gt;后记&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;后记&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%90%8e%e8%ae%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Jelastic 这家公司是专门做 PaaS，SaaS 解决方案的，看了官网还是很专业的，但是没有体验具体产品。这篇文章是他们 PaaS 产品总监的总结，整体方向上是 OK 的。&lt;/p&gt;
&lt;p&gt;我更关注的是他提到的 PaaS 抽象级别的划分和应用场景划分。这部分总结的还是挺好，就目前我的认识上来说，对我目前架构内部的 PaaS 平台是有指导意义的。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>什么是 GitOps？</title>
      <link>https://www.helight.info/blog/2022/what-is-gitops/</link>
      <pubDate>Tue, 08 Mar 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/what-is-gitops/</guid>
      <description>
        
        
        &lt;p&gt;本文译自 &lt;a href=&#34;https://www.redhat.com/en/topics/devops/what-is-gitops&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;What is GitOps&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;译者：&lt;a href=&#34;http://helight.cn/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;helight&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;原文地址：https://www.redhat.com/en/topics/devops/what-is-gitops&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../imgs/gitops.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;什么是 GitOps？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;什么是-gitops&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%80%e4%b9%88%e6%98%af-gitops&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;定义：GitOps 使用 Git 来管理基础设施和应用配置的一种开发运营实践，Git 是一个开源的版本控制系统。GitOps 的工作原理是使用 Git 作为声明基础设施和应用的单一可信源。&lt;/p&gt;
&lt;p&gt;GitOps 使用 Git pull 请求来自动的管理基础设施的提供和部署。Git 仓库中包含了系统的的整体状态，所以系统状态的变化过程是可见、可审计的。&lt;/p&gt;
&lt;p&gt;GitOps 是围绕开发者体验来构建的，并且帮助团队使用和他们进行软件开发同样的工具和过程来管理基础设施。不同于 Git，GitOps 让你有选择你使用工具的能力。&lt;/p&gt;
&lt;p&gt;目前认为是 Weaveworks 创造了 GitOps 这个词。&lt;/p&gt;
&lt;h2&gt;如何开始使用 GitOps&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;如何开始使用-gitops&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%a6%82%e4%bd%95%e5%bc%80%e5%a7%8b%e4%bd%bf%e7%94%a8-gitops&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;要开始使用 GitOps，你需要可以声明管理的基础设施。因为这个原因，GitOps 通常是作为 Kubernetes 和原生应用开发的一种操作模型，并且可以在 Kubernetes 上做持续部署。&lt;/p&gt;
&lt;p&gt;但是使用 Kubernetes 并不是 GitOps 的一个硬性要求。GitOps 是一项技术，他可以应用在其他的基础设施和部署流水线上。&lt;/p&gt;
&lt;p&gt;像 Kubernetes，Ansible 是一个期望状态流转引擎，他可以声明管理传统的 IT 系统，也是可以用在 GitOps 上的。Ansible 用户可以管理 Kubernetes 上的应用，可以管理已经存在的 IT 设施上应用，或者使用 Ansible 模块统一进行管理。&lt;/p&gt;
&lt;p&gt;GitOps 可以用于构建开发流水线，代码应用，管理配置，提供 Kubernetes 集群，并且部署到 Kubernetes 上或者容器注册中心上。&lt;/p&gt;
&lt;h2&gt;什么是 GitOps 工作流？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;什么是-gitops-工作流&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%80%e4%b9%88%e6%98%af-gitops-%e5%b7%a5%e4%bd%9c%e6%b5%81&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;GitOps 可以被认为是一种基础设施即代码（IaC）的演进，它使用 Git 作为基础设施配置的版本控制系统。IaC 通常通过采用声明式方式来达到基础设施管理：设置预期的系统状态，并跟踪系统的真实状态。&lt;/p&gt;
&lt;p&gt;通过使用 IaC，GitOps 要求你声明你期望的系统状态。通过使用描述工具，所有你的配置文件和源代码都可以使用 Git 来进行版本控制。&lt;/p&gt;
&lt;p&gt;CI/CD 流水线通常是被外部的一个事件来触发的，比如提交代码到代码仓库。在一个 GitOps 工作流中，变化流程是由修改修改 Git 仓库状态的 pull 请求触发的。&lt;/p&gt;
&lt;p&gt;要使用 GitOps 工作流发布新版本，使用 Git 来发起 pull 请求，这样可以变更集群状态的声明。处在 GitOps 流水线和编排系统之间的 GitOps 操作器会接收到 commit 请求，并且从 Git 中拉取新的状态声明。&lt;/p&gt;
&lt;p&gt;改变被通过和合并之后，就会被自动的应用到实时的基础设施上。开发者可以持续的使用他们的标准工作流并且进行持续集成和持续交付。&lt;/p&gt;
&lt;p&gt;当在 Kubernetes 上使用 GitOps 的时候，操作器一般就是一个 Kubernetes Operator。&lt;/p&gt;
&lt;p&gt;操作器比较仓库的期望状态和部署在基础设施上的实际状态。操作器在感知到实际状态和仓库期望状态的不同的时候就会更新基础设施。操作器也会监视容器镜像仓库，并且通过同样的方式来部署新镜像。&lt;/p&gt;
&lt;p&gt;GitOps 中还有一个重要概念——可观测性，指可观测的任何系统状态。GitOps 中的可观测性让你确保观测到的状态（或实际状态）与期望的状态一致。&lt;/p&gt;
&lt;p&gt;使用 pull 请求和像 Git 一样的版本控制系统，让开发过程中清晰明了。这可以让你看到和跟踪系统的任何改变，提供了一个审查跟踪，让你可以有能力在出现问题的时候进行回滚。&lt;/p&gt;
&lt;p&gt;GitOps 工作流可以提高生产效率和加快开发和部署速度，以此来提高系统的稳定性和可靠性。&lt;/p&gt;
&lt;h2&gt;GitOps 与 DevOps 之间有何区别？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;gitops-与-devops-之间有何区别&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#gitops-%e4%b8%8e-devops-%e4%b9%8b%e9%97%b4%e6%9c%89%e4%bd%95%e5%8c%ba%e5%88%ab&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;GitOps 和 DevOps 确实在一些原则和目标是一样的。但是 DevOps 是关注在文化转变和提供一种在开发团队和运维团队之间协作的方式。&lt;/p&gt;
&lt;p&gt;GitOps 给你工具和框架让你实践 DevOps，比如协作，CI/CD和版本控制，还有自动的应用到基础设施上和应用部署。&lt;/p&gt;
&lt;p&gt;开发者能在他们已知的代码仓库上，运维同学则可以将其他必要组件落实到位。&lt;/p&gt;
&lt;h2&gt;后记&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;后记&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%90%8e%e8%ae%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;内容比较短，看了之后感觉还是挺清晰的，所以简单翻译了一下，网站也有中文翻译，我还是学习翻译了一遍。有些产品介绍相关的内容就没有翻译了。&lt;/p&gt;
&lt;p&gt;作为了解什么 GitOps，以及其核心原理，还是比较有指导性的。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>2022 年 kubernetes 的 5 个发展趋势</title>
      <link>https://www.helight.info/blog/2022/5-kubernetes-trends-watch-2022/</link>
      <pubDate>Tue, 01 Mar 2022 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2022/5-kubernetes-trends-watch-2022/</guid>
      <description>
        
        
        &lt;p&gt;本文译自 &lt;a href=&#34;https://enterprisersproject.com/article/2022/1/5-kubernetes-trends-watch-2022&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;5 Kubernetes trends to watch in 2022&lt;/a&gt;。
作者：&lt;a href=&#34;https://twitter.com/kevinrcasey&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Kevin Casey&lt;/a&gt;，
译者：&lt;a href=&#34;http://helight.cn/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;helight&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;原文地址：https://enterprisersproject.com/article/2022/1/5-kubernetes-trends-watch-2022&lt;/p&gt;
&lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;随着企业云基础设施的不断发展，Kubernetes 的使用量也有望继续增长。从基本采用到安全使用，这里有 5 个方面需要关注。&lt;/p&gt;
&lt;p&gt;Kubernetes 还在继续发展 - 这是针对所有使用 Kubernetes 的团队都是一样的。&lt;/p&gt;
&lt;p&gt;这些早期的采用的同学现在正在在他们自己的领域中，基于积累的经验和云原生生态系统的增长，以新的方式来扩展 Kubernetes 的核心能力。&lt;/p&gt;
&lt;p&gt;Liberty Mutual 的高级架构师 Eric ​​Drobisewski 这样说到：“我们会继续把 Kubernetes 用在我们业务所需要解决混合云，多云场景中。就如和我们看到的一样，Kubernetes 提供的申明式 API 和强循环调度对于我们建立统一的无论是私有云还是公有云环境下的资产管理都非常关键，对我们持续实现如何定义，管理和安全管理数字资产非常重要。”&lt;/p&gt;
&lt;p&gt;100 强公广泛司在混合云和多云基础设施上加速使用 Kubernetes 作为他们的平台了，这样是反应 Kubernetes 在产业界的使用影响力趋势之一。&lt;/p&gt;
&lt;h2&gt;Kubernetes 发展的 5 个关键趋势&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;kubernetes-发展的-5-个关键趋势&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#kubernetes-%e5%8f%91%e5%b1%95%e7%9a%84-5-%e4%b8%aa%e5%85%b3%e9%94%ae%e8%b6%8b%e5%8a%bf&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;另外一个大的趋势：大量的公司才正在开始使用 Kubernetes。并且在他们上云之路的任何阶段，学多的 IT 负责人希望在生产中运行更多的容器化应用 - 使用 Kubernetes 是他们最普遍的做法。&lt;/p&gt;
&lt;p&gt;“Gartner 预测，到 2022年，超过 75% 的全球组织会在他们的生产中运行容器化的应用，而这一数据在 2020 年才不到 30%。” Red Hat 的高级执行产品  Brian Gracely 说。&lt;/p&gt;
&lt;p&gt;这和 Red Hat 2021 年企业开源状态报告一致，72% 的 IT 负责人说他们预期在他们的组织中容器使用会增加。他们几乎普遍都认为（85%）Kubernetes 是云原生中的关键。&lt;/p&gt;
&lt;p&gt;这对 Kubernetes 的能力，使用场景，使用技巧和其他领域都产生了连续的影响。&lt;/p&gt;
&lt;p&gt;伴随着其他新技术的发展，Kubernetes 在技术和学习曲线尚都逐步成熟。&lt;/p&gt;
&lt;p&gt;考虑到这些，在新年伊始，这里总结了了 Kubernetes 发展的 5 个关键趋势。&lt;/p&gt;
&lt;h2&gt;1. Kubernetes 成为所有服务的平台？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;1-kubernetes-成为所有服务的平台&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#1-kubernetes-%e6%88%90%e4%b8%ba%e6%89%80%e6%9c%89%e6%9c%8d%e5%8a%a1%e7%9a%84%e5%b9%b3%e5%8f%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Kubernetes 和容器是分不开的。这点不会改变，至少不会在 2022 年出现。在 2022 年和未来会继续发展的是基于 Kubernetes 的平台的管理应用的类型。&lt;/p&gt;
&lt;p&gt;在早期，用户都是自己在机器上构建 Kubernetes 平台，并且只是部署简单的一组应用，但是现在 Kubernetes 已经很稳定了，使用模式也显著的成熟了。&lt;/p&gt;
&lt;p&gt;多数早期应用在 Kubernetes 上是以无状态的方式运行的，曾经 Kubernetes 被看作是对状态服务是不适合的，但是现在已经不成问题了。&lt;/p&gt;
&lt;p&gt;当我们已经看到很多各种各样的应用使用容器运行，我们开始看到越来越多的组织也把他们的关键能力和状态应用放到了 Kubernetes 上。数据库，事件驱动消息和关键任务应用都希望可以迁移到 Kubernetes 上，来使用 Kubernetes 上的优势：扩展性，安全和便于迁移。&lt;/p&gt;
&lt;p&gt;同样，Kubernetes 主要更多的还是仅仅作为一个容器编排工具，到目前为止还是这样的，但是 Kubernetes 的控制面已经变成一个多云和混合云操作的通用骨架。&lt;/p&gt;
&lt;p&gt;Kubernetes 提供了超过容器编排的能力，如声明式 API，控制循环和强壮的基于角色的访问控制（RBAC），来满足多数组织对多云，混合云的需求。这种进化将会围绕控制面，通过扩展 Kubernetes API 系统来对任何资源或基础设施进行定义，管理，生命周期和安全防护，即便是这些资源和基础设施没有原生的链接到 Kubernetes 的运行中。&lt;/p&gt;
&lt;p&gt;数据库，时间驱动消息和关键任务应用程序都期望能迁移到 Kubernetes 上，可以利用 Kubernetes 的伸缩性，安全性和可移植能力。同时也期望更多有经验的团队可以使用新的方式 包括使用 Kubernetes Operators，继续发展 Kubernetes 的成熟应用能力。&lt;/p&gt;
&lt;p&gt;各种组织在他们 DevOps 应用过程的下一个环节就是使用 Kubernetes operator 框架。我们将会看到许多自服务的能力扩展，都会基于 Kubernetes 来构建，这些能扩展能力从基本的自动管理和生命周期管理发展到了全面自动管理模式，使用更底层的数据驱动来发展自动推荐和自我修复能力，让他们管理的服务可以动态的适应 workload 的要求。&lt;/p&gt;
&lt;h2&gt;2. Kubernetes 和 AI/ML 成为了明星组合&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;2-kubernetes-和-aiml-成为了明星组合&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#2-kubernetes-%e5%92%8c-aiml-%e6%88%90%e4%b8%ba%e4%ba%86%e6%98%8e%e6%98%9f%e7%bb%84%e5%90%88&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Kubernetes 的成熟和处理不断增加的复杂场景能力可能是它在 AI 和机器学习上的最好证据。Kubernetes 成为在生产环境中服务人工智能和机器学习的选择。&lt;/p&gt;
&lt;p&gt;这是一个强大的组合，在未来的几年中会产生巨大的商业影响。&lt;/p&gt;
&lt;p&gt;当数据科学变成每个公司的一个关键角色的时候，需要改进并增强许多类型应用能力的需求也在增加。从改进用户交互以利用数据做更好的决策，比如自动驾驶汽车的应用，AI/ML 影线了几乎现在商业的各个角落。&lt;/p&gt;
&lt;p&gt;就像容器化的好处一样，在生产中管理所有的也需要一种方式，所以 AI/ML 也明显需要一种坚固的 IT 基础设施来管理。&lt;/p&gt;
&lt;p&gt;Kubernetes 为 AI/ML 带来了一个非常好的平台能力 - 伸缩性，访问 GPU，workload 迁移等等。我们可以看到有组织在使用 Kubernetes 做了很厉害的 AI/ML 方面的事情，我们期望下一代的应用可以彻底改变工业产业。&lt;/p&gt;
&lt;h2&gt;3. 唯一比 Kubernetes 更热的东西？Kubernetes 人才&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;3-唯一比-kubernetes-更热的东西kubernetes-人才&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#3-%e5%94%af%e4%b8%80%e6%af%94-kubernetes-%e6%9b%b4%e7%83%ad%e7%9a%84%e4%b8%9c%e8%a5%bfkubernetes-%e4%ba%ba%e6%89%8d&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;我们知道，没人真想听到说“人才短缺”&lt;/p&gt;
&lt;p&gt;但是在可见的未来，对 Kubernetes 技能人才（包括云原生能力）的需求还是很热的。目前很难有可信的数据来说明，但是可以确定的是 2022 年依然是需求大于供给。&lt;/p&gt;
&lt;p&gt;目前 Kubernetes 和云原生技术的使用趋势还没有放缓的趋势。我希望可以看到更多的组织持续上云，并且增加微服务，serverless 和其他云原生技术的使用。更重要的是，我们希望更多的组织在意识到 Kubernetes, Linux, 和 DevOps 之间的关系。&lt;/p&gt;
&lt;p&gt;人才短缺会在几个方面表现出来。首先，通过云原生全景图可以很自然的引导很多人进行自己学习，也就会让大家掌握很好的技能。&lt;/p&gt;
&lt;p&gt;全球多元化和开放工程社区在加速发展，它帮忙建立一个充满活力的云原生生态。人们在寻求构建 Kubernetes 和云原生生态的知识和技能的趋势也在持续发展，还有各种规模的组织对具备这些技能的工程师的需求，都在帮助这方面的人才有更好的发展。&lt;/p&gt;
&lt;p&gt;其次，公司和招聘管理者必须要更加积极主动。如果放缓或是搁置关键的 IT 人才等招聘？那就等着吧。&lt;/p&gt;
&lt;p&gt;在 2022 年各个公司会继续愿意投入在新老雇员或者未来要雇佣的员工身上，培训他们 Kubernetes 和其他云相关技术（例如 Linux），真金白银的投入而不是说说。在 Kubernetes 认证上 Linux 基金会是最大的一个参与者。&lt;/p&gt;
&lt;p&gt;但是这个趋势这里不只是说认证。更多的说这是一种员工本身的思想转变，不是说一种漂亮的方式宣传说是一种职业发展，而实际上是他们自身愿意投入时间去学习。管理者如果想我招你来工作的不是来学习的，那么那就基本是招不到人的，除非他能忽悠。公司进行培训并且对有工作经验的员工进行云原生培训实践，就持续找到一大批愿意学习的人员的。&lt;/p&gt;
&lt;h2&gt;4. Kubernetes 商业化管理服务业将蓬勃发展&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;4-kubernetes-商业化管理服务业将蓬勃发展&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#4-kubernetes-%e5%95%86%e4%b8%9a%e5%8c%96%e7%ae%a1%e7%90%86%e6%9c%8d%e5%8a%a1%e4%b8%9a%e5%b0%86%e8%93%ac%e5%8b%83%e5%8f%91%e5%b1%95&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;商业 Kubernetes 平台，像 Red Hat 的 OpenShift，实在开源项目智商构建的，已经是企业 Kubernetes 采用和使用的主流方式。随着越来越多成功的案例出现，其他的组织自然要去寻找相似的商业产品。但是并不是所有的公司都需要从头构建能力来运行他们自己的平台。&lt;/p&gt;
&lt;p&gt;多数时候，他们不想在运营和管理维护 Kubernetes 上投入，只想使用而已。这就是我们看到快速发展的 Kubernetes 管理云服务。比如 OpenShift。&lt;/p&gt;
&lt;p&gt;Kubernetes 管理服务的增长实在公有云上（除了可以运行在任何云上一些商业平台），这就意味着很多组织是不需要或者不想自己来运维管理 Kubernetes 的。&lt;/p&gt;
&lt;p&gt;译者注：我也是这么看的，未来中小企业使用云来优化自己内部的资源问题，场景适配问题是核心，而 Kubernetes 以及底层资源的运维管理不是核心，完全可以托管。&lt;/p&gt;
&lt;h2&gt;5. Kubernetes 社区将继续优先考虑安全问题&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;5-kubernetes-社区将继续优先考虑安全问题&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#5-kubernetes-%e7%a4%be%e5%8c%ba%e5%b0%86%e7%bb%a7%e7%bb%ad%e4%bc%98%e5%85%88%e8%80%83%e8%99%91%e5%ae%89%e5%85%a8%e9%97%ae%e9%a2%98&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Kubernetes 内置了重要的安全特性，只需要配置 ok 即可。它繁荣的生态也非常重视平台的安全性，在 OperatorHub.io 上有 29 中不同的安全 app，这也是一个可以侧面反应对安全重视的指标。&lt;/p&gt;
&lt;p&gt;2022 年，企业组织剋使用这些可用的工具和服务来加强他们的云和云原生安全。例如，我们会看到企业如何使用管理应用入口上的变化。&lt;/p&gt;
&lt;p&gt;我们会看到基于策略的部署管理的增长，比如使用 OPA Gatekeeper, Kyverno, 和 Argo CD 等。&lt;/p&gt;
&lt;p&gt;总的来说，预计整个社区都会继续投入 Kubernetes 的安全性，尤其是在简化（而不是降低）团队安全性方面，并通过将其嵌入到他们用来管理集群的工具中来减少其预算。&lt;/p&gt;
&lt;p&gt;Kubernetes 发行版将开始在发行版中直接添加更多安全功能。这将有助于增强分发的整体安全性，并有助于降低 Kubernetes 安全部署的成本。&lt;/p&gt;
&lt;h2&gt;后记&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;后记&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%90%8e%e8%ae%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;整体来说这篇文章还是有点东西的，几个趋势应该也是今后 Kubernetes 的重要发展趋势。这些趋势目前确实也是我们在实际场景终于到的，比如 KaaS 的提出，人才的招聘难度，现在招聘 golang 开发在国内都比较紧张。还有 Kubernetes 在 AI 上的结合，确实 AI 重在应用，而 Kubernetes 重在底层调度，Kubernetes 的调度扩展特性也设计的非常好。&lt;/p&gt;
&lt;p&gt;但是我认为分析的不够深入，缺乏一些数据支持。所以在翻译过程中有些内容我也进行了删减。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>云原生技术解读3-云原生交付部署：不可变基础设施</title>
      <link>https://www.helight.info/blog/2021/cloud-native3/</link>
      <pubDate>Sun, 26 Dec 2021 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2021/cloud-native3/</guid>
      <description>
        
        
        &lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;9 月初给 BG 的新人开了一门课，专门来讲云原生技术，云原生技术从出现到现在按最早的时间出现来说也是有 10 多年了。尤其是这几年火热的不得了，但是 cloud native 这个外文词翻译成中文 “云原生” 就更加的不好理解，再加上本身这个词的定义在发展中又有多次的变化，导致很多学习这块技术的同学都感觉是云里雾里，不知所谓。&lt;/p&gt;
&lt;p&gt;所以根据我对这门技术的认识，我开了这门课，一方面我认为我的认识还算比较到位，另一方面我认为目前的新人必须要学习和了解云原生技术，这是目前底层技术发展的大趋势。非常有必要学习和了解，而且我在内部也是致力于推动云原生技术的落地。在推动的过程中也很费劲，很多人看不到这场技术变革的意义和价值，这是非常让人感慨的。&lt;/p&gt;
&lt;h2&gt;云原生技术架构&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;云原生技术架构&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%91%e5%8e%9f%e7%94%9f%e6%8a%80%e6%9c%af%e6%9e%b6%e6%9e%84&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;所以我继续接着上篇解读什么是云原生。这里要接着上面篇文章中的图来继续解释，如下图
&lt;img src=&#34;https://www.helight.info/blog/2021/cloud-native3/imgs/4.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
这张图较为清晰的展示了目前云原生架构的基本层次，从最下面的运行时到最上面的应用架构，再辅助于 CI/CD 的持续思想以及现编程成接口方式：声明式API。层次结构都非常清晰，容易让人理解。所以下面的介绍也是围绕这个图来进行的。&lt;/p&gt;
&lt;p&gt;前面也梳理了容器和容器编排技术，这一篇，想简单再梳理一下上面一层：交付部署，不可变基础设施。&lt;/p&gt;
&lt;h2&gt;交付部署介质&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;交付部署介质&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%a4%e4%bb%98%e9%83%a8%e7%bd%b2%e4%bb%8b%e8%b4%a8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这篇文章我们来聊一聊云原生的交付部署部分，在有了容器和容器编排之后，那下一步就是要做这块的打通，做交付，把我们的应用程序或者说我们开发的服务如何能部署到容器里面，如何能更加优雅的部署管理起来。大家也可以思考一下怎么做以及为什么。&lt;/p&gt;
&lt;p&gt;我们交付了什么，拿什么去部署呢？这里一般有 2 种做法，我们下面来一一介绍。&lt;/p&gt;
&lt;h2&gt;可变基础设施&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可变基础设施&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e5%8f%98%e5%9f%ba%e7%a1%80%e8%ae%be%e6%96%bd&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;在应用开发测试到上线的过程中，应用通常需要被频繁部署到开发环境、测试环境和生产环境中。&lt;/p&gt;
&lt;p&gt;传统运维做法：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;申请一台或一组服务器，运维人员通过SSH或是Agent的方式，&lt;/li&gt;
&lt;li&gt;将软件的二进制包的安装到服务器上并进行环境的配置。&lt;/li&gt;
&lt;li&gt;如果需要进行版本升级和参数变更等变更操作，就需要逐个服务器地调整配置文件，及将新代码直接部署到现有服务器上。&lt;/li&gt;
&lt;li&gt;这些服务器承载的应用和参数是可以改变的。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;在传统的交付发布时代，通常需要系统管理员保证所有环境的一致性，而随着时间的推移，这种靠人工维护的环境一致性很难维持，环境的不一致又会导致应用越来越容易出错。这种由人工维护、经常被更改的环境就是我们常说的“可变基础设施”。&lt;/p&gt;
&lt;p&gt;如下面这图所示，很多时候我们只是交付了运行的二进制包。
&lt;img src=&#34;https://www.helight.info/blog/2021/cloud-native3/imgs/1.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;可变基础设施（Immutable Infrastructure）&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可变基础设施immutable-infrastructure&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e5%8f%98%e5%9f%ba%e7%a1%80%e8%ae%be%e6%96%bdimmutable-infrastructure&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;与可变基础设施相对应的是不可变基础设施，是指一个基础设施环境被创建以后不接受任何方式的更新和修改。这个基础设施也可以作为模板来扩展更多的基础设施。&lt;/p&gt;
&lt;p&gt;如果需要对基础设施做更新迭代，那么应该先修改这些基础设施的公共配置部分，构建新的基础设施，将旧的替换下线。简而言之，不可变基础设施架构是通过整体替换而不是部分修改来创建和变更的。&lt;/p&gt;
&lt;p&gt;任何基础设施实例（服务器、容器等各种软硬件）一旦创建之后便成为一种只读状态，不可对其进行任何更改；
如果需要修改或升级实例，唯一方式是创建一批新实例以替换。&lt;/p&gt;
&lt;p&gt;不可变基础设施的优势在于能保持多套基础设施的一致性和可靠性，而且基础设施的创建和部署过程也是可预测的。在云原生结构中，借助Kubernetes和容器技术，云原生不可变基础设施提供了一个全新的方式来实现应用交付。&lt;/p&gt;
&lt;p&gt;云原生不可变基础设施具有以下优势：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;云原生的不可变基础设施以容器镜像为标准&lt;/strong&gt;，其中不但包含了二进制内容，还包含了程序运行需要的依赖环境，基础库，系统环境等。相对来说更加完整。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;能提升应用交付效率&lt;/strong&gt;：基于不可变基础设施的应用交付，可以由代码或编排模板来设定，这样就可以使用 Git 等控制工具来管理应用和维护环境。基础设施环境一致性能保证应用在开发测试环境、预发布环境和线上生产环境的运行表现一致，不会频繁出现开发测试时运行正常、发布后出现故障的情况。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;能快速、可靠地水平扩展&lt;/strong&gt;：基于不可变基础设施的配置模板，我们可以快速创建与已有基础设施环境一致的新基础设施环境。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;能保证基础设施的快速更新和回滚&lt;/strong&gt;：基于同一套基础设施模板，若某一环境被修改，则可以快速进行回滚和恢复，若需对所有环境进行更新升级，则只需更新基础设施模板并创建新环境，将旧环境一一替换。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2021/cloud-native3/imgs/2.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;云原生交付部署：不可变基础设施：镜像&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;云原生交付部署不可变基础设施镜像&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%ba%91%e5%8e%9f%e7%94%9f%e4%ba%a4%e4%bb%98%e9%83%a8%e7%bd%b2%e4%b8%8d%e5%8f%af%e5%8f%98%e5%9f%ba%e7%a1%80%e8%ae%be%e6%96%bd%e9%95%9c%e5%83%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这是镜像的宣传口号：Build, Ship, and Run Any App, Anywhere。
&lt;img src=&#34;blog/2021/cloud-native3/imgs/6.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;在这块镜像确实是做到了这一点，OCI 的成立，让容器镜像在只要符合 OCI 标准的环境下就可以使用，无论是 windows 还是 linux，包括不同版本的 linux。&lt;/p&gt;
&lt;h2&gt;容器镜像仓库&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;容器镜像仓库&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%ae%b9%e5%99%a8%e9%95%9c%e5%83%8f%e4%bb%93%e5%ba%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;就如上图一样，镜像总是要保存在一个地方，这也就催生了另外一个技术专门做镜像的存储，我们叫这个技术为镜像仓库技术。解决镜像的基本存储，延伸的功能还有镜像的声明周期管理，安全扫描，镜像分发加速等等。目前提供这类服务的商业公司也有很多，同时也有免费的镜像仓库，比如 docker 公司的这个，大家可以浏览看看：&lt;a href=&#34;https://hub.docker.com/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://hub.docker.com/&lt;/a&gt;。
&lt;img src=&#34;blog/2021/cloud-native3/imgs/3.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;目前我们内部使用的腾讯云的 tcr，也是比较好用的，而且提供了安全扫描，镜像分发加速等能力。TCR提供安全独享、高性能的容器镜像托管分发服务。可同时在全球多个地域创建独享实例，以实现容器镜像的就近拉取，降低拉取时间，节约带宽成本。
&lt;a href=&#34;https://cloud.tencent.com/product/tcr&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://cloud.tencent.com/product/tcr&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;另外还有一个 &lt;a href=&#34;https://github.com/goharbor/harbor&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;harbor&lt;/a&gt; 是一个开源的镜像仓库软件，你可以基于这个软件搭建自己的私有镜像仓库。&lt;/p&gt;
&lt;h2&gt;总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;目前来说，容器技术和容器镜像技术成为云上交付部署的标准。从应用层面来说，我们更多的是能理解这个交付思想和技术即可。目前这块的技术也是比较成熟的。所以一般应用场景中我们是直接使用现成的镜像仓库，再加上 CI 系统，打通代码和镜像仓库。像我们目前在使用 tcr，感觉还是比较好用的。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>我们是否真的需要使用服务网格？</title>
      <link>https://www.helight.info/blog/2021/need-service-mesh/</link>
      <pubDate>Fri, 10 Dec 2021 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2021/need-service-mesh/</guid>
      <description>
        
        
        &lt;p&gt;译者注：本文作者是 Tigera 产品总监 Phil DiCorpo ，&lt;a href=&#34;https://www.tigera.io/blog/do-you-really-need-a-service-mesh/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;原文地址在这里&lt;/a&gt;。作者介绍服务网格的价值和架构设计，并且分析了目前服务网格在落地上挑战点，这些都是非常有价值的。并且在后面介绍了他们在他们的产品 Calico 上的一些实践和解决思路。&lt;/p&gt;
&lt;p&gt;目前看服务网格在实施落地上确实是有非常大的挑战，根据具体的使用场景需求不一样，但是大多数的场景下使用服务网格还是有点太重了。所以目前大家的方向还是 2 个方面进行探索：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;如何降低目前边车架构下的部署运营成本，让使用团队可以低成本的使用这项技术。&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对于架构的优化，把传统的边车思路上进行突破，采用其它的架构从而减低运营成本。&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;本文的分析和介绍也是有一定的借鉴意义，我也坚信服务网格技术是服务治理的未来，而这项技术也在这几年的发展中不断发展壮大，但是还没有到很成熟的时候，&lt;strong&gt;服务网格技术是一个基础设施技术，一定要不断下沉，不断向上抽象。下沉到更高效的内核或者基础网络上，向上抽象到配置管理成本更低。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;首先任何事情要想明白为什么要用这项技术，国内这两年随着云原生技术的兴起而且不断的也把服务网格技术拉热了，&lt;strong&gt;但是应用场景和运营成本依然是我们要重点考虑的核心点，不是说为用而用。&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;正文&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;正文&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%ad%a3%e6%96%87&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;部署和管理微服务所面临的挑战导致了服务网格的出现，服务网格是一种用于在应用层添加可观察性、安全性和流量管理功能的工具和技术。虽然服务网格目的在帮助开发人员和 SRE 处理在 Kubernetes 集群内的服务对服务通信相关的场景，但服务网格还增加了操作复杂性，并引入了一个额外的控制平面，供安全团队管理。&lt;/p&gt;
&lt;h2&gt;什么是服务网格？&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;什么是服务网格&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bb%80%e4%b9%88%e6%98%af%e6%9c%8d%e5%8a%a1%e7%bd%91%e6%a0%bc&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;服务网格是一个软件基础设施层，用于控制和监控微服务应用内服务到服务流量。&lt;/p&gt;
&lt;p&gt;服务网格提供了一些中间件和一些组件，它们支持服务到服务的通信，例如动态发现。它提供了服务发现、跨服务流量负载平衡、加密和身份验证相关的安全功能、可观察性跟踪等功能。服务网格架构利用设计模式实现服务之间的通信，而无需微服务重写应用程序。&lt;/p&gt;
&lt;h2&gt;服务网格架构&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;服务网格架构&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%9c%8d%e5%8a%a1%e7%bd%91%e6%a0%bc%e6%9e%b6%e6%9e%84&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;服务网格工作的一个关键方式是它利用了 sidecar 设计模式。服务通过代理进行通信和处理请求，代理被动态地注入到每个 pod 中。Envoy 因其性能、可扩展性和 API 功能而成为在服务网格中使用最流行的代理之一。&lt;/p&gt;
&lt;p&gt;虽然 sidecar 代理的这种设计模式构成了服务网格的数据平面，但大多数服务网格还引入了一个额外的控制平面来配置和操作数据平面。&lt;/p&gt;
&lt;h3&gt;控制平面 vs 数据平面&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;控制平面-vs-数据平面&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%8e%a7%e5%88%b6%e5%b9%b3%e9%9d%a2-vs-%e6%95%b0%e6%8d%ae%e5%b9%b3%e9%9d%a2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;数据平面是作为代理实现的，如 Envoy，部署为 sidecar。这意味着每个 pod 中都包含该代理的一个实例，用于调解和控制微服务之间的通信，以及观察、收集和报告服务网格流量遥测数据。所有应用层通信都是通过数据平面进行路由的。&lt;/p&gt;
&lt;p&gt;控制平面管理和配置代理，以进行流量路由，收集和整合数据平面遥测数据。虽然 Kubernetes 有自己的控制平面，并且用于调度 pod 和处理部署的自动伸缩，但服务网格引入了另一个控制平面来管理这些代理正在执行的操作，以实现管理服务到服务间的通信。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2021/need-service-mesh/imgs/service-mesh-architecture.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
服务网格架构&lt;/p&gt;
&lt;h2&gt;服务网格特性&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;服务网格特性&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%9c%8d%e5%8a%a1%e7%bd%91%e6%a0%bc%e7%89%b9%e6%80%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;服务网格提供了一组功能强大但复杂的功能。最流行的开源服务网格之一 istio 将这些特性分解为了四大块：&lt;strong&gt;连接、安全、控制和观察特性。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在连接特性（也称为流量管理）中，如果正在对微服务进行版本控制，并且需要能够处理各种故障场景，那么你会在这个特性中获得一些可能需要的高级功能。&lt;/p&gt;
&lt;p&gt;接下来的两个特性，安全和控制。是服务网格提供的通过相互 TLS 身份验证来保护流量的设施，并对在服务间通信的流量实施管理策略。&lt;/p&gt;
&lt;p&gt;最后，观测性特性涵盖了可观察性功能，包括 sidecar 代理，它能够收集有关网格内服务间如何相互通信的遥测和日志数据。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2021/need-service-mesh/imgs/service-mesh-pillars.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;这四个特性代表了一个非常强大的功能集；然而，这种能力是有代价的。服务网格引入了一个额外的控制平面，这会增加部署复杂性和显著的操作开销。&lt;/p&gt;
&lt;h2&gt;服务网格的挑战点&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;服务网格的挑战点&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%9c%8d%e5%8a%a1%e7%bd%91%e6%a0%bc%e7%9a%84%e6%8c%91%e6%88%98%e7%82%b9&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&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;strong&gt;需要配置的内容太多&lt;/strong&gt;（上面提到的大多数功能都需要某种形式的配置）。&lt;/p&gt;
&lt;p&gt;虽然有许多服务网格实现，但在满足不同组织的需求时，并没有一站式的解决方案。很可能是安全团队需要花费大量的时间来确定哪个服务网格适用于他们的应用程序。&lt;/p&gt;
&lt;p&gt;因此，最终选择使用哪个服务网格就需要了解开发领域知识和专业技能。所以这在除了已经在使用的 Kubernetes 之外，这又增加了一层复杂性。&lt;/p&gt;
&lt;h2&gt;采用服务网格的主要原因&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;采用服务网格的主要原因&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%87%87%e7%94%a8%e6%9c%8d%e5%8a%a1%e7%bd%91%e6%a0%bc%e7%9a%84%e4%b8%bb%e8%a6%81%e5%8e%9f%e5%9b%a0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;通过与 DevOps 团队、平台和服务所有者的沟通，我们发现有三个主要场景是采用服务网格因素：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;安全/加密&lt;/li&gt;
&lt;li&gt;服务级别可观察性&lt;/li&gt;
&lt;li&gt;服务级别控制。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;安全/加密——群集中数据传输的安全性。有时候这是由行业特定的监管问题导致的，如 PCI 合规性或 HIPAA。在其他情况下，它由内部数据安全需求驱动。当面向 internet 的应用程序的安全性成为组织品牌和声誉的核心时，安全性就变得极其重要。&lt;/p&gt;
&lt;p&gt;服务级别可观察性——了解工作负载和服务在应用程序层的通信方式。根据设计，Kubernetes 是一个多租户环境。随着部署了更多的工作负载和服务，了解所有服务和工作负载是如何协同工作将会变得越来越困难，特别是当一个组织采用基于微服务的架构时。服务团队很希望了解服务的上游和下游依赖关系是什么。&lt;/p&gt;
&lt;p&gt;服务级别控制——控制哪些服务可以相互通信。这包括围绕零信任模型而实施最佳实践以确保安全性的能力。&lt;/p&gt;
&lt;p&gt;虽然这些是采用的主要驱动因素，但通过使用服务网格实现这些目标所涉及的复杂性可能会对许多组织和团队造成阻碍。&lt;/p&gt;
&lt;h2&gt;可操作的简化实现&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可操作的简化实现&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e6%93%8d%e4%bd%9c%e7%9a%84%e7%ae%80%e5%8c%96%e5%ae%9e%e7%8e%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;平台所有者、DevOps 团队和 SRE 的资源是有限的，因此由于配置和操作所需的资源成本，成为了采用服务网格是一项大工程。&lt;/p&gt;
&lt;p&gt;Calico 支持单窗格统一控制，以一种操作上更简单的方法来解决三个最流行的服务网格使用场景——安全性、可观察性和控制，同时避免了与部署独立服务网格相关的复杂工作。让我们看看这种方法的好处，以及如何轻松实现全栈可观察性和安全性，部署高性能加密，以及如何与防火墙等现有安全基础设施紧密集成。&lt;/p&gt;
&lt;h3&gt;安全&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;安全&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%ae%89%e5%85%a8&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Calico 使用开源的 WireGuard，利用最新的加密技术为传输中的数据提供加密。因此，Calico 的加密性能很高，同时仍然允许查看所有流量。&lt;/p&gt;
&lt;p&gt;引入相当多复杂性操作的其中一个领域就是与大多数服务网格中使用的 mTLS 相关联的证书管理。WireGuard 提供了一种高性能的替代方案，它是零配置的，甚至在协议中内置了密钥轮转等方面的能力。&lt;/p&gt;
&lt;h3&gt;可观测性&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可观测性&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Calico 以一种节省资源和成本的方式提供对服务间通信的可视性。它把它收集的所有数据以动态服务图的形式提供了 Kubernetes 原生可视化。该图允许用户可视化的跨服务和团队空间的通信流，以便于故障排除。这对平台运营商、服务所有者和开发团队都是有益的。&lt;/p&gt;
&lt;p&gt;通过 Calico，Envoy 被集成到数据平面中，提供操作简单性。无论使用的是哪种数据平面（标准 Linux iptables、Windows 或 eBPF），Calico 都通过在集群的每个节点上部署一个单一的 Envoy 实例作为守护进程集来提供可观察性、流量管理和控制。这种做法不是让每个 pod 中有一个 Envoy 容器作为 sidecar，而是每个节点有一个 Envoy 容器。这提供了性能优势，因为它有更好的资源效率和成本效益。&lt;/p&gt;
&lt;p&gt;这种可视性也可以轻松地扩展到集群之外的工作负载上。&lt;/p&gt;
&lt;h3&gt;实现控制&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;实现控制&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%ae%9e%e7%8e%b0%e6%8e%a7%e5%88%b6&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;多年来，Calico 都以其在实施控制方面的能力而闻名。现在，我们已经将这些功能扩展到了全栈，从网络层一直到应用层。可以使用服务网格获得应用程序层的控制能力，但可以将这些能力与你可能希望在网络或传输层实现的能力相结合。可以通过将已定义的策略分配给有顺序执行能力的层来实现这些策略，并且这些层中的每一层都可以绑定到基于角色的访问控制（RBAC）。&lt;/p&gt;
&lt;p&gt;例如，如果你想让一个安全团队管理可能面向 PCI 合规性的某些层，或者监视出口流量并将其与已知的攻击源进行比较，你可以很容易地做到这一点。更重要的是，您可以将这些策略落实到位，而不会干扰你的应用程序和开发团队为东西向流量和服务间通信（服务网格通常会处理这些通信）所做的工作。&lt;/p&gt;
&lt;p&gt;Calico 还提供了一些与出口访问控制相关的强大功能。这些功能使你可以轻松地与防火墙或其他类型的控件集成，你可能希望了解出口流量的来源，并围绕此实现某些控件。如果你使用的是 SIEM 或其他日志管理系统或监视工具，那么这对识别出口流量的来源非常有帮助，这样你就可以看到集群外部出口流量来自的特定应用程序或命名空间。&lt;/p&gt;
&lt;p&gt;Kubernetes 本身带来了很多挑战，通过启动和运行 Kubernetes，安全团队会非常忙碌。Calico 能够解决一些最流行的服务网格使用场景，而无需引入额外的控制平面。这使得操作上更容易处理，尤其是当您的团队资源有限时。&lt;/p&gt;
&lt;h2&gt;总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;那么。。。我们真的需要服务网格吗？在我看来，如果安全性和可观察性是你的主要驱动因素，那么答案是否定的。Calico 不仅在应用程序层，而且在全栈中提供了细粒度的可观察性和安全性，同时避免了部署服务网格时经常出现的操作复杂性和开销。&lt;/p&gt;
&lt;h2&gt;引用链接&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;引用链接&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%bc%95%e7%94%a8%e9%93%be%e6%8e%a5&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>云原生架构中 Kubernetes 可观测性的挑战和解决思路</title>
      <link>https://www.helight.info/blog/2021/kubernetes-observability/</link>
      <pubDate>Sat, 27 Nov 2021 21:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2021/kubernetes-observability/</guid>
      <description>
        
        
        &lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;本文是一篇翻译的文章，主要是学习，&lt;a href=&#34;https://www.tigera.io/blog/kubernetes-observability-challenges-in-cloud-native-architecture/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;原文地址在这里&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;这篇文章是 Calico 公司的员工写的，思路非常好。可观测性即代码，非常 k8s 范。在我们实际应用中，目前 k8s 的观测性确实是一个非常大的问题，就目前我在做的平台中，我就对这个问题很头大，虽然业界也有可观测性方案，但是 opentelemetry 目前较为成熟的只是 trace，log 还不够成熟，metrics 目前还是 Prometheus 比较成熟。所以目前大多数的业界平台都是混着用。虽然 opentelemetry 声称是要统一这三者，但是从实际技术角度和目前发展情况来看，还需要时日才能成熟。&lt;/p&gt;
&lt;p&gt;所以这篇文章从目前 Kubernetes 中可观测性的挑战做了分析，在这方面提出了一个解决思路，并且做了落地实践。我认为目前这个思路是大方向，但是目前的实现情况还是比较初步，还需要 k8s 在这方面能力上持续发展。或许未来是可以直接和 opentelemetry 的方案直接对接。&lt;/p&gt;
&lt;h2&gt;正文&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;正文&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%ad%a3%e6%96%87&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Kubernetes 已经是对工作负载和微服务进行容器编排的实时标准平台，目前 Kubernetes 已经在云原生应用广泛落地。 Kubernetes 的工作负载是高度动态变化的，并且部署在分布式和敏捷的基础架构上的。虽然 Kubernetes 管理云原生应用的好处非常多了，但是 Kubernetes 在云本地应用程序中遇到了一些新的可观测性问题挑战。这篇文章就是想讨论一下目前遇到的这些挑战。&lt;/p&gt;
&lt;h2&gt;可观测性挑战&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;可观测性挑战&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7%e6%8c%91%e6%88%98&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;先看看我们会遇到哪些挑战：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;数据孤立&lt;/strong&gt; - 传统的监控工具专门收集应用程序和基础架构级别的指标。考虑到云本机应用程序的高度动态、分布式和短暂性，这种度量收集方式会在仓库中创建数据，这些数据需要在服务上下文中缝合在一起，以便使 DevOps 和 SRE 能够调试服务问题（例如，响应时间慢、停机等）。此外，如果 DevOps 工程师或者服务所有者添加了新的观测指标，数据孤立仓库可能会导致交叉引用中断和数据误解，从而导致数据错位、通信速度减慢和分析错误。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据卷和细粒度组件&lt;/strong&gt; - Kubernetes 的部署有多个组件构成，比如 Pod，容器和微服务，他们都运行在分布式的基础设施上。由每个层面产生的海量的各种粒度的数据，如告警，日志和跟踪信息，这些数据随着服务扩展而增加。数据越多就越难梳理出模式和调试问题。随着数据增长，观察和故障排除会变得更加困难。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes 抽象&lt;/strong&gt; - Kubernetes 抽象让大家难以理解在动态，短时和分布式的基础设施底层发生的事情。要解开这些抽象的概念就像一层层剥开洋葱（在容器，node节点，网络，进程级别，有时甚至要深入到套接字和网络数据包级别），通过逐层分析才能理解这些底层的问题。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;鉴于Kubernetes微服务部署的复杂性和生成的大量数据，在 Kubernetes 中定位处理一个应用程序的问题是比较困难的。需要一种不同的方法来解决 Kubernetes 可观测性挑战。&lt;/p&gt;
&lt;h2&gt;Kubernetes 可观测性的另一种解决方式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;kubernetes-可观测性的另一种解决方式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#kubernetes-%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7%e7%9a%84%e5%8f%a6%e4%b8%80%e7%a7%8d%e8%a7%a3%e5%86%b3%e6%96%b9%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Kubernetes 的声明性方式使得正确地进行可观察性非常简单。DevOps，SRE 或者服务拥有者可以声明一种高级语言来构建他们想要的安全和观察系统，并且 Kubernetes 能负责这些构建的实现。可观测性可以被当作一种代码，以便它作为应用程序的一个组成部分连接到应用程序中，然后随应用程序一起部署，以便它可以在任何云、基础设施、网络或应用程序上运行。可观察性可以进一步改进，因为代码可以集成到 CI/CD 链中。这允许开发人员和软件工程师以适当的可观察性级别构建他们的应用程序，以确保应用程序按预期工作。&lt;/p&gt;
&lt;p&gt;为了进一步理解这一点，让我们看一个简单的示例，它展示了在 Kubernetes 环境中可观测性作为代码是怎么在的云原生应用程序中工作的。&lt;/p&gt;
&lt;p&gt;Online Boutique（以前称为 Hipster Shop）是来自谷歌云的 11 个微服务组成的演示应用程序。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2021/kubernetes-observability/imgs/Online-Boutique-microservices-architecture.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Online Boutique 的微服务架构&lt;/p&gt;
&lt;p&gt;其中一个微服务是 ProductCatalogService，其目的是显示最新的分类（分类会随着可买新产品和现有产品库存的变化而变化）。在 Online Boutique 应用部署后，我们将监控相关的微服务（包括 ProductCatalogService）的故障、超时和性能缓慢。&lt;/p&gt;
&lt;p&gt;使用传统的监控和故障排除方法，开发人员、DevOps 和 SRE 在各自的数据仓库中工作，分别为 ProductCatalogService 捕获数据，然后通过构建内部脚本或利用第三方软件将各自的数据相互关联。开始的时候，在数据量较低的情况下，这是可能的，但这种方法不会随着业务的增长而扩展（因为有更大的产品分类和/或业务逻辑来让更多的客户访问购买）。&lt;/p&gt;
&lt;p&gt;由于应用程序使用 Kubernetes 作为分布式、动态和短时作业的基础设施来运行 ProductCatalogService，Kubernetes 的抽象将使节点、容器、网络、进程和网络数据包级别的数据上下文分析变得困难。所有这些挑战加在一起将导致更长的故障排除时间，并在应用程序崩溃或性能降低时让大家只能瞎猜。&lt;/p&gt;
&lt;p&gt;DevOps 或 SRE 可以采用另一种方法：可观察性即代码，利用 Kubernetes 原生的抽象及其声明性模型来正确观察 ProductCatalogService。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;apiVersion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;projectcalico.org/v3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;PacketCapture&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;metadata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;productcatalogservice-pcap&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;namespace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;onlineboutique&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;spec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;selector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;app == &amp;#34;productcatalogservice&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;destination&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;                &lt;/span&gt;- &lt;span class=&#34;m&#34;&gt;80&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;protocol&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;TCP&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;以上是可观察性即代码的示例。在名称空间 “onlineboutique” 中创建作业 “packetcapture-pcap”，在该名称空间空间中用 “app == productcatalogservice” 为标签选择并过滤 Kubernetes 上运行的工作负载，并在 80 端口上捕捉 TCP 协议数据包。由于 Packetcapture 是 Online Boutique 中 ProductCatalogService 的一部分，并且收集了所有相关元数据，因此消除了数据孤岛和数据粒度问题。这种方法有以下的好处：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;由于应用程序和相关的微服务由 Kubernetes 部署在分布式基础设施上，代码中的标签和作业确保所有相关上下文都在所有团队成员的手上。这使得对流量有效载荷的过滤和后续分析变得很容易。&lt;/li&gt;
&lt;li&gt;此示例可由不同的团队成员用于其他服务或在不同端口捕获数据包，或用于不同的协议。&lt;/li&gt;
&lt;li&gt;与开发团队维护单元测试以确保构建时代码质量的方式相同，可以维护的可观察性代码（如本例中的代码），以确保各种参与者（DevOps、SRE 等）可以轻松地在运行时对应用程序进行故障排除。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如本例所示，数据孤岛、数据量和粒度组件以及 Kubernetes 抽象所带来的可观测性挑战，可以通过使用可观测性即代码的方式来解决，该方法利用 Kubernetes 的声明性。如果你的应用程序遇到性能、故障或超时问题，这种方式可以更快的排除故障和缩短解决时间。&lt;/p&gt;
&lt;h2&gt;总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;以上是所有的译文，这个做法初步看是可以的，对服务监控的时候可以使用 k8s 的能力直接捕捉端口数据包信息，但是很多的业务信息，处理逻辑产生的日志是无法通过这种方式获取到的，这种方式的前提还是网络通信捕获。但是实际上很多的异常是逻辑异常，是算法异常，这种问题的定位只能是日志来记录。&lt;/p&gt;
&lt;p&gt;但是整个思路并不是没有意义，我认为意义还是非常大的。&lt;strong&gt;监控能力可以说是一种基础设施或者基础能力，尤其最初的数据采集和集中，就应该是由基础设施种来做，而且这个思路种还以 k8s 能力作为落地，直接使用 yaml 配置启动。可以说这种方式非常 k8s 化，是非常巧妙的方式。&lt;/strong&gt; 但是数据收集只是一部分，接下来的处理可扩展如何可以更好的代码化配置这个例子中没有介绍。&lt;strong&gt;在实际的监控，分析这部更为重要，我认为未来这部分应该也是可以直接代码化配置。&lt;/strong&gt; 我相信未来估计逐步会有这类能力的实现的。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>必须知道的 Kubernetes 设计模式 Top 10</title>
      <link>https://www.helight.info/blog/2021/kubernetes-design-patterns/</link>
      <pubDate>Sat, 27 Nov 2021 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2021/kubernetes-design-patterns/</guid>
      <description>
        
        
        &lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;本文是一篇翻译的文章，主要是学习，&lt;a href=&#34;https://developers.redhat.com/blog/2020/05/11/top-10-must-know-kubernetes-design-patterns&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;原文地址在这里&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;这篇文章是对 redhat 写的一本书的概述，提炼了很多核心概念。&lt;/p&gt;
&lt;p&gt;这篇文章中介绍了和传统《设计模式》类似的云原生时代的设计模式，《设计模式》在软件开发中意义重大，现在多少软件研发都受到它的影响，而且我之前也在公司内开了这门课程，自己学习的同时，也是想让我们的开发者开发软件更有软件设计思维。&lt;/p&gt;
&lt;p&gt;而今这本书的出现是针对目前云原生时代的设计模式，之前的设计模式更多的是对单个模块或是简单系统的，但是云原生时代的开发方式和理念与之前的主机开发模式还是有大的不同的。所以现在开发者在学习了《设计模式》的基础上，还应该学习这些&lt;strong&gt;云上设计模式&lt;/strong&gt;。&lt;/p&gt;
&lt;h2&gt;正文&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;正文&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%ad%a3%e6%96%87&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这篇文章介绍了 Kubernetes 初学者必须知道的 Kubernetes 设计模式 Top 10，是从 &lt;a href=&#34;https://developers.redhat.com/books/kubernetes-patterns&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;the Kubernetes Patterns book&lt;/a&gt; 这本书中梳理总结出来的（大家如果无法下载这本书，可以联系我，我发给大家）。通过学习这些设计模式可以帮助大家能更好的理解 Kubernetes 基础概念，这些概念的理解可以帮助大家更好的设计基于 Kubernetes 的应用程序。&lt;/p&gt;
&lt;p&gt;在 Kubernetes 中有很多重要的概念，但是下面图中的这些是概念是大家使用 Kubernetes 时最重要的：&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2021/kubernetes-design-patterns/imgs/top_10_kubernetes_patterns.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
Top 10 Kubernetes Design Patterns&lt;/p&gt;
&lt;p&gt;为了帮助大家更好的理解，我们对这些设计模式进行了分类，这也是受《设计模式》的启发的。&lt;/p&gt;
&lt;h2&gt;Foundational patterns：基本模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;foundational-patterns基本模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#foundational-patterns%e5%9f%ba%e6%9c%ac%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这些设计模式也是云原生容器化应用开发的最佳实践和原则。不管你的应用程序的性质如何，你都应遵循这些指导规则。遵循这些原则将有助于确保你的应用程序适用于 Kubernetes 上的自动化。&lt;/p&gt;
&lt;h3&gt;Health Probe pattern：健康探测模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;health-probe-pattern健康探测模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#health-probe-pattern%e5%81%a5%e5%ba%b7%e6%8e%a2%e6%b5%8b%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;**健康探测指定了每个容器都应用实现一个特定的 API，以帮助平台可以最可行健康的方式观测和管理应用程序。**为了完全自动化，一个云原生应用程序必须是可以高度可观测的，并且可以以此推断其状态，并且让 Kubernetes 可以检测出应用程序是否已经启动并且已经可以准备好对外服务了。这些检测行为会影响 Pod 的生命周期管理，并且会决定流量是否会被路由到应用程序。&lt;/p&gt;
&lt;h3&gt;Predictable Demands pattern：可预测需求模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;predictable-demands-pattern可预测需求模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#predictable-demands-pattern%e5%8f%af%e9%a2%84%e6%b5%8b%e9%9c%80%e6%b1%82%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;**可预测的需求解决了为什么每个容器都应该声明其资源配置文件，并仅限于指定的资源需求。**在共享云环境中成功部署应用程序、管理和共存的基础依赖于识别和声明应用程序的资源需求和运行时依赖性。不管这些应用程序是有硬件运行依赖或者资源需求，这个模式描述了你应该如何声明应用程序的需求。声明应用程序的需求是让 Kubernetes 在集群中找到合适的地方部署的基础条件。&lt;/p&gt;
&lt;h3&gt;Automated Placement patterns：自动布置模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;automated-placement-patterns自动布置模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#automated-placement-patterns%e8%87%aa%e5%8a%a8%e5%b8%83%e7%bd%ae%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;**自动布置解决的是在集群中多个节点中如何影响 workload 的分布。**布置能力是 Kubernetes 调度器的核心功能：在满足容器资源需求和遵循调度策略的前提下给 Pod 分配合适的节点。这个模式描述了 Kubernetes 的调度算法的原则和在外部影响布置决策的方法。&lt;/p&gt;
&lt;h2&gt;Structural patterns：结构模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;structural-patterns结构模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#structural-patterns%e7%bb%93%e6%9e%84%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;有了好的云原生容器是第一步，但还不够。重用容器和组合容器到 Pod 中，并且达到我们期望的结果是下一步。这个分类中的模式会聚焦在结构和把容器组织安排到 Pod 中，并且满足不同的应用场景。在 Pod 中容器间的相互作用导致产生了这些模式。&lt;/p&gt;
&lt;h3&gt;Init Container pattern：初始化容器模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;init-container-pattern初始化容器模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#init-container-pattern%e5%88%9d%e5%a7%8b%e5%8c%96%e5%ae%b9%e5%99%a8%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;**Init Container 引入了一个独立生命周期的的初始化相关的任务相关和主应用程序容器。**Init Container 提供一个和主应用程序容器独立的初始化相关任务，这个任务的生命周期管理也是独立的，通过这种方式实现了不同阶段的事物分离。这种模式引入了一个基础的 Kubernetes 概念，这种概念也使用在很多其它需求初始化逻辑的设计模式中。&lt;/p&gt;
&lt;h3&gt;Sidecar patterns：边车模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;sidecar-patterns边车模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#sidecar-patterns%e8%be%b9%e8%bd%a6%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;**Sidecar 描述了在不改变已经存在容器的情况下，如何扩展和加强功能。**这个模式是基本模式之一，它可以让单一功能的容器放在一起配合起来提供服务。&lt;/p&gt;
&lt;h2&gt;Behavioral patterns：行为模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;behavioral-patterns行为模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#behavioral-patterns%e8%a1%8c%e4%b8%ba%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这些模式描述了由管理平台保障的 Pod 生命周期。根据不同类型的工作负载（workload），一个 Pod 会运行的他的任务完成，比如说一个批处理任务、或者是一个周期性调度执行的任务。或者它有可能是一个守护服务或者单例服务的形式运行。在最开始选择正确的 Pod 生命周期管理方式会有助于保证 Pod 按照你期望的方式运行并解决问题。&lt;/p&gt;
&lt;h3&gt;Batch Job patterns：批处理任务模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;batch-job-patterns批处理任务模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#batch-job-patterns%e6%89%b9%e5%a4%84%e7%90%86%e4%bb%bb%e5%8a%a1%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;**批处理模式描述了如何去运行一个独立，原子的任务，直到这个任务结束。**这种模式适合管理在分布式环境下独立、原子的任务。&lt;/p&gt;
&lt;h3&gt;Stateful Service patterns：有状态服务模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;stateful-service-patterns有状态服务模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#stateful-service-patterns%e6%9c%89%e7%8a%b6%e6%80%81%e6%9c%8d%e5%8a%a1%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;**有状态服务模式描述了如何使用 Kubernetes 来创建和管理分布式的有状态应用。**这种应用需要一些状态服务的特性需求，比如持久化的标识，网络，存储等。&lt;code&gt;StatefulSet&lt;/code&gt; 的出现为这些需求提供了强大的保证，是有状态应用程序管理的理想选择。&lt;/p&gt;
&lt;h3&gt;Service Discovery pattern：服务发现模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;service-discovery-pattern服务发现模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#service-discovery-pattern%e6%9c%8d%e5%8a%a1%e5%8f%91%e7%8e%b0%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;**服务发现模式描述了客户端如何能访问和发现哪那些提供应用服务的实例。**为了达成这个目的，Kubernetes 提供了多种机制，可以根据服务的消费者和提供者是在集群内还是在集群外而选择不同的机制。&lt;/p&gt;
&lt;h2&gt;Higher-level patterns：高级模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;higher-level-patterns高级模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#higher-level-patterns%e9%ab%98%e7%ba%a7%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这个分类中的模式是更为复杂的，并且代表了高级应用管理模式。这里的一些模式（比如控制器模式）是通用的，甚至Kubernetes 本身就是构建在他们之上的。&lt;/p&gt;
&lt;h3&gt;Controller pattern：控制器模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;controller-pattern控制器模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#controller-pattern%e6%8e%a7%e5%88%b6%e5%99%a8%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;**控制器模式是常活的监视器并在管理一组 Kubernetes 资源，让这些资源处在被期望的一个状态中。**Kubernetes 的核心就是由一系列的控制器组成，并且他们会例行的监控和调整当前应用的状态到申明的目标状态。这个模式描述的是我们如何使用这种理念来为我们自己的应用来扩展平台能力。&lt;/p&gt;
&lt;h3&gt;Operator pattern：Operator 模式&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;operator-patternoperator-模式&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#operator-patternoperator-%e6%a8%a1%e5%bc%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;**一个 Operator 就是一个控制器，并且这个控制器使用了用户自定义资源（CustomResourceDefinitions）将特定应用程序的操作知识封装在算法和自动化的方式中。**Operator 模式允许我们可以有更灵活和更强表示的能力来扩展控制器模式。目前 Kubernetes 的 Operator 越来越多，这种模式已经装变成操作复杂分布式系统的主要方式。&lt;/p&gt;
&lt;h2&gt;总结&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;总结&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e6%80%bb%e7%bb%93&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;如今，Kubernetes 是最流行的容器编排平台。它由所有主要的软件公司共同开发和支持，并由所有主要的云提供商作为服务提供。Kubernetes 支持 Linux 和 Windows 操作系统，还有所有的主流编程语言。这个平台可以编排和自动管理无状态和有状态服务，批处理任务，周期性任务和 serverless 工作负载。这里描述的模式是 Kubernetes 提供的一系列更广泛的模式中最常用的模式，如下所示。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/blog/2021/kubernetes-design-patterns/imgs/KubernetePatternsLevels-SingleColor-Copy-of-Full-1024x660.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
划分到不同分类中的 Kubernetes 模式&lt;/p&gt;
&lt;p&gt;**Kubernetes 是新的应用程序可移植性层，是对应用的一种高级抽象，也是云上所有应用的共同特征。**如果你是一个软件开发者或者架构师，Kubernetes 很有可能以这样或那样的方式成为你生活的一部分。学习这里讲述的这些 Kubernetes 模式会让你对这个平台的想法有所改变。我相信 Kubernetes 和这些从它上面发展出的这些概念会变成和面向对象编程概念一样的基本概念。&lt;/p&gt;
&lt;p&gt;这里介绍的这些模式尝试组织成为容器和云时代的《设计模式》。阅读这篇文章只是一个开头，更多的由于 Kubernetes 出现而出现的新的云原生软件开发方式还在等着大家去学习。&lt;/p&gt;
&lt;h2&gt;后记&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;后记&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%90%8e%e8%ae%b0&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;梳理翻译之后还是学到不少内容，至少对我之前知道的一些概念理解更加深刻了，国外一些软件论述更喜欢从理论和模式框架出发，我虽然是一个重实践的工程师，但是还是想从理论上能多了解一些，做到知行合一不容易的。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
    <item>
      <title>使用 eBPF 和 XDP 高速处理数据包</title>
      <link>https://www.helight.info/blog/2021/ebpf-and-xdp/</link>
      <pubDate>Sat, 20 Nov 2021 08:45:20 +0800</pubDate>
      
      <guid>https://www.helight.info/blog/2021/ebpf-and-xdp/</guid>
      <description>
        
        
        &lt;h2&gt;前言&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;前言&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e5%89%8d%e8%a8%80&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;本文是一篇学习翻译文章，&lt;a href=&#34;https://sematext.com/blog/ebpf-and-xdp-for-processing-packets-at-bare-metal-speed/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;原文在这里&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;XDP 是一种特殊的 eBPF 程序，在数据包处理上因为在协议栈之前就可以处理数据，所以有非常高的性能。&lt;/p&gt;
&lt;p&gt;这篇文章先在原理上对 XDP 进行了介绍，并由 2 个简单的例子来对使用场景进行说明。另外还介绍了作者所在公司的一个开源项目：https://github.com/sematext/oxdpus。里面有几个 XDP 的应用程序，有相关的应用空间程序和内核相关的代码。用户空间命令工具是 golang 写的，并且 eBPF 的操作是使用 gobpf ，对于学习了解 XDP 有帮助，命令基本可以直接使用。&lt;/p&gt;
&lt;h2&gt;XDP 介绍&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;xdp-介绍&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#xdp-%e4%bb%8b%e7%bb%8d&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;XDP 或 Express Data Path 的兴起是因为 Linux 内核需要一个高性能的包处理能力。很多绕过内核的技术（DPDK是最突出的一个）目标都是通过把包处理迁移到用户空间来加速网络操作。&lt;/p&gt;
&lt;p&gt;这就意味着要消除内核-用户空间边界之间的上下文切换、系统调用转换或 IRQ 请求所引起的开销。操作系统将网络堆栈的控制权交给用户空间进程，这些进程通过自己的驱动程序直接与 NIC 交互。&lt;/p&gt;
&lt;p&gt;虽然这种做法的带来了明显的高性能，但是它也带来了一系列的缺陷，包括在用户空间要重新实现 TCP/IP 协议栈以及其它网络功能，或者是放弃了内核中强大的资源抽象管理和安全管理。&lt;/p&gt;
&lt;p&gt;XDP 的目的是在内核中也达到可编程的包处理，并且仍然保留基础的网络协议栈模块。实际上，XDP 代表了 eBPF 指令的自然扩展能力。它使用 maps，可管理的帮助函数，沙箱字节运行器来做到可编程，这些字节码会被检测安全之后才会加载到内核中运行。&lt;/p&gt;
&lt;p&gt;XDP 高速处理路径的关键点在于这些编程字节码被夹在到网络协议栈最早期的可能处理点上，就在网络包接受队列（RX）之后。在网络协议栈的这一阶段中，还没有构建网络包的任何内核属性，所以非常有利于提升网络处理速度。&lt;/p&gt;
&lt;p&gt;如果你没有看过我之前关于 eBPF 基础的博文，我建议你首先应该读一下，这篇我也翻译了：&lt;a href=&#34;http://www.helight.cn/blog/2020/linux-kernel-observability-ebpf/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;基于 eBPF 的 Linux 可观测性&lt;/a&gt;。为了强调 XDP 在网络协议栈中的位置，让我们来一起看看一个 TCP 包的生命过程，从它到达 NIC 知道它发送到用户空间的目的 socket。始终要记住这是一个高级别的视图。我们将只触及这个复杂的核心网络堆栈的表面层。&lt;/p&gt;
&lt;h2&gt;通过网络协议栈的入包&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;通过网络协议栈的入包&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e9%80%9a%e8%bf%87%e7%bd%91%e7%bb%9c%e5%8d%8f%e8%ae%ae%e6%a0%88%e7%9a%84%e5%85%a5%e5%8c%85&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;网卡在收到一帧（所有校验和正常检查）时，网卡就会使用 DMA 来转发数据包到对于的内存区域。这意味着数据包是由驱动做了映射后直接从网卡队列拷贝到主内存区。当环形接受队列有数据进入的时候，网卡会产生一个硬中断，并且 CPU 会把处理事件下发到中断向量表中，执行驱动代码。&lt;/p&gt;
&lt;p&gt;因为驱动的执行路径必须非常短快，具体数据处理可以延迟到驱动中断上下文之外，使用软中断来触发处理（NET_RX_SOFTIRQ）。在中断处理的时候中断请求是被屏蔽的，内核更愿意把这种长时间处理的任务放在中断上下文之外，以避免在中断处理的时候丢失中断事件。设备驱动开始使用 NAPI 循环和一个 CPU 一个内核线程（ksoftirqd）来从环形缓冲区中消费数据包。NAPI 循环的责任主要就是触发软中断（NET_RX_SOFTIRQ），由软中断处理程序处理数据包并且发送数据到网络协议栈。&lt;/p&gt;
&lt;p&gt;设备驱动申请一个新的 socket 缓冲区（sk_buff）来存放入流量包。socket 缓冲区是内核中对数据包缓冲/处理抽象出来的一个最基础的数据结构。在整个网络协议栈中的上层中都在使用。&lt;/p&gt;
&lt;p&gt;socket 缓冲区的结构体由多个字段，来标识不同的网络层。从 CPU 队列上消费缓冲数据后，内核会填充这些元数据，复制 sk_buff 并且把它推到上游的网络层的自队列中做进一步处理。这是 IP 协议层在堆栈中注册的位置。IP 层执行一些基本的完整型检测，并且把包发送给 netfilter 的钩子函数。如果包没有被 netfilter 丢弃，IP 层会检测高级协议，并且为之前提取的协议把处理交给响应的处理函数。&lt;/p&gt;
&lt;p&gt;数据最终被拷贝到 socket 关联的用户空间缓冲区。进程通过阻塞系统调用（recv、read）函数或通过某种轮询机制（epoll）主动接收数据。&lt;/p&gt;
&lt;p&gt;在网卡把数据包拷贝到接受队列之后就触发了 XDP 的钩子函数，在这一点上我们可以高效的阻止申请各种各样的元数据结构，包括 sk_buffer。如果我们看一下非常简单的可能使用场景，比如在高流量网络中的包过滤或者阻止 DDos 攻击，传统的网络防火墙方案（iptables）由于网络堆栈中的每个阶段都会引入大量的工作负载，这将不可避免地给机器造成压力。&lt;/p&gt;
&lt;p&gt;在裸机速度下的 eBPF 和 XDP 包处理流程&lt;/p&gt;
&lt;p&gt;在网络协议栈中的 XDP 的钩子
&lt;img src=&#34;blog/2021/eBPF-and-XDP/imgs/1.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;具体上来看在软中断任务中调度顺序执行的 iptables 规则，会在 IP 协议层中去匹配指定的 IP 地址，以决定是否丢弃这个数据包。和 iptables 不一样的是 XDP 会直接操作一个从 DMA 后端环形缓冲区中拿的原始的以太帧包，所以丢弃逻辑可以很早的执行，这样就节省了内核时间，避免了会导致协议栈执行导致的延时。&lt;/p&gt;
&lt;h2&gt;XDP 组成&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;xdp-组成&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#xdp-%e7%bb%84%e6%88%90&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;正如你已经知道的，eBPF 的字节码可以挂载在各种策略执行点上，比如内核函数，socket，tracepoint，cgroup 层级或者用户空间符号。这样的话，每个 eBPF 程序操作特定的上下文- kprobes 场景下的 CPU 寄存器状态，socket 程序的 socket 缓冲区等等。用 XDP 的说法，生成的 eBPF 字节码的主干是围绕 XDP 元数据上下文建模的（xdp_md）。XDP 上下文包含了所有需要在原始形式下访问数据包的信息。&lt;/p&gt;
&lt;p&gt;为了更好地理解 XDP 程序的关键模块，让我们剖析以下章节：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;linux/bpf.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#define SEC(NAME) __attribute__((section(NAME), used))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;SEC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;prog&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;xdp_drop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xdp_md&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XDP_DROP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;__license&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SEC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;license&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;GPL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;这个小 XDP 程序一旦加载到网卡上就会丢弃所有数据包。我们引入了 &lt;strong&gt;bpf&lt;/strong&gt; 头文件，它里面包含了数据结构定义，包括 xdp_md 结构体。接下来，声明了 &lt;strong&gt;SEC&lt;/strong&gt; 宏来存放 map，函数，许可证元信息和其它 ELF 段中的元素（可以被 eBPF 加载器解析）。&lt;/p&gt;
&lt;p&gt;现在来看我们 XDP 程序中处理数据包逻辑最相关的部分。XDP 做了预定义的一组判定可以决定内核处理数据包流。例如，我们可以让数据包通过，从而发送到常规的网络协议栈中，或者丢弃它，或者重定向数据包到其它的网卡等。在我们的例子中，XDP_DROP 是说超快速的丢弃数据包。同时注意，我们声明了是在 prog 段中加载执行，eBPF 加载会检测加载（如果段名称没有找到会加载失败，但是我们可以根据 IP 来使用非标准段名称 ）。下面我们来编译试运行一下上面的代码。&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ clang -Wall -target bpf -c xdp-drop.c -o xdp-drop.o&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们可以使用不同的用户空间工具把二进制目标代码加载到内核中（iproute2 的部分工具就可以），tc 或者 ip 是是常用的。XDP支持虚拟网卡，所以要直接看出上面程序的作用，我们可以把代码加载到一个已经存在的容器网卡上。我们会启动一个 nginx 容器，并且在加载 XDP 程序之前和之后分别启动一组 curl 请求。之前的 curl 请求会返回一个成功的 HTTP 状态码：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ curl --write-out &lt;span class=&#34;s1&#34;&gt;&amp;#39;%{http_code}&amp;#39;&lt;/span&gt; -s --output /dev/null 172.17.0.4:80
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;m&#34;&gt;200&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;加载 XDP 字节码可以使用下面的命令：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ sudo ip link &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; dev veth74062a2 xdp obj xdp-drop.o&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们会看到虚拟网卡上有 xdp 被激活的标识：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;veth74062a2@if16: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu &lt;span class=&#34;m&#34;&gt;1500&lt;/span&gt; xdp/id:37 qdisc noqueue master docker0 state UP group default
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;link/ether 0a:5e:36:21:9e:63 brd ff:ff:ff:ff:ff:ff link-netnsid &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;inet6 fe80::85e:36ff:fe21:9e63/64 scope link
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;valid_lft forever preferred_lft forever&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;curl 请求将会被阻塞一段时间直到返回如下的错误信息，这就说明 XDP 代码生效了，也是我们预期的效果：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl: &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;7&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; Failed to connect to 172.17.0.4 port 80: No route to host&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;我们在测试完整之后，可以使用下面的命令卸载 XDP 程序：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$ sudo ip link &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; dev veth74062a2 xdp off&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;使用 GO 编写 XDP 程序&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;使用-go-编写-xdp-程序&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e4%bd%bf%e7%94%a8-go-%e7%bc%96%e5%86%99-xdp-%e7%a8%8b%e5%ba%8f&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;上面的代码片段演示了一些基本的概念，但是为了充分利用 XDP 的强大功能，我们将使用 Go 语言来制作稍微复杂点的软件 - 围绕某种规范用例构建的小工具:针对一些指定的黑名单 IP 地址进行包丢弃。完整的代码以及如何构建这个工具的文档说明在&lt;a href=&#34;https://github.com/sematext/oxdpus&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;这里&lt;/a&gt;。&lt;a href=&#34;http://www.helight.cn/blog/2020/linux-kernel-observability-ebpf/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;如上一篇博文所介绍&lt;/a&gt;，我们使用 gobpf 包，它提供了和 eBPF VM 交互的支持（加载程序到内核，访问/操作 eBPF map 以及其它功能）。大量的 eBPF 程序都可以直接由 C 编写，并且编译为 ELF 目标文件。但是可惜的是，基于 ELF 的 XDP 程序还不行。另外一种方法就是，通过 BCC 模块加载 XDP 程序仍然是可以的，但要是要依赖 libbcc。&lt;/p&gt;
&lt;p&gt;不管怎么处理，BCC maps 有一个非常重要的限制：不能把他们挂到 bpffs 上面（事实上，你可以从用户空间挂 maps，但是启动 BCC 模块的是，它就很容易忽略任何的挂载对象）。我们的工具需要侵入黑名单的 map，同时需要在 XDP 程序加载到网卡上之后仍然可以有能力从 map 中添加或者删除元素。&lt;/p&gt;
&lt;p&gt;我们就有足够的动力来考虑使用 ELF 目标文件支持 XDP 程序，所以我们给上游仓库提了这方面的 pr，并期望能合进去（目前这个 pr 已经被合并到 gobpf了）。我们认为这个功能对 XDP 程序的可移植性非常有价值，就像内核探测可以跨机器分布一样，即使它们不附带 clang、LLVM 和其他依赖项。&lt;/p&gt;
&lt;p&gt;不用多说了，让我们从下面 XDP 代码开始浏览最重要的&lt;a href=&#34;https://github.com/sematext/oxdpus/blob/master/pkg/xdp/prog/xdp.c&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;代码片段&lt;/a&gt;：&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;SEC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;xdp/xdp_ip_filter&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;xdp_ip_filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xdp_md&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;end&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data_end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ctx&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;u32&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ip_src&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;u64&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;u16&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eth_type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ethhdr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eth&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eth&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XDP_ABORTED&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;eth_type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eth&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h_proto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* handle VLAN tagged packet 处理 VLAN 标记的数据包*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eth_type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;htons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ETH_P_8021Q&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eth_type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;htons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ETH_P_8021AD&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;             &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vlan_hdr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vlan_hdr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;n&#34;&gt;vlan_hdr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eth&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vlan_hdr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eth&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;               &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;n&#34;&gt;eth_type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vlan_hdr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h_vlan_encapsulated_proto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* let&amp;#39;s only handle IPv4 addresses 只处理 IPv4 地址*/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eth_type&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ntohs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ETH_P_IPV6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XDP_PASS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iphdr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iph&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iphdr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;/* make sure the bytes you want to read are within the packet&amp;#39;s range before reading them 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    * 在读取之前，确保你要读取的子节在数据包的长度范围内
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iph&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XDP_ABORTED&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;ip_src&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;iph&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;saddr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;bpf_map_lookup_elem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;blacklist&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ip_src&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XDP_DROP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XDP_PASS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;复制代码&#34;
    aria-label=&#34;复制代码&#34;
    data-copied-label=&#34;已复制！&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;代码看起来是稍微有点多，但是可以先忽略代码中负责处理 VLAN 标签的数据包的代码。我们先从 XDP 元信息中访问包数据开始，并且把这个指针转换成 ethddr 的内核结构。你同时会注意到检测包边界的几个条件。如果你忽略了他们，检查器会拒绝加载 XDP 子节代码。这个强制规则保证了 XDP 代码在内核中的的正常运行，避免有无效指针或者违反安全策略的代码被加载到内核。剩下的代码从 IP 协议头中提取了源 IP 地址，并且检测是否在黑名单 map 中。如果从 map 中查找到了，就会丢弃这个包。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/sematext/oxdpus/blob/master/pkg/xdp/hook.go&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Hook&lt;/a&gt; 结构体是负责在网络协议栈中加载或者卸载 XDP 程序。它实例化并且从对象文件中加载 XDP 模块，最终调用 &lt;strong&gt;AttachXDP&lt;/strong&gt; 或者 &lt;strong&gt;RemoveXDP&lt;/strong&gt; 方法。&lt;/p&gt;
&lt;p&gt;IP 地址&lt;a href=&#34;https://github.com/sematext/oxdpus/blob/master/pkg/blacklist/map.go&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;黑名单&lt;/a&gt;是通过标准的 eBPF maps 来管理的。我们调用 &lt;strong&gt;UpdateElement&lt;/strong&gt; 和 &lt;strong&gt;DeleteElement&lt;/strong&gt; 来分别注册或者删除 IP 信息。黑名单管理者也包含了获取 map 中可用的 IP 地址列表的方法。&lt;/p&gt;
&lt;p&gt;其它的代码把所有的代码片段组合起来，以提供良好的 CLI 体验，用户可以利用这种体验执行 XDP 程序附加/删除和操作 IP 黑名单。要了解更多细节，&lt;a href=&#34;https://github.com/sematext/oxdpus&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;请看源码&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;结论&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;结论&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#%e7%bb%93%e8%ae%ba&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;此章节的永久链接&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;XDP 在 Linux 内核中慢慢以高速包处理标准出现。通过这篇博文，我介绍了组成数据包处理系统的基本构建模块。虽然网络协议栈是一个非常复杂的主题，由于 eBPF/XDP 的编程特性，创建 XDP 程序已经是相对比较轻松了。&lt;/p&gt;
&lt;center&gt;
看完本文有收获？请分享给更多人
&lt;p&gt;关注「黑光技术」，关注大数据+微服务&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.helight.info/images/qrcode_helight_tech.jpg&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/center&gt;
      </description>
    </item>
    
  </channel>
</rss>
