<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>L7Gateway on chengzhycn&#39;s blog</title>
		<link>https://blog.jinzhi.site/tags/l7gateway/</link>
		<description>Recent content in L7Gateway on chengzhycn&#39;s blog</description>
		<generator>Hugo</generator>
		<language>en-us</language>
		
		
		
		
			<lastBuildDate>Tue, 28 Apr 2026 15:18:28 +0800</lastBuildDate>
		
			<atom:link href="https://blog.jinzhi.site/tags/l7gateway/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Envoy Go HTTP Filter</title>
				<link>https://blog.jinzhi.site/posts/2026-04/envoy-go-http-filter/</link>
				<pubDate>Tue, 28 Apr 2026 15:18:28 +0800</pubDate>
				<guid>https://blog.jinzhi.site/posts/2026-04/envoy-go-http-filter/</guid>
				<description>&lt;p&gt;Go HTTP 过滤器 (&lt;code&gt;envoy.filters.http.golang&lt;/code&gt;) 允许使用 Go 编写 Envoy HTTP 过滤器。Go 代码被编译为共享库 (&lt;code&gt;.so&lt;/code&gt;)，在运行时通过 &lt;code&gt;dlopen&lt;/code&gt; 加载，并借由 CGo bridge 集成到 Envoy 的 C++ 过滤器链中。&lt;/p&gt;&#xA;&lt;h2 id=&#34;架构&#34;&gt;架构&lt;/h2&gt;&#xA;&lt;p&gt;Go HTTP Filter 主要分为两端：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;C++ 端&lt;/strong&gt;：负责 DSO 加载、过滤器链集成以及线程安全。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Go 端&lt;/strong&gt;：通过 Go SDK 实现过滤器逻辑，通过 CGo 与 C++ 通信。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;ABI 边界由 &lt;code&gt;contrib/golang/common/go/api/api.h&lt;/code&gt; 中的共享 C 结构体定义。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.jinzhi.site/images/notes/envoy-go-http-filter/1d4a997271052a5a6344e5235da18b13_MD5.jpeg&#34; alt=&#34;1d4a997271052a5a6344e5235da18b13_MD5&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;dso-动态共享对象-加载机制&#34;&gt;DSO (动态共享对象) 加载机制&lt;/h2&gt;&#xA;&lt;p&gt;Go HTTP 过滤器通过 &lt;code&gt;contrib/golang/common/dso/&lt;/code&gt; 中定义的专用 DSO 机制加载 Go 编译的共享库。这与 Envoy 核心扩展中的 &lt;code&gt;dynamic_modules&lt;/code&gt; 是两套独立的实现。&lt;/p&gt;&#xA;&lt;h3 id=&#34;核心组件&#34;&gt;核心组件&lt;/h3&gt;&#xA;&lt;h4 id=&#34;1-dso-管理器-dsomanager&#34;&gt;1. DSO 管理器 (DsoManager)&lt;/h4&gt;&#xA;&lt;p&gt;&lt;code&gt;DsoManager&lt;/code&gt; 类 (&lt;code&gt;contrib/golang/common/dso/dso.h&lt;/code&gt;) 负责管理共享库的生命周期：&lt;/p&gt;</description>
			</item>
			<item>
				<title>网关的限流方案</title>
				<link>https://blog.jinzhi.site/posts/2025-11/%E7%BD%91%E5%85%B3%E7%9A%84%E9%99%90%E6%B5%81%E6%96%B9%E6%A1%88/</link>
				<pubDate>Sun, 16 Nov 2025 15:18:28 +0800</pubDate>
				<guid>https://blog.jinzhi.site/posts/2025-11/%E7%BD%91%E5%85%B3%E7%9A%84%E9%99%90%E6%B5%81%E6%96%B9%E6%A1%88/</guid>
				<description>&lt;p&gt;&lt;strong&gt;Note：本文由 Google Gemini DeepResearch 生成。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;1网关限流服务的战略必要性与流量控制架构&#34;&gt;1.网关限流服务的战略必要性与流量控制架构&lt;/h2&gt;&#xA;&lt;h3 id=&#34;11-网关在流量管理中的控制点角色与核心必要性&#34;&gt;1.1. 网关在流量管理中的控制点角色与核心必要性&lt;/h3&gt;&#xA;&lt;p&gt;API 网关在现代微服务架构中扮演着至关重要的流量控制点角色，负责管理北向（Ingress）和南向（Egress）的流量。对流量实施限制（即限流）是保障上游服务稳定性、维持系统可用性和实现资源公平分配的核心防御机制。&lt;/p&gt;&#xA;&lt;p&gt;限流服务的战略必要性主要体现在以下几个方面：&lt;/p&gt;&#xA;&lt;p&gt;首先，限流是防止系统过载和雪崩效应的关键。当面临突发流量高峰时，如不加限制，后台服务器可能因资源耗尽而被压垮。通过限制客户端在指定时间窗内的请求次数，网关可以有效地保护应用编程接口（API）及其背后的微服务。其次，限流是抵御恶意攻击的有效手段，尤其是分布式拒绝服务攻击（DDoS）或防止未受限制的网络爬虫过度消耗计算资源。如果任由客户端无限制地访问上游服务，系统的可用性将受到负面影响。&lt;/p&gt;&#xA;&lt;p&gt;从架构设计的角度看，网关作为请求进入系统的唯一入口，是实施全局限流策略的最佳位置，可以根据 IP、API 密钥、特定消费者（Consumer）或其他定制标准来应用限流规则。&lt;/p&gt;&#xA;&lt;h3 id=&#34;12-限流策略的粒度层次结构与定制化响应&#34;&gt;1.2. 限流策略的粒度、层次结构与定制化响应&lt;/h3&gt;&#xA;&lt;p&gt;在实际应用中，灵活的限流服务需要支持精细的粒度和层次化配置模型，以满足不同业务和资源保护的需求。这种配置的优先级机制体现了一种 &lt;strong&gt;“微观精确控制”优于“宏观默认保护”&lt;/strong&gt; 的设计哲学。&lt;/p&gt;&#xA;&lt;p&gt;网关通常支持多层次的限流配置，包括：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;特定 API 或消费者限流：&lt;/strong&gt; 这是优先级最高的限流配置。例如，用户可以对单个关键 API 进行限流设置，或者对特定的消费者群体施加限制。这种配置会覆盖所有默认设置。这意味着在限流值冲突时，系统优先执行最明确定义或最严格的限制，确保关键资源的防护级别不受宏观策略的稀释。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;API 默认限流：&lt;/strong&gt; 作用于应用下大部分 API 的通用配置。当没有针对单个 API 配置限流值时，将采用此默认值。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;应用总限流 (App Total Limit)：&lt;/strong&gt; 这是对当前应用下所有 API 请求的总和设置的上限。应用总限流是防止资源被“虹吸”的最后防线。即使单个 API 的限流都没有达到，一旦应用的总请求量超出限流总和值，所有请求都将被限制。这种设计解决了在微服务架构中，攻击者通过对大量低 QPS API 进行频繁调用，最终耗尽整个应用共享资源预算的“长尾攻击”问题。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;网关在触发限流时，必须向客户端返回明确的、用户友好的响应。例如，默认的限流响应可能包含 &lt;code&gt;{&amp;quot;resultStatus&amp;quot;:1002, &amp;quot;tips&amp;quot;:&amp;quot;顾客太多，客官请稍候&amp;quot;}&lt;/code&gt; 。为了实现友好的降级体验，网关需要支持定制化的响应格式，允许用户配置 JSON 格式的返回内容，如通过 &lt;code&gt;resultStatus&lt;/code&gt; 字段（例如，1002 表示限流）和 &lt;code&gt;tips&lt;/code&gt; 字段向用户提供定制化的限流提示。&lt;/p&gt;&#xA;&lt;h2 id=&#34;2-常见限流算法的原理适用性与分布式性能剖析&#34;&gt;2. 常见限流算法的原理、适用性与分布式性能剖析&lt;/h2&gt;&#xA;&lt;p&gt;选择合适的限流算法是构建高性能网关服务的基石。不同的算法在精确度、突发处理能力和分布式系统中的扩展性方面存在显著差异。&lt;/p&gt;&#xA;&lt;h3 id=&#34;21-固定窗口计数器-fixed-window-counter-fwc&#34;&gt;2.1. 固定窗口计数器 (Fixed Window Counter, FWC)&lt;/h3&gt;&#xA;&lt;p&gt;固定窗口计数器是最简单、资源消耗最低的限流算法。它在一个固定的时间周期内（例如每 60 秒）累积请求计数，当周期结束时，计数器重置。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;优势与局限性：&lt;/strong&gt; FWC 的实现非常简单，查询和递增操作计算复杂度为 $O(1)$，因此延迟极低。然而，其主要局限在于&lt;strong&gt;边界突发问题&lt;/strong&gt;。如果客户端在窗口结束前的一刻发出大量请求，并在下一个窗口开始后的第一时间再次发出同等量的请求，系统在短时间内实际放行的请求量可能高达阈值的两倍。这使得 FWC 难以应对流量的瞬间爆发，可能导致上游服务过载。&lt;/p&gt;</description>
			</item>
			<item>
				<title>APISIX 插件体系</title>
				<link>https://blog.jinzhi.site/posts/2025-10/apisix-%E6%8F%92%E4%BB%B6%E4%BD%93%E7%B3%BB/</link>
				<pubDate>Thu, 30 Oct 2025 12:18:28 +0800</pubDate>
				<guid>https://blog.jinzhi.site/posts/2025-10/apisix-%E6%8F%92%E4%BB%B6%E4%BD%93%E7%B3%BB/</guid>
				<description>&lt;h2 id=&#34;背景知识&#34;&gt;背景知识&lt;/h2&gt;&#xA;&lt;p&gt;APISIX 基于 Openresty 和 Nginx 开发，了解 APISIX 的插件体系也有必要先了解下 Nginx 和 Openresty 的基础知识。&lt;/p&gt;&#xA;&lt;h3 id=&#34;nginx-请求处理阶段&#34;&gt;Nginx 请求处理阶段&lt;/h3&gt;&#xA;&lt;p&gt;Nginx 将一个 HTTP 请求的处理过程精心划分为一系列有序的阶段（Phases），就像一个工厂的流水线。每个阶段都有特定的任务，不同的模块可以将自己的处理程序（handler）注册到感兴趣的阶段。这种设计使得 Nginx 的功能高度模块化、可扩展，并且处理流程非常清晰高效。&lt;/p&gt;&#xA;&lt;p&gt;一个请求在 Nginx 中主要会经过以下 &lt;strong&gt;11 个处理阶段&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;h4 id=&#34;1ngx_http_post_read_phase请求读取后阶段&#34;&gt;1. &lt;code&gt;NGX_HTTP_POST_READ_PHASE&lt;/code&gt; (请求读取后阶段)&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务&lt;/strong&gt;: 接收到完整的请求头（Request Header）之后，第一个被执行的阶段。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;常用模块&lt;/strong&gt;: &lt;code&gt;ngx_http_realip_module&lt;/code&gt;。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;作用举例&lt;/strong&gt;: 在这个阶段，&lt;code&gt;realip&lt;/code&gt; 模块会根据 &lt;code&gt;X-Forwarded-For&lt;/code&gt; 或 &lt;code&gt;X-Real-IP&lt;/code&gt; 等请求头，将客户端的真实 IP 地址替换掉代理服务器的 IP 地址。这对后续的访问控制和日志记录至关重要。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;2ngx_http_server_rewrite_phaseserver-级别地址重写阶段&#34;&gt;2. &lt;code&gt;NGX_HTTP_SERVER_REWRITE_PHASE&lt;/code&gt; (Server 级别地址重写阶段)&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务&lt;/strong&gt;: 在 &lt;code&gt;server&lt;/code&gt; 配置块中执行 URL 重写。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;常用模块/指令&lt;/strong&gt;: &lt;code&gt;rewrite&lt;/code&gt; 指令（当它定义在 &lt;code&gt;server&lt;/code&gt; 块中时）。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;作用举例&lt;/strong&gt;: 在请求进入具体的 &lt;code&gt;location&lt;/code&gt; 匹配之前，对 URL 进行全局的、初步的改写。例如，将所有 &lt;code&gt;http&lt;/code&gt; 请求强制重定向到 &lt;code&gt;https&lt;/code&gt;。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;server&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&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;listen&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;80&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&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;server_name&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;example.com&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&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;# 这个 rewrite 就工作在 SERVER_REWRITE 阶段&#xA;&lt;/span&gt;&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;rewrite&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;^/(.*)&lt;/span&gt;$ &lt;span class=&#34;s&#34;&gt;https://example.com/&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$1&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;permanent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &#xA;&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;3ngx_http_find_config_phase配置查找阶段&#34;&gt;3. &lt;code&gt;NGX_HTTP_FIND_CONFIG_PHASE&lt;/code&gt; (配置查找阶段)&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务&lt;/strong&gt;: 根据上个阶段处理完的 URI，查找并匹配对应的 &lt;code&gt;location&lt;/code&gt; 配置块。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;核心功能&lt;/strong&gt;: 这是 Nginx 路由的核心。Nginx 会用请求的 URI 与 &lt;code&gt;location&lt;/code&gt; 指令定义的规则进行匹配，找到最合适的 &lt;code&gt;location&lt;/code&gt;。这个阶段没有模块可以注册 handler，是 Nginx 核心自己完成的。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;4ngx_http_rewrite_phaselocation-级别地址重写阶段&#34;&gt;4. &lt;code&gt;NGX_HTTP_REWRITE_PHASE&lt;/code&gt; (Location 级别地址重写阶段)&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务&lt;/strong&gt;: 在上一步匹配到的 &lt;code&gt;location&lt;/code&gt; 块内部，执行 URL 重写。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;常用模块/指令&lt;/strong&gt;: &lt;code&gt;rewrite&lt;/code&gt; 指令（当它定义在 &lt;code&gt;location&lt;/code&gt; 块中时）、&lt;code&gt;set&lt;/code&gt; 指令。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;作用举例&lt;/strong&gt;: 对特定 &lt;code&gt;location&lt;/code&gt; 的请求进行更精细的 URL 改写。这个阶段的 &lt;code&gt;rewrite&lt;/code&gt; 可能会导致 Nginx 重新回到 &lt;code&gt;FIND_CONFIG&lt;/code&gt; 阶段去匹配新的 &lt;code&gt;location&lt;/code&gt;，可能会有循环，最多执行 10 次以防止死循环。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;location&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;/app/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&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;# 这个 rewrite 工作在 REWRITE 阶段&#xA;&lt;/span&gt;&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;rewrite&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;^/app/(.*)&lt;/span&gt;$ &lt;span class=&#34;s&#34;&gt;/v2/app/&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$1&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &#xA;&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;5ngx_http_post_rewrite_phase地址重写后阶段&#34;&gt;5. &lt;code&gt;NGX_HTTP_POST_REWRITE_PHASE&lt;/code&gt; (地址重写后阶段)&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务&lt;/strong&gt;: 防止 &lt;code&gt;rewrite&lt;/code&gt; 阶段的重写指令导致死循环。如果 URI 在上一个阶段被重写，这个阶段会把重写后的 URI 交给 Nginx，让其重新开始 &lt;code&gt;FIND_CONFIG&lt;/code&gt; 阶段，查找新的 &lt;code&gt;location&lt;/code&gt;。这是一个内部阶段，用户通常不直接感知。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;6ngx_http_preaccess_phase访问权限控制前置阶段&#34;&gt;6. &lt;code&gt;NGX_HTTP_PREACCESS_PHASE&lt;/code&gt; (访问权限控制前置阶段)&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务&lt;/strong&gt;: 在正式的访问权限检查之前，做一些准备工作。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;常用模块&lt;/strong&gt;: &lt;code&gt;ngx_http_limit_conn_module&lt;/code&gt; (连接数限制), &lt;code&gt;ngx_http_limit_req_module&lt;/code&gt; (请求速率限制)。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;作用举例&lt;/strong&gt;: 在检查用户名密码之前，先检查客户端的请求速率是否过快，如果过快，直接拒绝，不必再执行后面的阶段。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;7ngx_http_access_phase访问权限控制阶段&#34;&gt;7. &lt;code&gt;NGX_HTTP_ACCESS_PHASE&lt;/code&gt; (访问权限控制阶段)&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务&lt;/strong&gt;: 对请求进行权限验证。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;常用模块/指令&lt;/strong&gt;: &lt;code&gt;ngx_http_access_module&lt;/code&gt; (&lt;code&gt;allow&lt;/code&gt;, &lt;code&gt;deny&lt;/code&gt;), &lt;code&gt;ngx_http_auth_basic_module&lt;/code&gt; (HTTP 基本认证)。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;作用举例&lt;/strong&gt;: 检查客户端 IP 是否在允许列表中，或者验证用户提供的用户名和密码是否正确。如果这个阶段有任何模块拒绝了请求，处理就会立即中断并返回错误（如 403 Forbidden）。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;8ngx_http_post_access_phase访问权限控制后置阶段&#34;&gt;8. &lt;code&gt;NGX_HTTP_POST_ACCESS_PHASE&lt;/code&gt; (访问权限控制后置阶段)&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务&lt;/strong&gt;: 主要用于配合 &lt;code&gt;ACCESS&lt;/code&gt; 阶段的 &lt;code&gt;satisfy&lt;/code&gt; 指令。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;作用举例&lt;/strong&gt;: 当 &lt;code&gt;satisfy any;&lt;/code&gt; 被使用时，如果 &lt;code&gt;ACCESS&lt;/code&gt; 阶段有模块允许了访问（例如 IP 匹配成功），&lt;code&gt;POST_ACCESS&lt;/code&gt; 阶段的处理就可以被跳过。如果 &lt;code&gt;ACCESS&lt;/code&gt; 阶段没有明确允许，这个阶段的处理（例如 HTTP 基本认证）就会被执行。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;9ngx_http_try_files_phasetry_files-阶段&#34;&gt;9. &lt;code&gt;NGX_HTTP_TRY_FILES_PHASE&lt;/code&gt; (Try_files 阶段)&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务&lt;/strong&gt;: &lt;code&gt;try_files&lt;/code&gt; 指令专属的特殊阶段。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;常用模块/指令&lt;/strong&gt;: &lt;code&gt;try_files&lt;/code&gt;。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;作用举例&lt;/strong&gt;: 按顺序检查文件或目录是否存在，如果找到，则内部重定向到该文件，如果都找不到，则执行最后一个参数（通常是内部重定向到一个 &lt;code&gt;location&lt;/code&gt; 或返回一个状态码）。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nginx&#34; data-lang=&#34;nginx&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;location&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&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;# 这个指令工作在 TRY_FILES 阶段&#xA;&lt;/span&gt;&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;try_files&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$uri&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$uri/&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;/index.html&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&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;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;10ngx_http_content_phase内容生成阶段&#34;&gt;10. &lt;code&gt;NGX_HTTP_CONTENT_PHASE&lt;/code&gt; (内容生成阶段)&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务&lt;/strong&gt;: &lt;strong&gt;核心阶段&lt;/strong&gt;，负责生成最终的响应内容并发送给客户端。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;重要特性&lt;/strong&gt;: 每个 &lt;code&gt;location&lt;/code&gt; 只有一个模块能成为“内容处理模块”（Content Handler）。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;常用模块&lt;/strong&gt;:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;ngx_http_static_module&lt;/code&gt;: 处理静态文件。&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ngx_http_proxy_module&lt;/code&gt;: 将请求反向代理到后端服务器 (&lt;code&gt;proxy_pass&lt;/code&gt;)。&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ngx_http_fastcgi_module&lt;/code&gt;: 将请求转发给 FastCGI 应用（如 PHP-FPM）。&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;ngx_http_index_module&lt;/code&gt;: 处理目录索引文件。&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;return&lt;/code&gt;: 直接返回指定的状态码或内容。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;执行逻辑&lt;/strong&gt;: Nginx 会调用在 &lt;code&gt;location&lt;/code&gt; 中找到的内容处理模块。例如，如果配置了 &lt;code&gt;proxy_pass&lt;/code&gt;，那么 &lt;code&gt;proxy_module&lt;/code&gt; 就会接管请求。如果没有特定的内容处理模块，默认会由 &lt;code&gt;static_module&lt;/code&gt; 尝试提供静态文件服务。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;11ngx_http_log_phase日志记录阶段&#34;&gt;11. &lt;code&gt;NGX_HTTP_LOG_PHASE&lt;/code&gt; (日志记录阶段)&lt;/h4&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;任务&lt;/strong&gt;: 请求处理完成后，记录访问日志。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;常用模块/指令&lt;/strong&gt;: &lt;code&gt;ngx_http_log_module&lt;/code&gt; (&lt;code&gt;access_log&lt;/code&gt;)。&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;作用举-例&lt;/strong&gt;: 无论请求成功还是失败，这个阶段都会被执行（除非有严重错误），用于将请求的相关信息（如客户端IP、请求时间、状态码等）写入到日志文件中。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h4 id=&#34;过滤器模块-filter-modules&#34;&gt;过滤器模块 (Filter Modules)&lt;/h4&gt;&#xA;&lt;p&gt;当 &lt;code&gt;CONTENT&lt;/code&gt; 阶段生成了响应内容后，在发送给客户端之前，响应数据还会经过一系列的 &lt;strong&gt;过滤器（Filter）&lt;/strong&gt; 链处理。过滤器负责对响应头和响应体进行修改或加工。&lt;/p&gt;</description>
			</item>
			<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>
	</channel>
</rss>
