<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Work on chengzhycn&#39;s blog</title>
		<link>https://blog.jinzhi.site/categories/work/</link>
		<description>Recent content in Work on chengzhycn&#39;s blog</description>
		<generator>Hugo</generator>
		<language>en-us</language>
		
		
		
		
			<lastBuildDate>Sun, 12 Oct 2025 15:18:28 +0800</lastBuildDate>
		
			<atom:link href="https://blog.jinzhi.site/categories/work/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>APISIX balancer 支持 domain</title>
				<link>https://blog.jinzhi.site/posts/2025-10/apisix-balancer-%E6%94%AF%E6%8C%81-domain/</link>
				<pubDate>Sun, 12 Oct 2025 15:18:28 +0800</pubDate>
				<guid>https://blog.jinzhi.site/posts/2025-10/apisix-balancer-%E6%94%AF%E6%8C%81-domain/</guid>
				<description>&lt;p&gt;最近在做网关开发时遇到了一个场景：&lt;strong&gt;业务在做多实例部署时需要通过 Ingress 将服务注册给 APISIX，由于每个实例属于一个单独的 namespace，导致在 APISIX 和 Ingress 上出现流量覆盖的问题：&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Ingress 通过 Host 和 URI 匹配入向流量，同一个服务的 Host 和 URI 是完全一致的（Host 用 ip:port 表示），因此注册多个 Ingress 流量只会引流到一个实例上。&lt;/li&gt;&#xA;&lt;li&gt;APISIX 侧在 balance 阶段对于相同 ip:port 的 upstream node 会做去重，导致跨集群多实例时流量分配并不符合预期。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;举个例子，有 A，B 两个集群，A 集群部署了 2 个实例，B 集群部署了一个实例。预期这 3 个实例应该平均分配流量（假设采用 rr），A 集群和 B 集群流量比例应该是 2:1，但实际上 A 集群和 B 集群在 APISIX 分配时流量是 1:1，而在 A 集群内一个实例占据了全部流量。&lt;/p&gt;&#xA;&lt;p&gt;从业务上来说这个可以通过重新规划 namespace 和实例的关系来解决。同一个集群同一个服务的所有实例分布在同一个 namespace 中。这样注册的 Ingress 和 APISIX upstream node 就只会有一个。&lt;/p&gt;&#xA;&lt;p&gt;抛开这个点，我们来看看从网关的角度如何解决这两个问题。&lt;/p&gt;&#xA;&lt;p&gt;第一个问题比较好解决，每个注册的实例采用独立的 Domain，Ingress 通过 Host Header 来区分流量。在 APISIX 采用域名注册，域名解析到 Ingress 地址。如果域名没法解析（我们遇到的场景），也可以将 Domain 信息放到 node 的 metadata 内，写一个插件将其注入到 node.domain 内来完成。&lt;/p&gt;</description>
			</item>
			<item>
				<title>Wasm Internals - Overview</title>
				<link>https://blog.jinzhi.site/posts/2025-08/wasm-internals-overview/</link>
				<pubDate>Tue, 26 Aug 2025 12:29:03 +0800</pubDate>
				<guid>https://blog.jinzhi.site/posts/2025-08/wasm-internals-overview/</guid>
				<description>&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://rsms.me/wasm-intro&#34;&gt;https://rsms.me/wasm-intro&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://hacks.mozilla.org/2017/02/a-cartoon-intro-to-webassembly/&#34;&gt;https://hacks.mozilla.org/2017/02/a-cartoon-intro-to-webassembly/&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;wasm-的历史发展&#34;&gt;Wasm 的历史发展&lt;/h2&gt;&#xA;&lt;h3 id=&#34;早期wasm-mvp---2017&#34;&gt;早期（Wasm MVP - 2017）&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;诞生背景：&lt;/strong&gt; Wasm 的设计目标是为了替代 asm.js，提供更小、更快、更安全的 Web 二进制格式。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;核心模块的初步定义：&lt;/strong&gt; MVP（Minimum Viable Product）阶段定义了 Wasm Core Module 的基本结构：函数、内存、表、导入、导出、全局变量等。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;主要用例：&lt;/strong&gt; 游戏引擎、音视频编解码、计算密集型任务等。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;限制：&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;没有模块化系统：&lt;/strong&gt; 模块之间没有标准的链接机制，只能通过宿主环境（如 JavaScript）进行协调。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;缺乏垃圾回收（GC）：&lt;/strong&gt; 需要手动内存管理或使用语言自带的 GC 机制（如 Emscripten 的 mimalloc）。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;没有线程：&lt;/strong&gt; 无法直接利用多核 CPU。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;没有宿主 API 标准化：&lt;/strong&gt; 模块与宿主环境的交互方式高度依赖宿主（如浏览器），没有统一的接口定义。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;没有组件模型：&lt;/strong&gt; 模块重用和组合非常困难。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;中期mvp-之后---持续演进&#34;&gt;中期（MVP 之后 - 持续演进）&lt;/h3&gt;&#xA;&lt;p&gt;Wasm 社区和工作组认识到 MVP 的局限性，并开始着手扩展 Wasm 的能力，这直接影响了 Core Module 的能力：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;多值（Multiple Returns &amp;amp; Parameters）：&lt;/strong&gt; 允许函数返回多个值，接收多个参数，提高表达能力。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;引用类型（Reference Types）：&lt;/strong&gt; 引入了 &lt;code&gt;externref&lt;/code&gt; 和 &lt;code&gt;funcref&lt;/code&gt;，允许 Wasm 直接引用宿主对象和函数，而无需通过数字 ID 传递，为未来的 GC 和组件模型打下基础。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;固定大小的 SIMD（Fixed-width SIMD）：&lt;/strong&gt; 引入了新的指令集，允许在 Wasm 中进行向量化操作，进一步提升某些计算密集型任务的性能。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;线程（Threads）：&lt;/strong&gt; 引入了共享内存和原子操作，允许 Wasm 模块在多线程环境下运行，极大地提升了并行计算能力。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;内存增长和限制（Memory Growth and Limits）：&lt;/strong&gt; 提供了更灵活的内存管理机制。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Tail Calls（尾调用）：&lt;/strong&gt; 优化了函数调用的性能。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;近期和未来wasm-component-model&#34;&gt;近期和未来（Wasm Component Model）&lt;/h3&gt;&#xA;&lt;p&gt;这是 Wasm 发展中最重要的方向之一，旨在解决 Core Module 在模块化和互操作性方面的根本性问题：&lt;/p&gt;</description>
			</item>
			<item>
				<title>Spurious Retransmit 导致 NAT 设备响应 RST</title>
				<link>https://blog.jinzhi.site/posts/2025-06/spurious-retransmit-%E5%AF%BC%E8%87%B4-nat-%E8%AE%BE%E5%A4%87%E5%93%8D%E5%BA%94-rst/</link>
				<pubDate>Fri, 13 Jun 2025 09:57:28 +0800</pubDate>
				<guid>https://blog.jinzhi.site/posts/2025-06/spurious-retransmit-%E5%AF%BC%E8%87%B4-nat-%E8%AE%BE%E5%A4%87%E5%93%8D%E5%BA%94-rst/</guid>
				<description>&lt;p&gt;在一个线上问题排查过程中，出现了一个新的问题：wget 下载文件在连接建立很短的时间内（1 - 2s）就被 RESET 了。&#xA;首先先简要说明一下链路：&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.jinzhi.site/images/notes/spurious-retransmit-%E5%AF%BC%E8%87%B4-nat-%E8%AE%BE%E5%A4%87%E5%93%8D%E5%BA%94-rst/5035a324e7b30c51292018e81c2e41b6_MD5.jpeg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;客户端经过一个SNAT设备出公网，在服务器上下载一个大文件。端到端的 RTT 大约 90 ms。由于最开始并没有怀疑到 SNAT 设备，并且 server 端无法抓包，我们分别在客户端 和 SNAT 设备到 server 间一台网元设备上抓包。&#xA;&lt;img src=&#34;https://blog.jinzhi.site/images/notes/spurious-retransmit-%E5%AF%BC%E8%87%B4-nat-%E8%AE%BE%E5%A4%87%E5%93%8D%E5%BA%94-rst/adc7d13285d32bfc4c287a8d5afd1da1_MD5.jpeg&#34; alt=&#34;中间网元设备&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.jinzhi.site/images/notes/spurious-retransmit-%E5%AF%BC%E8%87%B4-nat-%E8%AE%BE%E5%A4%87%E5%93%8D%E5%BA%94-rst/a9850b914275bd0d8c5c53f1dfd3b2d4_MD5.jpeg&#34; alt=&#34;SNAT 设备&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;如上，中间网元设备显示客户端（端口 34567）先发送了 RST 报文，随后服务器（端口 443）响应 RST 报文。但是客户端抓包显示它根本没有发送过 RST 报文。&lt;/p&gt;&#xA;&lt;p&gt;此时，我们再从 SNAT 设备上抓包，发现就是 SNAT 设备首先给服务器发送了 RST 报文。&lt;/p&gt;&#xA;&lt;p&gt;这里的 SNAT 设备实际上是一台基于 IPtables 的 Linux 设备。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.jinzhi.site/images/notes/spurious-retransmit-%E5%AF%BC%E8%87%B4-nat-%E8%AE%BE%E5%A4%87%E5%93%8D%E5%BA%94-rst/bc892bf5d9ba1a52cb9c0ea3baf99b64_MD5.jpg&#34; alt=&#34;&#34;&gt;&#xA;抓包可以看到，RST 是对一个 TCP Spurious Retransmission 的响应。为什么会发出这个 RST 呢？正好网上有一个相似的场景：&lt;a href=&#34;https://github.com/moby/libnetwork/issues/1090&#34;&gt;Add workaround for spurious retransmits leading to connection resets&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.jinzhi.site/images/notes/spurious-retransmit-%E5%AF%BC%E8%87%B4-nat-%E8%AE%BE%E5%A4%87%E5%93%8D%E5%BA%94-rst/1f45fd40111f9e29fb5a47fd8e1baad0_MD5.jpeg&#34; alt=&#34;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;总的来说，就是 spurious retransmits 报文在序列号超出 TCP 窗口时，会被 conntrack 认为是 invalid 包，从而不再经过反向 SNAT 规则的处理。由于目的地址没有被转换，报文会按照原来的目的地址送往 INPUT，而本地又没有这个 socket，则响应一个 RST 报文。&lt;/p&gt;</description>
			</item>
			<item>
				<title>Dns Zone Files</title>
				<link>https://blog.jinzhi.site/posts/2021-01/dns-zone-files/</link>
				<pubDate>Sun, 03 Jan 2021 10:18:55 +0800</pubDate>
				<guid>https://blog.jinzhi.site/posts/2021-01/dns-zone-files/</guid>
				<description>&lt;h2 id=&#34;cname-记录&#34;&gt;CNAME 记录&lt;/h2&gt;&#xA;&lt;h3 id=&#34;记录格式&#34;&gt;记录格式&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;bar.example.com.&#x9;CNAME&#x9;foo.example.com.&#xA;foo.example.com.&#x9;A&#x9;&#x9;192.168.0.1&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&#34;cname-记录的限制&#34;&gt;CNAME 记录的限制&lt;/h3&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;如果一个 domain name 有了一个 CNAME 记录，那么它不能再拥有其它类型的记录&lt;/li&gt;&#xA;&lt;li&gt;CNAME 记录必须指向另外一个 domain name，而不是一个 IP&lt;/li&gt;&#xA;&lt;li&gt;CNAME 记录最好不要指向另外一个 CNAME 记录&lt;/li&gt;&#xA;&lt;li&gt;MX 和 NS 记录不能指向一个 CNAME 记录&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;srv-记录&#34;&gt;SRV 记录&lt;/h2&gt;&#xA;&lt;p&gt;type code：33&lt;/p&gt;&#xA;&lt;h3 id=&#34;记录格式-1&#34;&gt;记录格式&lt;/h3&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;_service._protocol.name. TTL class SRV priority weight port target.&#xA;&#xA;_sip._tcp.example.com. 86400 IN SRV 0 5 5060 sipserver.example.com.&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#xA;&lt;li&gt;_service: 服务名称 symbolic name&lt;/li&gt;&#xA;&lt;li&gt;protocol: 协议&lt;/li&gt;&#xA;&lt;li&gt;name: domain name，以 . 结束&lt;/li&gt;&#xA;&lt;li&gt;priority: 条目优先级, 值越低优先级越高&lt;/li&gt;&#xA;&lt;li&gt;weight: 同样优先级内不同条目的权重&lt;/li&gt;&#xA;&lt;li&gt;target: canonical hostname，以 . 结束&#xA;如果是一个 MX 记录，那么 target 需要是一个 IP 地址（A 或者 AAAA）而不是 CNAME&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;soa-记录&#34;&gt;SOA 记录&lt;/h2&gt;&#xA;&lt;p&gt;start of authority, 一个权威的起始&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
