{"title":"wy471x","link":[{"@attributes":{"href":"https:\/\/wy471x.github.io\/feed.xml","rel":"self"}},{"@attributes":{"href":"https:\/\/wy471x.github.io"}}],"updated":"2026-08-16T22:53:21+08:00","id":"https:\/\/wy471x.github.io","author":{"name":"wy471x","email":"wy471x@gmail.com"},"entry":[{"title":"APISIX init.lua \u6e90\u7801\u5206\u6790","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/2026-08-16\/apisix-init-lua-analysis.html"}},"updated":"2026-08-16T23:00:00+08:00","id":"https:\/\/wy471x.github.io\/2026-08-16\/apisix-init-lua-analysis.html","content":"<h1 id=\"apisix-apisixinitlua-\u6e90\u7801\u5206\u6790\">APISIX <code class=\"language-plaintext highlighter-rouge\">apisix\/init.lua<\/code> \u6e90\u7801\u5206\u6790<\/h1>\n\n<blockquote>\n  <p>\u5206\u6790\u5bf9\u8c61:<code class=\"language-plaintext highlighter-rouge\">apisix\/init.lua<\/code>(\u672c\u6587\u884c\u53f7\u57fa\u4e8e\u4ed3\u5e93 master \u5206\u652f\u5f53\u524d\u7248\u672c)\n\u8be5\u6587\u4ef6\u662f APISIX \u7f51\u5173\u7684<strong>\u8bf7\u6c42\u751f\u547d\u5468\u671f\u603b\u5165\u53e3<\/strong>,HTTP \u4e0e Stream \u4e24\u4e2a\u5b50\u7cfb\u7edf\u5171\u7528\u3002<\/p>\n<\/blockquote>\n\n<hr \/>\n\n<h2 id=\"1-\u6587\u4ef6\u5b9a\u4f4d\">1. \u6587\u4ef6\u5b9a\u4f4d<\/h2>\n\n<p><code class=\"language-plaintext highlighter-rouge\">init.lua<\/code> \u672c\u8eab\u4e0d\u5904\u7406\u5177\u4f53\u4e1a\u52a1\u903b\u8f91,\u5b83\u627f\u62c5\u4e09\u7c7b\u804c\u8d23:<\/p>\n\n<ol>\n  <li><strong>\u8fdb\u7a0b\u751f\u547d\u5468\u671f\u94a9\u5b50<\/strong>:<code class=\"language-plaintext highlighter-rouge\">init<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">init_worker<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">exit_worker<\/code> \u9636\u6bb5\u7684\u521d\u59cb\u5316\u4e0e\u6e05\u7406;<\/li>\n  <li><strong>\u8bf7\u6c42\u751f\u547d\u5468\u671f\u7f16\u6392<\/strong>:\u6309 Nginx \u5904\u7406\u9636\u6bb5(<code class=\"language-plaintext highlighter-rouge\">access<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">balancer<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">header_filter<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">body_filter<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">log<\/code>)\u4f9d\u6b21\u8c03\u7528\u8def\u7531\u3001\u63d2\u4ef6\u3001\u8d1f\u8f7d\u5747\u8861\u7b49\u6a21\u5757;<\/li>\n  <li><strong>\u5b89\u5168\u4e0e\u534f\u8bae\u5904\u7406<\/strong>:mTLS \u6821\u9a8c\u3001URI \u89c4\u8303\u5316\u3001X-Forwarded-* \u9632\u4f2a\u9020\u3001gRPC\/Dubbo \u5185\u90e8\u91cd\u5b9a\u5411\u7b49\u3002<\/li>\n<\/ol>\n\n<p>\u8be5\u6587\u4ef6\u7684\u51fd\u6570\u7531 <code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/ngx_tpl.lua<\/code>(\u914d\u7f6e\u6a21\u677f)\u6e32\u67d3\u51fa\u7684 <code class=\"language-plaintext highlighter-rouge\">nginx.conf<\/code> \u5728\u5404\u9636\u6bb5\u6307\u4ee4\u4e2d\u8c03\u7528\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"2-\u4e0e-nginx-\u9636\u6bb5\u7684\u6302\u63a5\u5173\u7cfb\">2. \u4e0e Nginx \u9636\u6bb5\u7684\u6302\u63a5\u5173\u7cfb<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>Nginx \u6307\u4ee4<\/th>\n      <th>init.lua \u51fd\u6570<\/th>\n      <th>\u6a21\u677f\u4f4d\u7f6e<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">init_by_lua_block<\/code>(http)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_init(args)<\/code><\/td>\n      <td>ngx_tpl.lua:514<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">init_worker_by_lua_block<\/code>(http)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_init_worker()<\/code><\/td>\n      <td>:523<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">exit_worker_by_lua_block<\/code>(http)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_exit_worker()<\/code><\/td>\n      <td>:527<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">init_by_lua_block<\/code>(stream)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">stream_init(args)<\/code><\/td>\n      <td>:205<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">init_worker_by_lua_block<\/code>(stream)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">stream_init_worker()<\/code><\/td>\n      <td>:209<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ssl_client_hello_by_lua_block<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ssl_client_hello_phase()<\/code><\/td>\n      <td>:234 \/ :772<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ssl_certificate_by_lua_block<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ssl_phase()<\/code><\/td>\n      <td>:238 \/ :776<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">preread_by_lua_block<\/code>(stream)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">stream_preread_phase()<\/code><\/td>\n      <td>:247<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">log_by_lua_block<\/code>(stream)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">stream_log_phase()<\/code><\/td>\n      <td>:259<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">access_by_lua_block<\/code>(http \u4e3b server)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_access_phase()<\/code><\/td>\n      <td>:830<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">balancer_by_lua_block<\/code>(http upstream)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_balancer_phase()<\/code><\/td>\n      <td>:465 \/ :469 \/ :482<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">header_filter_by_lua_block<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_header_filter_phase()<\/code><\/td>\n      <td>:878 \/ :914 \/ :937<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">body_filter_by_lua_block<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_body_filter_phase()<\/code><\/td>\n      <td>:882 \/ :918 \/ :941<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">log_by_lua_block<\/code>(http)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_log_phase()<\/code><\/td>\n      <td>:886 \/ :922 \/ :945<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">location @grpc_pass<\/code> \u7684 <code class=\"language-plaintext highlighter-rouge\">access_by_lua<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">grpc_access_phase()<\/code><\/td>\n      <td>:893<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">location @dubbo_pass<\/code> \u7684 <code class=\"language-plaintext highlighter-rouge\">access_by_lua<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">dubbo_access_phase()<\/code><\/td>\n      <td>:929<\/td>\n    <\/tr>\n    <tr>\n      <td>control server \u7684 <code class=\"language-plaintext highlighter-rouge\">content_by_lua<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_control()<\/code><\/td>\n      <td>:549<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">\/apisix\/admin<\/code> \u7684 <code class=\"language-plaintext highlighter-rouge\">content_by_lua<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_admin()<\/code><\/td>\n      <td>:645<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">\/apisix\/status<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">status()<\/code><\/td>\n      <td>:561<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">\/apisix\/status\/ready<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">status_ready()<\/code><\/td>\n      <td>:566<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"3-\u6a21\u5757\u52a0\u8f7d\u671f\u521d\u59cb\u5316l17--l88\">3. \u6a21\u5757\u52a0\u8f7d\u671f\u521d\u59cb\u5316(L17 ~ L88)<\/h2>\n\n<h3 id=\"31-jit-\u53c2\u6570l17--l26\">3.1 JIT \u53c2\u6570(L17 ~ L26)<\/h3>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">if<\/span> <span class=\"nb\">require<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"ffi\"<\/span><span class=\"p\">).<\/span><span class=\"n\">os<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"Linux\"<\/span> <span class=\"k\">then<\/span>\n    <span class=\"nb\">require<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"ngx.re\"<\/span><span class=\"p\">).<\/span><span class=\"n\">opt<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"jit_stack_size\"<\/span><span class=\"p\">,<\/span> <span class=\"mi\">200<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">1024<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<ul>\n  <li>\u53ea\u5728 Linux \u4e0a\u8c03\u6574 PCRE JIT \u6808\u5927\u5c0f,\u4e14\u5fc5\u987b\u653e\u5728<strong>\u4efb\u4f55\u6b63\u5219\u7f16\u8bd1\u4e4b\u524d<\/strong>(\u5426\u5219\u62a5 \u201cchanging jit stack size is not allowed\u2026\u201d)\u3002<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">jit.opt.start(...)<\/code> \u7684\u8c03\u4f18\u53c2\u6570:\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">minstitch=2<\/code>:\u81f3\u5c11 2 \u6761 trace \u624d\u505a\u62fc\u63a5;<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">maxtrace=4000<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">maxrecord=8000<\/code>:\u9650\u5236 trace \u6570\u91cf\u4e0e\u5355\u6761 trace \u8bb0\u5f55\u957f\u5ea6,\u9632\u6b62 JIT \u5185\u5b58\u5931\u63a7;<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">sizemcode=64<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">maxmcode=4000<\/code>:mcode \u533a\u57df\u5927\u5c0f(64KB \u8d77\u6b65\u3001\u4e0a\u9650 4000KB);<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">maxirconst=1000<\/code>:IR \u5e38\u91cf\u4e0a\u9650\u3002<\/li>\n    <\/ul>\n  <\/li>\n<\/ul>\n\n<h3 id=\"32-\u6a21\u5757\u4f9d\u8d56l28--l69\">3.2 \u6a21\u5757\u4f9d\u8d56(L28 ~ L69)<\/h3>\n\n<p>\u6838\u5fc3\u4f9d\u8d56\u53ca\u5176\u4f5c\u7528:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u6a21\u5757<\/th>\n      <th>\u4f5c\u7528<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.patch<\/code><\/td>\n      <td>\u5bf9 OpenResty\/ngx_lua \u6253\u8fd0\u884c\u65f6\u8865\u4e01<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.core<\/code><\/td>\n      <td>\u65e5\u5fd7\u3001json\u3001tablepool\u3001lrucache \u7b49\u57fa\u7840\u8bbe\u65bd<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.plugin<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">plugin_config<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">consumer_group<\/code><\/td>\n      <td>\u63d2\u4ef6\u4f53\u7cfb\u3001\u63d2\u4ef6\u914d\u7f6e\u3001\u6d88\u8d39\u8005\u7ec4<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.router<\/code><\/td>\n      <td>\u8def\u7531\u5339\u914d:<code class=\"language-plaintext highlighter-rouge\">router_http<\/code>(HTTP)\u3001<code class=\"language-plaintext highlighter-rouge\">router_ssl<\/code>(\u8bc1\u4e66)\u3001<code class=\"language-plaintext highlighter-rouge\">router_stream<\/code>(Stream)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.upstream<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">apisix.balancer<\/code><\/td>\n      <td>\u4e0a\u6e38\u7ba1\u7406\u3001\u8d1f\u8f7d\u5747\u8861<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.ssl<\/code><\/td>\n      <td>TLS \u76f8\u5173\u5de5\u5177(SNI\u3001\u534f\u8bae\u3001\u4f1a\u8bdd)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.stream.xrpc<\/code><\/td>\n      <td>Stream \u5b50\u7cfb\u7edf\u4e0b\u7684\u534f\u8bae\u5206\u53d1<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.tracer<\/code><\/td>\n      <td>\u5206\u5e03\u5f0f\u8ffd\u8e2a span<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.pubsub.kafka<\/code><\/td>\n      <td>kafka \u7c7b\u578b\u4e0a\u6e38\u7684\u4e13\u95e8\u5904\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.utils.trusted-addresses<\/code><\/td>\n      <td>\u53ef\u4fe1\u5730\u5740\u5224\u65ad(\u7528\u4e8e X-Forwarded-* \u9632\u4f2a\u9020)<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"33-\u5173\u952e\u5168\u5c40\u6807\u5fd7\">3.3 \u5173\u952e\u5168\u5c40\u6807\u5fd7<\/h3>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">local<\/span> <span class=\"n\">is_http<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">false<\/span>\n<span class=\"k\">if<\/span> <span class=\"n\">ngx<\/span><span class=\"p\">.<\/span><span class=\"n\">config<\/span><span class=\"p\">.<\/span><span class=\"n\">subsystem<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"http\"<\/span> <span class=\"k\">then<\/span>\n    <span class=\"n\">is_http<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">true<\/span>\n    <span class=\"n\">control_api_router<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">require<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"apisix.control.router\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">is_http<\/code>:\u533a\u5206\u5b50\u7cfb\u7edf;\u540c\u4e00\u4efd\u4ee3\u7801\u91cc HTTP \u7528 <code class=\"language-plaintext highlighter-rouge\">core.response.exit(...)<\/code>,Stream \u7528 <code class=\"language-plaintext highlighter-rouge\">ngx_exit(...)<\/code> \u5206\u53c9\u5904\u7406\u3002<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">apisix_base_flags<\/code>(L77 ~ L80):<code class=\"language-plaintext highlighter-rouge\">resty.apisix.patch<\/code> \u662f APISIX \u5b9a\u5236\u7684 C \u6a21\u5757(apisix-base),pcall \u52a0\u8f7d\u5931\u8d25\u5219\u964d\u7ea7\u4e3a\u7a7a\u8868\u3002\u5178\u578b\u7528\u9014\u89c1 L402:<code class=\"language-plaintext highlighter-rouge\">client_cert_verified_in_handshake<\/code> \u6807\u5fd7\u2014\u2014\u65b0\u7248 apisix-base \u5728\u63e1\u624b\u9636\u6bb5\u5df2\u5b8c\u6210\u5ba2\u6237\u7aef\u8bc1\u4e66\u6821\u9a8c\u65f6,\u65e0\u9700\u518d\u67e5 <code class=\"language-plaintext highlighter-rouge\">$ssl_client_verify<\/code>\u3002<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">apisix_ngx_client<\/code>(L86):\u6765\u81ea <code class=\"language-plaintext highlighter-rouge\">resty.apisix.client<\/code>,\u63d0\u4f9b <code class=\"language-plaintext highlighter-rouge\">enable_mirror()<\/code>(L880 \u7528\u4e8e gRPC \u6d41\u91cf\u955c\u50cf)\u3002<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ver_header<\/code>(L84):\u54cd\u5e94 <code class=\"language-plaintext highlighter-rouge\">Server<\/code> \u5934,<code class=\"language-plaintext highlighter-rouge\">enable_server_tokens=false<\/code> \u65f6\u964d\u7ea7\u4e3a <code class=\"language-plaintext highlighter-rouge\">\"APISIX\"<\/code>(L162 ~ L164)\u3002<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"4-http-\u5b50\u7cfb\u7edf\">4. HTTP \u5b50\u7cfb\u7edf<\/h2>\n\n<h3 id=\"41-http_initl91--l110-init-\u9636\u6bb5\">4.1 <code class=\"language-plaintext highlighter-rouge\">http_init<\/code>(L91 ~ L110)\u2014 init \u9636\u6bb5<\/h3>\n\n<ol>\n  <li>\u521d\u59cb\u5316 DNS resolver\u3001ID \u751f\u6210\u5668\u3001\u73af\u5883\u53d8\u91cf;<\/li>\n  <li>\u542f\u7528 privileged agent \u8fdb\u7a0b(\u7528\u4e8e\u52a8\u6001\u8bbe\u7f6e\u4e0a\u6e38\u7b49\u7279\u6743\u64cd\u4f5c);<\/li>\n  <li>\u521d\u59cb\u5316\u914d\u7f6e\u4e2d\u5fc3(<code class=\"language-plaintext highlighter-rouge\">core.config.init<\/code>,etcd \/ \u72ec\u7acb\u6a21\u5f0f yaml);<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">xrpc.init()<\/code>\u3002<\/li>\n<\/ol>\n\n<h3 id=\"42-http_init_workerl113--l171-init_worker-\u9636\u6bb5\">4.2 <code class=\"language-plaintext highlighter-rouge\">http_init_worker<\/code>(L113 ~ L171)\u2014 init_worker \u9636\u6bb5<\/h3>\n\n<p>\u6309\u987a\u5e8f\u521d\u59cb\u5316\u5404\u5b50\u7cfb\u7edf,<strong>\u987a\u5e8f\u5373\u4f9d\u8d56\u5173\u7cfb<\/strong>:<\/p>\n\n<ol>\n  <li><strong>\u968f\u673a\u79cd\u5b50<\/strong>:\u4f18\u5148\u4ece <code class=\"language-plaintext highlighter-rouge\">\/dev\/urandom<\/code> \u53d6(L114);L121 \u7684 \u201crandom test\u201d \u65e5\u5fd7\u5b9e\u9645\u662f<strong>\u6d4b\u8bd5\u65ad\u8a00\u7528\u7684\u63a2\u9488<\/strong>(\u6d4b\u8bd5\u4ee3\u7801\u636e\u6b64\u786e\u8ba4 init_worker \u5df2\u6267\u884c);<\/li>\n  <li>\u4e8b\u4ef6\u7cfb\u7edf\u3001lrucache\u3001\u670d\u52a1\u53d1\u73b0(discovery)\u3001balancer\u3001admin\u3001\u540e\u53f0 timers\u3001debug;<\/li>\n  <li>\u914d\u7f6e\u4e2d\u5fc3 worker \u7ea7\u521d\u59cb\u5316;<\/li>\n  <li>\u63d2\u4ef6\u4f53\u7cfb:plugin \u2192 router \u2192 service \u2192 plugin_config \u2192 consumer \u2192 consumer_group \u2192 secret \u2192 global_rules \u2192 upstream \u2192 ext-plugin;<\/li>\n  <li>control API \u8def\u7531\u3001<code class=\"language-plaintext highlighter-rouge\">local_conf<\/code> \u7f13\u5b58\u3001<code class=\"language-plaintext highlighter-rouge\">Server<\/code> \u5934\u7248\u672c;<\/li>\n  <li>Prometheus \u63d2\u4ef6\u521d\u59cb\u5316(\u5fc5\u987b\u6700\u540e\u505a,\u4ee5\u4fdd\u8bc1\u6240\u6709 worker \u7684\u6307\u6807\u5c31\u7eea);<\/li>\n  <li>\u53ef\u4fe1\u5730\u5740\u5de5\u5177\u3002<\/li>\n<\/ol>\n\n<h3 id=\"43-tls--mtls-\u5904\u7406\">4.3 TLS \/ mTLS \u5904\u7406<\/h3>\n\n<h4 id=\"ssl_phasel182--l190\"><code class=\"language-plaintext highlighter-rouge\">ssl_phase<\/code>(L182 ~ L190)<\/h4>\n\n<p><code class=\"language-plaintext highlighter-rouge\">ssl_certificate_by_lua<\/code> \u9636\u6bb5:\u628a <code class=\"language-plaintext highlighter-rouge\">ssl_client_hello_phase<\/code> \u9636\u6bb5\u5339\u914d\u5230\u7684\u8bc1\u4e66\u914d\u7f6e(<code class=\"language-plaintext highlighter-rouge\">ngx.ctx.matched_ssl<\/code>)\u8bbe\u7f6e\u5230\u5f53\u524d TLS \u4f1a\u8bdd\u3002<\/p>\n\n<h4 id=\"ssl_client_hello_phasel193--l240\"><code class=\"language-plaintext highlighter-rouge\">ssl_client_hello_phase<\/code>(L193 ~ L240)<\/h4>\n\n<ul>\n  <li><strong>\u5fc5\u987b\u62ff\u5230 SNI<\/strong>(L195 ~ L200),\u62ff\u4e0d\u5230(\u6309 IP \u8bbf\u95ee\u6216\u534f\u8bae\u8fc7\u65e7)\u76f4\u63a5\u9000\u51fa;<\/li>\n  <li>\u8bfb\u53d6 OCSP <code class=\"language-plaintext highlighter-rouge\">status_request<\/code> \u6269\u5c55;<\/li>\n  <li>\u4ece tablepool \u53d6 <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> \u505a\u5339\u914d(\u6ce8\u610f L214 \u7528\u5b8c\u7acb\u5373\u91ca\u653e,\u8be5\u9636\u6bb5\u4e0d\u590d\u7528);<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">router_ssl.match_and_set(api_ctx, true, sni)<\/code> \u5339\u914d SNI \u8bc1\u4e66;<\/li>\n  <li>\u6309\u5339\u914d\u7ed3\u679c\u52a8\u6001\u8bbe\u7f6e <code class=\"language-plaintext highlighter-rouge\">ssl_protocols<\/code>(L228);<\/li>\n  <li><strong>L238<\/strong>:\u628a SNI \u5b58\u5165 <code class=\"language-plaintext highlighter-rouge\">ngx.ctx.client_hello_sni<\/code> \u2014\u2014 \u56e0\u4e3a Stream \u5b50\u7cfb\u7edf\u7684 preread \u9636\u6bb5 <code class=\"language-plaintext highlighter-rouge\">ngx.ssl.server_name()<\/code> \u62ff\u5230\u7684\u662f\u4f1a\u8bdd\u4e3b\u673a\u540d\u800c\u975e\u771f\u5b9e SNI,\u8fd9\u91cc\u63d0\u524d\u8bb0\u5f55\u4f9b\u540e\u7eed\u6821\u9a8c\u3002<\/li>\n<\/ul>\n\n<h4 id=\"mtls-\u6821\u9a8c\u7684\u4e09\u4e2a\u51fd\u6570\">mTLS \u6821\u9a8c\u7684\u4e09\u4e2a\u51fd\u6570<\/h4>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">verify_tls_session_resumption<\/code>(L318 ~ L331):<strong>TLS \u4f1a\u8bdd\u6062\u590d\u5b89\u5168\u6821\u9a8c<\/strong>\u3002\u4f1a\u8bdd\u590d\u7528\u65f6,\u6821\u9a8c\u4f1a\u8bdd\u4e2d\u7684 hostname \u4e0e\u672c\u6b21 client hello \u7684 SNI \u4e00\u81f4,\u9632\u6b62\u901a\u8fc7\u4f1a\u8bdd\u6062\u590d\u7ed5\u8fc7 mTLS \u7684\u5b89\u5168\u95ee\u9898\u3002<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">verify_tls_client<\/code>(L334 ~ L359,<strong>Stream \u7528<\/strong>):\u6309 SNI \u91cd\u65b0\u5339\u914d\u8bc1\u4e66;\u82e5\u914d\u7f6e\u4e86 <code class=\"language-plaintext highlighter-rouge\">client<\/code> \u8bc1\u4e66\u4e14\u652f\u6301\u5ba2\u6237\u7aef\u6821\u9a8c,\u68c0\u67e5 <code class=\"language-plaintext highlighter-rouge\">$ssl_client_verify == \"SUCCESS\"<\/code>,\u5e76\u505a\u4f1a\u8bdd\u6062\u590d\u6821\u9a8c\u3002<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">verify_https_client<\/code>(L371 ~ L434,<strong>HTTP \u7528<\/strong>):\n    <ol>\n      <li>\u652f\u6301 <code class=\"language-plaintext highlighter-rouge\">skip_mtls_uri_regex<\/code>:\u5bf9\u5339\u914d\u7684 URI \u8c41\u514d\u5ba2\u6237\u7aef\u8bc1\u4e66(L363 ~ L368,L381);<\/li>\n      <li>\u8bc1\u4e66\u6821\u9a8c(\u4f18\u5148\u4fe1\u4efb apisix-base \u7684\u63e1\u624b\u671f\u6821\u9a8c\u6807\u5fd7,L402);<\/li>\n      <li><strong>SNI \u4e0e Host \u4e00\u81f4\u6027\u6821\u9a8c<\/strong>(L417 ~ L426):\u9632\u6b62\u7528\u6237\u914d\u7f6e <code class=\"language-plaintext highlighter-rouge\">*.domain<\/code> \u901a\u914d\u8bc1\u4e66\u540e,\u7528 SNI <code class=\"language-plaintext highlighter-rouge\">a.domain<\/code> \u8bbf\u95ee\u5374\u643a\u5e26 Host <code class=\"language-plaintext highlighter-rouge\">b.domain<\/code> \u7684\u8de8\u57df\u8bc1\u4e66\u91cd\u7528;<\/li>\n      <li>\u4f1a\u8bdd\u6062\u590d\u6821\u9a8c\u3002<\/li>\n    <\/ol>\n  <\/li>\n<\/ul>\n\n<h3 id=\"44-http_access_phasel691--l857-access-\u9636\u6bb5\u6838\u5fc3\">4.4 <code class=\"language-plaintext highlighter-rouge\">http_access_phase<\/code>(L691 ~ L857)\u2014 access \u9636\u6bb5\u6838\u5fc3<\/h3>\n\n<p>\u6267\u884c\u987a\u5e8f:<\/p>\n\n<ol>\n  <li><strong>HTTP\/3 \u9002\u914d<\/strong>(L694 ~ L696):<code class=\"language-plaintext highlighter-rouge\">ngx.req.http_version() == 3<\/code> \u65f6,\u628a <code class=\"language-plaintext highlighter-rouge\">:authority<\/code> \u4f2a\u5934\u8f6c\u6210 <code class=\"language-plaintext highlighter-rouge\">upstream_host<\/code>;<\/li>\n  <li><strong>api_ctx \u521b\u5efa<\/strong>(L700 ~ L704):\u4ece tablepool \u53d6,\u6302\u5230 <code class=\"language-plaintext highlighter-rouge\">ngx.ctx<\/code>,\u5e76\u521d\u59cb\u5316 <code class=\"language-plaintext highlighter-rouge\">var<\/code> \u5143\u8868(\u60f0\u6027\u8bfb\u53d6 nginx \u53d8\u91cf);<\/li>\n  <li><strong>mTLS \u6821\u9a8c<\/strong>(L708);<\/li>\n  <li><strong>\u52a8\u6001\u8c03\u8bd5<\/strong>(L712);<\/li>\n  <li><strong>URI \u89c4\u8303\u5316<\/strong>(L714 ~ L735):\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">delete_uri_tail_slash<\/code>:\u5220\u9664\u672b\u5c3e <code class=\"language-plaintext highlighter-rouge\">\/<\/code>;<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">normalize_uri_like_servlet<\/code>:\u6a21\u62df Java Servlet \u8bed\u4e49,\u622a\u65ad <code class=\"language-plaintext highlighter-rouge\">;<\/code> \u540e\u7684\u8def\u5f84\u53c2\u6570,\u5e76\u505a\u9632\u7ed5\u8fc7\u68c0\u67e5(<code class=\"language-plaintext highlighter-rouge\">.<\/code>\/<code class=\"language-plaintext highlighter-rouge\">..<\/code> \u6bb5\u3001\u7a7a\u6bb5\u3001<code class=\"language-plaintext highlighter-rouge\">%2e<\/code> \u7f16\u7801\u70b9\u6bb5);<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong>request_uri \u9632\u6ce8\u5165\u91cd\u5199<\/strong>(L740 ~ L741):\u89c4\u8303\u5316\u540e\u7684 URI \u624d\u5199\u5165 <code class=\"language-plaintext highlighter-rouge\">request_uri<\/code>,\u539f\u59cb\u503c\u5b58\u5230 <code class=\"language-plaintext highlighter-rouge\">real_request_uri<\/code>;<\/li>\n  <li><strong>X-Forwarded-* \u9632\u4f2a\u9020<\/strong>(L743,\u8be6\u89c1 \u00a75.4);<\/li>\n  <li><strong>\u8def\u7531\u5339\u914d<\/strong>(L745 ~ L759):<code class=\"language-plaintext highlighter-rouge\">router.router_http.match(api_ctx)<\/code>;\u672a\u547d\u4e2d \u2192 \u4ecd\u6267\u884c global rules \u2192 \u8fd4\u56de 404;<\/li>\n  <li><strong>\u914d\u7f6e\u5408\u5e76<\/strong>(L767 ~ L802):<code class=\"language-plaintext highlighter-rouge\">plugin_config<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">service<\/code>(merge_service_route),\u8bbe\u7f6e <code class=\"language-plaintext highlighter-rouge\">conf_type<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">conf_version<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">conf_id<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">route_id<\/code> \u7b49\u4e0a\u4e0b\u6587\u5b57\u6bb5;<\/li>\n  <li><strong>\u6267\u884c global rules<\/strong>(L807 ~ L808);<\/li>\n  <li><strong>\u63d2\u4ef6\/\u811a\u672c\u6267\u884c<\/strong>(L810 ~ L851):\n    <ul>\n      <li>script \u8def\u7531:\u76f4\u63a5 <code class=\"language-plaintext highlighter-rouge\">script.run(\"access\")<\/code>;<\/li>\n      <li>\u63d2\u4ef6\u8def\u7531:<code class=\"language-plaintext highlighter-rouge\">plugin.filter<\/code> \u8fc7\u6ee4\u51fa\u8be5\u8def\u7531\u751f\u6548\u7684\u63d2\u4ef6 \u2192 \u5148\u8dd1 <code class=\"language-plaintext highlighter-rouge\">rewrite<\/code> \u9636\u6bb5 \u2192 \u82e5 rewrite \u9636\u6bb5\u4ea7\u751f\u4e86 <code class=\"language-plaintext highlighter-rouge\">consumer<\/code>(\u5982 key-auth \u8ba4\u8bc1\u6210\u529f),\u5408\u5e76 consumer \/ consumer_group \u914d\u7f6e,\u82e5\u914d\u7f6e\u6709\u53d8\u5316\u5219<strong>\u91cd\u65b0\u8fc7\u6ee4\u5e76\u8865\u8dd1 <code class=\"language-plaintext highlighter-rouge\">rewrite_in_consumer<\/code> \u9636\u6bb5<\/strong> \u2192 \u6700\u540e\u8dd1 <code class=\"language-plaintext highlighter-rouge\">access<\/code> \u9636\u6bb5;<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">handle_upstream<\/code><\/strong>(L854);<\/li>\n  <li><strong>\u8bbe\u7f6e\u4e0a\u6e38 X-Forwarded-* \u5934<\/strong>(L856)\u3002<\/li>\n<\/ol>\n\n<h3 id=\"45-handle_upstreaml493--l610\">4.5 <code class=\"language-plaintext highlighter-rouge\">handle_upstream<\/code>(L493 ~ L610)<\/h3>\n\n<ol>\n  <li><code class=\"language-plaintext highlighter-rouge\">bypass_nginx_upstream<\/code>:\u63d2\u4ef6(\u5982 ai-proxy)\u81ea\u5df1\u7528 HTTP \u5ba2\u6237\u7aef\u8bf7\u6c42\u4e0a\u6e38\u65f6,\u8df3\u8fc7 nginx \u4ee3\u7406,\u53ea\u6267\u884c <code class=\"language-plaintext highlighter-rouge\">before_proxy<\/code> \u63d2\u4ef6\u9636\u6bb5(L495 ~ L498);<\/li>\n  <li>\u786e\u5b9a\u4e0a\u6e38:<code class=\"language-plaintext highlighter-rouge\">upstream_id<\/code> \/ traffic-split \u8986\u76d6\u7684 <code class=\"language-plaintext highlighter-rouge\">upstream_id<\/code>(L500 ~ L535);\u5e26\u57df\u540d\u8282\u70b9(<code class=\"language-plaintext highlighter-rouge\">has_domain<\/code>)\u7684\u8def\u7531\u89e6\u53d1 <code class=\"language-plaintext highlighter-rouge\">parse_domain_in_route<\/code>(L258 ~ L287)\u505a DNS \u89e3\u6790,\u5e76\u7528 <code class=\"language-plaintext highlighter-rouge\">_nodes_ver<\/code> + <code class=\"language-plaintext highlighter-rouge\">resource<\/code> \u6a21\u5757\u7ef4\u62a4\u8282\u70b9\u7248\u672c;<\/li>\n  <li><strong>\u4e0a\u6e38 mTLS<\/strong>(L537 ~ L558):<code class=\"language-plaintext highlighter-rouge\">upstream.tls.client_cert_id<\/code> \u4ece <code class=\"language-plaintext highlighter-rouge\">router_ssl<\/code> \u53d6\u5ba2\u6237\u7aef\u8bc1\u4e66;<\/li>\n  <li><strong>WebSocket<\/strong>(L560 ~ L564):\u900f\u4f20 <code class=\"language-plaintext highlighter-rouge\">Upgrade<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">Connection<\/code> \u5934;<\/li>\n  <li><strong>kafka \u4e0a\u6e38<\/strong>:\u4ea4\u7531 <code class=\"language-plaintext highlighter-rouge\">pubsub_kafka.access<\/code> \u63a5\u7ba1(L569 ~ L571);<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">set_upstream<\/code> \u8bbe\u7f6e\u4ee3\u7406\u53c2\u6570 \u2192 <code class=\"language-plaintext highlighter-rouge\">load_balancer.pick_server<\/code> \u9009\u8282\u70b9(L573 ~ L587);<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">set_upstream_headers<\/code>(L587):\u6309 <code class=\"language-plaintext highlighter-rouge\">pass_host<\/code> \u8bed\u4e49\u8bbe\u7f6e Host(<code class=\"language-plaintext highlighter-rouge\">pass<\/code>\/<code class=\"language-plaintext highlighter-rouge\">rewrite<\/code>\/<code class=\"language-plaintext highlighter-rouge\">node<\/code>,L290 ~ L308);<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">before_proxy<\/code> \u63d0\u524d\u6267\u884c<\/strong>(L590):\u5728 access \u9636\u6bb5\u5c31\u6267\u884c before_proxy \u63d2\u4ef6,\u6ce8\u91ca\u8bf4\u660e\u662f\u4e3a\u4e86\u201d\u907f\u514d\u603b\u662f reinit \u8bf7\u6c42\u201d;<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">_apisix_proxied<\/code> \u6807\u8bb0<\/strong>(L592 ~ L598):\u5fc5\u987b\u5728 before_proxy \u4e4b\u540e\u3001proxy_pass \u6d3e\u53d1\u4e4b\u524d\u8bbe\u7f6e,log \u9636\u6bb5\u636e\u6b64\u533a\u5206\u201dnginx \u4ee3\u7406\u9519\u8bef\u201d\u4e0e\u201d\u4e0a\u6e38\u54cd\u5e94\u201d;<\/li>\n  <li><strong>gRPC \/ Dubbo \u5206\u6d41<\/strong>(L600 ~ L609):<code class=\"language-plaintext highlighter-rouge\">stash_ngx_ctx()<\/code> \u540e <code class=\"language-plaintext highlighter-rouge\">ngx.exec(\"@grpc_pass\")<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">\"@dubbo_pass\"<\/code>\u3002<\/li>\n<\/ol>\n\n<h3 id=\"46-\u4e0a\u4e0b\u6587\u8de8\u5185\u90e8\u91cd\u5b9a\u5411\u4f20\u9012l243--l256\">4.6 \u4e0a\u4e0b\u6587\u8de8\u5185\u90e8\u91cd\u5b9a\u5411\u4f20\u9012(L243 ~ L256)<\/h3>\n\n<p><code class=\"language-plaintext highlighter-rouge\">ngx.exec<\/code> \u5185\u90e8\u91cd\u5b9a\u5411\u4f1a<strong>\u4e22\u5931 <code class=\"language-plaintext highlighter-rouge\">ngx.ctx<\/code><\/strong>,APISIX \u7528 <code class=\"language-plaintext highlighter-rouge\">resty.ctxdump<\/code> \u89e3\u51b3:<\/p>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">stash_ngx_ctx()<\/code>:<code class=\"language-plaintext highlighter-rouge\">ctxdump.stash_ngx_ctx()<\/code> \u5e8f\u5217\u5316\u4e0a\u4e0b\u6587,\u5f15\u7528\u53f7\u5199\u5165 nginx \u53d8\u91cf <code class=\"language-plaintext highlighter-rouge\">$ctx_ref<\/code>;<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">fetch_ctx()<\/code>:\u5728\u76ee\u6807 location \u91cc\u6309\u5f15\u7528\u53f7\u6062\u590d <code class=\"language-plaintext highlighter-rouge\">ngx.ctx<\/code>,\u5e76\u6e05\u7a7a\u53d8\u91cf\u3002<\/li>\n<\/ul>\n\n<h3 id=\"47-\u54cd\u5e94\u4e0e\u65e5\u5fd7\u9636\u6bb5\">4.7 \u54cd\u5e94\u4e0e\u65e5\u5fd7\u9636\u6bb5<\/h3>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">http_header_filter_phase<\/code>(L910 ~ L938):\n    <ul>\n      <li>\u8bbe\u7f6e <code class=\"language-plaintext highlighter-rouge\">Server<\/code> \u5934;<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">X-APISIX-Upstream-Status<\/code>:\u6309\u914d\u7f6e\u5c55\u793a\u4e0a\u6e38\u72b6\u6001\u7801,\u9ed8\u8ba4\u53ea\u5728 5xx \u65f6\u5c55\u793a(L885 ~ L907);<\/li>\n      <li>\u6267\u884c <code class=\"language-plaintext highlighter-rouge\">header_filter<\/code> \u63d2\u4ef6\u9636\u6bb5;<\/li>\n      <li>\u8f93\u51fa\u8c03\u8bd5\u5934 <code class=\"language-plaintext highlighter-rouge\">Apisix-Plugins<\/code>(L927 ~ L934);<\/li>\n      <li>\u672b\u5c3e\u9884\u521b\u5efa body_filter \u9636\u6bb5\u7684 span\u3002<\/li>\n    <\/ul>\n  <\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">http_body_filter_phase<\/code>(L941 ~ L944):\u6267\u884c <code class=\"language-plaintext highlighter-rouge\">body_filter<\/code> \u4e0e <code class=\"language-plaintext highlighter-rouge\">delayed_body_filter<\/code> \u63d2\u4ef6\u9636\u6bb5\u3002<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">http_log_phase<\/code>(L1088 ~ L1123):\n    <ol>\n      <li>\u7ed3\u675f\u6240\u6709 tracer span;<\/li>\n      <li>\u515c\u5e95 <code class=\"language-plaintext highlighter-rouge\">apisix_upstream_response_time<\/code>;<\/li>\n      <li>\u6267\u884c <code class=\"language-plaintext highlighter-rouge\">log<\/code> \u63d2\u4ef6\u9636\u6bb5;<\/li>\n      <li><strong>\u88ab\u52a8\u5065\u5eb7\u68c0\u67e5\u4e0a\u62a5<\/strong>(L1104,\u00a74.8);<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">after_balance<\/code> \u94a9\u5b50;<\/li>\n      <li><strong>\u8d44\u6e90\u7edf\u4e00\u91ca\u653e<\/strong>:release_vars\u3001\u91ca\u653e <code class=\"language-plaintext highlighter-rouge\">plugins<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">matched_route_record<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> tablepool \u5bf9\u8c61\u2014\u2014access \u9636\u6bb5\u4ece tablepool \u501f\u7684\u4e1c\u897f\u5728\u8fd9\u91cc\u5f52\u8fd8\u3002<\/li>\n    <\/ol>\n  <\/li>\n<\/ul>\n\n<h3 id=\"48-\u88ab\u52a8\u5065\u5eb7\u68c0\u67e5-healthcheck_passivel947--l1006\">4.8 \u88ab\u52a8\u5065\u5eb7\u68c0\u67e5 <code class=\"language-plaintext highlighter-rouge\">healthcheck_passive<\/code>(L947 ~ L1006)<\/h3>\n\n<ul>\n  <li>\u4f9d\u8d56 <code class=\"language-plaintext highlighter-rouge\">api_ctx.up_checker<\/code>(balancer \u9636\u6bb5\u521b\u5efa);<\/li>\n  <li>HTTP:\u6309\u914d\u7f6e\u7684 healthy\/unhealthy <code class=\"language-plaintext highlighter-rouge\">http_statuses<\/code> \u4e0a\u62a5;<\/li>\n  <li>Stream:\u975e 200 \u4e00\u5f8b\u4e0a\u62a5 TCP \u5931\u8d25\u3002<\/li>\n<\/ul>\n\n<h3 id=\"49-\u7ba1\u7406\u63a7\u5236\u63a5\u53e3\">4.9 \u7ba1\u7406\/\u63a7\u5236\u63a5\u53e3<\/h3>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">status<\/code>(L1009):\u76f4\u63a5\u8fd4\u56de 200;<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">status_ready<\/code>(L1064):\u5c31\u7eea\u63a2\u9488,\u4e24\u6b65\u68c0\u67e5:\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">config_ready_check<\/code>(L1031):role \u7684 config_provider \u5fc5\u987b\u662f yaml\/etcd;<code class=\"language-plaintext highlighter-rouge\">status-report<\/code> shdict \u4e2d<strong>\u6bcf\u4e2a worker \u90fd\u6709\u4e00\u6761\u5c31\u7eea\u8bb0\u5f55<\/strong>(key \u6570 == worker \u6570,\u4e14\u503c\u975e\u7a7a);<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">discovery_ready_check<\/code>(L1014):\u5404\u670d\u52a1\u53d1\u73b0\u6a21\u5757\u53ef\u9009\u5b9e\u73b0 <code class=\"language-plaintext highlighter-rouge\">check_discovery_ready<\/code>;<\/li>\n    <\/ul>\n  <\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">http_admin<\/code>(L1169):Admin API \u8def\u7531\u5206\u53d1 + CORS(OPTIONS \u9884\u68c0\u76f4\u63a5 200)+ JSON Content-Type;router \u5b9e\u4f8b\u7f13\u5b58\u5728 do-block \u7684 upvalue \u4e2d,\u53ea\u521d\u59cb\u5316\u4e00\u6b21;<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">http_control<\/code>(L1191):control API \u8def\u7531\u5339\u914d\u3002<\/li>\n<\/ul>\n\n<h3 id=\"410-\u8d1f\u8f7d\u5747\u8861-http_balancer_phasel1126--l1134\">4.10 \u8d1f\u8f7d\u5747\u8861 <code class=\"language-plaintext highlighter-rouge\">http_balancer_phase<\/code>(L1126 ~ L1134)<\/h3>\n\n<p><code class=\"language-plaintext highlighter-rouge\">balancer_by_lua<\/code> \u9636\u6bb5:\u6821\u9a8c <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> \u5b58\u5728\u540e\u8c03\u7528 <code class=\"language-plaintext highlighter-rouge\">load_balancer.run<\/code>,<strong>\u771f\u6b63\u7684\u8282\u70b9\u9009\u62e9(peer \u8bbe\u7f6e)\u53d1\u751f\u5728\u8fd9\u91cc<\/strong>,access \u9636\u6bb5\u7684 <code class=\"language-plaintext highlighter-rouge\">pick_server<\/code> \u53ea\u662f\u9884\u9009\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"5-x-forwarded--\u9632\u4f2a\u9020l613--l688\">5. X-Forwarded-* \u9632\u4f2a\u9020(L613 ~ L688)<\/h2>\n\n<p>\u4e24\u6b65\u8d70,\u914d\u5408\u6a21\u677f\u4e2d <code class=\"language-plaintext highlighter-rouge\">proxy_set_header X-Forwarded-XXX $var_x_forwarded_xxx;<\/code> \u7684\u5199\u6cd5:<\/p>\n\n<ol>\n  <li><code class=\"language-plaintext highlighter-rouge\">handle_x_forwarded_headers<\/code>(access \u9636\u6bb5,\u5bf9<strong>\u975e\u53ef\u4fe1<\/strong>\u6765\u6e90):\n    <ul>\n      <li>\u539f\u59cb\u503c\u5907\u4efd\u5230 <code class=\"language-plaintext highlighter-rouge\">original_x_forwarded_*<\/code>;<\/li>\n      <li>\u7528 APISIX \u81ea\u5df1\u89c2\u6d4b\u5230\u7684\u503c(scheme\u3001host\u3001port)\u8986\u76d6;<\/li>\n      <li>\u6e05\u7a7a <code class=\"language-plaintext highlighter-rouge\">X-Forwarded-For<\/code>(\u7531 <code class=\"language-plaintext highlighter-rouge\">$proxy_add_x_forwarded_for<\/code> \u91cd\u65b0\u751f\u6210)\u548c RFC 7239 <code class=\"language-plaintext highlighter-rouge\">Forwarded<\/code> \u5934;<\/li>\n      <li>\u540c\u6b65\u66f4\u65b0 <code class=\"language-plaintext highlighter-rouge\">var.http_x_forwarded_*<\/code> \u7f13\u5b58\u3002<\/li>\n    <\/ul>\n  <\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">set_upstream_x_forwarded_headers<\/code>(access \u672b\u5c3e):\u628a\u53ef\u4fe1\u503c\u5199\u56de <code class=\"language-plaintext highlighter-rouge\">var_x_forwarded_*<\/code> \u53d8\u91cf,\u4f7f\u6a21\u677f\u91cc\u7684 proxy_set_header \u751f\u6548\u3002<\/li>\n<\/ol>\n\n<p>\u53ef\u4fe1\u6765\u6e90\u7531 <code class=\"language-plaintext highlighter-rouge\">apisix.utils.trusted-addresses<\/code>(\u57fa\u4e8e <code class=\"language-plaintext highlighter-rouge\">realip_remote_addr<\/code>)\u5224\u65ad\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"6-grpc-\u4e0e-dubbo-\u5185\u90e8\u91cd\u5b9a\u5411l860--l882\">6. gRPC \u4e0e Dubbo \u5185\u90e8\u91cd\u5b9a\u5411(L860 ~ L882)<\/h2>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">dubbo_access_phase<\/code>:\u4ec5\u6062\u590d\u4e0a\u4e0b\u6587;<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">grpc_access_phase<\/code>:\u6062\u590d\u4e0a\u4e0b\u6587 \u2192 <code class=\"language-plaintext highlighter-rouge\">set_grpcs_upstream_param<\/code> \u2192 \u82e5\u5f00\u542f\u6d41\u91cf\u955c\u50cf\u4e14\u52a0\u8f7d\u4e86 apisix-ngx-client,\u8c03\u7528 <code class=\"language-plaintext highlighter-rouge\">enable_mirror()<\/code>\u3002<\/li>\n<\/ul>\n\n<p>\u4e24\u4e2a location \u5171\u4eab\u4e3b server \u7684 header\/body\/log \u9636\u6bb5\u5904\u7406\u5668(\u89c1 \u00a72 \u8868\u683c)\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"7-stream-\u5b50\u7cfb\u7edf\">7. Stream \u5b50\u7cfb\u7edf<\/h2>\n\n<h3 id=\"71-\u521d\u59cb\u5316l1199--l1254\">7.1 \u521d\u59cb\u5316(L1199 ~ L1254)<\/h3>\n\n<p>\u4e0e HTTP \u7c7b\u4f3c\u4f46\u66f4\u7cbe\u7b80:resolver \u2192 \u914d\u7f6e\u4e2d\u5fc3 \u2192 xrpc \u2192 worker \u7ea7\u521d\u59cb\u5316(lrucache\u3001\u914d\u7f6e\u4e2d\u5fc3\u3001plugin\u3001xrpc\u3001router.stream\u3001service\u3001upstream\u3001events\u3001admin\u3001discovery\u3001balancer)\u3002<\/p>\n\n<h3 id=\"72-stream_preread_phasel1257--l1371\">7.2 <code class=\"language-plaintext highlighter-rouge\">stream_preread_phase<\/code>(L1257 ~ L1371)<\/h3>\n\n<ol>\n  <li><strong>mTLS \u6821\u9a8c<\/strong>(L1262,<code class=\"language-plaintext highlighter-rouge\">verify_tls_client<\/code>);<\/li>\n  <li>\u8def\u7531\u5339\u914d <code class=\"language-plaintext highlighter-rouge\">router_stream.match<\/code>;<\/li>\n  <li>\u4e0a\u6e38\u786e\u5b9a:\u4e09\u79cd\u6765\u6e90 \u2014\u2014 <code class=\"language-plaintext highlighter-rouge\">upstream_id<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">service_id<\/code>(merge_service_stream_route)\/ \u8def\u7531\u5185\u8054 upstream(\u542b <code class=\"language-plaintext highlighter-rouge\">has_domain<\/code> DNS \u89e3\u6790);<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">plugin.stream_filter<\/code> \u8fc7\u6ee4\u63d2\u4ef6 \u2192 \u6267\u884c <code class=\"language-plaintext highlighter-rouge\">preread<\/code> \u63d2\u4ef6\u9636\u6bb5;<\/li>\n  <li><strong>\u534f\u8bae\u5206\u53d1<\/strong>(L1350 ~ L1353):\u914d\u7f6e\u4e86 <code class=\"language-plaintext highlighter-rouge\">protocol<\/code> \u65f6\u4ea4\u7ed9 <code class=\"language-plaintext highlighter-rouge\">xrpc.run_protocol<\/code>(\u5982 Redis\u3001Kafka \u534f\u8bae\u63d2\u4ef6),\u5426\u5219\u8d70 TCP \u76f4\u8fde;<\/li>\n  <li>TCP \u76f4\u8fde\u8def\u5f84:set_upstream \u2192 pick_server \u2192 <code class=\"language-plaintext highlighter-rouge\">before_proxy<\/code>\u3002<\/li>\n<\/ol>\n\n<h3 id=\"73-\u540e\u7eed\u9636\u6bb5\">7.3 \u540e\u7eed\u9636\u6bb5<\/h3>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">stream_balancer_phase<\/code>(L1374):\u540c HTTP,\u8c03\u7528 <code class=\"language-plaintext highlighter-rouge\">load_balancer.run<\/code>;<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">stream_log_phase<\/code>(L1386):log \u63d2\u4ef6 \u2192 \u88ab\u52a8\u5065\u5eb7\u68c0\u67e5 \u2192 \u91ca\u653e api_ctx(\u6ce8\u610f\u4e0e HTTP \u4e0d\u540c,\u76f4\u63a5 <code class=\"language-plaintext highlighter-rouge\">plugin.run_plugin(\"log\")<\/code> \u53d6\u56de api_ctx)\u3002<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"8-http-\u8bf7\u6c42\u751f\u547d\u5468\u671f\u603b\u89c8\">8. HTTP \u8bf7\u6c42\u751f\u547d\u5468\u671f\u603b\u89c8<\/h2>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>client \u2500\u2500\u25b6 nginx\n            \u2502  ssl_client_hello_phase: SNI \u5339\u914d\u8bc1\u4e66\u3001\u8bb0\u5f55 client_hello_sni\n            \u2502  ssl_phase: \u8bbe\u7f6e\u8bc1\u4e66\u5230\u4f1a\u8bdd\n            \u2502  access: http_access_phase\n            \u2502    \u251c\u2500 verify_https_client (mTLS)\n            \u2502    \u251c\u2500 URI \u89c4\u8303\u5316 \/ request_uri \u91cd\u5199\n            \u2502    \u251c\u2500 X-Forwarded-* \u9632\u4f2a\u9020\n            \u2502    \u251c\u2500 router_http.match\n            \u2502    \u251c\u2500 plugin_config \/ service \/ consumer \u5408\u5e76\n            \u2502    \u251c\u2500 global rules \u2192 rewrite \u2192 (consumer) \u2192 access \u63d2\u4ef6\n            \u2502    \u251c\u2500 handle_upstream:\n            \u2502    \u2502    \u251c\u2500 \u9009\u4e0a\u6e38\u3001DNS \u89e3\u6790\u3001\u4e0a\u6e38 mTLS \u8bc1\u4e66\n            \u2502    \u2502    \u251c\u2500 pick_server(\u9884\u9009)\n            \u2502    \u2502    \u251c\u2500 before_proxy \u63d2\u4ef6\n            \u2502    \u2502    \u2514\u2500 grpc\/dubbo? \u2500\u2500\u25b6 stash ctx \u2500\u2500\u25b6 ngx.exec(@grpc_pass \/ @dubbo_pass)\n            \u2502    \u2514\u2500 set_upstream_x_forwarded_headers\n            \u2502  balancer: http_balancer_phase \u2500\u2500\u25b6 load_balancer.run(\u771f\u6b63\u9009 peer)\n            \u2502  @grpc_pass \/ @dubbo_pass: fetch ctx \u2500\u2500\u25b6 \u6062\u590d\u4e0a\u4e0b\u6587\n            \u2502  header_filter \/ body_filter: http_header\/body_filter_phase\n            \u2502  log: http_log_phase\n            \u2502    \u2514\u2500 log \u63d2\u4ef6 \u2192 \u88ab\u52a8\u5065\u5eb7\u68c0\u67e5 \u2192 \u91ca\u653e tablepool \u8d44\u6e90\n            \u2514\u2500\u25b6 upstream\n<\/code><\/pre><\/div><\/div>\n\n<hr \/>\n\n<h2 id=\"9-\u5b89\u5168\u8bbe\u8ba1\u8981\u70b9\u6c47\u603b\">9. \u5b89\u5168\u8bbe\u8ba1\u8981\u70b9\u6c47\u603b<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u673a\u5236<\/th>\n      <th>\u4f4d\u7f6e<\/th>\n      <th>\u9632\u62a4\u76ee\u6807<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>TLS \u4f1a\u8bdd\u6062\u590d SNI \u6821\u9a8c<\/td>\n      <td>L318 ~ L331<\/td>\n      <td>\u9632\u6b62\u4f1a\u8bdd\u590d\u7528\u7ed5\u8fc7 mTLS<\/td>\n    <\/tr>\n    <tr>\n      <td>SNI \u4e0e Host \u4e00\u81f4\u6027\u6821\u9a8c<\/td>\n      <td>L417 ~ L426<\/td>\n      <td>\u9632\u6b62\u901a\u914d\u8bc1\u4e66\u8de8\u57df\u91cd\u7528<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">skip_mtls_uri_regex<\/code> \u7cbe\u786e\u5339\u914d<\/td>\n      <td>L362 ~ L368<\/td>\n      <td>\u8bc1\u4e66\u8c41\u514d URI \u7684\u7ed5\u8fc7<\/td>\n    <\/tr>\n    <tr>\n      <td>URI <code class=\"language-plaintext highlighter-rouge\">;<\/code> \u53c2\u6570\u89c4\u8303\u5316 + \u70b9\u6bb5\/\u7f16\u7801\u68c0\u67e5<\/td>\n      <td>L437 ~ L472<\/td>\n      <td>\u8def\u5f84\u53c2\u6570\u6ce8\u5165\u3001\u76ee\u5f55\u7a7f\u8d8a<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">request_uri<\/code> \u91cd\u5199<\/td>\n      <td>L740 ~ L741<\/td>\n      <td>\u672a\u89c4\u8303\u5316 request_uri \u6ce8\u5165<\/td>\n    <\/tr>\n    <tr>\n      <td>X-Forwarded-* \u91cd\u5199\u4e0e Forwarded \u6e05\u9664<\/td>\n      <td>L613 ~ L656<\/td>\n      <td>\u4f2a\u9020\u5ba2\u6237\u7aef\u5730\u5740<\/td>\n    <\/tr>\n    <tr>\n      <td>\u65e5\u5fd7\u8131\u654f<\/td>\n      <td>L281 ~ L283<\/td>\n      <td>\u6253\u5370\u8def\u7531\u524d\u79fb\u9664 plugins\/auth_conf<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"10-\u6027\u80fd\u4e0e\u8d44\u6e90\u7ba1\u7406\u8981\u70b9\">10. \u6027\u80fd\u4e0e\u8d44\u6e90\u7ba1\u7406\u8981\u70b9<\/h2>\n\n<ul>\n  <li><strong>tablepool<\/strong>:<code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> \u5728 access \u9636\u6bb5\u4ece\u6c60\u4e2d\u83b7\u53d6,log \u9636\u6bb5\u7edf\u4e00\u5f52\u8fd8(L1122 \/ L1401);<code class=\"language-plaintext highlighter-rouge\">plugins<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">matched_route_record<\/code> \u540c\u7406\u3002\u82e5\u4e2d\u9014\u5f02\u5e38\u9000\u51fa\u5bfc\u81f4\u672a\u5f52\u8fd8,\u4f1a\u6709\u6cc4\u6f0f\u98ce\u9669,\u56e0\u6b64\u5404\u9636\u6bb5\u5904\u7406\u5668\u90fd\u505a\u4e86\u5b58\u5728\u6027\u5224\u65ad\u3002<\/li>\n  <li><strong>\u60f0\u6027\u53d8\u91cf<\/strong>:<code class=\"language-plaintext highlighter-rouge\">core.ctx.set_vars_meta(api_ctx)<\/code> \u5efa\u7acb <code class=\"language-plaintext highlighter-rouge\">var<\/code> \u5143\u8868,nginx \u53d8\u91cf\u6309\u9700\u8bfb\u53d6\u3002<\/li>\n  <li><strong>localize \u5316<\/strong>:L53 ~ L68 \u628a\u9ad8\u9891\u51fd\u6570(ngx.now\u3001ipairs \u7b49)\u5c40\u90e8\u5316,\u51cf\u5c11\u5168\u5c40\u67e5\u627e\u3002<\/li>\n  <li><strong>JIT \u53c2\u6570<\/strong>:\u89c1 \u00a73.1,\u63a7\u5236 trace \u6570\u91cf\u4e0e\u5185\u5b58\u4e0a\u9650\u3002<\/li>\n  <li><strong>DNS \u89e3\u6790\u7f13\u5b58<\/strong>:<code class=\"language-plaintext highlighter-rouge\">parse_domain_in_route<\/code> \u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">resource.set_nodes_ver_and_nodes<\/code> \u7f13\u5b58\u89e3\u6790\u7ed3\u679c,\u907f\u514d\u6bcf\u6b21\u8bf7\u6c42\u90fd\u505a DNS \u67e5\u8be2\u3002<\/li>\n  <li><strong>\u88ab\u52a8\u5065\u5eb7\u68c0\u67e5<\/strong>:\u53ea\u5728 log \u9636\u6bb5\u4e0a\u62a5,\u4e0d\u5f71\u54cd\u8f6c\u53d1\u8def\u5f84\u3002<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"11-\u6ce8\u610f\u4e8b\u9879\u4e0e\u6613\u9519\u70b9\">11. \u6ce8\u610f\u4e8b\u9879\u4e0e\u6613\u9519\u70b9<\/h2>\n\n<ol>\n  <li><strong>Stream \u4e0e HTTP \u7684\u9000\u51fa\u7801\u8bed\u4e49\u4e0d\u540c<\/strong>:\u540c\u4e00\u51fd\u6570\u91cc\u7528 <code class=\"language-plaintext highlighter-rouge\">is_http<\/code> \u5206\u53c9(\u5982 L510 ~ L514),HTTP \u8fd4\u56de\u5e26 JSON body \u7684 502,Stream \u53ea\u80fd <code class=\"language-plaintext highlighter-rouge\">ngx_exit(1)<\/code>\u3002<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">local_conf<\/code> \u4f1a\u88ab\u53cd\u590d\u5237\u65b0<\/strong>:<code class=\"language-plaintext highlighter-rouge\">http_init_worker<\/code> \u7f13\u5b58\u4e00\u6b21(L160),\u4f46 <code class=\"language-plaintext highlighter-rouge\">set_resp_upstream_status<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">cors_admin<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">status_ready<\/code> \u4e2d\u53c8\u8c03\u7528 <code class=\"language-plaintext highlighter-rouge\">core.config.local_conf()<\/code> \u91cd\u53d6,\u662f\u523b\u610f\u7684(\u72ec\u7acb\u6a21\u5f0f\u4e0b\u914d\u7f6e\u53ef\u80fd\u70ed\u66f4\u65b0)\u3002<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">ssl_client_hello_phase<\/code> \u4e2d api_ctx \u7528\u5b8c\u5373\u8fd8<\/strong>(L214 ~ L215):\u8be5\u9636\u6bb5\u7684 api_ctx \u4e0e access \u9636\u6bb5\u4e0d\u662f\u540c\u4e00\u4e2a,\u4e0d\u80fd\u590d\u7528\u3002<\/li>\n  <li><strong>before_proxy \u7684\u65f6\u673a<\/strong>:\u5fc5\u987b\u5728 <code class=\"language-plaintext highlighter-rouge\">_apisix_proxied<\/code> \u6807\u8bb0\u4e4b\u524d\u6267\u884c,\u56e0\u4e3a before_proxy \u63d2\u4ef6\u53ef\u80fd\u76f4\u63a5 <code class=\"language-plaintext highlighter-rouge\">core.response.exit()<\/code> \u7ed3\u675f\u8bf7\u6c42\u3002<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">fetch_ctx<\/code> \u5fc5\u987b\u6e05\u7a7a <code class=\"language-plaintext highlighter-rouge\">$ctx_ref<\/code><\/strong>(L254):\u9632\u6b62\u53d8\u91cf\u6b8b\u7559\u5bfc\u81f4\u9519\u8bef\u590d\u7528\u3002<\/li>\n<\/ol>\n","category":{"@attributes":{"term":"APISIX"}}},{"title":"APISIX init.lua Source Code Analysis","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/2026-08-16\/apisix-init-lua-analysis-en.html"}},"updated":"2026-08-16T23:00:00+08:00","id":"https:\/\/wy471x.github.io\/2026-08-16\/apisix-init-lua-analysis-en.html","content":"<h1 id=\"apisix-apisixinitlua-source-code-analysis\">APISIX <code class=\"language-plaintext highlighter-rouge\">apisix\/init.lua<\/code> Source Code Analysis<\/h1>\n\n<blockquote>\n  <p>Target: <code class=\"language-plaintext highlighter-rouge\">apisix\/init.lua<\/code> (line numbers are based on the current master branch of the repository)\nThis file is the <strong>request lifecycle entry point<\/strong> of the APISIX gateway, shared by both the HTTP and Stream subsystems.<\/p>\n<\/blockquote>\n\n<hr \/>\n\n<h2 id=\"1-file-positioning\">1. File Positioning<\/h2>\n\n<p><code class=\"language-plaintext highlighter-rouge\">init.lua<\/code> does not handle concrete business logic itself; it takes on three kinds of responsibilities:<\/p>\n\n<ol>\n  <li><strong>Process lifecycle hooks<\/strong>: initialization and cleanup for the <code class=\"language-plaintext highlighter-rouge\">init<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">init_worker<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">exit_worker<\/code> phases;<\/li>\n  <li><strong>Request lifecycle orchestration<\/strong>: invoking the routing, plugin, and load-balancing modules in sequence across Nginx phases (<code class=\"language-plaintext highlighter-rouge\">access<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">balancer<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">header_filter<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">body_filter<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">log<\/code>);<\/li>\n  <li><strong>Security and protocol handling<\/strong>: mTLS verification, URI normalization, X-Forwarded-* anti-spoofing, gRPC\/Dubbo internal redirects, etc.<\/li>\n<\/ol>\n\n<p>The functions in this file are called from the phase directives of the <code class=\"language-plaintext highlighter-rouge\">nginx.conf<\/code> rendered by <code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/ngx_tpl.lua<\/code> (the config template).<\/p>\n\n<hr \/>\n\n<h2 id=\"2-wiring-to-nginx-phases\">2. Wiring to Nginx Phases<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>Nginx directive<\/th>\n      <th>init.lua function<\/th>\n      <th>Template location<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">init_by_lua_block<\/code> (http)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_init(args)<\/code><\/td>\n      <td>ngx_tpl.lua:514<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">init_worker_by_lua_block<\/code> (http)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_init_worker()<\/code><\/td>\n      <td>:523<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">exit_worker_by_lua_block<\/code> (http)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_exit_worker()<\/code><\/td>\n      <td>:527<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">init_by_lua_block<\/code> (stream)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">stream_init(args)<\/code><\/td>\n      <td>:205<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">init_worker_by_lua_block<\/code> (stream)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">stream_init_worker()<\/code><\/td>\n      <td>:209<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ssl_client_hello_by_lua_block<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ssl_client_hello_phase()<\/code><\/td>\n      <td>:234 \/ :772<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ssl_certificate_by_lua_block<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ssl_phase()<\/code><\/td>\n      <td>:238 \/ :776<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">preread_by_lua_block<\/code> (stream)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">stream_preread_phase()<\/code><\/td>\n      <td>:247<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">log_by_lua_block<\/code> (stream)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">stream_log_phase()<\/code><\/td>\n      <td>:259<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">access_by_lua_block<\/code> (http main server)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_access_phase()<\/code><\/td>\n      <td>:830<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">balancer_by_lua_block<\/code> (http upstream)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_balancer_phase()<\/code><\/td>\n      <td>:465 \/ :469 \/ :482<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">header_filter_by_lua_block<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_header_filter_phase()<\/code><\/td>\n      <td>:878 \/ :914 \/ :937<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">body_filter_by_lua_block<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_body_filter_phase()<\/code><\/td>\n      <td>:882 \/ :918 \/ :941<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">log_by_lua_block<\/code> (http)<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_log_phase()<\/code><\/td>\n      <td>:886 \/ :922 \/ :945<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">access_by_lua<\/code> of <code class=\"language-plaintext highlighter-rouge\">location @grpc_pass<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">grpc_access_phase()<\/code><\/td>\n      <td>:893<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">access_by_lua<\/code> of <code class=\"language-plaintext highlighter-rouge\">location @dubbo_pass<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">dubbo_access_phase()<\/code><\/td>\n      <td>:929<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">content_by_lua<\/code> of the control server<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_control()<\/code><\/td>\n      <td>:549<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">content_by_lua<\/code> of <code class=\"language-plaintext highlighter-rouge\">\/apisix\/admin<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http_admin()<\/code><\/td>\n      <td>:645<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">\/apisix\/status<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">status()<\/code><\/td>\n      <td>:561<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">\/apisix\/status\/ready<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">status_ready()<\/code><\/td>\n      <td>:566<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"3-module-load-time-initialization-l17--l88\">3. Module-Load-Time Initialization (L17 ~ L88)<\/h2>\n\n<h3 id=\"31-jit-parameters-l17--l26\">3.1 JIT Parameters (L17 ~ L26)<\/h3>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">if<\/span> <span class=\"nb\">require<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"ffi\"<\/span><span class=\"p\">).<\/span><span class=\"n\">os<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"Linux\"<\/span> <span class=\"k\">then<\/span>\n    <span class=\"nb\">require<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"ngx.re\"<\/span><span class=\"p\">).<\/span><span class=\"n\">opt<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"jit_stack_size\"<\/span><span class=\"p\">,<\/span> <span class=\"mi\">200<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">1024<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<ul>\n  <li>The PCRE JIT stack size is only adjusted on Linux, and it must be placed <strong>before any regex compilation<\/strong> (otherwise it reports \u201cchanging jit stack size is not allowed\u2026\u201d).<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">jit.opt.start(...)<\/code> tuning parameters:\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">minstitch=2<\/code>: stitch traces only when there are at least 2 traces;<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">maxtrace=4000<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">maxrecord=8000<\/code>: cap the number of traces and the record length of a single trace, preventing JIT memory from running away;<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">sizemcode=64<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">maxmcode=4000<\/code>: mcode area size (starts at 64KB, capped at 4000KB);<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">maxirconst=1000<\/code>: IR constant limit.<\/li>\n    <\/ul>\n  <\/li>\n<\/ul>\n\n<h3 id=\"32-module-dependencies-l28--l69\">3.2 Module Dependencies (L28 ~ L69)<\/h3>\n\n<p>Core dependencies and their roles:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Module<\/th>\n      <th>Role<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.patch<\/code><\/td>\n      <td>Runtime patches for OpenResty\/ngx_lua<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.core<\/code><\/td>\n      <td>Infrastructure: logging, json, tablepool, lrucache, etc.<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.plugin<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">plugin_config<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">consumer_group<\/code><\/td>\n      <td>Plugin system, plugin configs, consumer groups<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.router<\/code><\/td>\n      <td>Route matching: <code class=\"language-plaintext highlighter-rouge\">router_http<\/code> (HTTP), <code class=\"language-plaintext highlighter-rouge\">router_ssl<\/code> (certificates), <code class=\"language-plaintext highlighter-rouge\">router_stream<\/code> (Stream)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.upstream<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">apisix.balancer<\/code><\/td>\n      <td>Upstream management, load balancing<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.ssl<\/code><\/td>\n      <td>TLS utilities (SNI, protocols, sessions)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.stream.xrpc<\/code><\/td>\n      <td>Protocol dispatch within the Stream subsystem<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.tracer<\/code><\/td>\n      <td>Distributed tracing spans<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.pubsub.kafka<\/code><\/td>\n      <td>Special handling for kafka-type upstreams<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.utils.trusted-addresses<\/code><\/td>\n      <td>Trusted-address detection (for X-Forwarded-* anti-spoofing)<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"33-key-global-flags\">3.3 Key Global Flags<\/h3>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">local<\/span> <span class=\"n\">is_http<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">false<\/span>\n<span class=\"k\">if<\/span> <span class=\"n\">ngx<\/span><span class=\"p\">.<\/span><span class=\"n\">config<\/span><span class=\"p\">.<\/span><span class=\"n\">subsystem<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"http\"<\/span> <span class=\"k\">then<\/span>\n    <span class=\"n\">is_http<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">true<\/span>\n    <span class=\"n\">control_api_router<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">require<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"apisix.control.router\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">is_http<\/code>: distinguishes the subsystem; within the same codebase, HTTP uses <code class=\"language-plaintext highlighter-rouge\">core.response.exit(...)<\/code> while Stream uses <code class=\"language-plaintext highlighter-rouge\">ngx_exit(...)<\/code>.<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">apisix_base_flags<\/code> (L77 ~ L80): <code class=\"language-plaintext highlighter-rouge\">resty.apisix.patch<\/code> is APISIX\u2019s customized C module (apisix-base); a pcall loading failure degrades to an empty table. A typical use is the <code class=\"language-plaintext highlighter-rouge\">client_cert_verified_in_handshake<\/code> flag at L402 \u2014 when the newer apisix-base has already completed client certificate verification during the handshake, there is no need to check <code class=\"language-plaintext highlighter-rouge\">$ssl_client_verify<\/code> again.<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">apisix_ngx_client<\/code> (L86): from <code class=\"language-plaintext highlighter-rouge\">resty.apisix.client<\/code>, provides <code class=\"language-plaintext highlighter-rouge\">enable_mirror()<\/code> (used at L880 for gRPC traffic mirroring).<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ver_header<\/code> (L84): the response <code class=\"language-plaintext highlighter-rouge\">Server<\/code> header, degraded to <code class=\"language-plaintext highlighter-rouge\">\"APISIX\"<\/code> when <code class=\"language-plaintext highlighter-rouge\">enable_server_tokens=false<\/code> (L162 ~ L164).<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"4-http-subsystem\">4. HTTP Subsystem<\/h2>\n\n<h3 id=\"41-http_init-l91--l110--init-phase\">4.1 <code class=\"language-plaintext highlighter-rouge\">http_init<\/code> (L91 ~ L110) \u2014 init Phase<\/h3>\n\n<ol>\n  <li>Initialize the DNS resolver, ID generator, and environment variables;<\/li>\n  <li>Enable the privileged agent process (for privileged operations such as dynamically setting upstreams);<\/li>\n  <li>Initialize the config center (<code class=\"language-plaintext highlighter-rouge\">core.config.init<\/code>, etcd \/ standalone yaml);<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">xrpc.init()<\/code>.<\/li>\n<\/ol>\n\n<h3 id=\"42-http_init_worker-l113--l171--init_worker-phase\">4.2 <code class=\"language-plaintext highlighter-rouge\">http_init_worker<\/code> (L113 ~ L171) \u2014 init_worker Phase<\/h3>\n\n<p>Initializes each subsystem in order, <strong>the order reflecting their dependencies<\/strong>:<\/p>\n\n<ol>\n  <li><strong>Random seed<\/strong>: preferentially taken from <code class=\"language-plaintext highlighter-rouge\">\/dev\/urandom<\/code> (L114); the \u201crandom test\u201d log at L121 is actually a <strong>probe for test assertions<\/strong> (tests rely on it to confirm that init_worker has executed);<\/li>\n  <li>Event system, lrucache, service discovery, balancer, admin, background timers, debug;<\/li>\n  <li>Worker-level initialization of the config center;<\/li>\n  <li>Plugin system: plugin \u2192 router \u2192 service \u2192 plugin_config \u2192 consumer \u2192 consumer_group \u2192 secret \u2192 global_rules \u2192 upstream \u2192 ext-plugin;<\/li>\n  <li>Control API router, <code class=\"language-plaintext highlighter-rouge\">local_conf<\/code> cache, <code class=\"language-plaintext highlighter-rouge\">Server<\/code> header version;<\/li>\n  <li>Prometheus plugin initialization (must come last so that metrics of all workers are ready);<\/li>\n  <li>Trusted-address utility.<\/li>\n<\/ol>\n\n<h3 id=\"43-tls--mtls-handling\">4.3 TLS \/ mTLS Handling<\/h3>\n\n<h4 id=\"ssl_phase-l182--l190\"><code class=\"language-plaintext highlighter-rouge\">ssl_phase<\/code> (L182 ~ L190)<\/h4>\n\n<p><code class=\"language-plaintext highlighter-rouge\">ssl_certificate_by_lua<\/code> phase: sets the certificate config matched during the <code class=\"language-plaintext highlighter-rouge\">ssl_client_hello_phase<\/code> (<code class=\"language-plaintext highlighter-rouge\">ngx.ctx.matched_ssl<\/code>) on the current TLS session.<\/p>\n\n<h4 id=\"ssl_client_hello_phase-l193--l240\"><code class=\"language-plaintext highlighter-rouge\">ssl_client_hello_phase<\/code> (L193 ~ L240)<\/h4>\n\n<ul>\n  <li><strong>Must obtain the SNI<\/strong> (L195 ~ L200); exit directly if unavailable (accessing by IP, or a too-old protocol);<\/li>\n  <li>Read the OCSP <code class=\"language-plaintext highlighter-rouge\">status_request<\/code> extension;<\/li>\n  <li>Take <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> from tablepool for matching (note L214 releases it immediately after use; it is not reused in this phase);<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">router_ssl.match_and_set(api_ctx, true, sni)<\/code> matches the SNI certificate;<\/li>\n  <li>Dynamically set <code class=\"language-plaintext highlighter-rouge\">ssl_protocols<\/code> according to the match result (L228);<\/li>\n  <li><strong>L238<\/strong>: store the SNI into <code class=\"language-plaintext highlighter-rouge\">ngx.ctx.client_hello_sni<\/code> \u2014 because in the Stream subsystem\u2019s preread phase, <code class=\"language-plaintext highlighter-rouge\">ngx.ssl.server_name()<\/code> returns the session hostname rather than the real SNI; recording it here allows later verification.<\/li>\n<\/ul>\n\n<h4 id=\"the-three-mtls-verification-functions\">The Three mTLS Verification Functions<\/h4>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">verify_tls_session_resumption<\/code> (L318 ~ L331): <strong>TLS session resumption security check<\/strong>. When a session is resumed, verify that the hostname in the session matches the SNI of the current client hello, preventing mTLS from being bypassed via session resumption.<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">verify_tls_client<\/code> (L334 ~ L359, <strong>used by Stream<\/strong>): re-match the certificate by SNI; if a <code class=\"language-plaintext highlighter-rouge\">client<\/code> certificate is configured and client verification is supported, check <code class=\"language-plaintext highlighter-rouge\">$ssl_client_verify == \"SUCCESS\"<\/code> and perform the session-resumption check.<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">verify_https_client<\/code> (L371 ~ L434, <strong>used by HTTP<\/strong>):\n    <ol>\n      <li>Support <code class=\"language-plaintext highlighter-rouge\">skip_mtls_uri_regex<\/code>: exempt matching URIs from client certificates (L363 ~ L368, L381);<\/li>\n      <li>Certificate verification (preferentially trusting the handshake-time verification flag from apisix-base, L402);<\/li>\n      <li><strong>SNI vs Host consistency check<\/strong> (L417 ~ L426): prevent cross-domain certificate reuse where a user configures a <code class=\"language-plaintext highlighter-rouge\">*.domain<\/code> wildcard certificate but accesses with SNI <code class=\"language-plaintext highlighter-rouge\">a.domain<\/code> while carrying Host <code class=\"language-plaintext highlighter-rouge\">b.domain<\/code>;<\/li>\n      <li>Session-resumption check.<\/li>\n    <\/ol>\n  <\/li>\n<\/ul>\n\n<h3 id=\"44-http_access_phase-l691--l857--core-of-the-access-phase\">4.4 <code class=\"language-plaintext highlighter-rouge\">http_access_phase<\/code> (L691 ~ L857) \u2014 Core of the access Phase<\/h3>\n\n<p>Execution order:<\/p>\n\n<ol>\n  <li><strong>HTTP\/3 adaptation<\/strong> (L694 ~ L696): when <code class=\"language-plaintext highlighter-rouge\">ngx.req.http_version() == 3<\/code>, convert the <code class=\"language-plaintext highlighter-rouge\">:authority<\/code> pseudo-header into <code class=\"language-plaintext highlighter-rouge\">upstream_host<\/code>;<\/li>\n  <li><strong>api_ctx creation<\/strong> (L700 ~ L704): take from tablepool, attach to <code class=\"language-plaintext highlighter-rouge\">ngx.ctx<\/code>, and initialize the <code class=\"language-plaintext highlighter-rouge\">var<\/code> metatable (lazily reads nginx variables);<\/li>\n  <li><strong>mTLS verification<\/strong> (L708);<\/li>\n  <li><strong>Dynamic debugging<\/strong> (L712);<\/li>\n  <li><strong>URI normalization<\/strong> (L714 ~ L735):\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">delete_uri_tail_slash<\/code>: remove the trailing <code class=\"language-plaintext highlighter-rouge\">\/<\/code>;<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">normalize_uri_like_servlet<\/code>: emulate Java Servlet semantics, truncate path parameters after <code class=\"language-plaintext highlighter-rouge\">;<\/code>, and perform anti-bypass checks (<code class=\"language-plaintext highlighter-rouge\">.<\/code>\/<code class=\"language-plaintext highlighter-rouge\">..<\/code> segments, empty segments, <code class=\"language-plaintext highlighter-rouge\">%2e<\/code> encoded dot segments);<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong>request_uri anti-injection rewrite<\/strong> (L740 ~ L741): only the normalized URI is written into <code class=\"language-plaintext highlighter-rouge\">request_uri<\/code>; the original value is stored in <code class=\"language-plaintext highlighter-rouge\">real_request_uri<\/code>;<\/li>\n  <li><strong>X-Forwarded-* anti-spoofing<\/strong> (L743, see \u00a75.4);<\/li>\n  <li><strong>Route matching<\/strong> (L745 ~ L759): <code class=\"language-plaintext highlighter-rouge\">router.router_http.match(api_ctx)<\/code>; on a miss \u2192 still run global rules \u2192 return 404;<\/li>\n  <li><strong>Config merging<\/strong> (L767 ~ L802): <code class=\"language-plaintext highlighter-rouge\">plugin_config<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">service<\/code> (merge_service_route), set context fields such as <code class=\"language-plaintext highlighter-rouge\">conf_type<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">conf_version<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">conf_id<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">route_id<\/code>;<\/li>\n  <li><strong>Run global rules<\/strong> (L807 ~ L808);<\/li>\n  <li><strong>Plugin\/script execution<\/strong> (L810 ~ L851):\n    <ul>\n      <li>Script routes: directly <code class=\"language-plaintext highlighter-rouge\">script.run(\"access\")<\/code>;<\/li>\n      <li>Plugin routes: <code class=\"language-plaintext highlighter-rouge\">plugin.filter<\/code> filters out the plugins active on this route \u2192 run the <code class=\"language-plaintext highlighter-rouge\">rewrite<\/code> phase first \u2192 if the rewrite phase produced a <code class=\"language-plaintext highlighter-rouge\">consumer<\/code> (e.g., key-auth succeeded), merge the consumer \/ consumer_group config; if the config changed, <strong>re-filter and additionally run the <code class=\"language-plaintext highlighter-rouge\">rewrite_in_consumer<\/code> phase<\/strong> \u2192 finally run the <code class=\"language-plaintext highlighter-rouge\">access<\/code> phase;<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">handle_upstream<\/code><\/strong> (L854);<\/li>\n  <li><strong>Set upstream X-Forwarded-* headers<\/strong> (L856).<\/li>\n<\/ol>\n\n<h3 id=\"45-handle_upstream-l493--l610\">4.5 <code class=\"language-plaintext highlighter-rouge\">handle_upstream<\/code> (L493 ~ L610)<\/h3>\n\n<ol>\n  <li><code class=\"language-plaintext highlighter-rouge\">bypass_nginx_upstream<\/code>: when a plugin (e.g., ai-proxy) requests the upstream with its own HTTP client, skip the nginx proxy and only run the <code class=\"language-plaintext highlighter-rouge\">before_proxy<\/code> plugin phase (L495 ~ L498);<\/li>\n  <li>Determine the upstream: <code class=\"language-plaintext highlighter-rouge\">upstream_id<\/code> \/ traffic-split overridden <code class=\"language-plaintext highlighter-rouge\">upstream_id<\/code> (L500 ~ L535); routes with domain nodes (<code class=\"language-plaintext highlighter-rouge\">has_domain<\/code>) trigger <code class=\"language-plaintext highlighter-rouge\">parse_domain_in_route<\/code> (L258 ~ L287) for DNS resolution, maintaining node versions via <code class=\"language-plaintext highlighter-rouge\">_nodes_ver<\/code> and the <code class=\"language-plaintext highlighter-rouge\">resource<\/code> module;<\/li>\n  <li><strong>Upstream mTLS<\/strong> (L537 ~ L558): <code class=\"language-plaintext highlighter-rouge\">upstream.tls.client_cert_id<\/code> fetches the client certificate from <code class=\"language-plaintext highlighter-rouge\">router_ssl<\/code>;<\/li>\n  <li><strong>WebSocket<\/strong> (L560 ~ L564): pass through the <code class=\"language-plaintext highlighter-rouge\">Upgrade<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">Connection<\/code> headers;<\/li>\n  <li><strong>kafka upstream<\/strong>: handed over to <code class=\"language-plaintext highlighter-rouge\">pubsub_kafka.access<\/code> (L569 ~ L571);<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">set_upstream<\/code> sets proxy parameters \u2192 <code class=\"language-plaintext highlighter-rouge\">load_balancer.pick_server<\/code> selects a node (L573 ~ L587);<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">set_upstream_headers<\/code> (L587): set the Host according to <code class=\"language-plaintext highlighter-rouge\">pass_host<\/code> semantics (<code class=\"language-plaintext highlighter-rouge\">pass<\/code>\/<code class=\"language-plaintext highlighter-rouge\">rewrite<\/code>\/<code class=\"language-plaintext highlighter-rouge\">node<\/code>, L290 ~ L308);<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">before_proxy<\/code> runs early<\/strong> (L590): the before_proxy plugins run in the access phase; the comment explains that this is to \u201cavoid always reinitializing the request\u201d;<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">_apisix_proxied<\/code> marker<\/strong> (L592 ~ L598): must be set after before_proxy and before the proxy_pass dispatch; the log phase uses it to distinguish \u201cnginx proxy errors\u201d from \u201cupstream responses\u201d;<\/li>\n  <li><strong>gRPC \/ Dubbo dispatch<\/strong> (L600 ~ L609): <code class=\"language-plaintext highlighter-rouge\">stash_ngx_ctx()<\/code> then <code class=\"language-plaintext highlighter-rouge\">ngx.exec(\"@grpc_pass\")<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">\"@dubbo_pass\"<\/code>.<\/li>\n<\/ol>\n\n<h3 id=\"46-passing-context-across-internal-redirects-l243--l256\">4.6 Passing Context Across Internal Redirects (L243 ~ L256)<\/h3>\n\n<p><code class=\"language-plaintext highlighter-rouge\">ngx.exec<\/code> internal redirects <strong>lose <code class=\"language-plaintext highlighter-rouge\">ngx.ctx<\/code><\/strong>; APISIX solves this with <code class=\"language-plaintext highlighter-rouge\">resty.ctxdump<\/code>:<\/p>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">stash_ngx_ctx()<\/code>: <code class=\"language-plaintext highlighter-rouge\">ctxdump.stash_ngx_ctx()<\/code> serializes the context; the reference number is written into the nginx variable <code class=\"language-plaintext highlighter-rouge\">$ctx_ref<\/code>;<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">fetch_ctx()<\/code>: restores <code class=\"language-plaintext highlighter-rouge\">ngx.ctx<\/code> in the target location by reference number, and clears the variable.<\/li>\n<\/ul>\n\n<h3 id=\"47-response-and-log-phases\">4.7 Response and Log Phases<\/h3>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">http_header_filter_phase<\/code> (L910 ~ L938):\n    <ul>\n      <li>Sets the <code class=\"language-plaintext highlighter-rouge\">Server<\/code> header;<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">X-APISIX-Upstream-Status<\/code>: shows the upstream status code per configuration, by default only on 5xx (L885 ~ L907);<\/li>\n      <li>Runs the <code class=\"language-plaintext highlighter-rouge\">header_filter<\/code> plugin phase;<\/li>\n      <li>Outputs the debug header <code class=\"language-plaintext highlighter-rouge\">Apisix-Plugins<\/code> (L927 ~ L934);<\/li>\n      <li>Pre-creates the span for the body_filter phase at the end.<\/li>\n    <\/ul>\n  <\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">http_body_filter_phase<\/code> (L941 ~ L944): runs the <code class=\"language-plaintext highlighter-rouge\">body_filter<\/code> and <code class=\"language-plaintext highlighter-rouge\">delayed_body_filter<\/code> plugin phases.<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">http_log_phase<\/code> (L1088 ~ L1123):\n    <ol>\n      <li>End all tracer spans;<\/li>\n      <li>Fallback for <code class=\"language-plaintext highlighter-rouge\">apisix_upstream_response_time<\/code>;<\/li>\n      <li>Run the <code class=\"language-plaintext highlighter-rouge\">log<\/code> plugin phase;<\/li>\n      <li><strong>Passive health check reporting<\/strong> (L1104, \u00a74.8);<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">after_balance<\/code> hook;<\/li>\n      <li><strong>Unified resource release<\/strong>: release_vars, release the <code class=\"language-plaintext highlighter-rouge\">plugins<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">matched_route_record<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> tablepool objects \u2014 everything borrowed from tablepool in the access phase is returned here.<\/li>\n    <\/ol>\n  <\/li>\n<\/ul>\n\n<h3 id=\"48-passive-health-check-healthcheck_passive-l947--l1006\">4.8 Passive Health Check <code class=\"language-plaintext highlighter-rouge\">healthcheck_passive<\/code> (L947 ~ L1006)<\/h3>\n\n<ul>\n  <li>Depends on <code class=\"language-plaintext highlighter-rouge\">api_ctx.up_checker<\/code> (created in the balancer phase);<\/li>\n  <li>HTTP: reports according to the configured healthy\/unhealthy <code class=\"language-plaintext highlighter-rouge\">http_statuses<\/code>;<\/li>\n  <li>Stream: reports TCP failure for anything other than 200.<\/li>\n<\/ul>\n\n<h3 id=\"49-admin--control-interfaces\">4.9 Admin \/ Control Interfaces<\/h3>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">status<\/code> (L1009): directly returns 200;<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">status_ready<\/code> (L1064): readiness probe, two checks:\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">config_ready_check<\/code> (L1031): the role\u2019s config_provider must be yaml\/etcd; the <code class=\"language-plaintext highlighter-rouge\">status-report<\/code> shdict must contain <strong>a ready record for every worker<\/strong> (key count == worker count, and values non-empty);<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">discovery_ready_check<\/code> (L1014): each service discovery module may optionally implement <code class=\"language-plaintext highlighter-rouge\">check_discovery_ready<\/code>;<\/li>\n    <\/ul>\n  <\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">http_admin<\/code> (L1169): Admin API route dispatch + CORS (OPTIONS preflight returns 200 directly) + JSON Content-Type; the router instance is cached in a do-block upvalue and initialized only once;<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">http_control<\/code> (L1191): control API route matching.<\/li>\n<\/ul>\n\n<h3 id=\"410-load-balancing-http_balancer_phase-l1126--l1134\">4.10 Load Balancing <code class=\"language-plaintext highlighter-rouge\">http_balancer_phase<\/code> (L1126 ~ L1134)<\/h3>\n\n<p><code class=\"language-plaintext highlighter-rouge\">balancer_by_lua<\/code> phase: verifies that <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> exists, then calls <code class=\"language-plaintext highlighter-rouge\">load_balancer.run<\/code>; <strong>the real node selection (peer setting) happens here<\/strong> \u2014 the <code class=\"language-plaintext highlighter-rouge\">pick_server<\/code> in the access phase is only a pre-selection.<\/p>\n\n<hr \/>\n\n<h2 id=\"5-x-forwarded--anti-spoofing-l613--l688\">5. X-Forwarded-* Anti-Spoofing (L613 ~ L688)<\/h2>\n\n<p>Two steps, working with the template\u2019s <code class=\"language-plaintext highlighter-rouge\">proxy_set_header X-Forwarded-XXX $var_x_forwarded_xxx;<\/code> pattern:<\/p>\n\n<ol>\n  <li><code class=\"language-plaintext highlighter-rouge\">handle_x_forwarded_headers<\/code> (access phase, for <strong>untrusted<\/strong> sources):\n    <ul>\n      <li>Back up the original values to <code class=\"language-plaintext highlighter-rouge\">original_x_forwarded_*<\/code>;<\/li>\n      <li>Overwrite them with the values observed by APISIX itself (scheme, host, port);<\/li>\n      <li>Clear <code class=\"language-plaintext highlighter-rouge\">X-Forwarded-For<\/code> (regenerated by <code class=\"language-plaintext highlighter-rouge\">$proxy_add_x_forwarded_for<\/code>) and the RFC 7239 <code class=\"language-plaintext highlighter-rouge\">Forwarded<\/code> header;<\/li>\n      <li>Sync the <code class=\"language-plaintext highlighter-rouge\">var.http_x_forwarded_*<\/code> cache.<\/li>\n    <\/ul>\n  <\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">set_upstream_x_forwarded_headers<\/code> (end of access): write the trusted values back into the <code class=\"language-plaintext highlighter-rouge\">var_x_forwarded_*<\/code> variables so that the proxy_set_header in the template takes effect.<\/li>\n<\/ol>\n\n<p>Trusted sources are determined by <code class=\"language-plaintext highlighter-rouge\">apisix.utils.trusted-addresses<\/code> (based on <code class=\"language-plaintext highlighter-rouge\">realip_remote_addr<\/code>).<\/p>\n\n<hr \/>\n\n<h2 id=\"6-grpc-and-dubbo-internal-redirects-l860--l882\">6. gRPC and Dubbo Internal Redirects (L860 ~ L882)<\/h2>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">dubbo_access_phase<\/code>: only restores the context;<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">grpc_access_phase<\/code>: restores the context \u2192 <code class=\"language-plaintext highlighter-rouge\">set_grpcs_upstream_param<\/code> \u2192 if traffic mirroring is enabled and apisix-ngx-client is loaded, calls <code class=\"language-plaintext highlighter-rouge\">enable_mirror()<\/code>.<\/li>\n<\/ul>\n\n<p>Both locations share the main server\u2019s header\/body\/log phase handlers (see the table in \u00a72).<\/p>\n\n<hr \/>\n\n<h2 id=\"7-stream-subsystem\">7. Stream Subsystem<\/h2>\n\n<h3 id=\"71-initialization-l1199--l1254\">7.1 Initialization (L1199 ~ L1254)<\/h3>\n\n<p>Similar to HTTP but leaner: resolver \u2192 config center \u2192 xrpc \u2192 worker-level initialization (lrucache, config center, plugin, xrpc, router.stream, service, upstream, events, admin, discovery, balancer).<\/p>\n\n<h3 id=\"72-stream_preread_phase-l1257--l1371\">7.2 <code class=\"language-plaintext highlighter-rouge\">stream_preread_phase<\/code> (L1257 ~ L1371)<\/h3>\n\n<ol>\n  <li><strong>mTLS verification<\/strong> (L1262, <code class=\"language-plaintext highlighter-rouge\">verify_tls_client<\/code>);<\/li>\n  <li>Route matching <code class=\"language-plaintext highlighter-rouge\">router_stream.match<\/code>;<\/li>\n  <li>Upstream determination: three sources \u2014 <code class=\"language-plaintext highlighter-rouge\">upstream_id<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">service_id<\/code> (merge_service_stream_route) \/ route inline upstream (including <code class=\"language-plaintext highlighter-rouge\">has_domain<\/code> DNS resolution);<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">plugin.stream_filter<\/code> filters plugins \u2192 run the <code class=\"language-plaintext highlighter-rouge\">preread<\/code> plugin phase;<\/li>\n  <li><strong>Protocol dispatch<\/strong> (L1350 ~ L1353): when <code class=\"language-plaintext highlighter-rouge\">protocol<\/code> is configured, hand over to <code class=\"language-plaintext highlighter-rouge\">xrpc.run_protocol<\/code> (e.g., Redis, Kafka protocol plugins); otherwise, direct TCP passthrough;<\/li>\n  <li>TCP direct path: set_upstream \u2192 pick_server \u2192 <code class=\"language-plaintext highlighter-rouge\">before_proxy<\/code>.<\/li>\n<\/ol>\n\n<h3 id=\"73-subsequent-phases\">7.3 Subsequent Phases<\/h3>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">stream_balancer_phase<\/code> (L1374): same as HTTP, calls <code class=\"language-plaintext highlighter-rouge\">load_balancer.run<\/code>;<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">stream_log_phase<\/code> (L1386): log plugins \u2192 passive health check \u2192 release api_ctx (note that, unlike HTTP, it directly does <code class=\"language-plaintext highlighter-rouge\">plugin.run_plugin(\"log\")<\/code> and retrieves api_ctx).<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"8-http-request-lifecycle-overview\">8. HTTP Request Lifecycle Overview<\/h2>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>client \u2500\u2500\u25b6 nginx\n            \u2502  ssl_client_hello_phase: match certificate by SNI, record client_hello_sni\n            \u2502  ssl_phase: set certificate on the session\n            \u2502  access: http_access_phase\n            \u2502    \u251c\u2500 verify_https_client (mTLS)\n            \u2502    \u251c\u2500 URI normalization \/ request_uri rewrite\n            \u2502    \u251c\u2500 X-Forwarded-* anti-spoofing\n            \u2502    \u251c\u2500 router_http.match\n            \u2502    \u251c\u2500 plugin_config \/ service \/ consumer merge\n            \u2502    \u251c\u2500 global rules \u2192 rewrite \u2192 (consumer) \u2192 access plugins\n            \u2502    \u251c\u2500 handle_upstream:\n            \u2502    \u2502    \u251c\u2500 select upstream, DNS resolution, upstream mTLS certificate\n            \u2502    \u2502    \u251c\u2500 pick_server (pre-selection)\n            \u2502    \u2502    \u251c\u2500 before_proxy plugins\n            \u2502    \u2502    \u2514\u2500 grpc\/dubbo? \u2500\u2500\u25b6 stash ctx \u2500\u2500\u25b6 ngx.exec(@grpc_pass \/ @dubbo_pass)\n            \u2502    \u2514\u2500 set_upstream_x_forwarded_headers\n            \u2502  balancer: http_balancer_phase \u2500\u2500\u25b6 load_balancer.run (real peer selection)\n            \u2502  @grpc_pass \/ @dubbo_pass: fetch ctx \u2500\u2500\u25b6 restore context\n            \u2502  header_filter \/ body_filter: http_header\/body_filter_phase\n            \u2502  log: http_log_phase\n            \u2502    \u2514\u2500 log plugins \u2192 passive health check \u2192 release tablepool resources\n            \u2514\u2500\u25b6 upstream\n<\/code><\/pre><\/div><\/div>\n\n<hr \/>\n\n<h2 id=\"9-security-design-highlights\">9. Security Design Highlights<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>Mechanism<\/th>\n      <th>Location<\/th>\n      <th>Protects against<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>TLS session resumption SNI check<\/td>\n      <td>L318 ~ L331<\/td>\n      <td>bypassing mTLS via session reuse<\/td>\n    <\/tr>\n    <tr>\n      <td>SNI vs Host consistency check<\/td>\n      <td>L417 ~ L426<\/td>\n      <td>wildcard certificate cross-domain reuse<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">skip_mtls_uri_regex<\/code> exact matching<\/td>\n      <td>L362 ~ L368<\/td>\n      <td>bypass of certificate-exempt URIs<\/td>\n    <\/tr>\n    <tr>\n      <td>URI <code class=\"language-plaintext highlighter-rouge\">;<\/code> parameter normalization + dot-segment\/encoding checks<\/td>\n      <td>L437 ~ L472<\/td>\n      <td>path parameter injection, directory traversal<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">request_uri<\/code> rewrite<\/td>\n      <td>L740 ~ L741<\/td>\n      <td>injection via unnormalized request_uri<\/td>\n    <\/tr>\n    <tr>\n      <td>X-Forwarded-* rewrite and Forwarded clearing<\/td>\n      <td>L613 ~ L656<\/td>\n      <td>spoofed client addresses<\/td>\n    <\/tr>\n    <tr>\n      <td>Log redaction<\/td>\n      <td>L281 ~ L283<\/td>\n      <td>removes plugins\/auth_conf before printing routes<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"10-performance-and-resource-management-highlights\">10. Performance and Resource Management Highlights<\/h2>\n\n<ul>\n  <li><strong>tablepool<\/strong>: <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> is fetched from the pool in the access phase and returned in the log phase (L1122 \/ L1401); same for <code class=\"language-plaintext highlighter-rouge\">plugins<\/code> and <code class=\"language-plaintext highlighter-rouge\">matched_route_record<\/code>. Exiting abnormally without returning them risks leaks, so every phase handler performs existence checks.<\/li>\n  <li><strong>Lazy variables<\/strong>: <code class=\"language-plaintext highlighter-rouge\">core.ctx.set_vars_meta(api_ctx)<\/code> builds the <code class=\"language-plaintext highlighter-rouge\">var<\/code> metatable; nginx variables are read on demand.<\/li>\n  <li><strong>Localization<\/strong>: L53 ~ L68 localizes hot functions (ngx.now, ipairs, etc.) to reduce global lookups.<\/li>\n  <li><strong>JIT parameters<\/strong>: see \u00a73.1, controlling trace count and memory caps.<\/li>\n  <li><strong>DNS resolution cache<\/strong>: <code class=\"language-plaintext highlighter-rouge\">parse_domain_in_route<\/code> caches resolution results via <code class=\"language-plaintext highlighter-rouge\">resource.set_nodes_ver_and_nodes<\/code>, avoiding a DNS query on every request.<\/li>\n  <li><strong>Passive health check<\/strong>: only reported in the log phase, off the forwarding path.<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"11-notes-and-pitfalls\">11. Notes and Pitfalls<\/h2>\n\n<ol>\n  <li><strong>Stream and HTTP differ in exit-code semantics<\/strong>: the same function branches on <code class=\"language-plaintext highlighter-rouge\">is_http<\/code> (e.g., L510 ~ L514) \u2014 HTTP returns 502 with a JSON body; Stream can only <code class=\"language-plaintext highlighter-rouge\">ngx_exit(1)<\/code>.<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">local_conf<\/code> gets refreshed repeatedly<\/strong>: cached once in <code class=\"language-plaintext highlighter-rouge\">http_init_worker<\/code> (L160), but <code class=\"language-plaintext highlighter-rouge\">set_resp_upstream_status<\/code>, <code class=\"language-plaintext highlighter-rouge\">cors_admin<\/code>, and <code class=\"language-plaintext highlighter-rouge\">status_ready<\/code> call <code class=\"language-plaintext highlighter-rouge\">core.config.local_conf()<\/code> again \u2014 deliberate (config may be hot-updated in standalone mode).<\/li>\n  <li><strong>The api_ctx in <code class=\"language-plaintext highlighter-rouge\">ssl_client_hello_phase<\/code> is returned right after use<\/strong> (L214 ~ L215): it is not the same api_ctx as in the access phase and cannot be reused.<\/li>\n  <li><strong>before_proxy timing<\/strong>: it must run before the <code class=\"language-plaintext highlighter-rouge\">_apisix_proxied<\/code> marker, because before_proxy plugins may end the request directly with <code class=\"language-plaintext highlighter-rouge\">core.response.exit()<\/code>.<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">fetch_ctx<\/code> must clear <code class=\"language-plaintext highlighter-rouge\">$ctx_ref<\/code><\/strong> (L254): prevents residual variables from causing erroneous reuse.<\/li>\n<\/ol>\n","category":{"@attributes":{"term":"APISIX"}}},{"title":"Easegress \u6e90\u7801\u9605\u8bfb\u6307\u5357","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/2026-07-31\/easegress-source-code-guide.html"}},"updated":"2026-07-31T23:00:00+08:00","id":"https:\/\/wy471x.github.io\/2026-07-31\/easegress-source-code-guide.html","content":"<h1 id=\"easegress-\u6e90\u7801\u9605\u8bfb\u6307\u5357\">Easegress \u6e90\u7801\u9605\u8bfb\u6307\u5357<\/h1>\n\n<h2 id=\"\u76ee\u5f55\">\u76ee\u5f55<\/h2>\n\n<ul>\n  <li><a href=\"#1-\u9879\u76ee\u6982\u89c8\">1. \u9879\u76ee\u6982\u89c8<\/a><\/li>\n  <li><a href=\"#2-\u6784\u5efa\u4e0e\u8fd0\u884c\">2. \u6784\u5efa\u4e0e\u8fd0\u884c<\/a><\/li>\n  <li><a href=\"#3-\u542f\u52a8\u6d41\u7a0b\">3. \u542f\u52a8\u6d41\u7a0b<\/a><\/li>\n  <li><a href=\"#4-\u6838\u5fc3\u67b6\u6784\">4. \u6838\u5fc3\u67b6\u6784<\/a>\n    <ul>\n      <li><a href=\"#41-object-\u4f53\u7cfb\u5bf9\u8c61\u6ce8\u518c\u4e0e\u751f\u547d\u5468\u671f\">4.1 Object \u4f53\u7cfb\uff08\u5bf9\u8c61\u6ce8\u518c\u4e0e\u751f\u547d\u5468\u671f\uff09<\/a><\/li>\n      <li><a href=\"#42-spec-\u7cfb\u7edf\u58f0\u660e\u5f0f\u914d\u7f6e\">4.2 Spec \u7cfb\u7edf\uff08\u58f0\u660e\u5f0f\u914d\u7f6e\uff09<\/a><\/li>\n      <li><a href=\"#43-supervisor\u751f\u547d\u5468\u671f\u7ba1\u7406\">4.3 Supervisor\uff08\u751f\u547d\u5468\u671f\u7ba1\u7406\uff09<\/a><\/li>\n      <li><a href=\"#44-cluster\u96c6\u7fa4\u4e0e\u5b58\u50a8\">4.4 Cluster\uff08\u96c6\u7fa4\u4e0e\u5b58\u50a8\uff09<\/a><\/li>\n      <li><a href=\"#45-traffic-pipeline\u6d41\u91cf\u7ba1\u7ebf\">4.5 Traffic Pipeline\uff08\u6d41\u91cf\u7ba1\u7ebf\uff09<\/a><\/li>\n      <li><a href=\"#46-filter-\u4f53\u7cfb\u8fc7\u6ee4\u5668\">4.6 Filter \u4f53\u7cfb\uff08\u8fc7\u6ee4\u5668\uff09<\/a><\/li>\n      <li><a href=\"#47-protocol-\u62bd\u8c61\u534f\u8bae\u5c42\">4.7 Protocol \u62bd\u8c61\uff08\u534f\u8bae\u5c42\uff09<\/a><\/li>\n      <li><a href=\"#48-resilience\u5f39\u6027\u7b56\u7565\">4.8 Resilience\uff08\u5f39\u6027\u7b56\u7565\uff09<\/a><\/li>\n      <li><a href=\"#49-admin-api\">4.9 Admin API<\/a><\/li>\n      <li><a href=\"#410-\u6821\u9a8c\u7cfb\u7edf\">4.10 \u6821\u9a8c\u7cfb\u7edf<\/a><\/li>\n    <\/ul>\n  <\/li>\n  <li><a href=\"#5-\u5bf9\u8c61\u5206\u7c7b\u8be6\u89e3\">5. \u5bf9\u8c61\u5206\u7c7b\u8be6\u89e3<\/a><\/li>\n  <li><a href=\"#6-\u9605\u8bfb\u8def\u5f84\u5efa\u8bae\">6. \u9605\u8bfb\u8def\u5f84\u5efa\u8bae<\/a><\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"1-\u9879\u76ee\u6982\u89c8\">1. \u9879\u76ee\u6982\u89c8<\/h2>\n\n<p><strong>Easegress<\/strong> \u662f\u4e00\u4e2a\u4e91\u539f\u751f\u6d41\u91cf\u7f16\u6392\uff08Traffic Orchestration\uff09\u7f51\u5173\uff0c\u7531 Go \u8bed\u8a00\u7f16\u5199\uff0c\u91c7\u7528\u58f0\u660e\u5f0f\u914d\u7f6e + \u63a7\u5236\u5668\u6a21\u5f0f\u7ba1\u7406\u6240\u6709\u7ec4\u4ef6\u3002\u9879\u76ee\u4f7f\u7528 etcd \u505a\u5206\u5e03\u5f0f\u914d\u7f6e\u5b58\u50a8\uff0c\u652f\u6301 HTTP\/gRPC\/MQTT \u7b49\u591a\u534f\u8bae\u4ee3\u7406\u3002<\/p>\n\n<ul>\n  <li><strong>\u4ed3\u5e93\u5730\u5740<\/strong>\uff1a<code class=\"language-plaintext highlighter-rouge\">github.com\/megaease\/easegress\/v2<\/code><\/li>\n  <li><strong>Go \u7248\u672c<\/strong>\uff1a1.26<\/li>\n  <li><strong>\u5f53\u524d\u7248\u672c<\/strong>\uff1av2.11.0<\/li>\n  <li><strong>\u8bb8\u53ef\u8bc1<\/strong>\uff1aApache License 2.0<\/li>\n<\/ul>\n\n<h3 id=\"\u76ee\u5f55\u603b\u89c8\">\u76ee\u5f55\u603b\u89c8<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>easegress\/\n\u251c\u2500\u2500 cmd\/                    # \u4e09\u4e2a\u4e8c\u8fdb\u5236\u7684\u5165\u53e3\n\u2502   \u251c\u2500\u2500 server\/main.go      # easegress-server \u5165\u53e3\n\u2502   \u251c\u2500\u2500 client\/main.go      # egctl \u547d\u4ee4\u884c\u5de5\u5177\u5165\u53e3\n\u2502   \u2514\u2500\u2500 builder\/main.go     # egbuilder \u81ea\u5b9a\u4e49\u6784\u5efa\u5de5\u5177\u5165\u53e3\n\u251c\u2500\u2500 cmd\/server.go           # RunServer() \u7f16\u6392\u51fd\u6570\n\u251c\u2500\u2500 pkg\/                    # \u6240\u6709\u6838\u5fc3\u5e93\u4ee3\u7801\uff0822 \u4e2a\u5305\uff09\n\u251c\u2500\u2500 build\/                  # Dockerfile \u548c\u96c6\u6210\u6d4b\u8bd5\n\u251c\u2500\u2500 docs\/                   # \u6587\u6863\u7ad9\u70b9\n\u251c\u2500\u2500 example\/                # \u96c6\u7fa4\u793a\u4f8b\u914d\u7f6e\n\u251c\u2500\u2500 helm-charts\/            # Helm Chart\n\u251c\u2500\u2500 scripts\/                # \u8f85\u52a9\u811a\u672c\n\u251c\u2500\u2500 Makefile                # \u6784\u5efa\u7cfb\u7edf\n\u2514\u2500\u2500 go.mod                  # \u5355 module \u5b9a\u4e49\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"\u4e09\u4e2a\u4e8c\u8fdb\u5236\u4ea7\u7269\">\u4e09\u4e2a\u4e8c\u8fdb\u5236\u4ea7\u7269<\/h3>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u4e8c\u8fdb\u5236<\/th>\n      <th>\u5165\u53e3<\/th>\n      <th>\u7528\u9014<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">easegress-server<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">cmd\/server\/main.go:26<\/code><\/td>\n      <td>\u6838\u5fc3\u7f51\u5173\u670d\u52a1\u8fdb\u7a0b<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">egctl<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">cmd\/client\/main.go:53<\/code><\/td>\n      <td>\u7ba1\u7406\u547d\u4ee4\u884c\u5de5\u5177\uff08\u57fa\u4e8e Cobra\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">egbuilder<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">cmd\/builder\/main.go:36<\/code><\/td>\n      <td>\u81ea\u5b9a\u4e49\u6a21\u5757\u6784\u5efa\u5de5\u5177<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"2-\u6784\u5efa\u4e0e\u8fd0\u884c\">2. \u6784\u5efa\u4e0e\u8fd0\u884c<\/h2>\n\n<h3 id=\"\u6784\u5efa\u547d\u4ee4\">\u6784\u5efa\u547d\u4ee4<\/h3>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\"># \u6784\u5efa\u5168\u90e8\u4e09\u4e2a\u4e8c\u8fdb\u5236<\/span>\nmake build\n\n<span class=\"c\"># \u4ec5\u6784\u5efa server<\/span>\nmake build_server\n\n<span class=\"c\"># \u6784\u5efa Docker \u955c\u50cf<\/span>\nmake build_docker\n\n<span class=\"c\"># \u8fd0\u884c\u6d4b\u8bd5<\/span>\nmake <span class=\"nb\">test<\/span>\n\n<span class=\"c\"># \u4ee3\u7801\u683c\u5f0f\u5316\u4e0e\u68c0\u67e5<\/span>\nmake <span class=\"nb\">fmt\n<\/span>make vet\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"makefile-\u5173\u952e\u53d8\u91cfmakefile20\">Makefile \u5173\u952e\u53d8\u91cf\uff08<code class=\"language-plaintext highlighter-rouge\">Makefile:20<\/code>\uff09<\/h3>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">RELEASE = v2.11.0<\/code><\/li>\n  <li>Server \u6784\u5efa\u5305\u542b <code class=\"language-plaintext highlighter-rouge\">wasmhost<\/code> build tag\uff0c\u9700\u5f00\u542f CGO<\/li>\n  <li>GoReleaser \u914d\u7f6e\u89c1 <code class=\"language-plaintext highlighter-rouge\">.goreleaser.yml<\/code>\uff0c\u652f\u6301 linux\/darwin + amd64\/arm64 \u4ea4\u53c9\u7f16\u8bd1<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"3-\u542f\u52a8\u6d41\u7a0b\">3. \u542f\u52a8\u6d41\u7a0b<\/h2>\n\n<p>\u670d\u52a1\u5668\u542f\u52a8\u7684\u5b8c\u6574\u6d41\u7a0b\u4f4d\u4e8e <code class=\"language-plaintext highlighter-rouge\">cmd\/server.go:40-147<\/code> \u7684 <code class=\"language-plaintext highlighter-rouge\">RunServer()<\/code> \u51fd\u6570\u3002\u6309\u987a\u5e8f\uff1a<\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>1. option.New().Parse()           \u2014 \u89e3\u6790\u542f\u52a8\u9009\u9879\u548c\u914d\u7f6e\u6587\u4ef6\n2. env.InitServerDir()            \u2014 \u521d\u59cb\u5316\u670d\u52a1\u7aef\u76ee\u5f55\u7ed3\u6784\n3. logger.Init(opt)               \u2014 \u521d\u59cb\u5316\u7ed3\u6784\u5316\u65e5\u5fd7\uff08\u57fa\u4e8e zap\uff09\n4. cluster.New(opt)               \u2014 \u542f\u52a8\u5d4c\u5165\u5f0f etcd \u6216\u8fde\u63a5\u5916\u90e8\u96c6\u7fa4\n5. supervisor.MustNew(opt, cls)   \u2014 \u521b\u5efa Supervisor\uff0c\u521d\u59cb\u5316 SystemController\n6. api.MustNewServer(...)         \u2014 \u542f\u52a8 Admin API HTTP \u670d\u52a1\n7. \u6ce8\u518c Graceful Upgrade \u4fe1\u53f7\u5904\u7406\n8. \u963b\u585e\u7b49\u5f85 SIGINT\/SIGTERM\uff0c\u4f18\u96c5\u5173\u95ed\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>\u5173\u952e\u70b9<\/strong>\uff1a<\/p>\n<ul>\n  <li>\u6b65\u9aa4 4-6 \u4e4b\u95f4\u5b58\u5728\u4e25\u683c\u7684\u987a\u5e8f\u4f9d\u8d56\uff1a\u96c6\u7fa4\u5fc5\u987b\u5148\u5c31\u7eea\uff0cSupervisor \u624d\u80fd\u76d1\u542c\u914d\u7f6e\u53d8\u66f4\uff0cAPI Server \u624d\u80fd\u5bf9\u5916\u66b4\u9732\u7ba1\u7406\u63a5\u53e3\u3002<\/li>\n  <li>\u6b65\u9aa4 5 \u4e2d Supervisor \u5185\u90e8\u4f1a\u521d\u59cb\u5316\u6240\u6709 <code class=\"language-plaintext highlighter-rouge\">SystemController<\/code>\uff08\u6309\u4f9d\u8d56\u987a\u5e8f\uff09\uff0c\u7136\u540e\u542f\u52a8 <code class=\"language-plaintext highlighter-rouge\">go s.run()<\/code> \u534f\u7a0b\u76d1\u542c\u914d\u7f6e\u53d8\u66f4\u3002<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"4-\u6838\u5fc3\u67b6\u6784\">4. \u6838\u5fc3\u67b6\u6784<\/h2>\n\n<h3 id=\"41-object-\u4f53\u7cfb\u5bf9\u8c61\u6ce8\u518c\u4e0e\u751f\u547d\u5468\u671f\">4.1 Object \u4f53\u7cfb\uff08\u5bf9\u8c61\u6ce8\u518c\u4e0e\u751f\u547d\u5468\u671f\uff09<\/h3>\n\n<p>Easegress \u4e2d\u6240\u6709\u88ab\u7ba1\u7406\u7684\u7ec4\u4ef6\u90fd\u5b9e\u73b0 <code class=\"language-plaintext highlighter-rouge\">Object<\/code> \u63a5\u53e3\uff0c\u8fd9\u662f\u7406\u89e3\u6574\u4e2a\u9879\u76ee\u6700\u91cd\u8981\u7684\u62bd\u8c61\u3002<\/p>\n\n<p><strong>\u6838\u5fc3\u5b9a\u4e49\u4f4d\u4e8e<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/registry.go:30-47<\/code>\uff1a<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">type<\/span> <span class=\"n\">Object<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Category<\/span><span class=\"p\">()<\/span> <span class=\"n\">ObjectCategory<\/span>   <span class=\"c\">\/\/ \u5bf9\u8c61\u7c7b\u522b\uff08\u51b3\u5b9a\u542f\u52a8\/\u9500\u6bc1\u987a\u5e8f\uff09<\/span>\n    <span class=\"n\">Kind<\/span><span class=\"p\">()<\/span> <span class=\"kt\">string<\/span>               <span class=\"c\">\/\/ \u552f\u4e00\u7c7b\u578b\u6807\u8bc6<\/span>\n    <span class=\"n\">DefaultSpec<\/span><span class=\"p\">()<\/span> <span class=\"k\">interface<\/span><span class=\"p\">{}<\/span>   <span class=\"c\">\/\/ \u8fd4\u56de\u9ed8\u8ba4\u914d\u7f6e\uff08\u5fc5\u987b\u662f\u6307\u9488\u6307\u5411\u7ed3\u6784\u4f53\uff09<\/span>\n    <span class=\"n\">Status<\/span><span class=\"p\">()<\/span> <span class=\"o\">*<\/span><span class=\"n\">Status<\/span>            <span class=\"c\">\/\/ \u8fd0\u884c\u65f6\u72b6\u6001<\/span>\n    <span class=\"n\">Close<\/span><span class=\"p\">()<\/span>                     <span class=\"c\">\/\/ \u9500\u6bc1\u65f6\u8c03\u7528<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>\u5bf9\u8c61\u7c7b\u522b<\/strong>\uff08<code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/registry.go:102-113<\/code>\uff09\u6309\u7167\u542f\u52a8\u4f18\u5148\u7ea7\u6392\u5e8f\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u7c7b\u522b<\/th>\n      <th>\u8bf4\u660e<\/th>\n      <th>\u5b9e\u4f8b<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">SystemController<\/code><\/td>\n      <td>\u7cfb\u7edf\u5185\u7f6e\u63a7\u5236\u5668\uff0c\u6700\u5148\u542f\u52a8<\/td>\n      <td>TrafficController, MeshController, AutoCertManager<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">BusinessController<\/code><\/td>\n      <td>\u7528\u6237\u521b\u5efa\u7684\u63a7\u5236\u5668<\/td>\n      <td>IngressController, GatewayController, WAFController<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">Pipeline<\/code><\/td>\n      <td>\u6d41\u91cf\u5904\u7406\u7ba1\u7ebf<\/td>\n      <td>Pipeline<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">TrafficGate<\/code><\/td>\n      <td>\u534f\u8bae\u76d1\u542c\u5165\u53e3<\/td>\n      <td>HTTPServer, gRPCServer, MQTTProxy<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p><strong>\u5bf9\u8c61\u6ce8\u518c\u673a\u5236<\/strong>\uff1a\u901a\u8fc7\u5728 <code class=\"language-plaintext highlighter-rouge\">init()<\/code> \u51fd\u6570\u4e2d\u8c03\u7528 <code class=\"language-plaintext highlighter-rouge\">supervisor.Register(&amp;MyObject{})<\/code> \u5b9e\u73b0\u81ea\u6ce8\u518c\u3002<code class=\"language-plaintext highlighter-rouge\">pkg\/registry\/registry.go<\/code> \u4f7f\u7528\u7a7a\u767d\u5bfc\u5165\uff08blank-import\uff09\u89e6\u53d1\u6240\u6709 filter \u548c object \u5305\u7684 <code class=\"language-plaintext highlighter-rouge\">init()<\/code>\uff1a<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ pkg\/registry\/registry.go<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">(<\/span>\n    <span class=\"n\">_<\/span> <span class=\"s\">\"github.com\/megaease\/easegress\/v2\/pkg\/filters\/httpproxy\"<\/span>\n    <span class=\"n\">_<\/span> <span class=\"s\">\"github.com\/megaease\/easegress\/v2\/pkg\/object\/httpserver\"<\/span>\n    <span class=\"c\">\/\/ ... \u6240\u6709 filter \u548c object \u5305<\/span>\n<span class=\"p\">)<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><code class=\"language-plaintext highlighter-rouge\">cmd\/server\/main.go<\/code> \u901a\u8fc7\u5bfc\u5165 <code class=\"language-plaintext highlighter-rouge\">pkg\/registry<\/code> \u5b8c\u6210\u6240\u6709\u6a21\u5757\u7684\u81ea\u52a8\u6ce8\u518c\u3002<\/p>\n\n<h3 id=\"42-spec-\u7cfb\u7edf\u58f0\u660e\u5f0f\u914d\u7f6e\">4.2 Spec \u7cfb\u7edf\uff08\u58f0\u660e\u5f0f\u914d\u7f6e\uff09<\/h3>\n\n<p><strong>\u5b9a\u4e49\u4f4d\u4e8e<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/spec.go<\/code>\uff1a<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Spec (pkg\/supervisor\/spec.go:34) \u2014 \u901a\u7528\u5bf9\u8c61\u914d\u7f6e<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Spec<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">super<\/span>       <span class=\"o\">*<\/span><span class=\"n\">Supervisor<\/span>\n    <span class=\"n\">category<\/span>    <span class=\"n\">ObjectCategory<\/span>\n    <span class=\"n\">jsonConfig<\/span>  <span class=\"kt\">string<\/span>            <span class=\"c\">\/\/ \u539f\u59cb JSON \u914d\u7f6e<\/span>\n    <span class=\"n\">meta<\/span>        <span class=\"o\">*<\/span><span class=\"n\">MetaSpec<\/span>         <span class=\"c\">\/\/ \u5143\u6570\u636e<\/span>\n    <span class=\"n\">rawSpec<\/span>     <span class=\"k\">map<\/span><span class=\"p\">[<\/span><span class=\"kt\">string<\/span><span class=\"p\">]<\/span><span class=\"k\">interface<\/span><span class=\"p\">{}<\/span>  <span class=\"c\">\/\/ \u672a\u53cd\u5e8f\u5217\u5316\u7684\u539f\u59cb map<\/span>\n    <span class=\"n\">objectSpec<\/span>  <span class=\"k\">interface<\/span><span class=\"p\">{}<\/span>       <span class=\"c\">\/\/ \u53cd\u5e8f\u5217\u5316\u540e\u7684 Go \u7ed3\u6784\u4f53<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ MetaSpec (pkg\/supervisor\/spec.go:45) \u2014 \u516c\u5171\u5143\u6570\u636e<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">MetaSpec<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Name<\/span>      <span class=\"kt\">string<\/span>            <span class=\"s\">`json:\"name\" jsonschema:\"required,format=urlname\"`<\/span>\n    <span class=\"n\">Kind<\/span>      <span class=\"kt\">string<\/span>            <span class=\"s\">`json:\"kind\" jsonschema:\"required\"`<\/span>\n    <span class=\"n\">Version<\/span>   <span class=\"kt\">string<\/span>            <span class=\"s\">`json:\"version,omitempty\"`<\/span>\n    <span class=\"n\">Labels<\/span>    <span class=\"k\">map<\/span><span class=\"p\">[<\/span><span class=\"kt\">string<\/span><span class=\"p\">]<\/span><span class=\"kt\">string<\/span> <span class=\"s\">`json:\"labels,omitempty\"`<\/span>\n    <span class=\"n\">CreatedAt<\/span> <span class=\"kt\">string<\/span>            <span class=\"s\">`json:\"createdAt,omitempty\"`<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>\u8bbe\u8ba1\u8981\u70b9<\/strong>\uff1a<\/p>\n<ul>\n  <li>\u6240\u6709\u5bf9\u8c61\u914d\u7f6e\u5728 etcd \u4e2d\u5b58\u50a8\u4e3a JSON\/YAML\uff0c\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">MetaSpec.Kind<\/code> \u8def\u7531\u5230\u5bf9\u5e94\u7684 <code class=\"language-plaintext highlighter-rouge\">Object<\/code> \u5b9e\u73b0\u3002<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">Spec<\/code> \u540c\u65f6\u6301\u6709\u539f\u59cb\u6570\u636e\uff08<code class=\"language-plaintext highlighter-rouge\">rawSpec<\/code>\uff09\u548c\u53cd\u5e8f\u5217\u5316\u540e\u7684 Go \u7ed3\u6784\u4f53\uff08<code class=\"language-plaintext highlighter-rouge\">objectSpec<\/code>\uff09\uff0c\u4fbf\u4e8e\u9a8c\u8bc1\u548c\u900f\u4f20\u3002<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">jsonschema<\/code> struct tag \u9a71\u52a8\u81ea\u52a8\u6821\u9a8c\uff0c\u8be6\u89c1 <a href=\"#410-\u6821\u9a8c\u7cfb\u7edf\">4.10 \u6821\u9a8c\u7cfb\u7edf<\/a>\u3002<\/li>\n<\/ul>\n\n<h3 id=\"43-supervisor\u751f\u547d\u5468\u671f\u7ba1\u7406\">4.3 Supervisor\uff08\u751f\u547d\u5468\u671f\u7ba1\u7406\uff09<\/h3>\n\n<p><strong>\u5b9a\u4e49\u4f4d\u4e8e<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/supervisor.go:36<\/code>\uff1a<\/p>\n\n<p>Supervisor \u662f\u5bf9\u8c61\u751f\u547d\u5468\u671f\u7684\u7ba1\u7406\u8005\uff0c\u6838\u5fc3\u804c\u8d23\uff1a<\/p>\n\n<ol>\n  <li><strong>\u6301\u6709 ObjectRegistry<\/strong>\uff08<code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/object.go:39-45<\/code>\uff09\u2014\u2014 \u4e00\u4e2a\u4fdd\u5b58\u5728 etcd \u4e2d\u914d\u7f6e\u7684\u672c\u5730\u7f13\u5b58<\/li>\n  <li><strong>\u6301\u6709 ObjectEntityWatcher<\/strong>\uff08<code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/object.go<\/code>\uff09\u2014\u2014 \u76d1\u542c etcd \u4e2d\u914d\u7f6e\u7684\u589e\/\u5220\/\u6539\u4e8b\u4ef6<\/li>\n  <li><strong>\u521d\u59cb\u5316\u548c\u542f\u52a8 SystemController<\/strong>\uff08<code class=\"language-plaintext highlighter-rouge\">supervisor.go:103<\/code>\uff09<\/li>\n  <li><strong>\u8fd0\u884c\u4e8b\u4ef6\u5faa\u73af<\/strong>\uff08<code class=\"language-plaintext highlighter-rouge\">go s.run()<\/code> at line 105\uff09\u2014\u2014 \u6536\u5230\u914d\u7f6e\u53d8\u66f4\u4e8b\u4ef6\u540e\uff0c\u521b\u5efa\/\u66f4\u65b0\/\u5220\u9664 <code class=\"language-plaintext highlighter-rouge\">ObjectEntity<\/code><\/li>\n<\/ol>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ ObjectEntity (pkg\/supervisor\/object.go:39-45) \u2014 Object \u7684\u8fd0\u884c\u65f6\u5305\u88c5<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">ObjectEntity<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">instance<\/span>   <span class=\"n\">Object<\/span>      <span class=\"c\">\/\/ \u5b9e\u9645\u7684 Object \u5b9e\u73b0<\/span>\n    <span class=\"n\">spec<\/span>       <span class=\"o\">*<\/span><span class=\"n\">Spec<\/span>       <span class=\"c\">\/\/ \u5173\u8054\u7684\u914d\u7f6e<\/span>\n    <span class=\"n\">generation<\/span> <span class=\"kt\">int64<\/span>       <span class=\"c\">\/\/ \u4ee3\u6570\uff08\u6bcf\u6b21\u66f4\u65b0\u9012\u589e\uff0c\u7528\u4e8e CAS \u68c0\u6d4b\uff09<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"44-cluster\u96c6\u7fa4\u4e0e\u5b58\u50a8\">4.4 Cluster\uff08\u96c6\u7fa4\u4e0e\u5b58\u50a8\uff09<\/h3>\n\n<p><strong>\u5b9a\u4e49\u4f4d\u4e8e<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/cluster\/cluster_interface.go:33<\/code>\uff1a<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">type<\/span> <span class=\"n\">Cluster<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">IsLeader<\/span><span class=\"p\">()<\/span> <span class=\"kt\">bool<\/span>\n    <span class=\"n\">Layout<\/span><span class=\"p\">()<\/span> <span class=\"o\">*<\/span><span class=\"n\">Layout<\/span>\n\n    <span class=\"c\">\/\/ KV \u64cd\u4f5c<\/span>\n    <span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"kt\">string<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">GetPrefix<\/span><span class=\"p\">(<\/span><span class=\"n\">prefix<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"k\">map<\/span><span class=\"p\">[<\/span><span class=\"kt\">string<\/span><span class=\"p\">]<\/span><span class=\"kt\">string<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">Put<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span><span class=\"p\">,<\/span> <span class=\"n\">value<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span>\n    <span class=\"n\">Delete<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span>\n    <span class=\"n\">DeletePrefix<\/span><span class=\"p\">(<\/span><span class=\"n\">prefix<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span>\n\n    <span class=\"c\">\/\/ \u539f\u5b50\u64cd\u4f5c\uff08\u57fa\u4e8e etcd STM\uff09<\/span>\n    <span class=\"n\">STM<\/span><span class=\"p\">(<\/span><span class=\"n\">apply<\/span> <span class=\"k\">func<\/span><span class=\"p\">(<\/span><span class=\"n\">concurrency<\/span><span class=\"o\">.<\/span><span class=\"n\">STM<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span>\n\n    <span class=\"c\">\/\/ \u914d\u7f6e\u53d8\u66f4\u76d1\u542c<\/span>\n    <span class=\"n\">Watcher<\/span><span class=\"p\">()<\/span> <span class=\"p\">(<\/span><span class=\"n\">Watcher<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">Syncer<\/span><span class=\"p\">(<\/span><span class=\"n\">pullInterval<\/span> <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Duration<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"n\">Syncer<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c\">\/\/ Leader \u9009\u4e3e<\/span>\n    <span class=\"n\">Mutex<\/span><span class=\"p\">(<\/span><span class=\"n\">name<\/span> <span class=\"kt\">string<\/span><span class=\"p\">,<\/span> <span class=\"n\">ttl<\/span> <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Duration<\/span><span class=\"p\">)<\/span> <span class=\"n\">concurrency<\/span><span class=\"o\">.<\/span><span class=\"n\">Locker<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>\u5173\u952e\u5b50\u63a5\u53e3<\/strong>\uff1a<\/p>\n\n<ul>\n  <li><strong>Watcher<\/strong> (<code class=\"language-plaintext highlighter-rouge\">pkg\/cluster\/cluster_interface.go:76<\/code>)\uff1a\u5b9e\u65f6\u76d1\u542c etcd \u4e2d\u6307\u5b9a key\/prefix \u7684\u53d8\u66f4\u4e8b\u4ef6<\/li>\n  <li><strong>Syncer<\/strong> (<code class=\"language-plaintext highlighter-rouge\">pkg\/cluster\/cluster_interface.go:91<\/code>)\uff1a\u7ef4\u62a4\u672c\u5730\u7f13\u5b58\uff0c\u901a\u8fc7\u5468\u671f\u6027\u5168\u91cf\u62c9\u53d6\u4fdd\u6301\u4e0e etcd \u540c\u6b65<\/li>\n<\/ul>\n\n<h3 id=\"45-traffic-pipeline\u6d41\u91cf\u7ba1\u7ebf\">4.5 Traffic Pipeline\uff08\u6d41\u91cf\u7ba1\u7ebf\uff09<\/h3>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/context\/context.go<\/code><\/strong> \u5b9a\u4e49\u4e86\u6d41\u91cf\u5904\u7406\u7684\u4e0a\u4e0b\u6587\u8f7d\u4f53\u3002<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Handler (pkg\/context\/context.go:35) \u2014 \u6240\u6709\u6d41\u91cf\u5904\u7406\u5668\u7684\u63a5\u53e3<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Handler<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Handle<\/span><span class=\"p\">(<\/span><span class=\"n\">ctx<\/span> <span class=\"o\">*<\/span><span class=\"n\">Context<\/span><span class=\"p\">)<\/span> <span class=\"kt\">string<\/span>   <span class=\"c\">\/\/ \u8fd4\u56de\u7ed3\u679c\u5b57\u7b26\u4e32\uff08\u7a7a\u4e32\u8868\u793a\u6210\u529f\u7ee7\u7eed\uff09<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ MuxMapper (pkg\/context\/context.go:40) \u2014 \u6309\u540d\u79f0\u67e5\u627e Handler<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">MuxMapper<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">GetHandler<\/span><span class=\"p\">(<\/span><span class=\"n\">name<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"n\">Handler<\/span><span class=\"p\">,<\/span> <span class=\"kt\">bool<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Pipeline \u7ed3\u6784<\/strong>\uff08<code class=\"language-plaintext highlighter-rouge\">pkg\/object\/pipeline\/pipeline.go:63<\/code>\uff09\uff1a<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">type<\/span> <span class=\"n\">Pipeline<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">filters<\/span> <span class=\"k\">map<\/span><span class=\"p\">[<\/span><span class=\"kt\">string<\/span><span class=\"p\">]<\/span><span class=\"n\">filters<\/span><span class=\"o\">.<\/span><span class=\"n\">Filter<\/span>  <span class=\"c\">\/\/ \u6240\u6709 Filter \u5b9e\u4f8b\uff08\u6309 name \u7d22\u5f15\uff09<\/span>\n    <span class=\"n\">flow<\/span>    <span class=\"p\">[]<\/span><span class=\"n\">FlowNode<\/span>                  <span class=\"c\">\/\/ \u5904\u7406\u6d41\u7a0b\u5b9a\u4e49\uff08\u987a\u5e8f\u6267\u884c + \u6761\u4ef6\u8df3\u8f6c\uff09<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>\u6d41\u91cf\u5904\u7406\u6d41\u7a0b<\/strong>\uff1a<\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>TrafficGate (e.g. HTTPServer)\n    \u2192 \u8def\u7531\u5339\u914d\n        \u2192 Pipeline\n            \u2192 FlowNode[0] \u2192 Filter A \u2192 \u6839\u636e\u7ed3\u679c\u8df3\u8f6c\n                \u2192 FlowNode[1] \u2192 Filter B\n                    \u2192 ...\n                        \u2192 \u8fd4\u56de\u54cd\u5e94\n<\/code><\/pre><\/div><\/div>\n\n<p><code class=\"language-plaintext highlighter-rouge\">Context<\/code> \u5728\u6574\u6761\u94fe\u8def\u4e0a\u4f20\u9012 <code class=\"language-plaintext highlighter-rouge\">Request<\/code> \u548c <code class=\"language-plaintext highlighter-rouge\">Response<\/code>\uff0c\u6bcf\u4e2a Filter \u53ef\u4ee5\u8bfb\u5199 Context\u3002<\/p>\n\n<h3 id=\"46-filter-\u4f53\u7cfb\u8fc7\u6ee4\u5668\">4.6 Filter \u4f53\u7cfb\uff08\u8fc7\u6ee4\u5668\uff09<\/h3>\n\n<p><strong>\u6838\u5fc3\u63a5\u53e3<\/strong> \u4f4d\u4e8e <code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/filters.go<\/code>\uff1a<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Kind (pkg\/filters\/filters.go:33) \u2014 \u63cf\u8ff0\u4e00\u79cd Filter \u7c7b\u578b\u7684\u5143\u4fe1\u606f<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Kind<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Name<\/span>           <span class=\"kt\">string<\/span>\n    <span class=\"n\">Description<\/span>    <span class=\"kt\">string<\/span>\n    <span class=\"n\">Results<\/span>        <span class=\"p\">[]<\/span><span class=\"kt\">string<\/span>                             <span class=\"c\">\/\/ \u9664\u7a7a\u4e32\u5916\u7684\u6240\u6709\u53ef\u80fd\u7ed3\u679c<\/span>\n    <span class=\"n\">CreateInstance<\/span> <span class=\"k\">func<\/span><span class=\"p\">(<\/span><span class=\"n\">spec<\/span> <span class=\"n\">Spec<\/span><span class=\"p\">)<\/span> <span class=\"n\">Filter<\/span>               <span class=\"c\">\/\/ \u5de5\u5382\u51fd\u6570<\/span>\n    <span class=\"n\">DefaultSpec<\/span>    <span class=\"k\">func<\/span><span class=\"p\">()<\/span> <span class=\"n\">Spec<\/span>                          <span class=\"c\">\/\/ \u8fd4\u56de\u9ed8\u8ba4\u914d\u7f6e\u526f\u672c<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ Filter (pkg\/filters\/filters.go:54) \u2014 \u8fc7\u6ee4\u5668\u57fa\u7840\u63a5\u53e3<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Filter<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Name<\/span><span class=\"p\">()<\/span> <span class=\"kt\">string<\/span>\n    <span class=\"n\">Kind<\/span><span class=\"p\">()<\/span> <span class=\"o\">*<\/span><span class=\"n\">Kind<\/span>\n    <span class=\"n\">Handle<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">context<\/span><span class=\"o\">.<\/span><span class=\"n\">Context<\/span><span class=\"p\">)<\/span> <span class=\"kt\">string<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Filter \u63d2\u4ef6\u6ce8\u518c\u8868<\/strong>\u4f4d\u4e8e <code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/registry.go<\/code>\uff0c\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">filters.Register(k *Kind)<\/code> \u6ce8\u518c\u3002<\/p>\n\n<p><strong>\u5185\u7f6e Filter \u5217\u8868<\/strong>\uff0827 \u79cd\uff09\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u5206\u7c7b<\/th>\n      <th>Filter<\/th>\n      <th>\u529f\u80fd<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>\u4ee3\u7406<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">httpproxy<\/code><\/td>\n      <td>HTTP \u53cd\u5411\u4ee3\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>\u4ee3\u7406<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">grpcproxy<\/code><\/td>\n      <td>gRPC \u4ee3\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>\u4ee3\u7406<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">aigatewayproxy<\/code><\/td>\n      <td>AI \u7f51\u5173\u4ee3\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>\u5b89\u5168<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">validator<\/code><\/td>\n      <td>\u8bf7\u6c42\u6821\u9a8c<\/td>\n    <\/tr>\n    <tr>\n      <td>\u5b89\u5168<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">waf<\/code><\/td>\n      <td>Web \u5e94\u7528\u9632\u706b\u5899\uff08\u57fa\u4e8e Coraza\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td>\u5b89\u5168<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">oidcadaptor<\/code><\/td>\n      <td>OIDC \u8ba4\u8bc1\u9002\u914d<\/td>\n    <\/tr>\n    <tr>\n      <td>\u5b89\u5168<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">corsadaptor<\/code><\/td>\n      <td>CORS \u5904\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>\u6d41\u91cf\u63a7\u5236<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ratelimiter<\/code><\/td>\n      <td>\u9650\u6d41<\/td>\n    <\/tr>\n    <tr>\n      <td>\u6d41\u91cf\u63a7\u5236<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">circuitbreaker<\/code><\/td>\n      <td>\u7194\u65ad\uff08resilience \u6a21\u5757\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td>\u8def\u7531<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">redirector<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">redirectorv2<\/code><\/td>\n      <td>\u91cd\u5b9a\u5411<\/td>\n    <\/tr>\n    <tr>\n      <td>\u8def\u7531<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">headerlookup<\/code><\/td>\n      <td>Header \u8def\u7531\u5339\u914d<\/td>\n    <\/tr>\n    <tr>\n      <td>\u8def\u7531<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">headertojson<\/code><\/td>\n      <td>Header \u8f6c JSON<\/td>\n    <\/tr>\n    <tr>\n      <td>\u6d88\u606f<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">kafka<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">kafkabackend<\/code><\/td>\n      <td>Kafka \u6d88\u606f\u5904\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>\u6d88\u606f<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">mqttclientauth<\/code><\/td>\n      <td>MQTT \u5ba2\u6237\u7aef\u8ba4\u8bc1<\/td>\n    <\/tr>\n    <tr>\n      <td>\u6d88\u606f<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">topicmapper<\/code><\/td>\n      <td>MQTT \u4e3b\u9898\u6620\u5c04<\/td>\n    <\/tr>\n    <tr>\n      <td>\u670d\u52a1\u7f51\u683c<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">meshadaptor<\/code><\/td>\n      <td>\u7f51\u683c\u9002\u914d<\/td>\n    <\/tr>\n    <tr>\n      <td>\u6269\u5c55<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">wasmhost<\/code><\/td>\n      <td>WebAssembly \u6c99\u7bb1<\/td>\n    <\/tr>\n    <tr>\n      <td>\u6269\u5c55<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">remotefilter<\/code><\/td>\n      <td>\u8fdc\u7a0b\u8fc7\u6ee4\u5668\u8c03\u7528<\/td>\n    <\/tr>\n    <tr>\n      <td>\u6269\u5c55<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">builder<\/code><\/td>\n      <td>\u6784\u5efa\u671f\u52a8\u6001 Filter<\/td>\n    <\/tr>\n    <tr>\n      <td>\u7b56\u7565<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">opafilter<\/code><\/td>\n      <td>OPA \u7b56\u7565\u5f15\u64ce<\/td>\n    <\/tr>\n    <tr>\n      <td>\u5de5\u5177<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">fileserver<\/code><\/td>\n      <td>\u9759\u6001\u6587\u4ef6\u670d\u52a1<\/td>\n    <\/tr>\n    <tr>\n      <td>\u5de5\u5177<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">mock<\/code><\/td>\n      <td>Mock \u54cd\u5e94<\/td>\n    <\/tr>\n    <tr>\n      <td>\u5de5\u5177<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">fallback<\/code><\/td>\n      <td>\u964d\u7ea7\u515c\u5e95<\/td>\n    <\/tr>\n    <tr>\n      <td>\u5de5\u5177<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">certextractor<\/code><\/td>\n      <td>\u8bc1\u4e66\u63d0\u53d6<\/td>\n    <\/tr>\n    <tr>\n      <td>\u5de5\u5177<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">connectcontrol<\/code><\/td>\n      <td>\u8fde\u63a5\u63a7\u5236<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"47-protocol-\u62bd\u8c61\u534f\u8bae\u5c42\">4.7 Protocol \u62bd\u8c61\uff08\u534f\u8bae\u5c42\uff09<\/h3>\n\n<p><strong>\u5b9a\u4e49\u4f4d\u4e8e<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/protocols.go<\/code>\uff1a<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Request (pkg\/protocols\/protocols.go:39) \u2014 \u534f\u8bae\u65e0\u5173\u7684\u8bf7\u6c42\u63a5\u53e3<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Request<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Header<\/span><span class=\"p\">()<\/span> <span class=\"n\">Header<\/span>\n    <span class=\"n\">RealIP<\/span><span class=\"p\">()<\/span> <span class=\"kt\">string<\/span>\n    <span class=\"n\">IsStream<\/span><span class=\"p\">()<\/span> <span class=\"kt\">bool<\/span>\n    <span class=\"n\">SetPayload<\/span><span class=\"p\">(<\/span><span class=\"n\">payload<\/span> <span class=\"k\">interface<\/span><span class=\"p\">{})<\/span>\n    <span class=\"c\">\/\/ ...<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ Response (pkg\/protocols\/protocols.go:84) \u2014 \u534f\u8bae\u65e0\u5173\u7684\u54cd\u5e94\u63a5\u53e3<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Response<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Header<\/span><span class=\"p\">()<\/span> <span class=\"n\">Header<\/span>\n    <span class=\"n\">SetPayload<\/span><span class=\"p\">(<\/span><span class=\"n\">payload<\/span> <span class=\"k\">interface<\/span><span class=\"p\">{})<\/span>\n    <span class=\"c\">\/\/ ...<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ Protocol (pkg\/protocols\/protocols.go:143) \u2014 \u534f\u8bae\u5b9e\u73b0<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Protocol<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">CreateRequest<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"n\">io<\/span><span class=\"o\">.<\/span><span class=\"n\">Reader<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"n\">Request<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">CreateResponse<\/span><span class=\"p\">(<\/span><span class=\"n\">body<\/span> <span class=\"n\">io<\/span><span class=\"o\">.<\/span><span class=\"n\">Reader<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"n\">Response<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n    <span class=\"c\">\/\/ ...<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>\u5df2\u5b9e\u73b0\u7684\u534f\u8bae<\/strong>\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u534f\u8bae<\/th>\n      <th>\u5305\u8def\u5f84<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>HTTP<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/httpprot\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>gRPC<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/grpcprot\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>MQTT<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/mqttprot\/<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>\u534f\u8bae\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">protocols.Register(name, p)<\/code> \u6ce8\u518c\u5230\u5168\u5c40\u6ce8\u518c\u8868\u3002<\/p>\n\n<h3 id=\"48-resilience\u5f39\u6027\u7b56\u7565\">4.8 Resilience\uff08\u5f39\u6027\u7b56\u7565\uff09<\/h3>\n\n<p><strong>\u5b9a\u4e49\u4f4d\u4e8e<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/resilience\/resilience.go<\/code>\uff1a<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Wrapper (pkg\/resilience\/resilience.go:46) \u2014 \u5305\u88c5 HandlerFunc<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Wrapper<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Wrap<\/span><span class=\"p\">(<\/span><span class=\"n\">HandlerFunc<\/span><span class=\"p\">)<\/span> <span class=\"n\">HandlerFunc<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ HandlerFunc (pkg\/resilience\/resilience.go:43)<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">HandlerFunc<\/span> <span class=\"k\">func<\/span><span class=\"p\">(<\/span><span class=\"n\">ctx<\/span> <span class=\"n\">context<\/span><span class=\"o\">.<\/span><span class=\"n\">Context<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p>\u5f39\u6027\u548c\u5bb9\u9519\u7b56\u7565\u4ee5 <strong>\u88c5\u9970\u5668\u6a21\u5f0f<\/strong> \u5305\u88f9 Filter \u7684 Handle \u8c03\u7528\uff1a<\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>Wrapper(Filter.Handle) \u2192 \u6267\u884c Filter \u903b\u8f91\uff0c\u6309\u7b56\u7565\u5bb9\u9519\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>\u5185\u7f6e\u7b56\u7565<\/strong>\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u7b56\u7565<\/th>\n      <th>\u6587\u4ef6<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>CircuitBreaker\uff08\u7194\u65ad\uff09<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/resilience\/circuitbreaker.go<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>Retry\uff08\u91cd\u8bd5\uff09<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/resilience\/retry.go<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"49-admin-api\">4.9 Admin API<\/h3>\n\n<p><strong>\u5b9a\u4e49\u4f4d\u4e8e<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/api\/api.go<\/code> \u548c <code class=\"language-plaintext highlighter-rouge\">pkg\/api\/server.go<\/code>\u3002<\/p>\n\n<p>Admin API \u4f7f\u7528 <strong>go-chi\/chi<\/strong> \u4f5c\u4e3a HTTP \u8def\u7531\u6846\u67b6\uff0c\u63d0\u4f9b\u52a8\u6001\u8def\u7531\u6ce8\u518c\u80fd\u529b\uff08<code class=\"language-plaintext highlighter-rouge\">pkg\/api\/dynamicmux.go<\/code> \u652f\u6301\u70ed\u66f4\u65b0\u8def\u7531\u8868\uff09\u3002<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Entry (pkg\/api\/server.go:59)<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Entry<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Path<\/span>    <span class=\"kt\">string<\/span>           <span class=\"c\">\/\/ API \u8def\u5f84<\/span>\n    <span class=\"n\">Method<\/span>  <span class=\"kt\">string<\/span>           <span class=\"c\">\/\/ HTTP \u65b9\u6cd5<\/span>\n    <span class=\"n\">Handler<\/span> <span class=\"n\">http<\/span><span class=\"o\">.<\/span><span class=\"n\">HandlerFunc<\/span> <span class=\"c\">\/\/ \u5904\u7406\u51fd\u6570<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p>API \u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">api.RegisterAPIs(group)<\/code> \u6ce8\u518c\uff0c\u6309\u529f\u80fd\u5206\u7ec4\uff08\u5982 v2 API\u3001\u5065\u5eb7\u68c0\u67e5\u3001Profile \u7b49\uff09\uff0c\u6700\u7ec8\u6302\u8f7d\u5230 API Server\u3002<\/p>\n\n<h3 id=\"410-\u6821\u9a8c\u7cfb\u7edf\">4.10 \u6821\u9a8c\u7cfb\u7edf<\/h3>\n\n<p><strong>\u5b9a\u4e49\u4f4d\u4e8e<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/v\/v.go<\/code>\u3002<\/p>\n\n<p>Easegress \u4f7f\u7528 JSON Schema \u505a\u914d\u7f6e\u6821\u9a8c\u3002\u901a\u8fc7\u8bfb\u53d6 Go struct \u4e0a\u7684 <code class=\"language-plaintext highlighter-rouge\">jsonschema<\/code> tag\uff0c\u81ea\u52a8\u751f\u6210 JSON Schema\uff0c\u5728\u6821\u9a8c\u73af\u8282\u4f7f\u7528\u3002<\/p>\n\n<p><strong>\u81ea\u5b9a\u4e49\u683c\u5f0f\u6821\u9a8c\u5668<\/strong>\uff08<code class=\"language-plaintext highlighter-rouge\">pkg\/v\/format.go:31<\/code>\uff09\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u683c\u5f0f<\/th>\n      <th>\u8bf4\u660e<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">urlname<\/code><\/td>\n      <td>URL \u5b89\u5168\u540d\u79f0<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">duration<\/code><\/td>\n      <td>\u65f6\u95f4\u95f4\u9694\uff08\u5982 <code class=\"language-plaintext highlighter-rouge\">10s<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">5m<\/code>\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ipcidr<\/code><\/td>\n      <td>IP CIDR \u683c\u5f0f<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">regexp<\/code><\/td>\n      <td>\u6b63\u5219\u8868\u8fbe\u5f0f<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">base64<\/code><\/td>\n      <td>Base64 \u7f16\u7801<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">byteurl<\/code><\/td>\n      <td>\u5b57\u8282\u5927\u5c0f + URL \u683c\u5f0f<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"5-\u5bf9\u8c61\u5206\u7c7b\u8be6\u89e3\">5. \u5bf9\u8c61\u5206\u7c7b\u8be6\u89e3<\/h2>\n\n<p>Easegress \u4e2d\u6240\u6709\u7ba1\u7406\u5bf9\u8c61\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">Supervisor<\/code> \u7edf\u4e00\u751f\u547d\u5468\u671f\u7ba1\u7406\uff0c\u6309\u8fd0\u884c\u65f6\u4f9d\u8d56\u5173\u7cfb\u5206\u7c7b\u5982\u4e0b\uff1a<\/p>\n\n<h3 id=\"systemcontroller\">SystemController<\/h3>\n\n<p>\u7cfb\u7edf\u5185\u7f6e\uff0c\u5355\u4f53\u5b9e\u4f8b\uff0c\u5728 Supervisor \u542f\u52a8\u65f6\u6700\u5148\u521d\u59cb\u5316\u3002<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u5bf9\u8c61<\/th>\n      <th>\u5305\u8def\u5f84<\/th>\n      <th>\u804c\u8d23<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>TrafficController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/trafficcontroller\/<\/code><\/td>\n      <td>\u7ba1\u7406 TrafficGate \u548c Pipeline \u7684\u521b\u5efa\/\u9500\u6bc1<\/td>\n    <\/tr>\n    <tr>\n      <td>MeshController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/meshcontroller\/<\/code><\/td>\n      <td>\u670d\u52a1\u7f51\u683c\u63a7\u5236\u5e73\u9762\uff08\u652f\u6301 Eureka\/Consul\/Nacos \u7b49\u670d\u52a1\u53d1\u73b0\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td>AutoCertManager<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/autocertmanager\/<\/code><\/td>\n      <td>\u81ea\u52a8 TLS \u8bc1\u4e66\u7ba1\u7406\uff08ACME\uff09<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"businesscontroller\">BusinessController<\/h3>\n\n<p>\u7528\u6237\u901a\u8fc7 Admin API \u6216\u914d\u7f6e\u6587\u4ef6\u521b\u5efa\u7684\u4e1a\u52a1\u63a7\u5236\u5668\u3002<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u5bf9\u8c61<\/th>\n      <th>\u5305\u8def\u5f84<\/th>\n      <th>\u804c\u8d23<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>IngressController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/ingresscontroller\/<\/code><\/td>\n      <td>Kubernetes Ingress \u63a7\u5236\u5668<\/td>\n    <\/tr>\n    <tr>\n      <td>GatewayController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/gatewaycontroller\/<\/code><\/td>\n      <td>Kubernetes Gateway API \u63a7\u5236\u5668<\/td>\n    <\/tr>\n    <tr>\n      <td>WAFController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/wafcontroller\/<\/code><\/td>\n      <td>Web \u5e94\u7528\u9632\u706b\u5899\u63a7\u7ba1<\/td>\n    <\/tr>\n    <tr>\n      <td>GlobalFilter<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/globalfilter\/<\/code><\/td>\n      <td>\u5168\u5c40 Filter \u7ba1\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>AIGatewayController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/aigatewaycontroller\/<\/code><\/td>\n      <td>AI \u7f51\u5173\uff08LLM \u4ee3\u7406\uff09\u7ba1\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>StatusSyncController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/statussynccontroller\/<\/code><\/td>\n      <td>\u72b6\u6001\u540c\u6b65<\/td>\n    <\/tr>\n    <tr>\n      <td>Function<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/function\/<\/code><\/td>\n      <td>Serverless Function<\/td>\n    <\/tr>\n    <tr>\n      <td>RawConfigTrafficController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/rawconfigtrafficcontroller\/<\/code><\/td>\n      <td>\u539f\u59cb\u914d\u7f6e\u65b9\u5f0f\u7684\u6d41\u91cf\u7ba1\u7406<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p><strong>\u670d\u52a1\u6ce8\u518c\u4e2d\u5fc3\u9002\u914d\u5668<\/strong>\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u670d\u52a1\u53d1\u73b0<\/th>\n      <th>\u5305\u8def\u5f84<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>Consul<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/consulserviceregistry\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>Etcd<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/etcdserviceregistry\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>Eureka<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/eurekaserviceregistry\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>Nacos<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/nacosserviceregistry\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>ZooKeeper<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/zookeeperserviceregistry\/<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"trafficgate\">TrafficGate<\/h3>\n\n<p>\u534f\u8bae\u76d1\u542c\u5165\u53e3\uff0c\u8d1f\u8d23\u63a5\u6536\u5916\u90e8\u6d41\u91cf\u5e76\u6309\u8def\u7531\u89c4\u5219\u8f6c\u53d1\u81f3 Pipeline\u3002<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u5bf9\u8c61<\/th>\n      <th>\u5305\u8def\u5f84<\/th>\n      <th>\u534f\u8bae<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>HTTPServer<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/httpserver\/<\/code><\/td>\n      <td>HTTP\/HTTPS<\/td>\n    <\/tr>\n    <tr>\n      <td>gRPCServer<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/grpcserver\/<\/code><\/td>\n      <td>gRPC<\/td>\n    <\/tr>\n    <tr>\n      <td>MQTTProxy<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/mqttproxy\/<\/code><\/td>\n      <td>MQTT<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"pipeline\">Pipeline<\/h3>\n\n<p>\u4f4d\u4e8e <code class=\"language-plaintext highlighter-rouge\">pkg\/object\/pipeline\/<\/code>\uff0c\u5c06\u4e00\u7ec4 Filter \u7ec4\u88c5\u6210\u5904\u7406\u94fe\u3002\u4e00\u4e2a Pipeline \u53ef\u88ab\u591a\u4e2a\u8def\u7531\u5f15\u7528\uff0c\u4e00\u4e2a TrafficGate \u53ef\u6302\u8f7d\u591a\u4e2a Pipeline\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"6-\u9605\u8bfb\u8def\u5f84\u5efa\u8bae\">6. \u9605\u8bfb\u8def\u5f84\u5efa\u8bae<\/h2>\n\n<p>\u6839\u636e\u4e0d\u540c\u5b66\u4e60\u76ee\u6807\uff0c\u63a8\u8350\u4ee5\u4e0b\u6e90\u7801\u9605\u8bfb\u987a\u5e8f\uff1a<\/p>\n\n<h3 id=\"\u8def\u5f84-a\u7406\u89e3\u6574\u4f53\u67b6\u6784\u63a8\u8350\u6240\u6709\u4eba\u5148\u8bfb\">\u8def\u5f84 A\uff1a\u7406\u89e3\u6574\u4f53\u67b6\u6784\uff08\u63a8\u8350\u6240\u6709\u4eba\u5148\u8bfb\uff09<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">cmd\/server.go<\/code><\/strong> \u2014 \u542f\u52a8\u6d41\u7a0b\u7f16\u6392\uff0c\u5efa\u7acb\u5168\u5c40\u8ba4\u77e5<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/registry.go<\/code><\/strong> \u2014 Object \u63a5\u53e3\u5b9a\u4e49\uff0c\u7406\u89e3\u5bf9\u8c61\u4f53\u7cfb<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/spec.go<\/code><\/strong> \u2014 Spec\/MetaSpec \u5b9a\u4e49\uff0c\u7406\u89e3\u914d\u7f6e\u6a21\u578b<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/supervisor.go<\/code><\/strong> \u2014 Supervisor \u751f\u547d\u5468\u671f\u7ba1\u7406<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/cluster\/cluster_interface.go<\/code><\/strong> \u2014 Cluster \u63a5\u53e3\uff0c\u7406\u89e3\u914d\u7f6e\u5b58\u50a8<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/registry\/registry.go<\/code><\/strong> \u2014 \u770b\u5168\u8c8c\uff1a\u6240\u6709\u6ce8\u518c\u7684 filter \u548c object<\/li>\n<\/ol>\n\n<h3 id=\"\u8def\u5f84-b\u6df1\u5165\u6d41\u91cf\u5904\u7406\u6d41\u7a0b\">\u8def\u5f84 B\uff1a\u6df1\u5165\u6d41\u91cf\u5904\u7406\u6d41\u7a0b<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/context\/context.go<\/code><\/strong> \u2014 Context\u3001Handler\u3001MuxMapper<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/protocols.go<\/code><\/strong> \u2014 Request\/Response\/Protocol \u63a5\u53e3<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/pipeline\/pipeline.go<\/code><\/strong> \u2014 Pipeline \u5982\u4f55\u7ec4\u7ec7 Filter \u94fe<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/filters.go<\/code><\/strong> \u2014 Filter \u63a5\u53e3\u548c Kind \u5b9a\u4e49<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/httpproxy\/<\/code><\/strong> \u2014 \u9009\u4e00\u4e2a\u5177\u4f53 filter\uff08\u5982 HTTP \u4ee3\u7406\uff09\u6df1\u5165\u9605\u8bfb<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/httpserver\/<\/code><\/strong> \u2014 \u770b\u5165\u53e3 Gate \u5982\u4f55\u521b\u5efa\u5e76\u8def\u7531\u5230 Pipeline<\/li>\n<\/ol>\n\n<h3 id=\"\u8def\u5f84-c\u7814\u7a76\u7279\u5b9a\u529f\u80fd\">\u8def\u5f84 C\uff1a\u7814\u7a76\u7279\u5b9a\u529f\u80fd<\/h3>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u60f3\u4e86\u89e3\u4ec0\u4e48<\/th>\n      <th>\u4ece\u8fd9\u91cc\u5f00\u59cb<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>\u670d\u52a1\u7f51\u683c\uff08Service Mesh\uff09<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/meshcontroller\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/meshadaptor\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>OIDC \u8ba4\u8bc1<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/oidcadaptor\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>AI Gateway<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/aigatewaycontroller\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/aigatewayproxy\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>WAF \u9632\u706b\u5899<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/wafcontroller\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/waf\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>Kubernetes \u96c6\u6210<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/ingresscontroller\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">pkg\/object\/gatewaycontroller\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>MQTT \u4ee3\u7406<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/mqttprot\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">pkg\/object\/mqttproxy\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>WebAssembly \u6269\u5c55<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/wasmhost\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>\u5206\u5e03\u5f0f\u8ffd\u8e2a<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/tracing\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>OPA \u7b56\u7565\u5f15\u64ce<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/opafilter\/<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"\u8def\u5f84-d\u5f00\u53d1\u65b0-filter\">\u8def\u5f84 D\uff1a\u5f00\u53d1\u65b0 Filter<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/filters.go<\/code><\/strong> \u2014 \u7406\u89e3 Filter \u63a5\u53e3<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/registry.go<\/code><\/strong> \u2014 \u4e86\u89e3\u6ce8\u518c\u673a\u5236<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/httpproxy\/<\/code><\/strong> \u6216 <strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/ratelimiter\/<\/code><\/strong> \u2014 \u53c2\u8003\u73b0\u6709 Filter \u5b9e\u73b0<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/context\/context.go<\/code><\/strong> \u2014 \u7406\u89e3 <code class=\"language-plaintext highlighter-rouge\">Handle(*Context)<\/code> \u7684\u5165\u53c2<\/li>\n<\/ol>\n\n<h3 id=\"\u8def\u5f84-e\u5f00\u53d1\u65b0-object\u63a7\u5236\u5668trafficgate\">\u8def\u5f84 E\uff1a\u5f00\u53d1\u65b0 Object\uff08\u63a7\u5236\u5668\/TrafficGate\uff09<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/registry.go<\/code><\/strong> \u2014 Object \u63a5\u53e3\u548c\u6ce8\u518c\u673a\u5236<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/trafficcontroller\/<\/code><\/strong> \u2014 SystemController \u53c2\u8003\u5b9e\u73b0<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/httpserver\/<\/code><\/strong> \u2014 TrafficGate \u53c2\u8003\u5b9e\u73b0<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/pipeline\/<\/code><\/strong> \u2014 Pipeline \u53c2\u8003\u5b9e\u73b0<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"\u9644\u5f55\u5173\u952e\u6587\u4ef6\u7d22\u5f15\">\u9644\u5f55\uff1a\u5173\u952e\u6587\u4ef6\u7d22\u5f15<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u6587\u4ef6<\/th>\n      <th>\u6838\u5fc3\u5185\u5bb9<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">cmd\/server.go:40-147<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">RunServer()<\/code> \u542f\u52a8\u7f16\u6392<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/registry.go:30-113<\/code><\/td>\n      <td>Object\/ObjectCategory \u63a5\u53e3\u5b9a\u4e49<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/spec.go:34-53<\/code><\/td>\n      <td>Spec\/MetaSpec \u7c7b\u578b<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/supervisor.go:36<\/code><\/td>\n      <td>Supervisor \u7ed3\u6784\u4f53<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/object.go:39<\/code><\/td>\n      <td>ObjectEntity\/ObjectRegistry<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/cluster\/cluster_interface.go:33<\/code><\/td>\n      <td>Cluster \u63a5\u53e3<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/context\/context.go:35-42<\/code><\/td>\n      <td>Handler\/MuxMapper \u63a5\u53e3<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/context\/context.go:70<\/code><\/td>\n      <td>Context \u7ed3\u6784\u4f53<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/protocols.go:39-143<\/code><\/td>\n      <td>Request\/Response\/Protocol \u63a5\u53e3<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/filters.go:33-60<\/code><\/td>\n      <td>Kind\/Filter \u63a5\u53e3<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/registry.go<\/code><\/td>\n      <td>Filter \u6ce8\u518c\u8868<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/resilience\/resilience.go:30-116<\/code><\/td>\n      <td>Policy\/Wrapper \u63a5\u53e3<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/v\/v.go<\/code><\/td>\n      <td>JSON Schema \u6821\u9a8c<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/v\/format.go:31<\/code><\/td>\n      <td>\u81ea\u5b9a\u4e49\u683c\u5f0f\u6821\u9a8c\u5668<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/api\/server.go:37-80<\/code><\/td>\n      <td>Admin API Server<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/registry\/registry.go<\/code><\/td>\n      <td>\u5168\u5c40\u6ce8\u518c\u8868\uff08\u7a7a\u767d\u5bfc\u5165\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">go.mod:1<\/code><\/td>\n      <td>Module \u5b9a\u4e49\uff08v2\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">Makefile:20<\/code><\/td>\n      <td>\u7248\u672c\u53f7\u548c\u6784\u5efa\u914d\u7f6e<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n","category":{"@attributes":{"term":"Easegress"}}},{"title":"Easegress Source Code Reading Guide","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/en\/2026-07-31\/easegress-source-code-guide.html"}},"updated":"2026-07-31T23:00:00+08:00","id":"https:\/\/wy471x.github.io\/en\/2026-07-31\/easegress-source-code-guide.html","content":"<h1 id=\"easegress-source-code-reading-guide\">Easegress Source Code Reading Guide<\/h1>\n\n<h2 id=\"table-of-contents\">Table of Contents<\/h2>\n\n<ul>\n  <li><a href=\"#1-project-overview\">1. Project Overview<\/a><\/li>\n  <li><a href=\"#2-build--run\">2. Build &amp; Run<\/a><\/li>\n  <li><a href=\"#3-startup-flow\">3. Startup Flow<\/a><\/li>\n  <li><a href=\"#4-core-architecture\">4. Core Architecture<\/a>\n    <ul>\n      <li><a href=\"#41-object-system-registration--lifecycle\">4.1 Object System (Registration &amp; Lifecycle)<\/a><\/li>\n      <li><a href=\"#42-spec-system-declarative-configuration\">4.2 Spec System (Declarative Configuration)<\/a><\/li>\n      <li><a href=\"#43-supervisor-lifecycle-management\">4.3 Supervisor (Lifecycle Management)<\/a><\/li>\n      <li><a href=\"#44-cluster-clustering--storage\">4.4 Cluster (Clustering &amp; Storage)<\/a><\/li>\n      <li><a href=\"#45-traffic-pipeline\">4.5 Traffic Pipeline<\/a><\/li>\n      <li><a href=\"#46-filter-system\">4.6 Filter System<\/a><\/li>\n      <li><a href=\"#47-protocol-abstraction\">4.7 Protocol Abstraction<\/a><\/li>\n      <li><a href=\"#48-resilience\">4.8 Resilience<\/a><\/li>\n      <li><a href=\"#49-admin-api\">4.9 Admin API<\/a><\/li>\n      <li><a href=\"#410-validation-system\">4.10 Validation System<\/a><\/li>\n    <\/ul>\n  <\/li>\n  <li><a href=\"#5-object-categories-in-detail\">5. Object Categories in Detail<\/a><\/li>\n  <li><a href=\"#6-suggested-reading-paths\">6. Suggested Reading Paths<\/a><\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"1-project-overview\">1. Project Overview<\/h2>\n\n<p><strong>Easegress<\/strong> is a cloud-native traffic orchestration gateway written in Go, using a declarative configuration + controller pattern to manage all components. It uses etcd for distributed configuration storage and supports HTTP\/gRPC\/MQTT multi-protocol proxying.<\/p>\n\n<ul>\n  <li><strong>Repository<\/strong>: <code class=\"language-plaintext highlighter-rouge\">github.com\/megaease\/easegress\/v2<\/code><\/li>\n  <li><strong>Go Version<\/strong>: 1.26<\/li>\n  <li><strong>Current Version<\/strong>: v2.11.0<\/li>\n  <li><strong>License<\/strong>: Apache License 2.0<\/li>\n<\/ul>\n\n<h3 id=\"directory-overview\">Directory Overview<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>easegress\/\n\u251c\u2500\u2500 cmd\/                    # Entry points for three binaries\n\u2502   \u251c\u2500\u2500 server\/main.go      # easegress-server entry point\n\u2502   \u251c\u2500\u2500 client\/main.go      # egctl CLI tool entry point\n\u2502   \u2514\u2500\u2500 builder\/main.go     # egbuilder custom build tool entry point\n\u251c\u2500\u2500 cmd\/server.go           # RunServer() orchestration function\n\u251c\u2500\u2500 pkg\/                    # All core library code (22 packages)\n\u251c\u2500\u2500 build\/                  # Dockerfile and integration tests\n\u251c\u2500\u2500 docs\/                   # Documentation site\n\u251c\u2500\u2500 example\/                # Cluster example configurations\n\u251c\u2500\u2500 helm-charts\/            # Helm Chart\n\u251c\u2500\u2500 scripts\/                # Helper scripts\n\u251c\u2500\u2500 Makefile                # Build system\n\u2514\u2500\u2500 go.mod                  # Single module definition\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"three-binary-artifacts\">Three Binary Artifacts<\/h3>\n\n<table>\n  <thead>\n    <tr>\n      <th>Binary<\/th>\n      <th>Entry Point<\/th>\n      <th>Purpose<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">easegress-server<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">cmd\/server\/main.go:26<\/code><\/td>\n      <td>Core gateway service process<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">egctl<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">cmd\/client\/main.go:53<\/code><\/td>\n      <td>Management CLI tool (built on Cobra)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">egbuilder<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">cmd\/builder\/main.go:36<\/code><\/td>\n      <td>Custom module build tool<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"2-build--run\">2. Build &amp; Run<\/h2>\n\n<h3 id=\"build-commands\">Build Commands<\/h3>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\"># Build all three binaries<\/span>\nmake build\n\n<span class=\"c\"># Build server only<\/span>\nmake build_server\n\n<span class=\"c\"># Build Docker image<\/span>\nmake build_docker\n\n<span class=\"c\"># Run tests<\/span>\nmake <span class=\"nb\">test<\/span>\n\n<span class=\"c\"># Code formatting and linting<\/span>\nmake <span class=\"nb\">fmt\n<\/span>make vet\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"key-makefile-variables-makefile20\">Key Makefile Variables (<code class=\"language-plaintext highlighter-rouge\">Makefile:20<\/code>)<\/h3>\n\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">RELEASE = v2.11.0<\/code><\/li>\n  <li>Server build includes <code class=\"language-plaintext highlighter-rouge\">wasmhost<\/code> build tag, requires CGO enabled<\/li>\n  <li>GoReleaser config in <code class=\"language-plaintext highlighter-rouge\">.goreleaser.yml<\/code>, supports linux\/darwin + amd64\/arm64 cross-compilation<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"3-startup-flow\">3. Startup Flow<\/h2>\n\n<p>The complete server startup flow is in the <code class=\"language-plaintext highlighter-rouge\">RunServer()<\/code> function at <code class=\"language-plaintext highlighter-rouge\">cmd\/server.go:40-147<\/code>. In order:<\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>1. option.New().Parse()           \u2014 Parse startup options and config file\n2. env.InitServerDir()            \u2014 Initialize server directory structure\n3. logger.Init(opt)               \u2014 Initialize structured logging (zap-based)\n4. cluster.New(opt)               \u2014 Start embedded etcd or connect to external cluster\n5. supervisor.MustNew(opt, cls)   \u2014 Create Supervisor, initialize SystemControllers\n6. api.MustNewServer(...)         \u2014 Start Admin API HTTP server\n7. Register Graceful Upgrade signal handling\n8. Block waiting for SIGINT\/SIGTERM, graceful shutdown\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Key points<\/strong>:<\/p>\n<ul>\n  <li>Steps 4-6 have strict sequential dependencies: the cluster must be ready before Supervisor can watch config changes, and the API Server can then expose the management interface.<\/li>\n  <li>In step 5, Supervisor internally initializes all <code class=\"language-plaintext highlighter-rouge\">SystemController<\/code>s (in dependency order), then starts the <code class=\"language-plaintext highlighter-rouge\">go s.run()<\/code> goroutine to listen for config changes.<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"4-core-architecture\">4. Core Architecture<\/h2>\n\n<h3 id=\"41-object-system-registration--lifecycle\">4.1 Object System (Registration &amp; Lifecycle)<\/h3>\n\n<p>All managed components in Easegress implement the <code class=\"language-plaintext highlighter-rouge\">Object<\/code> interface \u2014 the most important abstraction for understanding the entire project.<\/p>\n\n<p><strong>Core definition at<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/registry.go:30-47<\/code>:<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">type<\/span> <span class=\"n\">Object<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Category<\/span><span class=\"p\">()<\/span> <span class=\"n\">ObjectCategory<\/span>   <span class=\"c\">\/\/ Object category (determines startup\/shutdown order)<\/span>\n    <span class=\"n\">Kind<\/span><span class=\"p\">()<\/span> <span class=\"kt\">string<\/span>               <span class=\"c\">\/\/ Unique type identifier<\/span>\n    <span class=\"n\">DefaultSpec<\/span><span class=\"p\">()<\/span> <span class=\"k\">interface<\/span><span class=\"p\">{}<\/span>   <span class=\"c\">\/\/ Returns default config (must be a pointer to a struct)<\/span>\n    <span class=\"n\">Status<\/span><span class=\"p\">()<\/span> <span class=\"o\">*<\/span><span class=\"n\">Status<\/span>            <span class=\"c\">\/\/ Runtime status<\/span>\n    <span class=\"n\">Close<\/span><span class=\"p\">()<\/span>                     <span class=\"c\">\/\/ Called on teardown<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Object categories<\/strong> (<code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/registry.go:102-113<\/code>) sorted by startup priority:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Category<\/th>\n      <th>Description<\/th>\n      <th>Examples<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">SystemController<\/code><\/td>\n      <td>Built-in system controllers, started first<\/td>\n      <td>TrafficController, MeshController, AutoCertManager<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">BusinessController<\/code><\/td>\n      <td>User-created controllers<\/td>\n      <td>IngressController, GatewayController, WAFController<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">Pipeline<\/code><\/td>\n      <td>Traffic processing pipeline<\/td>\n      <td>Pipeline<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">TrafficGate<\/code><\/td>\n      <td>Protocol listener entry points<\/td>\n      <td>HTTPServer, gRPCServer, MQTTProxy<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p><strong>Object registration mechanism<\/strong>: Self-registration via calling <code class=\"language-plaintext highlighter-rouge\">supervisor.Register(&amp;MyObject{})<\/code> in <code class=\"language-plaintext highlighter-rouge\">init()<\/code> functions. <code class=\"language-plaintext highlighter-rouge\">pkg\/registry\/registry.go<\/code> uses blank imports to trigger <code class=\"language-plaintext highlighter-rouge\">init()<\/code> across all filter and object packages:<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ pkg\/registry\/registry.go<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">(<\/span>\n    <span class=\"n\">_<\/span> <span class=\"s\">\"github.com\/megaease\/easegress\/v2\/pkg\/filters\/httpproxy\"<\/span>\n    <span class=\"n\">_<\/span> <span class=\"s\">\"github.com\/megaease\/easegress\/v2\/pkg\/object\/httpserver\"<\/span>\n    <span class=\"c\">\/\/ ... all filter and object packages<\/span>\n<span class=\"p\">)<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><code class=\"language-plaintext highlighter-rouge\">cmd\/server\/main.go<\/code> imports <code class=\"language-plaintext highlighter-rouge\">pkg\/registry<\/code> to complete automatic registration of all modules.<\/p>\n\n<h3 id=\"42-spec-system-declarative-configuration\">4.2 Spec System (Declarative Configuration)<\/h3>\n\n<p><strong>Definition at<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/spec.go<\/code>:<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Spec (pkg\/supervisor\/spec.go:34) \u2014 Generic object configuration<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Spec<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">super<\/span>       <span class=\"o\">*<\/span><span class=\"n\">Supervisor<\/span>\n    <span class=\"n\">category<\/span>    <span class=\"n\">ObjectCategory<\/span>\n    <span class=\"n\">jsonConfig<\/span>  <span class=\"kt\">string<\/span>            <span class=\"c\">\/\/ Raw JSON configuration<\/span>\n    <span class=\"n\">meta<\/span>        <span class=\"o\">*<\/span><span class=\"n\">MetaSpec<\/span>         <span class=\"c\">\/\/ Metadata<\/span>\n    <span class=\"n\">rawSpec<\/span>     <span class=\"k\">map<\/span><span class=\"p\">[<\/span><span class=\"kt\">string<\/span><span class=\"p\">]<\/span><span class=\"k\">interface<\/span><span class=\"p\">{}<\/span>  <span class=\"c\">\/\/ Un-deserialized raw map<\/span>\n    <span class=\"n\">objectSpec<\/span>  <span class=\"k\">interface<\/span><span class=\"p\">{}<\/span>       <span class=\"c\">\/\/ Deserialized Go struct<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ MetaSpec (pkg\/supervisor\/spec.go:45) \u2014 Common metadata<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">MetaSpec<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Name<\/span>      <span class=\"kt\">string<\/span>            <span class=\"s\">`json:\"name\" jsonschema:\"required,format=urlname\"`<\/span>\n    <span class=\"n\">Kind<\/span>      <span class=\"kt\">string<\/span>            <span class=\"s\">`json:\"kind\" jsonschema:\"required\"`<\/span>\n    <span class=\"n\">Version<\/span>   <span class=\"kt\">string<\/span>            <span class=\"s\">`json:\"version,omitempty\"`<\/span>\n    <span class=\"n\">Labels<\/span>    <span class=\"k\">map<\/span><span class=\"p\">[<\/span><span class=\"kt\">string<\/span><span class=\"p\">]<\/span><span class=\"kt\">string<\/span> <span class=\"s\">`json:\"labels,omitempty\"`<\/span>\n    <span class=\"n\">CreatedAt<\/span> <span class=\"kt\">string<\/span>            <span class=\"s\">`json:\"createdAt,omitempty\"`<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Design highlights<\/strong>:<\/p>\n<ul>\n  <li>All object configurations are stored in etcd as JSON\/YAML, routed to the corresponding <code class=\"language-plaintext highlighter-rouge\">Object<\/code> implementation via <code class=\"language-plaintext highlighter-rouge\">MetaSpec.Kind<\/code>.<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">Spec<\/code> holds both raw data (<code class=\"language-plaintext highlighter-rouge\">rawSpec<\/code>) and the deserialized Go struct (<code class=\"language-plaintext highlighter-rouge\">objectSpec<\/code>), facilitating validation and passthrough.<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">jsonschema<\/code> struct tags drive automatic validation, see <a href=\"#410-validation-system\">4.10 Validation System<\/a>.<\/li>\n<\/ul>\n\n<h3 id=\"43-supervisor-lifecycle-management\">4.3 Supervisor (Lifecycle Management)<\/h3>\n\n<p><strong>Definition at<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/supervisor.go:36<\/code>:<\/p>\n\n<p>Supervisor is the lifecycle manager for objects. Core responsibilities:<\/p>\n\n<ol>\n  <li><strong>Holds ObjectRegistry<\/strong> (<code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/object.go:39-45<\/code>) \u2014 a local cache of configurations stored in etcd<\/li>\n  <li><strong>Holds ObjectEntityWatcher<\/strong> (<code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/object.go<\/code>) \u2014 watches etcd for config create\/update\/delete events<\/li>\n  <li><strong>Initializes and starts SystemControllers<\/strong> (<code class=\"language-plaintext highlighter-rouge\">supervisor.go:103<\/code>)<\/li>\n  <li><strong>Runs the event loop<\/strong> (<code class=\"language-plaintext highlighter-rouge\">go s.run()<\/code> at line 105) \u2014 upon receiving config change events, creates\/updates\/deletes <code class=\"language-plaintext highlighter-rouge\">ObjectEntity<\/code> instances<\/li>\n<\/ol>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ ObjectEntity (pkg\/supervisor\/object.go:39-45) \u2014 Runtime wrapper for Object<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">ObjectEntity<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">instance<\/span>   <span class=\"n\">Object<\/span>      <span class=\"c\">\/\/ Actual Object implementation<\/span>\n    <span class=\"n\">spec<\/span>       <span class=\"o\">*<\/span><span class=\"n\">Spec<\/span>       <span class=\"c\">\/\/ Associated configuration<\/span>\n    <span class=\"n\">generation<\/span> <span class=\"kt\">int64<\/span>       <span class=\"c\">\/\/ Generation (incremented on each update, for CAS detection)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"44-cluster-clustering--storage\">4.4 Cluster (Clustering &amp; Storage)<\/h3>\n\n<p><strong>Definition at<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/cluster\/cluster_interface.go:33<\/code>:<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">type<\/span> <span class=\"n\">Cluster<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">IsLeader<\/span><span class=\"p\">()<\/span> <span class=\"kt\">bool<\/span>\n    <span class=\"n\">Layout<\/span><span class=\"p\">()<\/span> <span class=\"o\">*<\/span><span class=\"n\">Layout<\/span>\n\n    <span class=\"c\">\/\/ KV operations<\/span>\n    <span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"kt\">string<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">GetPrefix<\/span><span class=\"p\">(<\/span><span class=\"n\">prefix<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"k\">map<\/span><span class=\"p\">[<\/span><span class=\"kt\">string<\/span><span class=\"p\">]<\/span><span class=\"kt\">string<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">Put<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span><span class=\"p\">,<\/span> <span class=\"n\">value<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span>\n    <span class=\"n\">Delete<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span>\n    <span class=\"n\">DeletePrefix<\/span><span class=\"p\">(<\/span><span class=\"n\">prefix<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span>\n\n    <span class=\"c\">\/\/ Atomic operations (based on etcd STM)<\/span>\n    <span class=\"n\">STM<\/span><span class=\"p\">(<\/span><span class=\"n\">apply<\/span> <span class=\"k\">func<\/span><span class=\"p\">(<\/span><span class=\"n\">concurrency<\/span><span class=\"o\">.<\/span><span class=\"n\">STM<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span>\n\n    <span class=\"c\">\/\/ Config change watching<\/span>\n    <span class=\"n\">Watcher<\/span><span class=\"p\">()<\/span> <span class=\"p\">(<\/span><span class=\"n\">Watcher<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">Syncer<\/span><span class=\"p\">(<\/span><span class=\"n\">pullInterval<\/span> <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Duration<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"n\">Syncer<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c\">\/\/ Leader election<\/span>\n    <span class=\"n\">Mutex<\/span><span class=\"p\">(<\/span><span class=\"n\">name<\/span> <span class=\"kt\">string<\/span><span class=\"p\">,<\/span> <span class=\"n\">ttl<\/span> <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Duration<\/span><span class=\"p\">)<\/span> <span class=\"n\">concurrency<\/span><span class=\"o\">.<\/span><span class=\"n\">Locker<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Key sub-interfaces<\/strong>:<\/p>\n\n<ul>\n  <li><strong>Watcher<\/strong> (<code class=\"language-plaintext highlighter-rouge\">pkg\/cluster\/cluster_interface.go:76<\/code>): Real-time monitoring of change events for specified keys\/prefixes in etcd<\/li>\n  <li><strong>Syncer<\/strong> (<code class=\"language-plaintext highlighter-rouge\">pkg\/cluster\/cluster_interface.go:91<\/code>): Maintains a local cache, keeping in sync with etcd via periodic full pulls<\/li>\n<\/ul>\n\n<h3 id=\"45-traffic-pipeline\">4.5 Traffic Pipeline<\/h3>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/context\/context.go<\/code><\/strong> defines the context carrier for traffic processing.<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Handler (pkg\/context\/context.go:35) \u2014 Interface for all traffic processors<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Handler<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Handle<\/span><span class=\"p\">(<\/span><span class=\"n\">ctx<\/span> <span class=\"o\">*<\/span><span class=\"n\">Context<\/span><span class=\"p\">)<\/span> <span class=\"kt\">string<\/span>   <span class=\"c\">\/\/ Returns result string (empty string means continue on success)<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ MuxMapper (pkg\/context\/context.go:40) \u2014 Look up Handler by name<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">MuxMapper<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">GetHandler<\/span><span class=\"p\">(<\/span><span class=\"n\">name<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"n\">Handler<\/span><span class=\"p\">,<\/span> <span class=\"kt\">bool<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Pipeline structure<\/strong> (<code class=\"language-plaintext highlighter-rouge\">pkg\/object\/pipeline\/pipeline.go:63<\/code>):<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">type<\/span> <span class=\"n\">Pipeline<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">filters<\/span> <span class=\"k\">map<\/span><span class=\"p\">[<\/span><span class=\"kt\">string<\/span><span class=\"p\">]<\/span><span class=\"n\">filters<\/span><span class=\"o\">.<\/span><span class=\"n\">Filter<\/span>  <span class=\"c\">\/\/ All Filter instances (indexed by name)<\/span>\n    <span class=\"n\">flow<\/span>    <span class=\"p\">[]<\/span><span class=\"n\">FlowNode<\/span>                  <span class=\"c\">\/\/ Processing flow definition (sequential + conditional jumps)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Traffic processing flow<\/strong>:<\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>TrafficGate (e.g. HTTPServer)\n    \u2192 Route matching\n        \u2192 Pipeline\n            \u2192 FlowNode[0] \u2192 Filter A \u2192 Jump based on result\n                \u2192 FlowNode[1] \u2192 Filter B\n                    \u2192 ...\n                        \u2192 Return response\n<\/code><\/pre><\/div><\/div>\n\n<p><code class=\"language-plaintext highlighter-rouge\">Context<\/code> carries <code class=\"language-plaintext highlighter-rouge\">Request<\/code> and <code class=\"language-plaintext highlighter-rouge\">Response<\/code> throughout the entire chain, with each Filter able to read and write to Context.<\/p>\n\n<h3 id=\"46-filter-system\">4.6 Filter System<\/h3>\n\n<p><strong>Core interfaces<\/strong> at <code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/filters.go<\/code>:<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Kind (pkg\/filters\/filters.go:33) \u2014 Metadata describing a Filter type<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Kind<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Name<\/span>           <span class=\"kt\">string<\/span>\n    <span class=\"n\">Description<\/span>    <span class=\"kt\">string<\/span>\n    <span class=\"n\">Results<\/span>        <span class=\"p\">[]<\/span><span class=\"kt\">string<\/span>                             <span class=\"c\">\/\/ All possible results beyond empty string<\/span>\n    <span class=\"n\">CreateInstance<\/span> <span class=\"k\">func<\/span><span class=\"p\">(<\/span><span class=\"n\">spec<\/span> <span class=\"n\">Spec<\/span><span class=\"p\">)<\/span> <span class=\"n\">Filter<\/span>               <span class=\"c\">\/\/ Factory function<\/span>\n    <span class=\"n\">DefaultSpec<\/span>    <span class=\"k\">func<\/span><span class=\"p\">()<\/span> <span class=\"n\">Spec<\/span>                          <span class=\"c\">\/\/ Returns a copy of default config<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ Filter (pkg\/filters\/filters.go:54) \u2014 Base filter interface<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Filter<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Name<\/span><span class=\"p\">()<\/span> <span class=\"kt\">string<\/span>\n    <span class=\"n\">Kind<\/span><span class=\"p\">()<\/span> <span class=\"o\">*<\/span><span class=\"n\">Kind<\/span>\n    <span class=\"n\">Handle<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">context<\/span><span class=\"o\">.<\/span><span class=\"n\">Context<\/span><span class=\"p\">)<\/span> <span class=\"kt\">string<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Filter plugin registry<\/strong> at <code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/registry.go<\/code>, registered via <code class=\"language-plaintext highlighter-rouge\">filters.Register(k *Kind)<\/code>.<\/p>\n\n<p><strong>Built-in Filter list<\/strong> (27 types):<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Category<\/th>\n      <th>Filter<\/th>\n      <th>Function<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>Proxy<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">httpproxy<\/code><\/td>\n      <td>HTTP reverse proxy<\/td>\n    <\/tr>\n    <tr>\n      <td>Proxy<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">grpcproxy<\/code><\/td>\n      <td>gRPC proxy<\/td>\n    <\/tr>\n    <tr>\n      <td>Proxy<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">aigatewayproxy<\/code><\/td>\n      <td>AI gateway proxy<\/td>\n    <\/tr>\n    <tr>\n      <td>Security<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">validator<\/code><\/td>\n      <td>Request validation<\/td>\n    <\/tr>\n    <tr>\n      <td>Security<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">waf<\/code><\/td>\n      <td>Web Application Firewall (Coraza-based)<\/td>\n    <\/tr>\n    <tr>\n      <td>Security<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">oidcadaptor<\/code><\/td>\n      <td>OIDC authentication adapter<\/td>\n    <\/tr>\n    <tr>\n      <td>Security<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">corsadaptor<\/code><\/td>\n      <td>CORS handling<\/td>\n    <\/tr>\n    <tr>\n      <td>Traffic Control<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ratelimiter<\/code><\/td>\n      <td>Rate limiting<\/td>\n    <\/tr>\n    <tr>\n      <td>Traffic Control<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">circuitbreaker<\/code><\/td>\n      <td>Circuit breaking (resilience module)<\/td>\n    <\/tr>\n    <tr>\n      <td>Routing<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">redirector<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">redirectorv2<\/code><\/td>\n      <td>Redirection<\/td>\n    <\/tr>\n    <tr>\n      <td>Routing<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">headerlookup<\/code><\/td>\n      <td>Header-based route matching<\/td>\n    <\/tr>\n    <tr>\n      <td>Routing<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">headertojson<\/code><\/td>\n      <td>Header to JSON conversion<\/td>\n    <\/tr>\n    <tr>\n      <td>Messaging<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">kafka<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">kafkabackend<\/code><\/td>\n      <td>Kafka message processing<\/td>\n    <\/tr>\n    <tr>\n      <td>Messaging<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">mqttclientauth<\/code><\/td>\n      <td>MQTT client authentication<\/td>\n    <\/tr>\n    <tr>\n      <td>Messaging<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">topicmapper<\/code><\/td>\n      <td>MQTT topic mapping<\/td>\n    <\/tr>\n    <tr>\n      <td>Service Mesh<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">meshadaptor<\/code><\/td>\n      <td>Mesh adaptation<\/td>\n    <\/tr>\n    <tr>\n      <td>Extension<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">wasmhost<\/code><\/td>\n      <td>WebAssembly sandbox<\/td>\n    <\/tr>\n    <tr>\n      <td>Extension<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">remotefilter<\/code><\/td>\n      <td>Remote filter invocation<\/td>\n    <\/tr>\n    <tr>\n      <td>Extension<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">builder<\/code><\/td>\n      <td>Build-time dynamic Filter<\/td>\n    <\/tr>\n    <tr>\n      <td>Policy<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">opafilter<\/code><\/td>\n      <td>OPA policy engine<\/td>\n    <\/tr>\n    <tr>\n      <td>Utility<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">fileserver<\/code><\/td>\n      <td>Static file serving<\/td>\n    <\/tr>\n    <tr>\n      <td>Utility<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">mock<\/code><\/td>\n      <td>Mock responses<\/td>\n    <\/tr>\n    <tr>\n      <td>Utility<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">fallback<\/code><\/td>\n      <td>Degradation fallback<\/td>\n    <\/tr>\n    <tr>\n      <td>Utility<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">certextractor<\/code><\/td>\n      <td>Certificate extraction<\/td>\n    <\/tr>\n    <tr>\n      <td>Utility<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">connectcontrol<\/code><\/td>\n      <td>Connection control<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"47-protocol-abstraction\">4.7 Protocol Abstraction<\/h3>\n\n<p><strong>Definition at<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/protocols.go<\/code>:<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Request (pkg\/protocols\/protocols.go:39) \u2014 Protocol-agnostic request interface<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Request<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Header<\/span><span class=\"p\">()<\/span> <span class=\"n\">Header<\/span>\n    <span class=\"n\">RealIP<\/span><span class=\"p\">()<\/span> <span class=\"kt\">string<\/span>\n    <span class=\"n\">IsStream<\/span><span class=\"p\">()<\/span> <span class=\"kt\">bool<\/span>\n    <span class=\"n\">SetPayload<\/span><span class=\"p\">(<\/span><span class=\"n\">payload<\/span> <span class=\"k\">interface<\/span><span class=\"p\">{})<\/span>\n    <span class=\"c\">\/\/ ...<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ Response (pkg\/protocols\/protocols.go:84) \u2014 Protocol-agnostic response interface<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Response<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Header<\/span><span class=\"p\">()<\/span> <span class=\"n\">Header<\/span>\n    <span class=\"n\">SetPayload<\/span><span class=\"p\">(<\/span><span class=\"n\">payload<\/span> <span class=\"k\">interface<\/span><span class=\"p\">{})<\/span>\n    <span class=\"c\">\/\/ ...<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ Protocol (pkg\/protocols\/protocols.go:143) \u2014 Protocol implementation<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Protocol<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">CreateRequest<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"n\">io<\/span><span class=\"o\">.<\/span><span class=\"n\">Reader<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"n\">Request<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">CreateResponse<\/span><span class=\"p\">(<\/span><span class=\"n\">body<\/span> <span class=\"n\">io<\/span><span class=\"o\">.<\/span><span class=\"n\">Reader<\/span><span class=\"p\">)<\/span> <span class=\"p\">(<\/span><span class=\"n\">Response<\/span><span class=\"p\">,<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n    <span class=\"c\">\/\/ ...<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Implemented protocols<\/strong>:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Protocol<\/th>\n      <th>Package Path<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>HTTP<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/httpprot\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>gRPC<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/grpcprot\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>MQTT<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/mqttprot\/<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>Protocols are registered in the global registry via <code class=\"language-plaintext highlighter-rouge\">protocols.Register(name, p)<\/code>.<\/p>\n\n<h3 id=\"48-resilience\">4.8 Resilience<\/h3>\n\n<p><strong>Definition at<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/resilience\/resilience.go<\/code>:<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Wrapper (pkg\/resilience\/resilience.go:46) \u2014 Wraps a HandlerFunc<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Wrapper<\/span> <span class=\"k\">interface<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Wrap<\/span><span class=\"p\">(<\/span><span class=\"n\">HandlerFunc<\/span><span class=\"p\">)<\/span> <span class=\"n\">HandlerFunc<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ HandlerFunc (pkg\/resilience\/resilience.go:43)<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">HandlerFunc<\/span> <span class=\"k\">func<\/span><span class=\"p\">(<\/span><span class=\"n\">ctx<\/span> <span class=\"n\">context<\/span><span class=\"o\">.<\/span><span class=\"n\">Context<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p>Resilience and fault-tolerance strategies wrap Filter Handle calls using the <strong>decorator pattern<\/strong>:<\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>Wrapper(Filter.Handle) \u2192 Execute Filter logic, tolerate faults per policy\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Built-in strategies<\/strong>:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Strategy<\/th>\n      <th>File<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>CircuitBreaker<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/resilience\/circuitbreaker.go<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>Retry<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/resilience\/retry.go<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"49-admin-api\">4.9 Admin API<\/h3>\n\n<p><strong>Definitions at<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/api\/api.go<\/code> and <code class=\"language-plaintext highlighter-rouge\">pkg\/api\/server.go<\/code>.<\/p>\n\n<p>The Admin API uses <strong>go-chi\/chi<\/strong> as the HTTP routing framework, providing dynamic route registration (<code class=\"language-plaintext highlighter-rouge\">pkg\/api\/dynamicmux.go<\/code> supports hot-reloading the route table).<\/p>\n\n<div class=\"language-go highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\">\/\/ Entry (pkg\/api\/server.go:59)<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">Entry<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Path<\/span>    <span class=\"kt\">string<\/span>           <span class=\"c\">\/\/ API path<\/span>\n    <span class=\"n\">Method<\/span>  <span class=\"kt\">string<\/span>           <span class=\"c\">\/\/ HTTP method<\/span>\n    <span class=\"n\">Handler<\/span> <span class=\"n\">http<\/span><span class=\"o\">.<\/span><span class=\"n\">HandlerFunc<\/span> <span class=\"c\">\/\/ Handler function<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p>APIs are registered via <code class=\"language-plaintext highlighter-rouge\">api.RegisterAPIs(group)<\/code>, grouped by functionality (e.g., v2 APIs, health checks, profiles), and ultimately mounted on the API Server.<\/p>\n\n<h3 id=\"410-validation-system\">4.10 Validation System<\/h3>\n\n<p><strong>Definition at<\/strong> <code class=\"language-plaintext highlighter-rouge\">pkg\/v\/v.go<\/code>.<\/p>\n\n<p>Easegress uses JSON Schema for configuration validation. JSON schemas are auto-generated from <code class=\"language-plaintext highlighter-rouge\">jsonschema<\/code> tags on Go structs and used during validation.<\/p>\n\n<p><strong>Custom format validators<\/strong> (<code class=\"language-plaintext highlighter-rouge\">pkg\/v\/format.go:31<\/code>):<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Format<\/th>\n      <th>Description<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">urlname<\/code><\/td>\n      <td>URL-safe name<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">duration<\/code><\/td>\n      <td>Time interval (e.g., <code class=\"language-plaintext highlighter-rouge\">10s<\/code>, <code class=\"language-plaintext highlighter-rouge\">5m<\/code>)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ipcidr<\/code><\/td>\n      <td>IP CIDR format<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">regexp<\/code><\/td>\n      <td>Regular expression<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">base64<\/code><\/td>\n      <td>Base64 encoding<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">byteurl<\/code><\/td>\n      <td>Byte size + URL format<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"5-object-categories-in-detail\">5. Object Categories in Detail<\/h2>\n\n<p>All managed objects in Easegress are lifecycle-managed by <code class=\"language-plaintext highlighter-rouge\">Supervisor<\/code>, categorized by runtime dependencies as follows:<\/p>\n\n<h3 id=\"systemcontroller\">SystemController<\/h3>\n\n<p>Built-in, single-instance, initialized first when Supervisor starts.<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Object<\/th>\n      <th>Package Path<\/th>\n      <th>Responsibility<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>TrafficController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/trafficcontroller\/<\/code><\/td>\n      <td>Manages TrafficGate and Pipeline creation\/destruction<\/td>\n    <\/tr>\n    <tr>\n      <td>MeshController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/meshcontroller\/<\/code><\/td>\n      <td>Service mesh control plane (supports Eureka\/Consul\/Nacos service discovery)<\/td>\n    <\/tr>\n    <tr>\n      <td>AutoCertManager<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/autocertmanager\/<\/code><\/td>\n      <td>Automatic TLS certificate management (ACME)<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"businesscontroller\">BusinessController<\/h3>\n\n<p>Business controllers created by users via Admin API or configuration files.<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Object<\/th>\n      <th>Package Path<\/th>\n      <th>Responsibility<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>IngressController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/ingresscontroller\/<\/code><\/td>\n      <td>Kubernetes Ingress controller<\/td>\n    <\/tr>\n    <tr>\n      <td>GatewayController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/gatewaycontroller\/<\/code><\/td>\n      <td>Kubernetes Gateway API controller<\/td>\n    <\/tr>\n    <tr>\n      <td>WAFController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/wafcontroller\/<\/code><\/td>\n      <td>WAF management<\/td>\n    <\/tr>\n    <tr>\n      <td>GlobalFilter<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/globalfilter\/<\/code><\/td>\n      <td>Global filter management<\/td>\n    <\/tr>\n    <tr>\n      <td>AIGatewayController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/aigatewaycontroller\/<\/code><\/td>\n      <td>AI gateway (LLM proxy) management<\/td>\n    <\/tr>\n    <tr>\n      <td>StatusSyncController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/statussynccontroller\/<\/code><\/td>\n      <td>Status synchronization<\/td>\n    <\/tr>\n    <tr>\n      <td>Function<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/function\/<\/code><\/td>\n      <td>Serverless Function<\/td>\n    <\/tr>\n    <tr>\n      <td>RawConfigTrafficController<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/rawconfigtrafficcontroller\/<\/code><\/td>\n      <td>Raw-config-based traffic management<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p><strong>Service registry adapters<\/strong>:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Service Discovery<\/th>\n      <th>Package Path<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>Consul<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/consulserviceregistry\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>Etcd<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/etcdserviceregistry\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>Eureka<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/eurekaserviceregistry\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>Nacos<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/nacosserviceregistry\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>ZooKeeper<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/zookeeperserviceregistry\/<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"trafficgate\">TrafficGate<\/h3>\n\n<p>Protocol listener entry points, responsible for receiving external traffic and forwarding it to Pipelines based on routing rules.<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Object<\/th>\n      <th>Package Path<\/th>\n      <th>Protocol<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>HTTPServer<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/httpserver\/<\/code><\/td>\n      <td>HTTP\/HTTPS<\/td>\n    <\/tr>\n    <tr>\n      <td>gRPCServer<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/grpcserver\/<\/code><\/td>\n      <td>gRPC<\/td>\n    <\/tr>\n    <tr>\n      <td>MQTTProxy<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/mqttproxy\/<\/code><\/td>\n      <td>MQTT<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"pipeline\">Pipeline<\/h3>\n\n<p>Located at <code class=\"language-plaintext highlighter-rouge\">pkg\/object\/pipeline\/<\/code>, assembles a set of Filters into a processing chain. A Pipeline can be referenced by multiple routes, and a TrafficGate can mount multiple Pipelines.<\/p>\n\n<hr \/>\n\n<h2 id=\"6-suggested-reading-paths\">6. Suggested Reading Paths<\/h2>\n\n<p>Based on different learning goals, the following source code reading orders are recommended:<\/p>\n\n<h3 id=\"path-a-understanding-the-overall-architecture-recommended-for-everyone\">Path A: Understanding the Overall Architecture (Recommended for Everyone)<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">cmd\/server.go<\/code><\/strong> \u2014 Startup flow orchestration, establish a global understanding<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/registry.go<\/code><\/strong> \u2014 Object interface definition, understand the object system<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/spec.go<\/code><\/strong> \u2014 Spec\/MetaSpec definitions, understand the configuration model<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/supervisor.go<\/code><\/strong> \u2014 Supervisor lifecycle management<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/cluster\/cluster_interface.go<\/code><\/strong> \u2014 Cluster interface, understand configuration storage<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/registry\/registry.go<\/code><\/strong> \u2014 See the big picture: all registered filters and objects<\/li>\n<\/ol>\n\n<h3 id=\"path-b-deep-dive-into-traffic-processing\">Path B: Deep Dive into Traffic Processing<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/context\/context.go<\/code><\/strong> \u2014 Context, Handler, MuxMapper<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/protocols.go<\/code><\/strong> \u2014 Request\/Response\/Protocol interfaces<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/pipeline\/pipeline.go<\/code><\/strong> \u2014 How Pipeline organizes Filter chains<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/filters.go<\/code><\/strong> \u2014 Filter interface and Kind definition<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/httpproxy\/<\/code><\/strong> \u2014 Pick a specific filter (e.g., HTTP proxy) for deep reading<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/httpserver\/<\/code><\/strong> \u2014 See how the entry Gate creates and routes to Pipelines<\/li>\n<\/ol>\n\n<h3 id=\"path-c-studying-specific-features\">Path C: Studying Specific Features<\/h3>\n\n<table>\n  <thead>\n    <tr>\n      <th>What You Want to Learn<\/th>\n      <th>Start Here<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>Service Mesh<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/meshcontroller\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/meshadaptor\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>OIDC Authentication<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/oidcadaptor\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>AI Gateway<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/aigatewaycontroller\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/aigatewayproxy\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>WAF Firewall<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/wafcontroller\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/waf\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>Kubernetes Integration<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/ingresscontroller\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">pkg\/object\/gatewaycontroller\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>MQTT Proxy<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/mqttprot\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">pkg\/object\/mqttproxy\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>WebAssembly Extension<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/wasmhost\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>Distributed Tracing<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/tracing\/<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>OPA Policy Engine<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/opafilter\/<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"path-d-developing-a-new-filter\">Path D: Developing a New Filter<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/filters.go<\/code><\/strong> \u2014 Understand the Filter interface<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/registry.go<\/code><\/strong> \u2014 Learn the registration mechanism<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/httpproxy\/<\/code><\/strong> or <strong><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/ratelimiter\/<\/code><\/strong> \u2014 Reference existing Filter implementations<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/context\/context.go<\/code><\/strong> \u2014 Understand <code class=\"language-plaintext highlighter-rouge\">Handle(*Context)<\/code> input parameters<\/li>\n<\/ol>\n\n<h3 id=\"path-e-developing-a-new-object-controllertrafficgate\">Path E: Developing a New Object (Controller\/TrafficGate)<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/registry.go<\/code><\/strong> \u2014 Object interface and registration mechanism<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/trafficcontroller\/<\/code><\/strong> \u2014 SystemController reference implementation<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/httpserver\/<\/code><\/strong> \u2014 TrafficGate reference implementation<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">pkg\/object\/pipeline\/<\/code><\/strong> \u2014 Pipeline reference implementation<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"appendix-key-file-index\">Appendix: Key File Index<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>File<\/th>\n      <th>Core Content<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">cmd\/server.go:40-147<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">RunServer()<\/code> startup orchestration<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/registry.go:30-113<\/code><\/td>\n      <td>Object\/ObjectCategory interface definitions<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/spec.go:34-53<\/code><\/td>\n      <td>Spec\/MetaSpec types<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/supervisor.go:36<\/code><\/td>\n      <td>Supervisor struct<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/supervisor\/object.go:39<\/code><\/td>\n      <td>ObjectEntity\/ObjectRegistry<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/cluster\/cluster_interface.go:33<\/code><\/td>\n      <td>Cluster interface<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/context\/context.go:35-42<\/code><\/td>\n      <td>Handler\/MuxMapper interfaces<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/context\/context.go:70<\/code><\/td>\n      <td>Context struct<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/protocols\/protocols.go:39-143<\/code><\/td>\n      <td>Request\/Response\/Protocol interfaces<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/filters.go:33-60<\/code><\/td>\n      <td>Kind\/Filter interfaces<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/filters\/registry.go<\/code><\/td>\n      <td>Filter registry<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/resilience\/resilience.go:30-116<\/code><\/td>\n      <td>Policy\/Wrapper interfaces<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/v\/v.go<\/code><\/td>\n      <td>JSON Schema validation<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/v\/format.go:31<\/code><\/td>\n      <td>Custom format validators<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/api\/server.go:37-80<\/code><\/td>\n      <td>Admin API Server<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">pkg\/registry\/registry.go<\/code><\/td>\n      <td>Global registry (blank imports)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">go.mod:1<\/code><\/td>\n      <td>Module definition (v2)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">Makefile:20<\/code><\/td>\n      <td>Version number and build configuration<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n","category":{"@attributes":{"term":"Easegress"}}},{"title":"APISIX CLI ops.lua \u6e90\u7801\u5206\u6790","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/2026-07-29\/ops-lua-analysis.html"}},"updated":"2026-07-29T23:00:00+08:00","id":"https:\/\/wy471x.github.io\/2026-07-29\/ops-lua-analysis.html","content":"<h1 id=\"apisix-cli-opslua-\u6e90\u7801\u5206\u6790\">APISIX CLI <code class=\"language-plaintext highlighter-rouge\">ops.lua<\/code> \u6e90\u7801\u5206\u6790<\/h1>\n\n<h2 id=\"\u6587\u4ef6\u6982\u89c8\">\u6587\u4ef6\u6982\u89c8<\/h2>\n\n<p><code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/ops.lua<\/code> \u662f Apache APISIX \u7684\u547d\u4ee4\u884c\u5165\u53e3\u64cd\u4f5c\u6a21\u5757\uff0c\u8d1f\u8d23\u5904\u7406\u6240\u6709 CLI \u5b50\u547d\u4ee4\uff08init\u3001start\u3001stop\u3001restart\u3001reload\u3001test \u7b49\uff09\u3002\u5b83\u5c06 YAML \u914d\u7f6e\u8f6c\u6362\u4e3a nginx.conf\uff0c\u7ba1\u7406 OpenResty \u8fdb\u7a0b\u751f\u547d\u5468\u671f\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"1-\u547d\u4ee4\u8def\u7531\u673a\u5236action-\u8868--_mexecute\">1. \u547d\u4ee4\u8def\u7531\u673a\u5236\uff08<code class=\"language-plaintext highlighter-rouge\">action<\/code> \u8868 + <code class=\"language-plaintext highlighter-rouge\">_M.execute<\/code>\uff09<\/h2>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">-- \u7b2c1104-1115\u884c\uff1a\u547d\u4ee4\u6ce8\u518c\u8868<\/span>\n<span class=\"kd\">local<\/span> <span class=\"n\">action<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">help<\/span> <span class=\"o\">=<\/span> <span class=\"n\">help<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">version<\/span> <span class=\"o\">=<\/span> <span class=\"n\">version<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">init<\/span> <span class=\"o\">=<\/span> <span class=\"n\">init<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">init_etcd<\/span> <span class=\"o\">=<\/span> <span class=\"n\">etcd<\/span><span class=\"p\">.<\/span><span class=\"n\">init<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">start<\/span> <span class=\"o\">=<\/span> <span class=\"n\">start<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">stop<\/span> <span class=\"o\">=<\/span> <span class=\"n\">stop<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">quit<\/span> <span class=\"o\">=<\/span> <span class=\"n\">quit<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">restart<\/span> <span class=\"o\">=<\/span> <span class=\"n\">restart<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">reload<\/span> <span class=\"o\">=<\/span> <span class=\"n\">reload<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">test<\/span> <span class=\"o\">=<\/span> <span class=\"n\">test<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c1\">-- \u7b2c1118-1130\u884c\uff1a\u547d\u4ee4\u5206\u53d1<\/span>\n<span class=\"k\">function<\/span> <span class=\"nc\">_M<\/span><span class=\"p\">.<\/span><span class=\"nf\">execute<\/span><span class=\"p\">(<\/span><span class=\"n\">env<\/span><span class=\"p\">,<\/span> <span class=\"n\">arg<\/span><span class=\"p\">)<\/span>\n    <span class=\"kd\">local<\/span> <span class=\"n\">cmd_action<\/span> <span class=\"o\">=<\/span> <span class=\"n\">arg<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span>\n    <span class=\"k\">if<\/span> <span class=\"ow\">not<\/span> <span class=\"n\">cmd_action<\/span> <span class=\"k\">then<\/span>\n        <span class=\"k\">return<\/span> <span class=\"n\">help<\/span><span class=\"p\">()<\/span>\n    <span class=\"k\">end<\/span>\n    <span class=\"k\">if<\/span> <span class=\"ow\">not<\/span> <span class=\"n\">action<\/span><span class=\"p\">[<\/span><span class=\"n\">cmd_action<\/span><span class=\"p\">]<\/span> <span class=\"k\">then<\/span>\n        <span class=\"n\">stderr<\/span><span class=\"p\">:<\/span><span class=\"n\">write<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"invalid argument: \"<\/span><span class=\"p\">,<\/span> <span class=\"n\">cmd_action<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"<\/span><span class=\"se\">\\n<\/span><span class=\"s2\">\"<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span> <span class=\"n\">help<\/span><span class=\"p\">()<\/span>\n    <span class=\"k\">end<\/span>\n    <span class=\"n\">action<\/span><span class=\"p\">[<\/span><span class=\"n\">cmd_action<\/span><span class=\"p\">](<\/span><span class=\"n\">env<\/span><span class=\"p\">,<\/span> <span class=\"n\">arg<\/span><span class=\"p\">[<\/span><span class=\"mi\">2<\/span><span class=\"p\">])<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>\u8bbe\u8ba1\u8981\u70b9<\/strong>\uff1a\u7528\u4e00\u4e2a <code class=\"language-plaintext highlighter-rouge\">action<\/code> \u8868\u505a\u547d\u4ee4\u5230\u51fd\u6570\u7684\u6620\u5c04\uff0c\u7b80\u6d01\u4e14\u6613\u4e8e\u6269\u5c55\u3002\u65e0\u6548\u547d\u4ee4\u65f6\u6253\u5370\u63d0\u793a\u5e76\u5c55\u793a help\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"2-initenv--\u521d\u59cb\u5316-nginxconf\u7b2c234-890\u884c\">2. <code class=\"language-plaintext highlighter-rouge\">init(env)<\/code> \u2014 \u521d\u59cb\u5316 nginx.conf\uff08\u7b2c234-890\u884c\uff09<\/h2>\n\n<p>\u8fd9\u662f\u6700\u6838\u5fc3\u7684\u51fd\u6570\uff0c\u8d1f\u8d23\u4ece YAML \u914d\u7f6e\u751f\u6210 nginx \u914d\u7f6e\u3002\u6d41\u7a0b\u5982\u4e0b\uff1a<\/p>\n\n<h3 id=\"21-\u73af\u5883\u9884\u68c0\u7b2c236-248\u884c\">2.1 \u73af\u5883\u9884\u68c0\uff08\u7b2c236-248\u884c\uff09<\/h3>\n<ul>\n  <li>\u68c0\u6d4b\u662f\u5426\u5728 <code class=\"language-plaintext highlighter-rouge\">\/root<\/code> \u76ee\u5f55\u8fd0\u884c\uff08\u4ec5\u5f00\u53d1\u73af\u5883\u5141\u8bb8\uff09<\/li>\n  <li>\u68c0\u67e5 <code class=\"language-plaintext highlighter-rouge\">ulimit<\/code>\uff0c\u4f4e\u4e8e 1024 \u53d1\u51fa\u8b66\u544a<\/li>\n<\/ul>\n\n<h3 id=\"22-yaml-\u52a0\u8f7d\u4e0e\u6821\u9a8c\u7b2c251-259\u884c\">2.2 YAML \u52a0\u8f7d\u4e0e\u6821\u9a8c\uff08\u7b2c251-259\u884c\uff09<\/h3>\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">local<\/span> <span class=\"n\">yaml_conf<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">=<\/span> <span class=\"n\">file<\/span><span class=\"p\">.<\/span><span class=\"n\">read_yaml_conf<\/span><span class=\"p\">(<\/span><span class=\"n\">env<\/span><span class=\"p\">.<\/span><span class=\"n\">apisix_home<\/span><span class=\"p\">)<\/span>\n<span class=\"kd\">local<\/span> <span class=\"n\">ok<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">=<\/span> <span class=\"n\">schema<\/span><span class=\"p\">.<\/span><span class=\"n\">validate<\/span><span class=\"p\">(<\/span><span class=\"n\">yaml_conf<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"23-\u5173\u952e\u914d\u7f6e\u6821\u9a8c\">2.3 \u5173\u952e\u914d\u7f6e\u6821\u9a8c<\/h3>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u6821\u9a8c\u9879<\/th>\n      <th>\u4f4d\u7f6e<\/th>\n      <th>\u8bf4\u660e<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>admin_key<\/td>\n      <td>\u7b2c284-331\u884c<\/td>\n      <td>\u68c0\u67e5 Admin API token \u662f\u5426\u8bbe\u7f6e\uff0c\u652f\u6301\u7a7a token \u81ea\u52a8\u751f\u6210<\/td>\n    <\/tr>\n    <tr>\n      <td>admin_api_mtls<\/td>\n      <td>\u7b2c333-344\u884c<\/td>\n      <td>\u542f\u7528 https_admin \u65f6\u5fc5\u987b\u914d\u7f6e SSL \u8bc1\u4e66<\/td>\n    <\/tr>\n    <tr>\n      <td>OpenResty \u7248\u672c<\/td>\n      <td>\u7b2c346-354\u884c<\/td>\n      <td>\u8981\u6c42 &gt;= 1.21.4<\/td>\n    <\/tr>\n    <tr>\n      <td>http_stub_status_module<\/td>\n      <td>\u7b2c357-361\u884c<\/td>\n      <td>\u5fc5\u987b\u7f16\u8bd1\u8be5\u6a21\u5757<\/td>\n    <\/tr>\n    <tr>\n      <td>proxy-cache \u63d2\u4ef6<\/td>\n      <td>\u7b2c397-399\u884c<\/td>\n      <td>\u542f\u7528\u65f6\u5fc5\u987b\u914d\u7f6e <code class=\"language-plaintext highlighter-rouge\">apisix.proxy_cache<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td>batch-requests \u63d2\u4ef6<\/td>\n      <td>\u7b2c401-421\u884c<\/td>\n      <td>\u68c0\u67e5 <code class=\"language-plaintext highlighter-rouge\">real_ip_from<\/code> \u662f\u5426\u5305\u542b loopback<\/td>\n    <\/tr>\n    <tr>\n      <td>standalone \u6a21\u5f0f<\/td>\n      <td>\u7b2c262-281\u884c<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">APISIX_STAND_ALONE=true<\/code> \u65f6 config_provider \u5fc5\u987b\u4e3a yaml\/json<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"24-\u4ee3\u7406\u6a21\u5f0f\u5904\u7406\u7b2c362-380\u884c\">2.4 \u4ee3\u7406\u6a21\u5f0f\u5904\u7406\uff08\u7b2c362-380\u884c\uff09<\/h3>\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">if<\/span> <span class=\"n\">yaml_conf<\/span><span class=\"p\">.<\/span><span class=\"n\">apisix<\/span><span class=\"p\">.<\/span><span class=\"n\">proxy_mode<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"http\"<\/span> <span class=\"k\">then<\/span>\n    <span class=\"n\">enable_http<\/span><span class=\"p\">,<\/span> <span class=\"n\">enable_stream<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span> <span class=\"kc\">false<\/span>\n<span class=\"k\">elseif<\/span> <span class=\"n\">yaml_conf<\/span><span class=\"p\">.<\/span><span class=\"n\">apisix<\/span><span class=\"p\">.<\/span><span class=\"n\">proxy_mode<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"stream\"<\/span> <span class=\"k\">then<\/span>\n    <span class=\"n\">enable_http<\/span><span class=\"p\">,<\/span> <span class=\"n\">enable_stream<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span> <span class=\"kc\">true<\/span>\n<span class=\"k\">elseif<\/span> <span class=\"n\">yaml_conf<\/span><span class=\"p\">.<\/span><span class=\"n\">apisix<\/span><span class=\"p\">.<\/span><span class=\"n\">proxy_mode<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"http&amp;stream\"<\/span> <span class=\"k\">then<\/span>\n    <span class=\"n\">enable_http<\/span><span class=\"p\">,<\/span> <span class=\"n\">enable_stream<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span> <span class=\"kc\">true<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"25-\u7aef\u53e3\u51b2\u7a81\u68c0\u6d4b\u7b2c423-521\u884c\">2.5 \u7aef\u53e3\u51b2\u7a81\u68c0\u6d4b\uff08\u7b2c423-521\u884c\uff09<\/h3>\n\n<p><code class=\"language-plaintext highlighter-rouge\">validate_and_get_listen_addr()<\/code> \u548c <code class=\"language-plaintext highlighter-rouge\">listen_table_insert()<\/code> \u4f7f\u7528 <code class=\"language-plaintext highlighter-rouge\">ports_to_check<\/code> \u8868\u786e\u4fdd admin\/status\/control\/prometheus\/HTTP\/HTTPS \u5404\u7aef\u53e3\u4e0d\u51b2\u7a81\u3002<\/p>\n\n<p>\u6d89\u53ca\u7684\u7aef\u53e3\uff1a<\/p>\n<ul>\n  <li><strong>Admin<\/strong>\uff1a\u9ed8\u8ba4 9180<\/li>\n  <li><strong>Status<\/strong>\uff1a\u9ed8\u8ba4 7085<\/li>\n  <li><strong>Control<\/strong>\uff1a\u9ed8\u8ba4 9090<\/li>\n  <li><strong>Prometheus<\/strong>\uff1a\u9ed8\u8ba4 9091<\/li>\n<\/ul>\n\n<h3 id=\"26-httphttps-\u76d1\u542c\u6807\u51c6\u5316\u7b2c523-601\u884c\">2.6 HTTP\/HTTPS \u76d1\u542c\u6807\u51c6\u5316\uff08\u7b2c523-601\u884c\uff09<\/h3>\n<ul>\n  <li>\u5c06 <code class=\"language-plaintext highlighter-rouge\">node_listen<\/code>\uff08\u53ef\u4e3a number\u3001table\u3001\u5d4c\u5957 table\uff09\u7edf\u4e00\u4e3a\u6807\u51c6\u683c\u5f0f <code class=\"language-plaintext highlighter-rouge\">[{ip, port, enable_http3}]<\/code><\/li>\n  <li>\u5c06 <code class=\"language-plaintext highlighter-rouge\">ssl.listen<\/code> \u540c\u7406\u6807\u51c6\u5316<\/li>\n  <li>\u4ece 3.9 \u7248\u672c\u8d77\uff0c<code class=\"language-plaintext highlighter-rouge\">enable_http2<\/code> \u5df2\u4ece\u7aef\u53e3\u7ea7\u79fb\u81f3 apisix \u5168\u5c40\u7ea7\u522b\uff0c\u7aef\u53e3\u7ea7\u914d\u7f6e\u4f1a\u62a5\u9519<\/li>\n<\/ul>\n\n<h3 id=\"27-\u7aef\u53e3\u6821\u9a8cvalidate_port_or_range\u7b2c61-131\u884c\">2.7 \u7aef\u53e3\u6821\u9a8c\uff08<code class=\"language-plaintext highlighter-rouge\">validate_port_or_range<\/code>\uff0c\u7b2c61-131\u884c\uff09<\/h3>\n\n<p>\u4e00\u4e2a\u624b\u5199\u7684\u7aef\u53e3\u53f7\/\u7aef\u53e3\u8303\u56f4\u6821\u9a8c\u5668\uff0c\u652f\u6301\uff1a<\/p>\n<ul>\n  <li>\u6574\u6570\u7aef\u53e3\u53f7\uff081-65535\uff09<\/li>\n  <li>\u8303\u56f4\u683c\u5f0f\uff08<code class=\"language-plaintext highlighter-rouge\">start-end<\/code>\uff09<\/li>\n  <li>IPv4 \u5e26\u7aef\u53e3\uff08<code class=\"language-plaintext highlighter-rouge\">0.0.0.0:8080<\/code>\uff09<\/li>\n  <li>IPv6 \u5e26\u7aef\u53e3\uff08<code class=\"language-plaintext highlighter-rouge\">[::1]:8080<\/code>\uff09<\/li>\n<\/ul>\n\n<h3 id=\"28-\u6a21\u677f\u6e32\u67d3\u7b2c679-889\u884c\">2.8 \u6a21\u677f\u6e32\u67d3\uff08\u7b2c679-889\u884c\uff09<\/h3>\n\n<p>\u5c06\u5904\u7406\u540e\u7684\u6240\u6709\u914d\u7f6e\u6253\u5305\u6210 <code class=\"language-plaintext highlighter-rouge\">sys_conf<\/code> \u8868\uff0c\u4f7f\u7528 <code class=\"language-plaintext highlighter-rouge\">resty.template<\/code> \u6e32\u67d3 nginx \u6a21\u677f\u5e76\u5199\u5165 <code class=\"language-plaintext highlighter-rouge\">conf\/nginx.conf<\/code>\u3002<\/p>\n\n<p>\u5173\u952e sys_conf \u5b57\u6bb5\uff1a<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">worker_rlimit_nofile<\/code>\uff1a\u81ea\u52a8\u8bbe\u4e3a <code class=\"language-plaintext highlighter-rouge\">worker_connections + 128<\/code><\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">worker_processes<\/code>\uff1adev_mode \u4e0b\u5f3a\u5236\u4e3a 1\uff0c\u5426\u5219\u9ed8\u8ba4 \u201cauto\u201d<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">dns_resolver<\/code>\uff1a\u672a\u914d\u7f6e\u65f6\u81ea\u52a8\u4ece <code class=\"language-plaintext highlighter-rouge\">\/etc\/resolv.conf<\/code> \u8bfb\u53d6<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">extra_lua_path\/cpath<\/code>\uff1a\u8ffd\u52a0\u81ea\u5b9a\u4e49 Lua \u8def\u5f84<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">envs<\/code>\uff1a\u6ce8\u5165\u73af\u5883\u53d8\u91cf\uff08\u542b Kubernetes \u670d\u52a1\u53d1\u73b0\u6240\u9700\u7684\u53d8\u91cf\uff09<\/li>\n<\/ul>\n\n<h3 id=\"29-\u96c6\u7fa4\u89d2\u8272\u5904\u7406\u7b2c663-671\u884c\">2.9 \u96c6\u7fa4\u89d2\u8272\u5904\u7406\uff08\u7b2c663-671\u884c\uff09<\/h3>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">if<\/span> <span class=\"n\">role<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"control_plane\"<\/span> <span class=\"ow\">and<\/span> <span class=\"ow\">not<\/span> <span class=\"n\">admin_server_addr<\/span> <span class=\"k\">then<\/span>\n    <span class=\"kd\">local<\/span> <span class=\"n\">listen<\/span> <span class=\"o\">=<\/span> <span class=\"n\">node_listen<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span>\n    <span class=\"n\">admin_server_addr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">str_format<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"%s:%s\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">listen<\/span><span class=\"p\">.<\/span><span class=\"n\">ip<\/span><span class=\"p\">,<\/span> <span class=\"n\">listen<\/span><span class=\"p\">.<\/span><span class=\"n\">port<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre><\/div><\/div>\n<p>control_plane \u89d2\u8272\u81ea\u52a8\u590d\u7528\u7b2c\u4e00\u4e2a node_listen \u5730\u5740\u4f5c\u4e3a admin \u5730\u5740\u3002<\/p>\n\n<h3 id=\"210-\u670d\u52a1\u53d1\u73b0\u7279\u6b8a\u5904\u7406\u7b2c811-876\u884c\">2.10 \u670d\u52a1\u53d1\u73b0\u7279\u6b8a\u5904\u7406\uff08\u7b2c811-876\u884c\uff09<\/h3>\n<ul>\n  <li><strong>Kubernetes<\/strong>\uff1a\u6ce8\u5165 shared_dict\uff0c\u89e3\u6790\u73af\u5883\u53d8\u91cf\u5360\u4f4d\u7b26\uff08<code class=\"language-plaintext highlighter-rouge\">${VAR}<\/code>\uff09<\/li>\n  <li><strong>Consul<\/strong>\uff1a\u6ce8\u5165 shared_dict<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"3-startenv---\u542f\u52a8-apisix\u7b2c923-1019\u884c\">3. <code class=\"language-plaintext highlighter-rouge\">start(env, ...)<\/code> \u2014 \u542f\u52a8 APISIX\uff08\u7b2c923-1019\u884c\uff09<\/h2>\n\n<p><strong>\u6267\u884c\u6d41\u7a0b<\/strong>\uff1a<\/p>\n<ol>\n  <li><strong>cleanup(env)<\/strong> \u2014 \u5220\u9664\u81ea\u5b9a\u4e49 yaml \u7d22\u5f15\u6587\u4ef6<\/li>\n  <li><strong>\u7981\u6b62 root \u8fd0\u884c<\/strong> \u2014 \u751f\u4ea7\u73af\u5883\u786c\u6027\u62d2\u7edd<\/li>\n  <li><strong>\u521b\u5efa logs \u76ee\u5f55<\/strong><\/li>\n  <li><strong>\u7b49\u5f85\u65e7\u8fdb\u7a0b\u9000\u51fa<\/strong> \u2014 \u6700\u591a 3 \u79d2\uff0830\u6b21 \u00d7 0.1\u79d2\uff09\uff0c\u7528 <code class=\"language-plaintext highlighter-rouge\">signal.kill(pid, 0)<\/code> \u68c0\u6d4b<\/li>\n  <li><strong>\u89e3\u6790 -c \u53c2\u6570<\/strong> \u2014 \u652f\u6301 <code class=\"language-plaintext highlighter-rouge\">--config<\/code> \u6307\u5b9a\u81ea\u5b9a\u4e49 YAML \u8def\u5f84<\/li>\n  <li><strong>init(env)<\/strong> \u2014 \u751f\u6210 nginx.conf<\/li>\n  <li><strong>init_etcd(env, args)<\/strong> \u2014 \u975e data_plane \u89d2\u8272\u65f6\u521d\u59cb\u5316 etcd<\/li>\n  <li><strong>\u6267\u884c openresty<\/strong> \u2014 \u771f\u6b63\u7684\u542f\u52a8<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"4-testenv--\u914d\u7f6e\u6d4b\u8bd5\u7b2c1022-1057\u884c\">4. <code class=\"language-plaintext highlighter-rouge\">test(env)<\/code> \u2014 \u914d\u7f6e\u6d4b\u8bd5\uff08\u7b2c1022-1057\u884c\uff09<\/h2>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">-- \u5907\u4efd\u539f nginx.conf \u2192 \u751f\u6210\u65b0\u7684 \u2192 nginx -t \u2192 \u6062\u590d\u539f nginx.conf<\/span>\n<\/code><\/pre><\/div><\/div>\n<p>\u8fd9\u662f\u4e00\u4e2a\u975e\u7834\u574f\u6027\u64cd\u4f5c\uff0c\u6d4b\u8bd5\u5b8c\u540e<strong>\u4fdd\u8bc1\u6062\u590d<\/strong>\u539f\u6765\u7684 nginx.conf\u3002\u517c\u5bb9 macOS \u548c Linux \u7684 <code class=\"language-plaintext highlighter-rouge\">os.execute<\/code> \u8fd4\u56de\u503c\u5dee\u5f02\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"5-stopenv--quitenv--\u505c\u6b62\u670d\u52a1\u7b2c1060-1073\u884c\">5. <code class=\"language-plaintext highlighter-rouge\">stop(env)<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">quit(env)<\/code> \u2014 \u505c\u6b62\u670d\u52a1\uff08\u7b2c1060-1073\u884c\uff09<\/h2>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">local<\/span> <span class=\"n\">cmd<\/span> <span class=\"o\">=<\/span> <span class=\"n\">env<\/span><span class=\"p\">.<\/span><span class=\"n\">openresty_args<\/span> <span class=\"o\">..<\/span> <span class=\"s\">[[ -s quit]]<\/span>   <span class=\"c1\">-- \u4f18\u96c5\u505c\u6b62<\/span>\n<span class=\"kd\">local<\/span> <span class=\"n\">cmd<\/span> <span class=\"o\">=<\/span> <span class=\"n\">env<\/span><span class=\"p\">.<\/span><span class=\"n\">openresty_args<\/span> <span class=\"o\">..<\/span> <span class=\"s\">[[ -s stop]]<\/span>   <span class=\"c1\">-- \u5feb\u901f\u505c\u6b62<\/span>\n<\/code><\/pre><\/div><\/div>\n<p>\u4e24\u8005\u90fd\u5148\u6267\u884c <code class=\"language-plaintext highlighter-rouge\">cleanup(env)<\/code>\uff0c\u7136\u540e\u53d1\u9001\u5bf9\u5e94\u7684 nginx \u4fe1\u53f7\u3002<\/p>\n<ul>\n  <li><strong>quit<\/strong>\uff1a\u4f18\u96c5\u505c\u6b62\uff0c\u7b49\u5f85 worker \u5904\u7406\u5b8c\u5f53\u524d\u8bf7\u6c42<\/li>\n  <li><strong>stop<\/strong>\uff1a\u5feb\u901f\u505c\u6b62\uff0c\u7acb\u5373\u7ec8\u6b62\u6240\u6709 worker<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"6-restartenv--reloadenv--\u91cd\u542f\u4e0e\u70ed\u52a0\u8f7d\u7b2c1076-1100\u884c\">6. <code class=\"language-plaintext highlighter-rouge\">restart(env)<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">reload(env)<\/code> \u2014 \u91cd\u542f\u4e0e\u70ed\u52a0\u8f7d\uff08\u7b2c1076-1100\u884c\uff09<\/h2>\n\n<p><strong>restart<\/strong>\uff1a<code class=\"language-plaintext highlighter-rouge\">test \u2192 stop \u2192 start<\/code>\uff08\u5148\u6d4b\u518d\u505c\u518d\u542f\uff09<\/p>\n\n<p><strong>reload<\/strong>\uff1a<code class=\"language-plaintext highlighter-rouge\">init \u2192 nginx -t \u2192 nginx -s reload<\/code>\uff08\u70ed\u52a0\u8f7d\uff0c\u4e0d\u4e2d\u65ad\u670d\u52a1\uff09<\/p>\n\n<p>reload \u5931\u8d25\u65f6\u53ea\u6253\u5370\u6d88\u606f\uff0c\u4e0d\u4f1a <code class=\"language-plaintext highlighter-rouge\">die<\/code>\uff0c\u907f\u514d\u4e2d\u65ad\u5df2\u6709\u8fd0\u884c\u5b9e\u4f8b\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"7-\u8f85\u52a9\u51fd\u6570\">7. \u8f85\u52a9\u51fd\u6570<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u51fd\u6570<\/th>\n      <th>\u4f4d\u7f6e<\/th>\n      <th>\u4f5c\u7528<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">local_dns_resolver()<\/code><\/td>\n      <td>\u7b2c189\u884c<\/td>\n      <td>\u4ece <code class=\"language-plaintext highlighter-rouge\">\/etc\/resolv.conf<\/code> \u89e3\u6790 DNS \u670d\u52a1\u5668\u5730\u5740<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">version_greater_equal()<\/code><\/td>\n      <td>\u7b2c152\u884c<\/td>\n      <td>\u8bed\u4e49\u7248\u672c\u6bd4\u8f83<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">get_openresty_version()<\/code><\/td>\n      <td>\u7b2c173\u884c<\/td>\n      <td>\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">openresty -v<\/code> \u83b7\u53d6\u7248\u672c\u53f7<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">check_running()<\/code><\/td>\n      <td>\u7b2c912\u884c<\/td>\n      <td>\u901a\u8fc7 pid \u6587\u4ef6\u5224\u65ad\u8fdb\u7a0b\u662f\u5426\u5b58\u6d3b<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">get_lua_path()<\/code><\/td>\n      <td>\u7b2c215\u884c<\/td>\n      <td>\u89c4\u8303\u5316 Lua \u8def\u5f84\uff08\u786e\u4fdd\u4ee5 <code class=\"language-plaintext highlighter-rouge\">;<\/code> \u7ed3\u5c3e\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">validate_port_or_range()<\/code><\/td>\n      <td>\u7b2c61\u884c<\/td>\n      <td>\u7aef\u53e3\/\u7aef\u53e3\u8303\u56f4\u5408\u6cd5\u6027\u6821\u9a8c<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">validate_and_get_listen_addr()<\/code><\/td>\n      <td>\u7b2c425\u884c<\/td>\n      <td>\u5185\u5d4c\u51fd\u6570\uff0c\u6821\u9a8c\u7aef\u53e3\u51b2\u7a81\u5e76\u62fc\u63a5\u5730\u5740\u5b57\u7b26\u4e32<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">listen_table_insert()<\/code><\/td>\n      <td>\u7b2c480\u884c<\/td>\n      <td>\u5185\u5d4c\u51fd\u6570\uff0c\u6807\u51c6\u5316\u76d1\u542c\u8868\u63d2\u5165\uff08\u652f\u6301 IPv6 \u53cc\u6808\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">cleanup()<\/code><\/td>\n      <td>\u7b2c898\u884c<\/td>\n      <td>\u5220\u9664\u81ea\u5b9a\u4e49 yaml \u7d22\u5f15\u6587\u4ef6<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">sleep()<\/code><\/td>\n      <td>\u7b2c907\u884c<\/td>\n      <td>\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">os.execute(\"sleep \" .. n)<\/code> \u5b9e\u73b0\u7b49\u5f85<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"8-\u5b89\u5168\u4e0e\u8bbe\u8ba1\u4eae\u70b9\">8. \u5b89\u5168\u4e0e\u8bbe\u8ba1\u4eae\u70b9<\/h2>\n\n<ol>\n  <li><strong>\u7aef\u53e3\u51b2\u7a81\u68c0\u67e5<\/strong> \u2014 \u591a\u4e2a\u670d\u52a1\u7aef\u53e3\uff08admin\/status\/control\/prometheus\/http\/https\uff09\u7edf\u4e00\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">ports_to_check<\/code> \u9632\u6b62\u51b2\u7a81<\/li>\n  <li><strong>\u914d\u7f6e\u6821\u9a8c\u524d\u7f6e<\/strong> \u2014 start\/reload\/restart\/test \u90fd\u4f1a\u91cd\u65b0\u8fd0\u884c <code class=\"language-plaintext highlighter-rouge\">init()<\/code>\uff0c\u786e\u4fdd\u914d\u7f6e\u53d8\u66f4\u540e\u5373\u65f6\u6821\u9a8c<\/li>\n  <li><strong>\u5b89\u5168\u8b66\u544a<\/strong> \u2014 root \u8fd0\u884c\u3001\u7a7a admin_key\u3001\u4f4e ulimit\u3001admin_key_required=false \u90fd\u7ed9\u51fa\u660e\u786e\u8b66\u544a<\/li>\n  <li><strong>\u8fdb\u7a0b\u68c0\u6d4b<\/strong> \u2014 \u542f\u52a8\u524d\u68c0\u6d4b\u65e7\u8fdb\u7a0b\uff0c\u907f\u514d\u7aef\u53e3\u51b2\u7a81\uff1b\u68c0\u6d4b pid \u5bf9\u5e94\u7684\u8fdb\u7a0b\u662f\u5426\u771f\u5b9e\u5b58\u5728\uff08\u800c\u975e\u4ec5\u68c0\u67e5\u6587\u4ef6\uff09<\/li>\n  <li><strong>\u5411\u540e\u517c\u5bb9<\/strong> \u2014 <code class=\"language-plaintext highlighter-rouge\">node_listen<\/code> \u652f\u6301 number\/table\/\u5d4c\u5957 table \u4e09\u79cd\u5386\u53f2\u683c\u5f0f<\/li>\n  <li><strong>\u975e\u7834\u574f\u6027\u6d4b\u8bd5<\/strong> \u2014 <code class=\"language-plaintext highlighter-rouge\">test<\/code> \u547d\u4ee4\u5907\u4efd\u5e76\u6062\u590d\u539f\u59cb nginx.conf<\/li>\n  <li><strong>\u4f18\u96c5\u964d\u7ea7<\/strong> \u2014 reload \u5931\u8d25\u4e0d\u7ec8\u6b62\u8fd0\u884c\u4e2d\u7684\u5b9e\u4f8b<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"9-\u6267\u884c\u6d41\u7a0b\u56fe\">9. \u6267\u884c\u6d41\u7a0b\u56fe<\/h2>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>apisix start\n  \u2502\n  \u251c\u2500\u2500 cleanup()\n  \u251c\u2500\u2500 \u68c0\u67e5 \/root \u7981\u6b62\u8fd0\u884c\n  \u251c\u2500\u2500 \u521b\u5efa logs\/\n  \u251c\u2500\u2500 \u7b49\u5f85\u65e7\u8fdb\u7a0b\u9000\u51fa\uff08\u6700\u591a3\u79d2\uff09\n  \u251c\u2500\u2500 \u89e3\u6790 -c \u53c2\u6570\n  \u251c\u2500\u2500 init(env)\n  \u2502     \u251c\u2500\u2500 \u8bfb\u53d6 &amp; \u6821\u9a8c config.yaml\n  \u2502     \u251c\u2500\u2500 \u6821\u9a8c admin_key \/ mtls \/ plugins\n  \u2502     \u251c\u2500\u2500 \u5904\u7406 proxy_mode (http\/stream\/http&amp;stream)\n  \u2502     \u251c\u2500\u2500 \u7aef\u53e3\u51b2\u7a81\u68c0\u6d4b\n  \u2502     \u251c\u2500\u2500 \u6807\u51c6\u5316 node_listen \/ ssl.listen\n  \u2502     \u251c\u2500\u2500 \u5904\u7406 \u670d\u52a1\u53d1\u73b0 (K8s\/Consul)\n  \u2502     \u251c\u2500\u2500 DNS \u89e3\u6790\u5668\u914d\u7f6e\n  \u2502     \u2514\u2500\u2500 \u6a21\u677f\u6e32\u67d3 \u2192 nginx.conf\n  \u251c\u2500\u2500 init_etcd() [\u975e data_plane]\n  \u2514\u2500\u2500 \u542f\u52a8 openresty\n\napisix reload\n  \u251c\u2500\u2500 init(env)          # \u91cd\u65b0\u751f\u6210 nginx.conf\n  \u251c\u2500\u2500 nginx -t           # \u8bed\u6cd5\u6d4b\u8bd5\n  \u2514\u2500\u2500 nginx -s reload    # \u70ed\u52a0\u8f7d\u4fe1\u53f7\n\napisix restart\n  \u251c\u2500\u2500 test(env)          # \u5907\u4efd\u2192\u751f\u6210\u2192\u6d4b\u8bd5\u2192\u6062\u590d\n  \u251c\u2500\u2500 stop(env)          # nginx -s stop\n  \u2514\u2500\u2500 start(env)         # \u5b8c\u6574\u542f\u52a8\u6d41\u7a0b\n<\/code><\/pre><\/div><\/div>\n","category":{"@attributes":{"term":"APISIX"}}},{"title":"APISIX CLI ops.lua Source Code Analysis","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/2026-07-29\/ops-lua-analysis-en.html"}},"updated":"2026-07-29T23:00:00+08:00","id":"https:\/\/wy471x.github.io\/2026-07-29\/ops-lua-analysis-en.html","content":"<h1 id=\"apisix-cli-opslua-source-code-analysis\">APISIX CLI <code class=\"language-plaintext highlighter-rouge\">ops.lua<\/code> Source Code Analysis<\/h1>\n\n<h2 id=\"file-overview\">File Overview<\/h2>\n\n<p><code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/ops.lua<\/code> is the CLI entry point module of Apache APISIX, responsible for handling all CLI subcommands (init, start, stop, restart, reload, test, etc.). It converts YAML configuration into nginx.conf and manages the OpenResty process lifecycle.<\/p>\n\n<hr \/>\n\n<h2 id=\"1-command-routing-mechanism-action-table--_mexecute\">1. Command Routing Mechanism (<code class=\"language-plaintext highlighter-rouge\">action<\/code> Table + <code class=\"language-plaintext highlighter-rouge\">_M.execute<\/code>)<\/h2>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">-- Lines 1104-1115: Command registry<\/span>\n<span class=\"kd\">local<\/span> <span class=\"n\">action<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">help<\/span> <span class=\"o\">=<\/span> <span class=\"n\">help<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">version<\/span> <span class=\"o\">=<\/span> <span class=\"n\">version<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">init<\/span> <span class=\"o\">=<\/span> <span class=\"n\">init<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">init_etcd<\/span> <span class=\"o\">=<\/span> <span class=\"n\">etcd<\/span><span class=\"p\">.<\/span><span class=\"n\">init<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">start<\/span> <span class=\"o\">=<\/span> <span class=\"n\">start<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">stop<\/span> <span class=\"o\">=<\/span> <span class=\"n\">stop<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">quit<\/span> <span class=\"o\">=<\/span> <span class=\"n\">quit<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">restart<\/span> <span class=\"o\">=<\/span> <span class=\"n\">restart<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">reload<\/span> <span class=\"o\">=<\/span> <span class=\"n\">reload<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">test<\/span> <span class=\"o\">=<\/span> <span class=\"n\">test<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c1\">-- Lines 1118-1130: Command dispatch<\/span>\n<span class=\"k\">function<\/span> <span class=\"nc\">_M<\/span><span class=\"p\">.<\/span><span class=\"nf\">execute<\/span><span class=\"p\">(<\/span><span class=\"n\">env<\/span><span class=\"p\">,<\/span> <span class=\"n\">arg<\/span><span class=\"p\">)<\/span>\n    <span class=\"kd\">local<\/span> <span class=\"n\">cmd_action<\/span> <span class=\"o\">=<\/span> <span class=\"n\">arg<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span>\n    <span class=\"k\">if<\/span> <span class=\"ow\">not<\/span> <span class=\"n\">cmd_action<\/span> <span class=\"k\">then<\/span>\n        <span class=\"k\">return<\/span> <span class=\"n\">help<\/span><span class=\"p\">()<\/span>\n    <span class=\"k\">end<\/span>\n    <span class=\"k\">if<\/span> <span class=\"ow\">not<\/span> <span class=\"n\">action<\/span><span class=\"p\">[<\/span><span class=\"n\">cmd_action<\/span><span class=\"p\">]<\/span> <span class=\"k\">then<\/span>\n        <span class=\"n\">stderr<\/span><span class=\"p\">:<\/span><span class=\"n\">write<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"invalid argument: \"<\/span><span class=\"p\">,<\/span> <span class=\"n\">cmd_action<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"<\/span><span class=\"se\">\\n<\/span><span class=\"s2\">\"<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span> <span class=\"n\">help<\/span><span class=\"p\">()<\/span>\n    <span class=\"k\">end<\/span>\n    <span class=\"n\">action<\/span><span class=\"p\">[<\/span><span class=\"n\">cmd_action<\/span><span class=\"p\">](<\/span><span class=\"n\">env<\/span><span class=\"p\">,<\/span> <span class=\"n\">arg<\/span><span class=\"p\">[<\/span><span class=\"mi\">2<\/span><span class=\"p\">])<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Design note<\/strong>: An <code class=\"language-plaintext highlighter-rouge\">action<\/code> table maps commands to functions \u2014 simple and extensible. Invalid commands print a hint and display help.<\/p>\n\n<hr \/>\n\n<h2 id=\"2-initenv--initialize-nginxconf-lines-234-890\">2. <code class=\"language-plaintext highlighter-rouge\">init(env)<\/code> \u2014 Initialize nginx.conf (Lines 234-890)<\/h2>\n\n<p>This is the core function, responsible for generating nginx configuration from YAML. The flow:<\/p>\n\n<h3 id=\"21-environment-pre-check-lines-236-248\">2.1 Environment Pre-check (Lines 236-248)<\/h3>\n<ul>\n  <li>Detect running under <code class=\"language-plaintext highlighter-rouge\">\/root<\/code> (only allowed in dev environments)<\/li>\n  <li>Check <code class=\"language-plaintext highlighter-rouge\">ulimit<\/code>; warn if below 1024<\/li>\n<\/ul>\n\n<h3 id=\"22-yaml-loading--validation-lines-251-259\">2.2 YAML Loading &amp; Validation (Lines 251-259)<\/h3>\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">local<\/span> <span class=\"n\">yaml_conf<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">=<\/span> <span class=\"n\">file<\/span><span class=\"p\">.<\/span><span class=\"n\">read_yaml_conf<\/span><span class=\"p\">(<\/span><span class=\"n\">env<\/span><span class=\"p\">.<\/span><span class=\"n\">apisix_home<\/span><span class=\"p\">)<\/span>\n<span class=\"kd\">local<\/span> <span class=\"n\">ok<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">=<\/span> <span class=\"n\">schema<\/span><span class=\"p\">.<\/span><span class=\"n\">validate<\/span><span class=\"p\">(<\/span><span class=\"n\">yaml_conf<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"23-key-configuration-validation\">2.3 Key Configuration Validation<\/h3>\n\n<table>\n  <thead>\n    <tr>\n      <th>Check<\/th>\n      <th>Location<\/th>\n      <th>Description<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>admin_key<\/td>\n      <td>Lines 284-331<\/td>\n      <td>Checks if Admin API token is set; supports auto-generation of empty tokens<\/td>\n    <\/tr>\n    <tr>\n      <td>admin_api_mtls<\/td>\n      <td>Lines 333-344<\/td>\n      <td>SSL cert must be configured when https_admin is enabled<\/td>\n    <\/tr>\n    <tr>\n      <td>OpenResty version<\/td>\n      <td>Lines 346-354<\/td>\n      <td>Requires &gt;= 1.21.4<\/td>\n    <\/tr>\n    <tr>\n      <td>http_stub_status_module<\/td>\n      <td>Lines 357-361<\/td>\n      <td>This module must be compiled in<\/td>\n    <\/tr>\n    <tr>\n      <td>proxy-cache plugin<\/td>\n      <td>Lines 397-399<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix.proxy_cache<\/code> must be configured when enabled<\/td>\n    <\/tr>\n    <tr>\n      <td>batch-requests plugin<\/td>\n      <td>Lines 401-421<\/td>\n      <td>Checks if <code class=\"language-plaintext highlighter-rouge\">real_ip_from<\/code> includes loopback<\/td>\n    <\/tr>\n    <tr>\n      <td>standalone mode<\/td>\n      <td>Lines 262-281<\/td>\n      <td>config_provider must be yaml\/json when <code class=\"language-plaintext highlighter-rouge\">APISIX_STAND_ALONE=true<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"24-proxy-mode-handling-lines-362-380\">2.4 Proxy Mode Handling (Lines 362-380)<\/h3>\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">if<\/span> <span class=\"n\">yaml_conf<\/span><span class=\"p\">.<\/span><span class=\"n\">apisix<\/span><span class=\"p\">.<\/span><span class=\"n\">proxy_mode<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"http\"<\/span> <span class=\"k\">then<\/span>\n    <span class=\"n\">enable_http<\/span><span class=\"p\">,<\/span> <span class=\"n\">enable_stream<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span> <span class=\"kc\">false<\/span>\n<span class=\"k\">elseif<\/span> <span class=\"n\">yaml_conf<\/span><span class=\"p\">.<\/span><span class=\"n\">apisix<\/span><span class=\"p\">.<\/span><span class=\"n\">proxy_mode<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"stream\"<\/span> <span class=\"k\">then<\/span>\n    <span class=\"n\">enable_http<\/span><span class=\"p\">,<\/span> <span class=\"n\">enable_stream<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span> <span class=\"kc\">true<\/span>\n<span class=\"k\">elseif<\/span> <span class=\"n\">yaml_conf<\/span><span class=\"p\">.<\/span><span class=\"n\">apisix<\/span><span class=\"p\">.<\/span><span class=\"n\">proxy_mode<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"http&amp;stream\"<\/span> <span class=\"k\">then<\/span>\n    <span class=\"n\">enable_http<\/span><span class=\"p\">,<\/span> <span class=\"n\">enable_stream<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span> <span class=\"kc\">true<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"25-port-conflict-detection-lines-423-521\">2.5 Port Conflict Detection (Lines 423-521)<\/h3>\n\n<p><code class=\"language-plaintext highlighter-rouge\">validate_and_get_listen_addr()<\/code> and <code class=\"language-plaintext highlighter-rouge\">listen_table_insert()<\/code> use a <code class=\"language-plaintext highlighter-rouge\">ports_to_check<\/code> table to prevent conflicts among admin\/status\/control\/prometheus\/HTTP\/HTTPS ports.<\/p>\n\n<p>Ports involved:<\/p>\n<ul>\n  <li><strong>Admin<\/strong>: default 9180<\/li>\n  <li><strong>Status<\/strong>: default 7085<\/li>\n  <li><strong>Control<\/strong>: default 9090<\/li>\n  <li><strong>Prometheus<\/strong>: default 9091<\/li>\n<\/ul>\n\n<h3 id=\"26-httphttps-listen-normalization-lines-523-601\">2.6 HTTP\/HTTPS Listen Normalization (Lines 523-601)<\/h3>\n<ul>\n  <li>Normalizes <code class=\"language-plaintext highlighter-rouge\">node_listen<\/code> (which can be a number, table, or nested table) to a standard format <code class=\"language-plaintext highlighter-rouge\">[{ip, port, enable_http3}]<\/code><\/li>\n  <li>Normalizes <code class=\"language-plaintext highlighter-rouge\">ssl.listen<\/code> similarly<\/li>\n  <li>Since v3.9, <code class=\"language-plaintext highlighter-rouge\">enable_http2<\/code> has moved from port-level to the global apisix level; port-level configs now raise errors<\/li>\n<\/ul>\n\n<h3 id=\"27-port-validation-validate_port_or_range-lines-61-131\">2.7 Port Validation (<code class=\"language-plaintext highlighter-rouge\">validate_port_or_range<\/code>, Lines 61-131)<\/h3>\n\n<p>A hand-written port number\/range validator supporting:<\/p>\n<ul>\n  <li>Integer port numbers (1-65535)<\/li>\n  <li>Range format (<code class=\"language-plaintext highlighter-rouge\">start-end<\/code>)<\/li>\n  <li>IPv4 with port (<code class=\"language-plaintext highlighter-rouge\">0.0.0.0:8080<\/code>)<\/li>\n  <li>IPv6 with port (<code class=\"language-plaintext highlighter-rouge\">[::1]:8080<\/code>)<\/li>\n<\/ul>\n\n<h3 id=\"28-template-rendering-lines-679-889\">2.8 Template Rendering (Lines 679-889)<\/h3>\n\n<p>Packs all processed configuration into a <code class=\"language-plaintext highlighter-rouge\">sys_conf<\/code> table, renders the nginx template using <code class=\"language-plaintext highlighter-rouge\">resty.template<\/code>, and writes to <code class=\"language-plaintext highlighter-rouge\">conf\/nginx.conf<\/code>.<\/p>\n\n<p>Key sys_conf fields:<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">worker_rlimit_nofile<\/code>: Automatically set to <code class=\"language-plaintext highlighter-rouge\">worker_connections + 128<\/code><\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">worker_processes<\/code>: Forced to 1 in dev_mode, otherwise defaults to \u201cauto\u201d<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">dns_resolver<\/code>: Auto-read from <code class=\"language-plaintext highlighter-rouge\">\/etc\/resolv.conf<\/code> when not configured<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">extra_lua_path\/cpath<\/code>: Appends custom Lua paths<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">envs<\/code>: Injects environment variables (including those needed for Kubernetes service discovery)<\/li>\n<\/ul>\n\n<h3 id=\"29-cluster-role-handling-lines-663-671\">2.9 Cluster Role Handling (Lines 663-671)<\/h3>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">if<\/span> <span class=\"n\">role<\/span> <span class=\"o\">==<\/span> <span class=\"s2\">\"control_plane\"<\/span> <span class=\"ow\">and<\/span> <span class=\"ow\">not<\/span> <span class=\"n\">admin_server_addr<\/span> <span class=\"k\">then<\/span>\n    <span class=\"kd\">local<\/span> <span class=\"n\">listen<\/span> <span class=\"o\">=<\/span> <span class=\"n\">node_listen<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span>\n    <span class=\"n\">admin_server_addr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">str_format<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"%s:%s\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">listen<\/span><span class=\"p\">.<\/span><span class=\"n\">ip<\/span><span class=\"p\">,<\/span> <span class=\"n\">listen<\/span><span class=\"p\">.<\/span><span class=\"n\">port<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">end<\/span>\n<\/code><\/pre><\/div><\/div>\n<p>The control_plane role automatically reuses the first node_listen address as the admin address.<\/p>\n\n<h3 id=\"210-service-discovery-special-handling-lines-811-876\">2.10 Service Discovery Special Handling (Lines 811-876)<\/h3>\n<ul>\n  <li><strong>Kubernetes<\/strong>: Injects shared_dict, resolves environment variable placeholders (<code class=\"language-plaintext highlighter-rouge\">${VAR}<\/code>)<\/li>\n  <li><strong>Consul<\/strong>: Injects shared_dict<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"3-startenv---start-apisix-lines-923-1019\">3. <code class=\"language-plaintext highlighter-rouge\">start(env, ...)<\/code> \u2014 Start APISIX (Lines 923-1019)<\/h2>\n\n<p><strong>Execution flow<\/strong>:<\/p>\n<ol>\n  <li><strong>cleanup(env)<\/strong> \u2014 Delete custom yaml index files<\/li>\n  <li><strong>Deny root execution<\/strong> \u2014 Hard reject in production<\/li>\n  <li><strong>Create logs directory<\/strong><\/li>\n  <li><strong>Wait for old process to exit<\/strong> \u2014 Up to 3 seconds (30\u00d7 0.1s), detected via <code class=\"language-plaintext highlighter-rouge\">signal.kill(pid, 0)<\/code><\/li>\n  <li><strong>Parse <code class=\"language-plaintext highlighter-rouge\">-c<\/code> argument<\/strong> \u2014 Supports <code class=\"language-plaintext highlighter-rouge\">--config<\/code> to specify a custom YAML path<\/li>\n  <li><strong>init(env)<\/strong> \u2014 Generate nginx.conf<\/li>\n  <li><strong>init_etcd(env, args)<\/strong> \u2014 Initialize etcd for non-data_plane roles<\/li>\n  <li><strong>Execute openresty<\/strong> \u2014 The actual launch<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"4-testenv--config-test-lines-1022-1057\">4. <code class=\"language-plaintext highlighter-rouge\">test(env)<\/code> \u2014 Config Test (Lines 1022-1057)<\/h2>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">-- Backup original nginx.conf \u2192 generate new \u2192 nginx -t \u2192 restore original nginx.conf<\/span>\n<\/code><\/pre><\/div><\/div>\n<p>This is a non-destructive operation that <strong>guarantees restoration<\/strong> of the original nginx.conf. Handles macOS\/Linux <code class=\"language-plaintext highlighter-rouge\">os.execute<\/code> return value differences.<\/p>\n\n<hr \/>\n\n<h2 id=\"5-stopenv--quitenv--stop-service-lines-1060-1073\">5. <code class=\"language-plaintext highlighter-rouge\">stop(env)<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">quit(env)<\/code> \u2014 Stop Service (Lines 1060-1073)<\/h2>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">local<\/span> <span class=\"n\">cmd<\/span> <span class=\"o\">=<\/span> <span class=\"n\">env<\/span><span class=\"p\">.<\/span><span class=\"n\">openresty_args<\/span> <span class=\"o\">..<\/span> <span class=\"s\">[[ -s quit]]<\/span>   <span class=\"c1\">-- Graceful stop<\/span>\n<span class=\"kd\">local<\/span> <span class=\"n\">cmd<\/span> <span class=\"o\">=<\/span> <span class=\"n\">env<\/span><span class=\"p\">.<\/span><span class=\"n\">openresty_args<\/span> <span class=\"o\">..<\/span> <span class=\"s\">[[ -s stop]]<\/span>   <span class=\"c1\">-- Fast stop<\/span>\n<\/code><\/pre><\/div><\/div>\n<p>Both run <code class=\"language-plaintext highlighter-rouge\">cleanup(env)<\/code> first, then send the corresponding nginx signal.<\/p>\n<ul>\n  <li><strong>quit<\/strong>: Graceful stop; waits for workers to finish current requests<\/li>\n  <li><strong>stop<\/strong>: Fast stop; immediately terminates all workers<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"6-restartenv--reloadenv--restart--hot-reload-lines-1076-1100\">6. <code class=\"language-plaintext highlighter-rouge\">restart(env)<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">reload(env)<\/code> \u2014 Restart &amp; Hot Reload (Lines 1076-1100)<\/h2>\n\n<p><strong>restart<\/strong>: <code class=\"language-plaintext highlighter-rouge\">test \u2192 stop \u2192 start<\/code> (verify first, then stop, then start)<\/p>\n\n<p><strong>reload<\/strong>: <code class=\"language-plaintext highlighter-rouge\">init \u2192 nginx -t \u2192 nginx -s reload<\/code> (hot reload without service interruption)<\/p>\n\n<p>On reload failure, only prints a message without <code class=\"language-plaintext highlighter-rouge\">die<\/code>, avoiding disruption to the running instance.<\/p>\n\n<hr \/>\n\n<h2 id=\"7-helper-functions\">7. Helper Functions<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>Function<\/th>\n      <th>Location<\/th>\n      <th>Purpose<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">local_dns_resolver()<\/code><\/td>\n      <td>Line 189<\/td>\n      <td>Parse DNS server addresses from <code class=\"language-plaintext highlighter-rouge\">\/etc\/resolv.conf<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">version_greater_equal()<\/code><\/td>\n      <td>Line 152<\/td>\n      <td>Semantic version comparison<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">get_openresty_version()<\/code><\/td>\n      <td>Line 173<\/td>\n      <td>Get version via <code class=\"language-plaintext highlighter-rouge\">openresty -v<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">check_running()<\/code><\/td>\n      <td>Line 912<\/td>\n      <td>Check if process is alive via pid file<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">get_lua_path()<\/code><\/td>\n      <td>Line 215<\/td>\n      <td>Normalize Lua path (ensure trailing <code class=\"language-plaintext highlighter-rouge\">;<\/code>)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">validate_port_or_range()<\/code><\/td>\n      <td>Line 61<\/td>\n      <td>Port\/port-range validity check<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">validate_and_get_listen_addr()<\/code><\/td>\n      <td>Line 425<\/td>\n      <td>Inner function: validate port conflicts and build address string<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">listen_table_insert()<\/code><\/td>\n      <td>Line 480<\/td>\n      <td>Inner function: normalize listen table insertion (supports IPv6 dual-stack)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">cleanup()<\/code><\/td>\n      <td>Line 898<\/td>\n      <td>Delete custom yaml index files<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">sleep()<\/code><\/td>\n      <td>Line 907<\/td>\n      <td>Wait via <code class=\"language-plaintext highlighter-rouge\">os.execute(\"sleep \" .. n)<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"8-security--design-highlights\">8. Security &amp; Design Highlights<\/h2>\n\n<ol>\n  <li><strong>Port conflict checks<\/strong> \u2014 Multiple service ports (admin\/status\/control\/prometheus\/http\/https) unified through <code class=\"language-plaintext highlighter-rouge\">ports_to_check<\/code> to prevent conflicts<\/li>\n  <li><strong>Pre-emptive config validation<\/strong> \u2014 start\/reload\/restart\/test all re-run <code class=\"language-plaintext highlighter-rouge\">init()<\/code>, ensuring instant validation on config changes<\/li>\n  <li><strong>Safety warnings<\/strong> \u2014 Root execution, empty admin_key, low ulimit, admin_key_required=false all produce clear warnings<\/li>\n  <li><strong>Process detection<\/strong> \u2014 Checks for old processes before starting to avoid port conflicts; verifies the pid corresponds to a real process, not just a stale file<\/li>\n  <li><strong>Backward compatibility<\/strong> \u2014 <code class=\"language-plaintext highlighter-rouge\">node_listen<\/code> supports three historical formats: number, table, and nested table<\/li>\n  <li><strong>Non-destructive testing<\/strong> \u2014 The <code class=\"language-plaintext highlighter-rouge\">test<\/code> command backs up and restores the original nginx.conf<\/li>\n  <li><strong>Graceful degradation<\/strong> \u2014 Reload failure does not terminate the running instance<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"9-execution-flow-diagram\">9. Execution Flow Diagram<\/h2>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>apisix start\n  \u2502\n  \u251c\u2500\u2500 cleanup()\n  \u251c\u2500\u2500 Deny \/root execution\n  \u251c\u2500\u2500 Create logs\/\n  \u251c\u2500\u2500 Wait for old process exit (max 3s)\n  \u251c\u2500\u2500 Parse -c argument\n  \u251c\u2500\u2500 init(env)\n  \u2502     \u251c\u2500\u2500 Read &amp; validate config.yaml\n  \u2502     \u251c\u2500\u2500 Validate admin_key \/ mtls \/ plugins\n  \u2502     \u251c\u2500\u2500 Handle proxy_mode (http\/stream\/http&amp;stream)\n  \u2502     \u251c\u2500\u2500 Port conflict detection\n  \u2502     \u251c\u2500\u2500 Normalize node_listen \/ ssl.listen\n  \u2502     \u251c\u2500\u2500 Handle service discovery (K8s\/Consul)\n  \u2502     \u251c\u2500\u2500 DNS resolver config\n  \u2502     \u2514\u2500\u2500 Template rendering \u2192 nginx.conf\n  \u251c\u2500\u2500 init_etcd() [non data_plane]\n  \u2514\u2500\u2500 Launch openresty\n\napisix reload\n  \u251c\u2500\u2500 init(env)          # Regenerate nginx.conf\n  \u251c\u2500\u2500 nginx -t           # Syntax test\n  \u2514\u2500\u2500 nginx -s reload    # Hot reload signal\n\napisix restart\n  \u251c\u2500\u2500 test(env)          # Backup\u2192Generate\u2192Test\u2192Restore\n  \u251c\u2500\u2500 stop(env)          # nginx -s stop\n  \u2514\u2500\u2500 start(env)         # Full start flow\n<\/code><\/pre><\/div><\/div>\n","category":{"@attributes":{"term":"APISIX"}}},{"title":"Apache APISIX \u6e90\u7801\u9605\u8bfb\u6307\u5357","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/2026-07-26\/apisix-source-code-guide.html"}},"updated":"2026-07-26T23:00:00+08:00","id":"https:\/\/wy471x.github.io\/2026-07-26\/apisix-source-code-guide.html","content":"<h1 id=\"apache-apisix-\u6e90\u7801\u9605\u8bfb\u6307\u5357\">Apache APISIX \u6e90\u7801\u9605\u8bfb\u6307\u5357<\/h1>\n\n<h2 id=\"\u524d\u8a00\">\u524d\u8a00<\/h2>\n\n<p>Apache APISIX \u662f\u4e00\u4e2a\u57fa\u4e8e OpenResty\uff08Nginx + LuaJIT\uff09\u6784\u5efa\u7684\u52a8\u6001\u3001\u9ad8\u6027\u80fd API \u7f51\u5173\u3002\u672c\u6587\u6863\u65e8\u5728\u5e2e\u52a9\u5f00\u53d1\u8005\u5feb\u901f\u5efa\u7acb\u5bf9 APISIX \u6e90\u7801\u7ed3\u6784\u7684\u6574\u4f53\u8ba4\u77e5\uff0c\u5e76\u6309\u5408\u7406\u7684\u987a\u5e8f\u6df1\u5165\u9605\u8bfb\u5173\u952e\u6a21\u5757\u3002<\/p>\n\n<p><strong>\u524d\u7f6e\u77e5\u8bc6\u5efa\u8bae\uff1a<\/strong><\/p>\n<ul>\n  <li>\u719f\u6089 Nginx\/OpenResty \u7684\u8bf7\u6c42\u5904\u7406\u9636\u6bb5\uff08rewrite \u2192 access \u2192 content \u2192 header_filter \u2192 body_filter \u2192 log\uff09<\/li>\n  <li>\u4e86\u89e3 Lua \u7684\u57fa\u672c\u8bed\u6cd5\u548c\u6a21\u5757\u7cfb\u7edf<\/li>\n  <li>\u4e86\u89e3 etcd \u7684\u57fa\u672c\u6982\u5ff5\uff08etcd \u662f APISIX \u7684\u9ed8\u8ba4\u914d\u7f6e\u4e2d\u5fc3\uff09<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"\u4e00\u9879\u76ee\u9876\u5c42\u7ed3\u6784\u603b\u89c8\">\u4e00\u3001\u9879\u76ee\u9876\u5c42\u7ed3\u6784\u603b\u89c8<\/h2>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>apisix\/\n\u251c\u2500\u2500 apisix\/                 # Lua \u6838\u5fc3\u6e90\u7801\uff08\u9879\u76ee\u7684\u5fc3\u810f\uff09\n\u2502   \u251c\u2500\u2500 core\/               # \u57fa\u7840\u5e93\uff08\u65e5\u5fd7\u3001JSON\u3001\u914d\u7f6e\u3001\u8bf7\u6c42\/\u54cd\u5e94\u3001\u7f13\u5b58\u7b49\uff09\n\u2502   \u251c\u2500\u2500 admin\/              # Admin API \u5b9e\u73b0\uff08CRUD \u64cd\u4f5c\uff09\n\u2502   \u251c\u2500\u2500 plugins\/            # HTTP \u63d2\u4ef6\uff0890+ \u63d2\u4ef6\uff09\n\u2502   \u251c\u2500\u2500 http\/               # HTTP \u5b50\u6a21\u5757\uff08\u8def\u7531\u5339\u914d\u5668\u7b49\uff09\n\u2502   \u251c\u2500\u2500 stream\/             # \u56db\u5c42\u4ee3\u7406\uff08TCP\/UDP\uff09\n\u2502   \u251c\u2500\u2500 control\/            # Control API\uff08\u5185\u90e8\u7ba1\u7406\u63a5\u53e3\uff09\n\u2502   \u251c\u2500\u2500 discovery\/          # \u670d\u52a1\u53d1\u73b0\uff08Consul\u3001Nacos\u3001Eureka \u7b49\uff09\n\u2502   \u251c\u2500\u2500 balancer\/           # \u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5\n\u2502   \u251c\u2500\u2500 secret\/             # \u5bc6\u94a5\u7ba1\u7406\u540e\u7aef\n\u2502   \u251c\u2500\u2500 utils\/              # \u5de5\u5177\u6a21\u5757\n\u2502   \u251c\u2500\u2500 cli\/                # \u547d\u4ee4\u884c\u5de5\u5177\uff08\u542f\u505c\u3001\u914d\u7f6e\u751f\u6210\uff09\n\u2502   \u2514\u2500\u2500 init.lua            # \u4e3b\u5165\u53e3\uff0c\u5b9a\u4e49\u6240\u6709 OpenResty \u9636\u6bb5\u94a9\u5b50\n\u251c\u2500\u2500 bin\/apisix              # Shell \u542f\u52a8\u811a\u672c\n\u251c\u2500\u2500 conf\/                   # \u8fd0\u884c\u65f6\u914d\u7f6e\n\u2502   \u251c\u2500\u2500 config.yaml         # \u7528\u6237\u914d\u7f6e\n\u2502   \u251c\u2500\u2500 config-default.yaml # \u9ed8\u8ba4\u914d\u7f6e\n\u2502   \u2514\u2500\u2500 ...\n\u251c\u2500\u2500 t\/                      # Perl \u6d4b\u8bd5\u5957\u4ef6\uff08Test::Nginx\uff09\n\u2502   \u251c\u2500\u2500 admin\/              # Admin API \u6d4b\u8bd5\n\u2502   \u251c\u2500\u2500 plugin\/             # \u5404\u63d2\u4ef6\u6d4b\u8bd5\uff08250+ \u6587\u4ef6\uff09\n\u2502   \u251c\u2500\u2500 core\/               # \u6838\u5fc3\u6a21\u5757\u6d4b\u8bd5\n\u2502   \u251c\u2500\u2500 lib\/                # \u6d4b\u8bd5\u8f85\u52a9\u5e93\n\u2502   \u2514\u2500\u2500 ...\n\u251c\u2500\u2500 docs\/                   # \u6587\u6863\uff08en + zh\uff09\n\u2514\u2500\u2500 Makefile                # \u6784\u5efa\/\u90e8\u7f72\/\u6d4b\u8bd5\u547d\u4ee4\n<\/code><\/pre><\/div><\/div>\n\n<hr \/>\n\n<h2 id=\"\u4e8c\u542f\u52a8\u6d41\u7a0b\u5efa\u8bae\u4ece\u8fd9\u91cc\u5f00\u59cb\u9605\u8bfb\">\u4e8c\u3001\u542f\u52a8\u6d41\u7a0b\uff08\u5efa\u8bae\u4ece\u8fd9\u91cc\u5f00\u59cb\u9605\u8bfb\uff09<\/h2>\n\n<p>\u8fd9\u662f\u7406\u89e3\u6574\u4e2a\u7cfb\u7edf\u7684\u5207\u5165\u70b9\uff0c\u6cbf\u7740\u542f\u52a8\u94fe\u8def\u4ece\u5934\u8bfb\u5230\u5c3e\uff0c\u53ef\u4ee5\u5efa\u7acb\u5bf9\u7cfb\u7edf\u9aa8\u67b6\u7684\u6574\u4f53\u8ba4\u77e5\u3002<\/p>\n\n<h3 id=\"21-shell-\u5165\u53e3--lua-cli\">2.1 Shell \u5165\u53e3 \u2192 Lua CLI<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>bin\/apisix  \u2500\u2500\u2192  apisix\/cli\/apisix.lua  \u2500\u2500\u2192  apisix\/cli\/ops.lua\n<\/code><\/pre><\/div><\/div>\n\n<ul>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">bin\/apisix<\/code><\/strong>\uff08Shell \u811a\u672c\uff0c\u7ea6 50 \u884c\uff09\uff1a\u5b9a\u4f4d OpenResty \u548c <code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/apisix.lua<\/code>\uff0c\u7136\u540e\u6267\u884c <code class=\"language-plaintext highlighter-rouge\">luajit &lt;apisix.lua&gt; &lt;\u547d\u4ee4\u53c2\u6570&gt;<\/code><\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/apisix.lua<\/code><\/strong>\uff1a\u8bbe\u7f6e Lua \u6a21\u5757\u641c\u7d22\u8def\u5f84\uff0c\u7136\u540e\u59d4\u6258\u7ed9 <code class=\"language-plaintext highlighter-rouge\">apisix.cli.ops<\/code> \u6267\u884c<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/ops.lua<\/code><\/strong>\uff1a\u5b9e\u73b0 <code class=\"language-plaintext highlighter-rouge\">init<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">start<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">stop<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">restart<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">reload<\/code> \u7b49\u547d\u4ee4<\/li>\n<\/ul>\n\n<h3 id=\"22-nginxconf-\u751f\u6210\">2.2 nginx.conf \u751f\u6210<\/h3>\n\n<p>\u5f53\u6267\u884c <code class=\"language-plaintext highlighter-rouge\">apisix start<\/code> \u65f6\uff0c<code class=\"language-plaintext highlighter-rouge\">ops.lua<\/code> \u7684 <code class=\"language-plaintext highlighter-rouge\">init()<\/code> \u51fd\u6570\u4f1a\uff1a<\/p>\n<ol>\n  <li>\u8bfb\u53d6 YAML \u914d\u7f6e \u2192 \u7528 <code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/schema.lua<\/code> \u505a schema \u6821\u9a8c<\/li>\n  <li>\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/ngx_tpl.lua<\/code>\uff08nginx \u914d\u7f6e\u6a21\u677f\u5f15\u64ce\uff09\u751f\u6210 <code class=\"language-plaintext highlighter-rouge\">conf\/nginx.conf<\/code><\/li>\n<\/ol>\n\n<h3 id=\"23-worker-\u521d\u59cb\u5316\">2.3 Worker \u521d\u59cb\u5316<\/h3>\n\n<p>\u751f\u6210\u7684 <code class=\"language-plaintext highlighter-rouge\">nginx.conf<\/code> \u4e2d\u6307\u5b9a\u4e86 Lua \u5165\u53e3\u4e3a <code class=\"language-plaintext highlighter-rouge\">apisix\/init.lua<\/code>\uff0c\u8be5\u6587\u4ef6\u5b9a\u4e49\u4e86\u5b8c\u6574\u7684\u8bf7\u6c42\u5904\u7406\u751f\u547d\u5468\u671f\uff1a<\/p>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">-- init.lua \u4e2d\u5b9a\u4e49\u7684\u5173\u952e\u51fd\u6570<\/span>\n<span class=\"n\">http_init<\/span><span class=\"p\">(<\/span><span class=\"n\">args<\/span><span class=\"p\">)<\/span>          <span class=\"c1\">-- \u5168\u5c40\u521d\u59cb\u5316\uff08\u53ea\u6267\u884c\u4e00\u6b21\uff09<\/span>\n<span class=\"n\">http_init_worker<\/span><span class=\"p\">()<\/span>       <span class=\"c1\">-- \u6bcf\u4e2a worker \u8fdb\u7a0b\u7684\u521d\u59cb\u5316<\/span>\n<span class=\"n\">http_access_phase<\/span><span class=\"p\">()<\/span>      <span class=\"c1\">-- \u8bf7\u6c42\u63a5\u5165\u9636\u6bb5\uff08\u8def\u7531\u5339\u914d\u3001\u63d2\u4ef6\u6267\u884c\u7684\u6838\u5fc3\uff09<\/span>\n<span class=\"n\">http_header_filter_phase<\/span><span class=\"p\">()<\/span>\n<span class=\"n\">http_body_filter_phase<\/span><span class=\"p\">()<\/span>\n<span class=\"n\">http_log_phase<\/span><span class=\"p\">()<\/span>         <span class=\"c1\">-- \u65e5\u5fd7\/\u4e0a\u62a5\u9636\u6bb5<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">http_init_worker()<\/code> \u4e2d\u7684\u521d\u59cb\u5316\u987a\u5e8f\uff08\u503c\u5f97\u5173\u6ce8\uff09\uff1a<\/strong><\/p>\n<ol>\n  <li>\u968f\u673a\u79cd\u5b50\u3001LRU \u7f13\u5b58\u3001DNS \u89e3\u6790\u5668<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">discovery.init_worker()<\/code> \u2014 \u670d\u52a1\u53d1\u73b0<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">balancer.init_worker()<\/code> \u2014 \u8d1f\u8f7d\u5747\u8861\u5668<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">admin.init_worker()<\/code> \u2014 Admin API<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">plugin.load()<\/code> \u2014 \u52a0\u8f7d\u6240\u6709\u63d2\u4ef6\uff08\u6309\u4f18\u5148\u7ea7\u6392\u5e8f\uff09<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">router.http_init_worker()<\/code> \u2014 HTTP \u8def\u7531\u8868\u521d\u59cb\u5316<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">require(\"apisix.http.service\").init_worker()<\/code> \u2014 Service \u5bf9\u8c61\u521d\u59cb\u5316<\/li>\n  <li>\u76d1\u542c\u914d\u7f6e\u53d8\u66f4\uff08etcd watch\uff09\uff0c\u5b9e\u73b0\u70ed\u66f4\u65b0<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"\u4e09\u6838\u5fc3\u6a21\u5757\u4f53\u7cfbapisixcore\">\u4e09\u3001\u6838\u5fc3\u6a21\u5757\u4f53\u7cfb\uff08<code class=\"language-plaintext highlighter-rouge\">apisix\/core\/<\/code>\uff09<\/h2>\n\n<p><code class=\"language-plaintext highlighter-rouge\">apisix\/core.lua<\/code> \u662f\u4e00\u4e2a<strong>\u5916\u89c2\u6a21\u5757\uff08Facade\uff09<\/strong>\uff0c\u5c06\u6240\u6709\u6838\u5fc3\u5b50\u6a21\u5757\u805a\u5408\u5230\u4e00\u4e2a <code class=\"language-plaintext highlighter-rouge\">core<\/code> \u8868\u4e2d\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u6a21\u5757<\/th>\n      <th>\u6587\u4ef6<\/th>\n      <th>\u804c\u8d23<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.log<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/log.lua<\/code><\/td>\n      <td>\u65e5\u5fd7\u8f93\u51fa\uff08warn\/error\/info\/debug\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.json<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/json.lua<\/code><\/td>\n      <td>JSON \u7f16\u89e3\u7801\uff0c\u652f\u6301\u5ef6\u8fdf\u7f16\u7801\u4f18\u5316<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.table<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/table.lua<\/code><\/td>\n      <td>\u8868\u5de5\u5177\u51fd\u6570\uff08deepcopy\u3001merge \u7b49\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.request<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/request.lua<\/code><\/td>\n      <td>\u8bf7\u6c42\u5934\u90e8\/Body \u8bfb\u5199<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.response<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/response.lua<\/code><\/td>\n      <td>\u54cd\u5e94\u5934\u90e8\u8bbe\u7f6e\u3001\u9000\u51fa\u3001CORS<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.schema<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/schema.lua<\/code><\/td>\n      <td>JSON Schema \u6821\u9a8c\u5668\u5c01\u88c5<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.config<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/config_etcd.lua<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">core\/config_yaml.lua<\/code><\/td>\n      <td>\u914d\u7f6e\u63d0\u4f9b\u8005\uff08etcd \/ \u672c\u5730 YAML \/ xDS\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.lrucache<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/lrucache.lua<\/code><\/td>\n      <td>LRU \u7f13\u5b58\uff0c\u652f\u6301 TTL<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.ctx<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/ctx.lua<\/code><\/td>\n      <td>\u8bf7\u6c42\u4e0a\u4e0b\u6587\u7ba1\u7406\uff08tablepool \u590d\u7528\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.etcd<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/etcd.lua<\/code><\/td>\n      <td>etcd \u5ba2\u6237\u7aef\u5c01\u88c5<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.string<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/string.lua<\/code><\/td>\n      <td>\u5b57\u7b26\u4e32\u5de5\u5177\u51fd\u6570<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.id<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/id.lua<\/code><\/td>\n      <td>ID \u751f\u6210\u5668\uff08\u652f\u6301\u96ea\u82b1 ID\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.dns.client<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/dns\/<\/code><\/td>\n      <td>DNS \u5ba2\u6237\u7aef<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.pubsub<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/pubsub.lua<\/code><\/td>\n      <td>\u53d1\u5e03\/\u8ba2\u9605\u62bd\u8c61<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.event<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/event.lua<\/code><\/td>\n      <td>Worker \u95f4\u4e8b\u4ef6\u7cfb\u7edf<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p><strong>\u5173\u952e\u8bbe\u8ba1\u6a21\u5f0f\uff1a<\/strong> \u6240\u6709\u6a21\u5757\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">require(\"apisix.core\")<\/code> \u83b7\u53d6\u7edf\u4e00\u7684 <code class=\"language-plaintext highlighter-rouge\">core<\/code> \u5f15\u7528\uff0c\u907f\u514d\u6563\u4e71\u7684\u4f9d\u8d56\u5173\u7cfb\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"\u56db\u8bf7\u6c42\u5904\u7406\u6d41\u7a0b\u6700\u6838\u5fc3\u7684\u94fe\u8def\">\u56db\u3001\u8bf7\u6c42\u5904\u7406\u6d41\u7a0b\uff08\u6700\u6838\u5fc3\u7684\u94fe\u8def\uff09<\/h2>\n\n<p>\u5f53\u7528\u6237\u8bf7\u6c42\u5230\u8fbe APISIX \u540e\uff0c\u7ecf\u8fc7\u5982\u4e0b\u9636\u6bb5\uff08\u90fd\u5728 <code class=\"language-plaintext highlighter-rouge\">apisix\/init.lua<\/code> \u4e2d\u5b9a\u4e49\uff09\uff1a<\/p>\n\n<h3 id=\"\u7b2c\u4e00\u9636\u6bb5http_access_phase--\u63a5\u5165\u4e0e\u8def\u7531\u5339\u914d\">\u7b2c\u4e00\u9636\u6bb5\uff1a<code class=\"language-plaintext highlighter-rouge\">http_access_phase()<\/code> \u2014 \u63a5\u5165\u4e0e\u8def\u7531\u5339\u914d<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>1. HTTPS \u5ba2\u6237\u7aef\u8bc1\u4e66\u6821\u9a8c\n2. Debug \u52a8\u6001\u8c03\u8bd5\u68c0\u67e5\n3. URI \u89c4\u8303\u5316\uff08\u5c3e\u90e8\u659c\u6760\u5904\u7406\u3001servlet \u8def\u5f84\u5904\u7406\uff09\n4. X-Forwarded-* \u8bf7\u6c42\u5934\u5904\u7406\n5. Router \u5339\u914d \u2192 \u627e\u5230\u5339\u914d\u7684 Route\n6. \u65e0\u5339\u914d Route \u2192 \u6267\u884c Global Rules \u2192 \u8fd4\u56de 404\n7. \u5408\u5e76\u914d\u7f6e\uff1a\n   plugin_config_id \u2192 service_id \u2192 consumer \u2192 consumer_group\n8. \u6267\u884c Global Rules\n9. \u6709 script \u2192 \u6267\u884c script \u811a\u672c\n10. \u5426\u5219 \u2192 \u8fc7\u6ee4\u63d2\u4ef6 \u2192 \u4f9d\u6b21\u6267\u884c rewrite \u9636\u6bb5\u63d2\u4ef6 \u2192 access \u9636\u6bb5\u63d2\u4ef6\n11. handle_upstream()\uff1a\n    - \u901a\u8fc7 upstream_id \u6216\u5185\u8054 upstream \u83b7\u53d6\u4e0a\u6e38\u914d\u7f6e\n    - \u8d1f\u8f7d\u5747\u8861\u5668\u9009\u62e9\u540e\u7aef\u8282\u70b9\n    - \u6267\u884c before_proxy \u9636\u6bb5\n    - \u4ee3\u7406\u8bf7\u6c42\u5230\u4e0a\u6e38\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"\u7b2c\u4e8c\u4e09\u9636\u6bb5headerbody-\u8fc7\u6ee4\">\u7b2c\u4e8c\/\u4e09\u9636\u6bb5\uff1aHeader\/Body \u8fc7\u6ee4<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>header_filter \u2192 \u8bbe\u7f6e Server \u5934\u3001\u4e0a\u6e38\u72b6\u6001\u5934 \u2192 \u6267\u884c header_filter \u63d2\u4ef6\nbody_filter   \u2192 \u6267\u884c body_filter \u63d2\u4ef6 &amp; delayed_body_filter \u63d2\u4ef6\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"\u7b2c\u56db\u9636\u6bb5http_log_phase--\u65e5\u5fd7\u4e0a\u62a5\">\u7b2c\u56db\u9636\u6bb5\uff1a<code class=\"language-plaintext highlighter-rouge\">http_log_phase()<\/code> \u2014 \u65e5\u5fd7\u4e0a\u62a5<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>\u5b8c\u6210 Tracing span \u2192 \u6267\u884c log \u9636\u6bb5\u63d2\u4ef6 \u2192 \u88ab\u52a8\u5065\u5eb7\u68c0\u67e5 \u2192 \u91ca\u653e api_ctx\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"\u5173\u952e\u6570\u636e\u7ed3\u6784api_ctx\">\u5173\u952e\u6570\u636e\u7ed3\u6784\uff1a<code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code><\/h3>\n\n<p>\u6bcf\u4e2a\u8bf7\u6c42\u4f1a\u4ece tablepool \u5206\u914d\u4e00\u4e2a <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> \u8868\uff0c\u643a\u5e26\uff1a<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">matched_route<\/code> \u2014 \u5339\u914d\u5230\u7684\u8def\u7531<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">upstream_conf<\/code> \u2014 \u4e0a\u6e38\u914d\u7f6e<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">plugins<\/code> \u2014 \u8981\u6267\u884c\u7684\u63d2\u4ef6\u5217\u8868<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">consumer<\/code> \u2014 \u6d88\u8d39\u8005\u4fe1\u606f<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">var<\/code> \u2014 Nginx \u53d8\u91cf\u5feb\u7167<\/li>\n<\/ul>\n\n<p>\u8be5\u8868\u8d2f\u7a7f\u6240\u6709\u9636\u6bb5\uff0c\u5728 log \u9636\u6bb5\u7ed3\u675f\u65f6\u91ca\u653e\u56de tablepool\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"\u4e94\u63d2\u4ef6\u7cfb\u7edfapisixpluginlua--apisixplugins\">\u4e94\u3001\u63d2\u4ef6\u7cfb\u7edf\uff08<code class=\"language-plaintext highlighter-rouge\">apisix\/plugin.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/plugins\/<\/code>\uff09<\/h2>\n\n<h3 id=\"51-\u63d2\u4ef6\u52a0\u8f7d\u673a\u5236\">5.1 \u63d2\u4ef6\u52a0\u8f7d\u673a\u5236<\/h3>\n\n<p><code class=\"language-plaintext highlighter-rouge\">apisix\/plugin.lua<\/code> \u662f\u63d2\u4ef6\u5f15\u64ce\uff0c\u6838\u5fc3\u51fd\u6570\uff1a<\/p>\n\n<ul>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">load()<\/code><\/strong>\uff1a\u8bfb\u53d6\u914d\u7f6e\u7684\u63d2\u4ef6\u5217\u8868 \u2192 \u9010\u4e2a\u8c03\u7528 <code class=\"language-plaintext highlighter-rouge\">load_plugin()<\/code> \u2192 \u6309\u4f18\u5148\u7ea7\u964d\u5e8f\u6392\u5e8f<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">load_plugin(name)<\/code><\/strong>\uff1arequire \u63d2\u4ef6\u6a21\u5757 \u2192 \u6821\u9a8c priority\/version\/schema \u2192 \u8c03\u7528 <code class=\"language-plaintext highlighter-rouge\">plugin.init()<\/code> \u2192 \u6ce8\u5165 <code class=\"language-plaintext highlighter-rouge\">_meta<\/code> \u5b57\u6bb5<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">run_plugin(phase, ...)<\/code><\/strong>\uff1a\u6309\u9636\u6bb5\u6267\u884c\u63d2\u4ef6\u94fe<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">filter_plugins(user_plugins, conf_version)<\/code><\/strong>\uff1a\u6839\u636e Route \u914d\u7f6e\u7b5b\u9009\u8981\u6267\u884c\u7684\u63d2\u4ef6<\/li>\n<\/ul>\n\n<h3 id=\"52-\u63d2\u4ef6\u63a5\u53e3\u89c4\u8303\">5.2 \u63d2\u4ef6\u63a5\u53e3\u89c4\u8303<\/h3>\n\n<p>\u6bcf\u4e2a\u63d2\u4ef6\u6a21\u5757\u5bfc\u51fa\u4ee5\u4e0b\u5b57\u6bb5\uff08\u4ee5 <code class=\"language-plaintext highlighter-rouge\">apisix\/plugins\/example-plugin.lua<\/code> \u4e3a\u53c2\u8003\uff09\uff1a<\/p>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">local<\/span> <span class=\"n\">plugin_name<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">\"example-plugin\"<\/span>\n\n<span class=\"kd\">local<\/span> <span class=\"n\">_M<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">version<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span><span class=\"p\">.<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span>          <span class=\"c1\">-- \u63d2\u4ef6\u7248\u672c\u53f7\uff08\u5fc5\u586b\uff09<\/span>\n    <span class=\"n\">priority<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span>            <span class=\"c1\">-- \u6267\u884c\u4f18\u5148\u7ea7\uff08\u5fc5\u586b\uff0c\u6570\u5b57\u8d8a\u5927\u8d8a\u5148\u6267\u884c\uff09<\/span>\n    <span class=\"n\">name<\/span> <span class=\"o\">=<\/span> <span class=\"n\">plugin_name<\/span><span class=\"p\">,<\/span>      <span class=\"c1\">-- \u63d2\u4ef6\u540d\u79f0<\/span>\n    <span class=\"n\">schema<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{},<\/span>             <span class=\"c1\">-- JSON Schema \u5b9a\u4e49\uff08\u5fc5\u586b\uff09<\/span>\n    <span class=\"nb\">type<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'auth'<\/span><span class=\"p\">,<\/span>           <span class=\"c1\">-- \u63d2\u4ef6\u7c7b\u578b\uff08\u9009\u586b\uff0cauth \u7c7b\u578b\u6709\u7279\u6b8a\u5904\u7406\uff09<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p>\u751f\u547d\u5468\u671f\u94a9\u5b50\uff08\u5747\u53ef\u9009\uff09\uff1a<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">init()<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">destroy()<\/code> \u2014 \u52a0\u8f7d\/\u5378\u8f7d\u65f6\u8c03\u7528<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">check_schema(conf, schema_type)<\/code> \u2014 \u81ea\u5b9a\u4e49 schema \u6821\u9a8c<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">rewrite(conf, ctx)<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">access(conf, ctx)<\/code> \u2014 \u8bf7\u6c42\u5904\u7406<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">header_filter(conf, ctx)<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">body_filter(conf, ctx)<\/code> \u2014 \u54cd\u5e94\u5904\u7406<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">delayed_body_filter(conf, ctx)<\/code> \u2014 \u5ef6\u8fdf body \u8fc7\u6ee4<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">log(conf, ctx)<\/code> \u2014 \u65e5\u5fd7\u4e0a\u62a5<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">api()<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">control_api()<\/code> \u2014 \u6ce8\u518c\u989d\u5916\u7684 Admin\/Control API<\/li>\n<\/ul>\n\n<h3 id=\"53-\u63d2\u4ef6\u4f18\u5148\u7ea7\u4f53\u7cfb\">5.3 \u63d2\u4ef6\u4f18\u5148\u7ea7\u4f53\u7cfb<\/h3>\n\n<p>\u63d2\u4ef6\u6309 <code class=\"language-plaintext highlighter-rouge\">priority<\/code> \u964d\u5e8f\u6267\u884c\uff0c\u90e8\u5206\u5173\u952e\u63d2\u4ef6\u7684\u4f18\u5148\u7ea7\u53c2\u8003\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u4f18\u5148\u7ea7\u8303\u56f4<\/th>\n      <th>\u5178\u578b\u63d2\u4ef6<\/th>\n      <th>\u8bf4\u660e<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>4000+<\/td>\n      <td>ip-restriction, referer-restriction<\/td>\n      <td>\u5b89\u5168\u62e6\u622a\u7c7b<\/td>\n    <\/tr>\n    <tr>\n      <td>3000-3999<\/td>\n      <td>cors, csrf, fault-injection<\/td>\n      <td>\u5b89\u5168\/\u6d4b\u8bd5\u7c7b<\/td>\n    <\/tr>\n    <tr>\n      <td>2500-2999<\/td>\n      <td>key-auth, jwt-auth, basic-auth<\/td>\n      <td>\u8ba4\u8bc1\u7c7b<\/td>\n    <\/tr>\n    <tr>\n      <td>1000-1999<\/td>\n      <td>limit-count, limit-conn, limit-req<\/td>\n      <td>\u9650\u6d41\u7c7b<\/td>\n    <\/tr>\n    <tr>\n      <td>500-999<\/td>\n      <td>proxy-rewrite, response-rewrite<\/td>\n      <td>\u91cd\u5199\u7c7b<\/td>\n    <\/tr>\n    <tr>\n      <td>1-499<\/td>\n      <td>\u65e5\u5fd7\u63d2\u4ef6, prometheus<\/td>\n      <td>\u53ef\u89c2\u6d4b\u7c7b<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"54-\u63d2\u4ef6\u5206\u7c7b\u901f\u89c8\">5.4 \u63d2\u4ef6\u5206\u7c7b\u901f\u89c8<\/h3>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u7c7b\u522b<\/th>\n      <th>\u4ee3\u8868\u63d2\u4ef6<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><strong>\u8ba4\u8bc1<\/strong><\/td>\n      <td>key-auth, jwt-auth, basic-auth, hmac-auth, openid-connect, forward-auth<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u5b89\u5168<\/strong><\/td>\n      <td>ip-restriction, ua-restriction, cors, csrf, uri-blocker, api-breaker<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u9650\u6d41<\/strong><\/td>\n      <td>limit-count, limit-conn, limit-req, traffic-split<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u91cd\u5199<\/strong><\/td>\n      <td>proxy-rewrite, redirect, response-rewrite, proxy-mirror<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Serverless<\/strong><\/td>\n      <td>serverless-pre-function, serverless-post-function<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>AI<\/strong><\/td>\n      <td>ai-proxy, ai-prompt-decorator, ai-prompt-guard, ai-rag, ai-rate-limiting<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u65e5\u5fd7<\/strong><\/td>\n      <td>kafka-logger, http-logger, syslog, elasticsearch-logger, loki-logger \u7b49<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u53ef\u89c2\u6d4b<\/strong><\/td>\n      <td>prometheus, zipkin, skywalking, opentelemetry, datadog<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u96c6\u6210<\/strong><\/td>\n      <td>aws-lambda, azure-functions, grpc-transcode, grpc-web, dubbo-proxy<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"\u516dadmin-api-\u4e0e-crud-\u4f53\u7cfbapisixadmin\">\u516d\u3001Admin API \u4e0e CRUD \u4f53\u7cfb\uff08<code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/<\/code>\uff09<\/h2>\n\n<h3 id=\"61-\u67b6\u6784\">6.1 \u67b6\u6784<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>HTTP \u8bf7\u6c42 \u2192 admin\/init.lua\uff08Token \u8ba4\u8bc1 + \u8def\u7531\u5206\u53d1\uff09\u2192 resource.lua\uff08\u901a\u7528 CRUD\uff09\u2192 etcd\n<\/code><\/pre><\/div><\/div>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/init.lua<\/code><\/strong> \u4e2d\u5b9a\u4e49\u4e86\u8d44\u6e90\u5230\u5904\u7406\u6a21\u5757\u7684\u6620\u5c04\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u8d44\u6e90<\/th>\n      <th>\u5904\u7406\u6a21\u5757<\/th>\n      <th>\u5bf9\u5e94\u7528\u9014<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>routes<\/td>\n      <td>admin\/routes.lua<\/td>\n      <td>\u8def\u7531\u7ba1\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>services<\/td>\n      <td>admin\/services.lua<\/td>\n      <td>\u670d\u52a1\u7ba1\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>upstreams<\/td>\n      <td>admin\/upstreams.lua<\/td>\n      <td>\u4e0a\u6e38\u7ba1\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>consumers<\/td>\n      <td>admin\/consumers.lua<\/td>\n      <td>\u6d88\u8d39\u8005\u7ba1\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>ssls<\/td>\n      <td>admin\/ssl.lua<\/td>\n      <td>SSL \u8bc1\u4e66\u7ba1\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td>global_rules<\/td>\n      <td>admin\/global_rules.lua<\/td>\n      <td>\u5168\u5c40\u89c4\u5219<\/td>\n    <\/tr>\n    <tr>\n      <td>plugin_configs<\/td>\n      <td>admin\/plugin_config.lua<\/td>\n      <td>\u63d2\u4ef6\u914d\u7f6e\u590d\u7528<\/td>\n    <\/tr>\n    <tr>\n      <td>stream_routes<\/td>\n      <td>admin\/stream_routes.lua<\/td>\n      <td>\u56db\u5c42\u8def\u7531<\/td>\n    <\/tr>\n    <tr>\n      <td>secrets<\/td>\n      <td>admin\/secrets.lua<\/td>\n      <td>\u5bc6\u94a5\u7ba1\u7406<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"62-\u901a\u7528-crud-\u6a21\u5f0fadminresourcelua\">6.2 \u901a\u7528 CRUD \u6a21\u5f0f\uff08<code class=\"language-plaintext highlighter-rouge\">admin\/resource.lua<\/code>\uff09<\/h3>\n\n<p>\u8fd9\u662f\u4e00\u4e2a\u7ecf\u5178\u7684<strong>\u6a21\u677f\u65b9\u6cd5\u6a21\u5f0f<\/strong>\u3002\u6bcf\u4e2a\u8d44\u6e90\u6a21\u5757\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">resource.new({...})<\/code> \u521b\u5efa\uff0c\u81ea\u52a8\u83b7\u5f97 GET\/PUT\/POST\/DELETE\/PATCH \u7684\u6807\u51c6\u5b9e\u73b0\u3002\u5177\u4f53\u6bcf\u4e2a\u8d44\u6e90\u7684\u5dee\u5f02\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">schema<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">validator<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">id_schema<\/code> \u7b49\u914d\u7f6e\u9879\u6ce8\u5165\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"\u4e03\u8def\u7531\u7cfb\u7edfapisixrouterlua--apisixhttprouter\">\u4e03\u3001\u8def\u7531\u7cfb\u7edf\uff08<code class=\"language-plaintext highlighter-rouge\">apisix\/router.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/http\/router\/<\/code>\uff09<\/h2>\n\n<h3 id=\"71-\u8def\u7531\u5b9e\u73b0\">7.1 \u8def\u7531\u5b9e\u73b0<\/h3>\n\n<p>APISIX \u652f\u6301 3 \u79cd HTTP \u8def\u7531\u5b9e\u73b0\uff08\u57fa\u4e8e <code class=\"language-plaintext highlighter-rouge\">lua-resty-radixtree<\/code>\uff09\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u5b9e\u73b0<\/th>\n      <th>\u5339\u914d\u4f9d\u636e<\/th>\n      <th>\u6587\u4ef6<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">radixtree_uri<\/code><\/td>\n      <td>\u4ec5 URI<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http\/router\/radixtree_uri.lua<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">radixtree_host_uri<\/code><\/td>\n      <td>Host + URI<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http\/router\/radixtree_host_uri.lua<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">radixtree_uri_with_parameter<\/code><\/td>\n      <td>URI + \u53c2\u6570<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http\/router\/radixtree_uri_with_parameter.lua<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>\u6b64\u5916\u8fd8\u6709\uff1a<\/p>\n<ul>\n  <li>SSL \u8def\u7531\uff1a<code class=\"language-plaintext highlighter-rouge\">ssl\/router\/radixtree_sni.lua<\/code>\uff08\u57fa\u4e8e SNI \u5339\u914d\uff09<\/li>\n  <li>Stream \u8def\u7531\uff1a\u57fa\u4e8e IP:Port \u5339\u914d<\/li>\n<\/ul>\n\n<h3 id=\"72-route--service--upstream-\u7684\u5c42\u7ea7\u5173\u7cfb\">7.2 Route \u2192 Service \u2192 Upstream \u7684\u5c42\u7ea7\u5173\u7cfb<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>Route \u2500\u2500\u53ef\u9009\u5f15\u7528\u2500\u2500\u2192 Service \u2500\u2500\u53ef\u9009\u5f15\u7528\u2500\u2500\u2192 Upstream\n  \u2502                    \u2502                      \u2502\n  \u2514\u2500\u2500 \u5b9a\u4e49 URI\/Host    \u2514\u2500\u2500 \u5171\u4eab\u516c\u5171\u914d\u7f6e      \u2514\u2500\u2500 \u540e\u7aef\u8282\u70b9\u6c60\n      \u5339\u914d\u89c4\u5219              (plugins\u7b49)            (\u8d1f\u8f7d\u5747\u8861\u914d\u7f6e)\n<\/code><\/pre><\/div><\/div>\n\n<p>\u914d\u7f6e\u5408\u5e76\u987a\u5e8f\uff1a<code class=\"language-plaintext highlighter-rouge\">plugin_config \u2192 consumer \u2192 consumer_group \u2192 route \u2192 service<\/code><\/p>\n\n<hr \/>\n\n<h2 id=\"\u516b\u8d1f\u8f7d\u5747\u8861apisixbalancerlua--apisixbalancer\">\u516b\u3001\u8d1f\u8f7d\u5747\u8861\uff08<code class=\"language-plaintext highlighter-rouge\">apisix\/balancer.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/balancer\/<\/code>\uff09<\/h2>\n\n<p><code class=\"language-plaintext highlighter-rouge\">balancer.lua<\/code> \u662f\u8d1f\u8f7d\u5747\u8861\u7684\u8c03\u5ea6\u4e2d\u5fc3\uff0c\u8d1f\u8d23\u5728\u8bf7\u6c42\u5904\u7406\u65f6\u521b\u5efa balancer \u5bf9\u8c61\u5e76\u9009\u62e9\u5408\u9002\u7684\u540e\u7aef\u8282\u70b9\u3002<\/p>\n\n<p>\u652f\u6301\u7684\u7b97\u6cd5\uff08<code class=\"language-plaintext highlighter-rouge\">apisix\/balancer\/<\/code>\uff09\uff1a<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">roundrobin.lua<\/code> \u2014 \u52a0\u6743\u8f6e\u8be2<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">chash.lua<\/code> \u2014 \u4e00\u81f4\u6027\u54c8\u5e0c<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ewma.lua<\/code> \u2014 \u6307\u6570\u52a0\u6743\u79fb\u52a8\u5e73\u5747\uff08\u6700\u5c0f\u5ef6\u8fdf\u7b97\u6cd5\uff09<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">least_conn.lua<\/code> \u2014 \u6700\u5c0f\u8fde\u63a5\u6570<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">priority.lua<\/code> \u2014 \u4f18\u5148\u7ea7<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"\u4e5d\u914d\u7f6e\u7ba1\u7406\u4e0e\u70ed\u66f4\u65b0\">\u4e5d\u3001\u914d\u7f6e\u7ba1\u7406\u4e0e\u70ed\u66f4\u65b0<\/h2>\n\n<h3 id=\"91-\u914d\u7f6e\u63d0\u4f9b\u8005\u62bd\u8c61\">9.1 \u914d\u7f6e\u63d0\u4f9b\u8005\u62bd\u8c61<\/h3>\n\n<p>APISIX \u652f\u6301\u4e09\u79cd\u914d\u7f6e\u6765\u6e90\uff0c\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">config.yaml<\/code> \u4e2d\u7684 <code class=\"language-plaintext highlighter-rouge\">config_provider<\/code> \u5207\u6362\uff1a<\/p>\n\n<ul>\n  <li><strong>etcd<\/strong>\uff08<code class=\"language-plaintext highlighter-rouge\">core\/config_etcd.lua<\/code>\uff09\uff1a\u9ed8\u8ba4\u6a21\u5f0f\uff0c\u901a\u8fc7 etcd watch \u5b9e\u73b0\u5b9e\u65f6\u70ed\u66f4\u65b0<\/li>\n  <li><strong>yaml<\/strong>\uff08<code class=\"language-plaintext highlighter-rouge\">core\/config_yaml.lua<\/code>\uff09\uff1a\u72ec\u7acb\u6a21\u5f0f\uff0c\u4ece\u672c\u5730 YAML\/JSON \u6587\u4ef6\u8bfb\u53d6<\/li>\n  <li><strong>xDS<\/strong>\uff08<code class=\"language-plaintext highlighter-rouge\">core\/config_xds.lua<\/code>\uff09\uff1a\u5bf9\u63a5 Envoy xDS \u63a7\u5236\u9762<\/li>\n<\/ul>\n\n<p>\u4e09\u79cd\u63d0\u4f9b\u8005\u5b9e\u73b0\u540c\u4e00\u63a5\u53e3\uff1a<\/p>\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"n\">init<\/span><span class=\"p\">()<\/span> <span class=\"err\">\u2192<\/span> <span class=\"n\">init_worker<\/span><span class=\"p\">()<\/span> <span class=\"err\">\u2192<\/span> <span class=\"n\">values<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span><span class=\"p\">)<\/span> <span class=\"err\">\u2192<\/span> <span class=\"n\">conf_version<\/span><span class=\"p\">()<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"92-etcd-\u70ed\u66f4\u65b0\u6d41\u7a0b\">9.2 etcd \u70ed\u66f4\u65b0\u6d41\u7a0b<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>etcd PUT \/routes\/xxx \u2192 core\/config_etcd.lua watch \u56de\u8c03\n  \u2192 \u8def\u7531\u8868\u91cd\u5efa \u2192 \u65b0\u8bf7\u6c42\u4f7f\u7528\u65b0\u8def\u7531\uff08\u65e0\u9700 reload Nginx\uff09\n<\/code><\/pre><\/div><\/div>\n\n<p>\u540c\u7406\u9002\u7528\u4e8e Service\u3001Upstream\u3001Plugin\u3001SSL \u8bc1\u4e66\u7b49\u6240\u6709\u914d\u7f6e\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"\u5341\u6d4b\u8bd5\u4f53\u7cfbt\">\u5341\u3001\u6d4b\u8bd5\u4f53\u7cfb\uff08<code class=\"language-plaintext highlighter-rouge\">t\/<\/code>\uff09<\/h2>\n\n<p>APISIX \u4f7f\u7528 <strong>Perl \u7248 Test::Nginx::Socket::Lua<\/strong> \u4f5c\u4e3a\u6d4b\u8bd5\u6846\u67b6\u3002<\/p>\n\n<p>\u542f\u52a8\u6587\u4ef6\uff1a<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/APISIX.pm<\/code> \u2014 \u6d4b\u8bd5\u57fa\u7840\u914d\u7f6e\u548c\u8f85\u52a9\u51fd\u6570<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/lib\/<\/code> \u2014 \u6d4b\u8bd5\u8f85\u52a9\u5e93<\/li>\n<\/ul>\n\n<p>\u76ee\u5f55\u7ed3\u6784\uff1a<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/admin\/<\/code> \u2014 Admin API CRUD \u6d4b\u8bd5\uff0860+ \u6587\u4ef6\uff09<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/plugin\/<\/code> \u2014 \u63d2\u4ef6\u6d4b\u8bd5\uff08250+ \u6587\u4ef6\uff09<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/core\/<\/code> \u2014 \u6838\u5fc3\u6a21\u5757\u6d4b\u8bd5\uff0835+ \u6587\u4ef6\uff09<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/cli\/<\/code> \u2014 CLI \u6d4b\u8bd5<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/stream-node\/<\/code>, <code class=\"language-plaintext highlighter-rouge\">t\/stream-plugin\/<\/code> \u2014 \u56db\u5c42\u4ee3\u7406\u6d4b\u8bd5<\/li>\n<\/ul>\n\n<p>\u6d4b\u8bd5\u7528\u4f8b\u7ed3\u6784\u793a\u4f8b\uff1a<\/p>\n<div class=\"language-perl highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">use<\/span> <span class=\"nn\">t::<\/span><span class=\"nv\">APISIX<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">use<\/span> <span class=\"nn\">Test::Nginx::Socket::<\/span><span class=\"nv\">Lua<\/span><span class=\"p\">;<\/span>\n\n<span class=\"nv\">run_tests<\/span><span class=\"p\">();<\/span>\n\n<span class=\"cp\">__DATA__\n=== TEST 1: \u6d4b\u8bd5\u63cf\u8ff0\n--- config\n    location \/t {\n        content_by_lua_block {\n            -- \u6d4b\u8bd5\u903b\u8f91\n        }\n    }\n--- response_body\n\u671f\u671b\u7684\u8f93\u51fa\n--- no_error_log\n[error]\n<\/span><\/code><\/pre><\/div><\/div>\n\n<hr \/>\n\n<h2 id=\"\u5341\u4e00\u5efa\u8bae\u7684\u9605\u8bfb\u987a\u5e8f\">\u5341\u4e00\u3001\u5efa\u8bae\u7684\u9605\u8bfb\u987a\u5e8f<\/h2>\n\n<p>\u6309\u7167\u4ee5\u4e0b\u987a\u5e8f\u9605\u8bfb\uff0c\u53ef\u4ee5\u9010\u6b65\u5efa\u7acb\u8d77\u5bf9\u6574\u4e2a\u7cfb\u7edf\u7684\u5b8c\u6574\u8ba4\u77e5\uff1a<\/p>\n\n<h3 id=\"\u7b2c\u4e00\u9636\u6bb5\u9aa8\u67b6\u5efa\u7acb\u5168\u5c40\u89c2\">\u7b2c\u4e00\u9636\u6bb5\uff1a\u9aa8\u67b6\uff08\u5efa\u7acb\u5168\u5c40\u89c2\uff09<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">bin\/apisix<\/code><\/strong> \u2014 \u542f\u52a8\u811a\u672c\uff0c\u4e86\u89e3\u5982\u4f55\u62c9\u8d77 OpenResty<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/apisix.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/ops.lua<\/code><\/strong> \u2014 CLI \u547d\u4ee4\u5904\u7406\uff0c\u4e86\u89e3 init\/start \u7b49\u547d\u4ee4\u7684\u5b9e\u73b0<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/init.lua<\/code><\/strong> \u2014 \u4e3b\u5165\u53e3\u6587\u4ef6\uff0c\u91cd\u70b9\u5173\u6ce8 <code class=\"language-plaintext highlighter-rouge\">http_init_worker()<\/code> \u7684\u521d\u59cb\u5316\u987a\u5e8f\u548c <code class=\"language-plaintext highlighter-rouge\">http_access_phase()<\/code> \u7684\u8bf7\u6c42\u5904\u7406\u6d41\u7a0b<\/li>\n<\/ol>\n\n<h3 id=\"\u7b2c\u4e8c\u9636\u6bb5\u6838\u5fc3\u6a21\u5757\u7406\u89e3\u57fa\u7840\u8bbe\u65bd\">\u7b2c\u4e8c\u9636\u6bb5\uff1a\u6838\u5fc3\u6a21\u5757\uff08\u7406\u89e3\u57fa\u7840\u8bbe\u65bd\uff09<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/core.lua<\/code><\/strong> \u2014 \u6838\u5fc3\u6a21\u5757\u805a\u5408\u5165\u53e3\uff0c\u4e86\u89e3\u6709\u54ea\u4e9b\u6838\u5fc3\u80fd\u529b<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/core\/ctx.lua<\/code><\/strong> \u2014 \u8bf7\u6c42\u4e0a\u4e0b\u6587\uff0c\u7406\u89e3 <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> \u7684\u521b\u5efa\/\u91ca\u653e\u673a\u5236<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/core\/config_etcd.lua<\/code><\/strong> \u2014 etcd \u914d\u7f6e\u63d0\u4f9b\u8005\uff0c\u7406\u89e3\u914d\u7f6e\u5982\u4f55\u8bfb\u53d6\u548c\u70ed\u66f4\u65b0<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/core\/lrucache.lua<\/code><\/strong> \u2014 \u7f13\u5b58\u673a\u5236<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/core\/request.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/core\/response.lua<\/code><\/strong> \u2014 \u8bf7\u6c42\/\u54cd\u5e94\u64cd\u4f5c\u5c01\u88c5<\/li>\n<\/ol>\n\n<h3 id=\"\u7b2c\u4e09\u9636\u6bb5\u6838\u5fc3\u5f15\u64ce\u7406\u89e3\u5173\u952e\u94fe\u8def\">\u7b2c\u4e09\u9636\u6bb5\uff1a\u6838\u5fc3\u5f15\u64ce\uff08\u7406\u89e3\u5173\u952e\u94fe\u8def\uff09<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/router.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/http\/router\/radixtree_uri.lua<\/code><\/strong> \u2014 \u8def\u7531\u5339\u914d\u673a\u5236<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/plugin.lua<\/code><\/strong> \u2014 \u63d2\u4ef6\u5f15\u64ce\uff0c\u7406\u89e3\u63d2\u4ef6\u52a0\u8f7d\u3001\u8fc7\u6ee4\u3001\u6267\u884c\u7684\u751f\u547d\u5468\u671f<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/upstream.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/balancer.lua<\/code><\/strong> \u2014 \u4e0a\u6e38\u7ba1\u7406\u548c\u8d1f\u8f7d\u5747\u8861<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/http\/service.lua<\/code><\/strong> \u2014 Route \u2192 Service \u7684\u914d\u7f6e\u7ee7\u627f\u903b\u8f91<\/li>\n<\/ol>\n\n<h3 id=\"\u7b2c\u56db\u9636\u6bb5admin-api\u7406\u89e3\u63a7\u5236\u9762\">\u7b2c\u56db\u9636\u6bb5\uff1aAdmin API\uff08\u7406\u89e3\u63a7\u5236\u9762\uff09<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/init.lua<\/code><\/strong> \u2014 Admin API \u8def\u7531\u5206\u53d1<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/resource.lua<\/code><\/strong> \u2014 \u901a\u7528 CRUD \u57fa\u7c7b<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/routes.lua<\/code><\/strong> \u2014 \u4ee5 Route CRUD \u4e3a\u4f8b\uff0c\u7406\u89e3\u5177\u4f53\u8d44\u6e90\u7684\u5b9e\u73b0\u65b9\u5f0f<\/li>\n<\/ol>\n\n<h3 id=\"\u7b2c\u4e94\u9636\u6bb5\u6df1\u5165\u63d2\u4ef6\u5b9e\u8df5\u51fa\u771f\u77e5\">\u7b2c\u4e94\u9636\u6bb5\uff1a\u6df1\u5165\u63d2\u4ef6\uff08\u5b9e\u8df5\u51fa\u771f\u77e5\uff09<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/plugins\/example-plugin.lua<\/code><\/strong> \u2014 \u63d2\u4ef6\u5f00\u53d1\u6a21\u677f<\/li>\n  <li>\u9009\u62e9\u4e00\u4e2a\u4f60\u611f\u5174\u8da3\u7684\u7b80\u5355\u63d2\u4ef6\u6df1\u5165\u9605\u8bfb\uff08\u63a8\u8350\u4ece <code class=\"language-plaintext highlighter-rouge\">key-auth.lua<\/code> \u6216 <code class=\"language-plaintext highlighter-rouge\">limit-count.lua<\/code> \u5f00\u59cb\uff09<\/li>\n  <li>\u9605\u8bfb <strong><code class=\"language-plaintext highlighter-rouge\">apisix\/plugins\/ai-proxy.lua<\/code><\/strong> \u2014 \u4e86\u89e3\u590d\u6742\u63d2\u4ef6\u7684\u7ed3\u6784\u548c AI \u7f51\u5173\u80fd\u529b<\/li>\n<\/ol>\n\n<h3 id=\"\u7b2c\u516d\u9636\u6bb5\u6269\u5c55\u8bdd\u9898\">\u7b2c\u516d\u9636\u6bb5\uff1a\u6269\u5c55\u8bdd\u9898<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/stream\/<\/code><\/strong> \u2014 \u56db\u5c42\u4ee3\u7406\u5b50\u7cfb\u7edf<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/discovery\/<\/code><\/strong> \u2014 \u670d\u52a1\u53d1\u73b0\uff08consul\/nacos\/eureka \u7b49\uff09<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/secret\/<\/code><\/strong> \u2014 \u5bc6\u94a5\u7ba1\u7406<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">t\/<\/code><\/strong> \u2014 \u6d4b\u8bd5\u7f16\u5199\uff0c\u901a\u8fc7\u6d4b\u8bd5\u53cd\u5411\u7406\u89e3\u529f\u80fd<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"\u5341\u4e8c\u5173\u952e\u8bbe\u8ba1\u6a21\u5f0f\u603b\u7ed3\">\u5341\u4e8c\u3001\u5173\u952e\u8bbe\u8ba1\u6a21\u5f0f\u603b\u7ed3<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u6a21\u5f0f<\/th>\n      <th>\u4f53\u73b0\u4f4d\u7f6e<\/th>\n      <th>\u8bf4\u660e<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><strong>\u5916\u89c2\u6a21\u5f0f<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix\/core.lua<\/code><\/td>\n      <td>\u805a\u5408\u6240\u6709\u6838\u5fc3\u5b50\u6a21\u5757\uff0c\u7edf\u4e00\u8bbf\u95ee\u5165\u53e3<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u6a21\u677f\u65b9\u6cd5<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/resource.lua<\/code><\/td>\n      <td>\u901a\u7528 CRUD \u57fa\u7c7b\uff0c\u5b50\u6a21\u5757\u6ce8\u5165\u5dee\u5f02\u5316\u914d\u7f6e<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u7b56\u7565\u6a21\u5f0f<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix\/router.lua<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">apisix\/balancer.lua<\/code><\/td>\n      <td>\u53ef\u63d2\u62d4\u7684\u8def\u7531\/\u8d1f\u8f7d\u5747\u8861\u5b9e\u73b0<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u63d2\u4ef6\u751f\u547d\u5468\u671f<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix\/plugin.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/plugins\/*.lua<\/code><\/td>\n      <td>\u6309\u4f18\u5148\u7ea7\u6392\u5e8f\uff0c\u5206\u9636\u6bb5\u6267\u884c<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u89c2\u5bdf\u8005\u6a21\u5f0f<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix\/core\/config_etcd.lua<\/code> \u4e2d\u7684 etcd watch<\/td>\n      <td>\u914d\u7f6e\u53d8\u66f4\u81ea\u52a8\u89e6\u53d1\u70ed\u66f4\u65b0<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u5bf9\u8c61\u6c60\u6a21\u5f0f<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">tablepool<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/core\/ctx.lua<\/code><\/td>\n      <td>\u590d\u7528 <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> \u8868\uff0c\u51cf\u5c11 GC \u538b\u529b<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>\u63d0\u4f9b\u8005\u62bd\u8c61<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/config_etcd.lua<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">core\/config_yaml.lua<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">core\/config_xds.lua<\/code><\/td>\n      <td>\u7edf\u4e00\u7684\u914d\u7f6e\u63a5\u53e3\uff0c\u53ef\u5207\u6362\u540e\u7aef<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"\u5341\u4e09\u5f00\u53d1\u73af\u5883\u642d\u5efa\u901f\u67e5\">\u5341\u4e09\u3001\u5f00\u53d1\u73af\u5883\u642d\u5efa\uff08\u901f\u67e5\uff09<\/h2>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\"># \u5b89\u88c5\u4f9d\u8d56<\/span>\nmake deps\n\n<span class=\"c\"># \u542f\u52a8 APISIX<\/span>\nmake run\n\n<span class=\"c\"># \u505c\u6b62<\/span>\nmake stop\n\n<span class=\"c\"># \u8fd0\u884c\u6d4b\u8bd5<\/span>\nmake <span class=\"nb\">test<\/span>\n\n<span class=\"c\"># \u8fd0\u884c\u7279\u5b9a\u6d4b\u8bd5<\/span>\nprove <span class=\"nt\">-I<\/span> t\/ t\/plugin\/key-auth.t\n\n<span class=\"c\"># \u4ee3\u7801\u98ce\u683c\u68c0\u67e5<\/span>\nmake lint\n<\/code><\/pre><\/div><\/div>\n\n<hr \/>\n\n<blockquote>\n  <p>\u5efa\u8bae\u914d\u5408 <a href=\"https:\/\/apisix.apache.org\/docs\/apisix\/getting-started\/\">Apache APISIX \u5b98\u65b9\u6587\u6863<\/a> \u548c\u6e90\u7801\u4e2d\u7684\u6ce8\u91ca\u4e00\u8d77\u9605\u8bfb\u3002\u9047\u5230\u95ee\u9898\u65f6\uff0c<code class=\"language-plaintext highlighter-rouge\">t\/<\/code> \u76ee\u5f55\u4e0b\u7684\u6d4b\u8bd5\u7528\u4f8b\u662f\u7406\u89e3\u5404\u9879\u529f\u80fd\u7684\u6700\u4f73\u53c2\u8003\u8d44\u6599\u3002<\/p>\n<\/blockquote>\n","category":{"@attributes":{"term":"APISIX"}}},{"title":"Apache APISIX Source Code Reading Guide","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/en\/2026-07-26\/apisix-source-code-guide.html"}},"updated":"2026-07-26T23:00:00+08:00","id":"https:\/\/wy471x.github.io\/en\/2026-07-26\/apisix-source-code-guide.html","content":"<h1 id=\"apache-apisix-source-code-reading-guide\">Apache APISIX Source Code Reading Guide<\/h1>\n\n<h2 id=\"preface\">Preface<\/h2>\n\n<p>Apache APISIX is a dynamic, high-performance API gateway built on OpenResty (Nginx + LuaJIT). This guide helps developers quickly build a holistic understanding of the APISIX source code structure and dive into key modules in a logical order.<\/p>\n\n<p><strong>Recommended prerequisites:<\/strong><\/p>\n<ul>\n  <li>Familiarity with Nginx\/OpenResty request processing phases (rewrite \u2192 access \u2192 content \u2192 header_filter \u2192 body_filter \u2192 log)<\/li>\n  <li>Basic knowledge of Lua syntax and module system<\/li>\n  <li>Understanding of etcd basics (etcd is APISIX\u2019s default configuration center)<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"1-top-level-project-structure\">1. Top-Level Project Structure<\/h2>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>apisix\/\n\u251c\u2500\u2500 apisix\/                 # Lua core source (the heart of the project)\n\u2502   \u251c\u2500\u2500 core\/               # Foundation libraries (logging, JSON, config, request\/response, cache, etc.)\n\u2502   \u251c\u2500\u2500 admin\/              # Admin API implementation (CRUD operations)\n\u2502   \u251c\u2500\u2500 plugins\/            # HTTP plugins (90+ plugins)\n\u2502   \u251c\u2500\u2500 http\/               # HTTP submodules (route matcher, etc.)\n\u2502   \u251c\u2500\u2500 stream\/             # Layer 4 proxy (TCP\/UDP)\n\u2502   \u251c\u2500\u2500 control\/            # Control API (internal management interface)\n\u2502   \u251c\u2500\u2500 discovery\/          # Service discovery (Consul, Nacos, Eureka, etc.)\n\u2502   \u251c\u2500\u2500 balancer\/           # Load balancing algorithms\n\u2502   \u251c\u2500\u2500 secret\/             # Secret management backends\n\u2502   \u251c\u2500\u2500 utils\/              # Utility modules\n\u2502   \u251c\u2500\u2500 cli\/                # CLI tools (start\/stop, config generation)\n\u2502   \u2514\u2500\u2500 init.lua            # Main entry point, defines all OpenResty phase hooks\n\u251c\u2500\u2500 bin\/apisix              # Shell startup script\n\u251c\u2500\u2500 conf\/                   # Runtime configuration\n\u2502   \u251c\u2500\u2500 config.yaml         # User configuration\n\u2502   \u251c\u2500\u2500 config-default.yaml # Default configuration\n\u2502   \u2514\u2500\u2500 ...\n\u251c\u2500\u2500 t\/                      # Perl test suite (Test::Nginx)\n\u2502   \u251c\u2500\u2500 admin\/              # Admin API tests\n\u2502   \u251c\u2500\u2500 plugin\/             # Plugin tests (250+ files)\n\u2502   \u251c\u2500\u2500 core\/               # Core module tests\n\u2502   \u251c\u2500\u2500 lib\/                # Test helper libraries\n\u2502   \u2514\u2500\u2500 ...\n\u251c\u2500\u2500 docs\/                   # Documentation (en + zh)\n\u2514\u2500\u2500 Makefile                # Build\/deploy\/test commands\n<\/code><\/pre><\/div><\/div>\n\n<hr \/>\n\n<h2 id=\"2-startup-flow-recommended-starting-point\">2. Startup Flow (Recommended Starting Point)<\/h2>\n\n<p>This is the entry point for understanding the entire system. Following the startup chain from end to end builds a holistic view of the system skeleton.<\/p>\n\n<h3 id=\"21-shell-entry--lua-cli\">2.1 Shell Entry \u2192 Lua CLI<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>bin\/apisix  \u2500\u2500\u2192  apisix\/cli\/apisix.lua  \u2500\u2500\u2192  apisix\/cli\/ops.lua\n<\/code><\/pre><\/div><\/div>\n\n<ul>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">bin\/apisix<\/code><\/strong> (Shell script, ~50 lines): Locates OpenResty and <code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/apisix.lua<\/code>, then executes <code class=\"language-plaintext highlighter-rouge\">luajit &lt;apisix.lua&gt; &lt;command args&gt;<\/code><\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/apisix.lua<\/code><\/strong>: Sets up Lua module search paths, then delegates to <code class=\"language-plaintext highlighter-rouge\">apisix.cli.ops<\/code><\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/ops.lua<\/code><\/strong>: Implements <code class=\"language-plaintext highlighter-rouge\">init<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">start<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">stop<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">restart<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">reload<\/code> commands<\/li>\n<\/ul>\n\n<h3 id=\"22-nginxconf-generation\">2.2 nginx.conf Generation<\/h3>\n\n<p>When <code class=\"language-plaintext highlighter-rouge\">apisix start<\/code> is executed, <code class=\"language-plaintext highlighter-rouge\">ops.lua<\/code>\u2019s <code class=\"language-plaintext highlighter-rouge\">init()<\/code> function:<\/p>\n<ol>\n  <li>Reads YAML config \u2192 validates schema via <code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/schema.lua<\/code><\/li>\n  <li>Generates <code class=\"language-plaintext highlighter-rouge\">conf\/nginx.conf<\/code> via <code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/ngx_tpl.lua<\/code> (nginx config template engine)<\/li>\n<\/ol>\n\n<h3 id=\"23-worker-initialization\">2.3 Worker Initialization<\/h3>\n\n<p>The generated <code class=\"language-plaintext highlighter-rouge\">nginx.conf<\/code> specifies the Lua entry point as <code class=\"language-plaintext highlighter-rouge\">apisix\/init.lua<\/code>, which defines the complete request processing lifecycle:<\/p>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">-- Key functions defined in init.lua<\/span>\n<span class=\"n\">http_init<\/span><span class=\"p\">(<\/span><span class=\"n\">args<\/span><span class=\"p\">)<\/span>          <span class=\"c1\">-- Global initialization (runs once)<\/span>\n<span class=\"n\">http_init_worker<\/span><span class=\"p\">()<\/span>       <span class=\"c1\">-- Per-worker process initialization<\/span>\n<span class=\"n\">http_access_phase<\/span><span class=\"p\">()<\/span>      <span class=\"c1\">-- Request access phase (core of route matching and plugin execution)<\/span>\n<span class=\"n\">http_header_filter_phase<\/span><span class=\"p\">()<\/span>\n<span class=\"n\">http_body_filter_phase<\/span><span class=\"p\">()<\/span>\n<span class=\"n\">http_log_phase<\/span><span class=\"p\">()<\/span>         <span class=\"c1\">-- Logging\/reporting phase<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Initialization order in <code class=\"language-plaintext highlighter-rouge\">http_init_worker()<\/code> (worth noting):<\/strong><\/p>\n<ol>\n  <li>Random seed, LRU cache, DNS resolver<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">discovery.init_worker()<\/code> \u2014 Service discovery<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">balancer.init_worker()<\/code> \u2014 Load balancer<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">admin.init_worker()<\/code> \u2014 Admin API<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">plugin.load()<\/code> \u2014 Load all plugins (sorted by priority)<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">router.http_init_worker()<\/code> \u2014 HTTP routing table initialization<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">require(\"apisix.http.service\").init_worker()<\/code> \u2014 Service object initialization<\/li>\n  <li>Watch for config changes (etcd watch) for hot reload<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"3-core-module-system-apisixcore\">3. Core Module System (<code class=\"language-plaintext highlighter-rouge\">apisix\/core\/<\/code>)<\/h2>\n\n<p><code class=\"language-plaintext highlighter-rouge\">apisix\/core.lua<\/code> is a <strong>Facade module<\/strong> that aggregates all core submodules into a single <code class=\"language-plaintext highlighter-rouge\">core<\/code> table:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Module<\/th>\n      <th>File<\/th>\n      <th>Responsibility<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.log<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/log.lua<\/code><\/td>\n      <td>Log output (warn\/error\/info\/debug)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.json<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/json.lua<\/code><\/td>\n      <td>JSON encode\/decode with lazy encoding optimization<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.table<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/table.lua<\/code><\/td>\n      <td>Table utility functions (deepcopy, merge, etc.)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.request<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/request.lua<\/code><\/td>\n      <td>Request header\/body read\/write<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.response<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/response.lua<\/code><\/td>\n      <td>Response header setting, exit, CORS<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.schema<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/schema.lua<\/code><\/td>\n      <td>JSON Schema validator wrapper<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.config<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/config_etcd.lua<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">core\/config_yaml.lua<\/code><\/td>\n      <td>Config providers (etcd \/ local YAML \/ xDS)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.lrucache<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/lrucache.lua<\/code><\/td>\n      <td>LRU cache with TTL support<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.ctx<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/ctx.lua<\/code><\/td>\n      <td>Request context management (tablepool reuse)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.etcd<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/etcd.lua<\/code><\/td>\n      <td>etcd client wrapper<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.string<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/string.lua<\/code><\/td>\n      <td>String utility functions<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.id<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/id.lua<\/code><\/td>\n      <td>ID generator (snowflake ID support)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.dns.client<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/dns\/<\/code><\/td>\n      <td>DNS client<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.pubsub<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/pubsub.lua<\/code><\/td>\n      <td>Publish\/subscribe abstraction<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">core.event<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/event.lua<\/code><\/td>\n      <td>Inter-worker event system<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p><strong>Key design pattern:<\/strong> All modules access a unified <code class=\"language-plaintext highlighter-rouge\">core<\/code> reference via <code class=\"language-plaintext highlighter-rouge\">require(\"apisix.core\")<\/code>, avoiding scattered dependencies.<\/p>\n\n<hr \/>\n\n<h2 id=\"4-request-processing-flow-the-core-pipeline\">4. Request Processing Flow (The Core Pipeline)<\/h2>\n\n<p>When a user request reaches APISIX, it goes through the following phases (all defined in <code class=\"language-plaintext highlighter-rouge\">apisix\/init.lua<\/code>):<\/p>\n\n<h3 id=\"phase-1-http_access_phase--access-and-route-matching\">Phase 1: <code class=\"language-plaintext highlighter-rouge\">http_access_phase()<\/code> \u2014 Access and Route Matching<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>1. HTTPS client certificate verification\n2. Debug dynamic debugging check\n3. URI normalization (trailing slash handling, servlet path processing)\n4. X-Forwarded-* header processing\n5. Router matching \u2192 find the matching Route\n6. No matching Route \u2192 execute Global Rules \u2192 return 404\n7. Config merging:\n   plugin_config_id \u2192 service_id \u2192 consumer \u2192 consumer_group\n8. Execute Global Rules\n9. If script exists \u2192 execute script\n10. Otherwise \u2192 filter plugins \u2192 execute rewrite phase plugins \u2192 access phase plugins in order\n11. handle_upstream():\n    - Get upstream config via upstream_id or inline upstream\n    - Load balancer selects a backend node\n    - Execute before_proxy phase\n    - Proxy request to upstream\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"phases-23-headerbody-filtering\">Phases 2\/3: Header\/Body Filtering<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>header_filter \u2192 set Server header, upstream status header \u2192 execute header_filter plugins\nbody_filter   \u2192 execute body_filter plugins &amp; delayed_body_filter plugins\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"phase-4-http_log_phase--log-reporting\">Phase 4: <code class=\"language-plaintext highlighter-rouge\">http_log_phase()<\/code> \u2014 Log Reporting<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>Complete tracing span \u2192 execute log phase plugins \u2192 passive health check \u2192 release api_ctx\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"key-data-structure-api_ctx\">Key Data Structure: <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code><\/h3>\n\n<p>Each request allocates an <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> table from tablepool, carrying:<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">matched_route<\/code> \u2014 The matched route<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">upstream_conf<\/code> \u2014 Upstream configuration<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">plugins<\/code> \u2014 List of plugins to execute<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">consumer<\/code> \u2014 Consumer information<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">var<\/code> \u2014 Nginx variable snapshot<\/li>\n<\/ul>\n\n<p>This table spans all phases and is released back to tablepool at the end of the log phase.<\/p>\n\n<hr \/>\n\n<h2 id=\"5-plugin-system-apisixpluginlua--apisixplugins\">5. Plugin System (<code class=\"language-plaintext highlighter-rouge\">apisix\/plugin.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/plugins\/<\/code>)<\/h2>\n\n<h3 id=\"51-plugin-loading-mechanism\">5.1 Plugin Loading Mechanism<\/h3>\n\n<p><code class=\"language-plaintext highlighter-rouge\">apisix\/plugin.lua<\/code> is the plugin engine, with core functions:<\/p>\n\n<ul>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">load()<\/code><\/strong>: Read configured plugin list \u2192 call <code class=\"language-plaintext highlighter-rouge\">load_plugin()<\/code> for each \u2192 sort by priority descending<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">load_plugin(name)<\/code><\/strong>: Require plugin module \u2192 validate priority\/version\/schema \u2192 call <code class=\"language-plaintext highlighter-rouge\">plugin.init()<\/code> \u2192 inject <code class=\"language-plaintext highlighter-rouge\">_meta<\/code> field<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">run_plugin(phase, ...)<\/code><\/strong>: Execute plugin chain by phase<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">filter_plugins(user_plugins, conf_version)<\/code><\/strong>: Filter plugins to execute based on Route config<\/li>\n<\/ul>\n\n<h3 id=\"52-plugin-interface-specification\">5.2 Plugin Interface Specification<\/h3>\n\n<p>Each plugin module exports the following fields (reference: <code class=\"language-plaintext highlighter-rouge\">apisix\/plugins\/example-plugin.lua<\/code>):<\/p>\n\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"kd\">local<\/span> <span class=\"n\">plugin_name<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">\"example-plugin\"<\/span>\n\n<span class=\"kd\">local<\/span> <span class=\"n\">_M<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">version<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span><span class=\"p\">.<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span>          <span class=\"c1\">-- Plugin version (required)<\/span>\n    <span class=\"n\">priority<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span>            <span class=\"c1\">-- Execution priority (required, higher runs first)<\/span>\n    <span class=\"n\">name<\/span> <span class=\"o\">=<\/span> <span class=\"n\">plugin_name<\/span><span class=\"p\">,<\/span>      <span class=\"c1\">-- Plugin name<\/span>\n    <span class=\"n\">schema<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{},<\/span>             <span class=\"c1\">-- JSON Schema definition (required)<\/span>\n    <span class=\"nb\">type<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'auth'<\/span><span class=\"p\">,<\/span>           <span class=\"c1\">-- Plugin type (optional, auth type has special handling)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p>Lifecycle hooks (all optional):<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">init()<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">destroy()<\/code> \u2014 Called on load\/unload<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">check_schema(conf, schema_type)<\/code> \u2014 Custom schema validation<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">rewrite(conf, ctx)<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">access(conf, ctx)<\/code> \u2014 Request processing<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">header_filter(conf, ctx)<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">body_filter(conf, ctx)<\/code> \u2014 Response processing<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">delayed_body_filter(conf, ctx)<\/code> \u2014 Delayed body filtering<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">log(conf, ctx)<\/code> \u2014 Log reporting<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">api()<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">control_api()<\/code> \u2014 Register additional Admin\/Control API endpoints<\/li>\n<\/ul>\n\n<h3 id=\"53-plugin-priority-system\">5.3 Plugin Priority System<\/h3>\n\n<p>Plugins execute in descending <code class=\"language-plaintext highlighter-rouge\">priority<\/code> order. Reference priorities for key plugins:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Priority Range<\/th>\n      <th>Typical Plugins<\/th>\n      <th>Description<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>4000+<\/td>\n      <td>ip-restriction, referer-restriction<\/td>\n      <td>Security blocking<\/td>\n    <\/tr>\n    <tr>\n      <td>3000-3999<\/td>\n      <td>cors, csrf, fault-injection<\/td>\n      <td>Security\/testing<\/td>\n    <\/tr>\n    <tr>\n      <td>2500-2999<\/td>\n      <td>key-auth, jwt-auth, basic-auth<\/td>\n      <td>Authentication<\/td>\n    <\/tr>\n    <tr>\n      <td>1000-1999<\/td>\n      <td>limit-count, limit-conn, limit-req<\/td>\n      <td>Rate limiting<\/td>\n    <\/tr>\n    <tr>\n      <td>500-999<\/td>\n      <td>proxy-rewrite, response-rewrite<\/td>\n      <td>Rewriting<\/td>\n    <\/tr>\n    <tr>\n      <td>1-499<\/td>\n      <td>Logging plugins, prometheus<\/td>\n      <td>Observability<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"54-plugin-category-overview\">5.4 Plugin Category Overview<\/h3>\n\n<table>\n  <thead>\n    <tr>\n      <th>Category<\/th>\n      <th>Representative Plugins<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><strong>Authentication<\/strong><\/td>\n      <td>key-auth, jwt-auth, basic-auth, hmac-auth, openid-connect, forward-auth<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Security<\/strong><\/td>\n      <td>ip-restriction, ua-restriction, cors, csrf, uri-blocker, api-breaker<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Rate Limiting<\/strong><\/td>\n      <td>limit-count, limit-conn, limit-req, traffic-split<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Rewrite<\/strong><\/td>\n      <td>proxy-rewrite, redirect, response-rewrite, proxy-mirror<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Serverless<\/strong><\/td>\n      <td>serverless-pre-function, serverless-post-function<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>AI<\/strong><\/td>\n      <td>ai-proxy, ai-prompt-decorator, ai-prompt-guard, ai-rag, ai-rate-limiting<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Logging<\/strong><\/td>\n      <td>kafka-logger, http-logger, syslog, elasticsearch-logger, loki-logger, etc.<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Observability<\/strong><\/td>\n      <td>prometheus, zipkin, skywalking, opentelemetry, datadog<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Integration<\/strong><\/td>\n      <td>aws-lambda, azure-functions, grpc-transcode, grpc-web, dubbo-proxy<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"6-admin-api-and-crud-system-apisixadmin\">6. Admin API and CRUD System (<code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/<\/code>)<\/h2>\n\n<h3 id=\"61-architecture\">6.1 Architecture<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>HTTP Request \u2192 admin\/init.lua (Token auth + route dispatch) \u2192 resource.lua (generic CRUD) \u2192 etcd\n<\/code><\/pre><\/div><\/div>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/init.lua<\/code><\/strong> defines the mapping from resources to handler modules:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Resource<\/th>\n      <th>Handler Module<\/th>\n      <th>Purpose<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>routes<\/td>\n      <td>admin\/routes.lua<\/td>\n      <td>Route management<\/td>\n    <\/tr>\n    <tr>\n      <td>services<\/td>\n      <td>admin\/services.lua<\/td>\n      <td>Service management<\/td>\n    <\/tr>\n    <tr>\n      <td>upstreams<\/td>\n      <td>admin\/upstreams.lua<\/td>\n      <td>Upstream management<\/td>\n    <\/tr>\n    <tr>\n      <td>consumers<\/td>\n      <td>admin\/consumers.lua<\/td>\n      <td>Consumer management<\/td>\n    <\/tr>\n    <tr>\n      <td>ssls<\/td>\n      <td>admin\/ssl.lua<\/td>\n      <td>SSL certificate management<\/td>\n    <\/tr>\n    <tr>\n      <td>global_rules<\/td>\n      <td>admin\/global_rules.lua<\/td>\n      <td>Global rules<\/td>\n    <\/tr>\n    <tr>\n      <td>plugin_configs<\/td>\n      <td>admin\/plugin_config.lua<\/td>\n      <td>Plugin config reuse<\/td>\n    <\/tr>\n    <tr>\n      <td>stream_routes<\/td>\n      <td>admin\/stream_routes.lua<\/td>\n      <td>Layer 4 routes<\/td>\n    <\/tr>\n    <tr>\n      <td>secrets<\/td>\n      <td>admin\/secrets.lua<\/td>\n      <td>Secret management<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"62-generic-crud-pattern-adminresourcelua\">6.2 Generic CRUD Pattern (<code class=\"language-plaintext highlighter-rouge\">admin\/resource.lua<\/code>)<\/h3>\n\n<p>This is a classic <strong>Template Method pattern<\/strong>. Each resource module is created via <code class=\"language-plaintext highlighter-rouge\">resource.new({...})<\/code> and automatically gets standard GET\/PUT\/POST\/DELETE\/PATCH implementations. Differences between resources are injected through <code class=\"language-plaintext highlighter-rouge\">schema<\/code>, <code class=\"language-plaintext highlighter-rouge\">validator<\/code>, <code class=\"language-plaintext highlighter-rouge\">id_schema<\/code> and other config options.<\/p>\n\n<hr \/>\n\n<h2 id=\"7-routing-system-apisixrouterlua--apisixhttprouter\">7. Routing System (<code class=\"language-plaintext highlighter-rouge\">apisix\/router.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/http\/router\/<\/code>)<\/h2>\n\n<h3 id=\"71-router-implementations\">7.1 Router Implementations<\/h3>\n\n<p>APISIX supports 3 HTTP router implementations (based on <code class=\"language-plaintext highlighter-rouge\">lua-resty-radixtree<\/code>):<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Implementation<\/th>\n      <th>Match Criteria<\/th>\n      <th>File<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">radixtree_uri<\/code><\/td>\n      <td>URI only<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http\/router\/radixtree_uri.lua<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">radixtree_host_uri<\/code><\/td>\n      <td>Host + URI<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http\/router\/radixtree_host_uri.lua<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">radixtree_uri_with_parameter<\/code><\/td>\n      <td>URI + Parameters<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">http\/router\/radixtree_uri_with_parameter.lua<\/code><\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>Additionally:<\/p>\n<ul>\n  <li>SSL routing: <code class=\"language-plaintext highlighter-rouge\">ssl\/router\/radixtree_sni.lua<\/code> (SNI-based matching)<\/li>\n  <li>Stream routing: IP:Port-based matching<\/li>\n<\/ul>\n\n<h3 id=\"72-route--service--upstream-hierarchy\">7.2 Route \u2192 Service \u2192 Upstream Hierarchy<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>Route \u2500\u2500optional ref\u2500\u2500\u2192 Service \u2500\u2500optional ref\u2500\u2500\u2192 Upstream\n  \u2502                        \u2502                        \u2502\n  \u2514\u2500\u2500 Defines URI\/Host     \u2514\u2500\u2500 Shared common        \u2514\u2500\u2500 Backend node pool\n      matching rules           config (plugins, etc.)   (load balancing config)\n<\/code><\/pre><\/div><\/div>\n\n<p>Config merge order: <code class=\"language-plaintext highlighter-rouge\">plugin_config \u2192 consumer \u2192 consumer_group \u2192 route \u2192 service<\/code><\/p>\n\n<hr \/>\n\n<h2 id=\"8-load-balancing-apisixbalancerlua--apisixbalancer\">8. Load Balancing (<code class=\"language-plaintext highlighter-rouge\">apisix\/balancer.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/balancer\/<\/code>)<\/h2>\n\n<p><code class=\"language-plaintext highlighter-rouge\">balancer.lua<\/code> is the load balancing dispatch center, responsible for creating balancer objects and selecting appropriate backend nodes during request processing.<\/p>\n\n<p>Supported algorithms (<code class=\"language-plaintext highlighter-rouge\">apisix\/balancer\/<\/code>):<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">roundrobin.lua<\/code> \u2014 Weighted round-robin<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">chash.lua<\/code> \u2014 Consistent hashing<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ewma.lua<\/code> \u2014 Exponentially weighted moving average (least latency)<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">least_conn.lua<\/code> \u2014 Least connections<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">priority.lua<\/code> \u2014 Priority-based<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"9-config-management-and-hot-reload\">9. Config Management and Hot Reload<\/h2>\n\n<h3 id=\"91-config-provider-abstraction\">9.1 Config Provider Abstraction<\/h3>\n\n<p>APISIX supports three config sources, switchable via <code class=\"language-plaintext highlighter-rouge\">config_provider<\/code> in <code class=\"language-plaintext highlighter-rouge\">config.yaml<\/code>:<\/p>\n\n<ul>\n  <li><strong>etcd<\/strong> (<code class=\"language-plaintext highlighter-rouge\">core\/config_etcd.lua<\/code>): Default mode, real-time hot reload via etcd watch<\/li>\n  <li><strong>yaml<\/strong> (<code class=\"language-plaintext highlighter-rouge\">core\/config_yaml.lua<\/code>): Standalone mode, reads from local YAML\/JSON files<\/li>\n  <li><strong>xDS<\/strong> (<code class=\"language-plaintext highlighter-rouge\">core\/config_xds.lua<\/code>): Integrates with Envoy xDS control plane<\/li>\n<\/ul>\n\n<p>All three providers implement the same interface:<\/p>\n<div class=\"language-lua highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"n\">init<\/span><span class=\"p\">()<\/span> <span class=\"err\">\u2192<\/span> <span class=\"n\">init_worker<\/span><span class=\"p\">()<\/span> <span class=\"err\">\u2192<\/span> <span class=\"n\">values<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span><span class=\"p\">)<\/span> <span class=\"err\">\u2192<\/span> <span class=\"n\">conf_version<\/span><span class=\"p\">()<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"92-etcd-hot-reload-flow\">9.2 etcd Hot Reload Flow<\/h3>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>etcd PUT \/routes\/xxx \u2192 core\/config_etcd.lua watch callback\n  \u2192 Route table rebuild \u2192 New requests use new routes (no Nginx reload needed)\n<\/code><\/pre><\/div><\/div>\n\n<p>The same applies to Service, Upstream, Plugin, SSL certificates, and all other config.<\/p>\n\n<hr \/>\n\n<h2 id=\"10-testing-system-t\">10. Testing System (<code class=\"language-plaintext highlighter-rouge\">t\/<\/code>)<\/h2>\n\n<p>APISIX uses the <strong>Perl Test::Nginx::Socket::Lua<\/strong> testing framework.<\/p>\n\n<p>Bootstrap files:<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/APISIX.pm<\/code> \u2014 Test base config and helper functions<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/lib\/<\/code> \u2014 Test helper libraries<\/li>\n<\/ul>\n\n<p>Directory structure:<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/admin\/<\/code> \u2014 Admin API CRUD tests (60+ files)<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/plugin\/<\/code> \u2014 Plugin tests (250+ files)<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/core\/<\/code> \u2014 Core module tests (35+ files)<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/cli\/<\/code> \u2014 CLI tests<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">t\/stream-node\/<\/code>, <code class=\"language-plaintext highlighter-rouge\">t\/stream-plugin\/<\/code> \u2014 Layer 4 proxy tests<\/li>\n<\/ul>\n\n<p>Test case structure example:<\/p>\n<div class=\"language-perl highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">use<\/span> <span class=\"nn\">t::<\/span><span class=\"nv\">APISIX<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">use<\/span> <span class=\"nn\">Test::Nginx::Socket::<\/span><span class=\"nv\">Lua<\/span><span class=\"p\">;<\/span>\n\n<span class=\"nv\">run_tests<\/span><span class=\"p\">();<\/span>\n\n<span class=\"cp\">__DATA__\n=== TEST 1: Test description\n--- config\n    location \/t {\n        content_by_lua_block {\n            -- Test logic\n        }\n    }\n--- response_body\nExpected output\n--- no_error_log\n[error]\n<\/span><\/code><\/pre><\/div><\/div>\n\n<hr \/>\n\n<h2 id=\"11-recommended-reading-order\">11. Recommended Reading Order<\/h2>\n\n<p>Following this order will help you gradually build a complete understanding of the system:<\/p>\n\n<h3 id=\"phase-1-skeleton-build-the-big-picture\">Phase 1: Skeleton (Build the Big Picture)<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">bin\/apisix<\/code><\/strong> \u2014 Startup script, understand how OpenResty is launched<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/apisix.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/cli\/ops.lua<\/code><\/strong> \u2014 CLI command handling, understand init\/start command implementation<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/init.lua<\/code><\/strong> \u2014 Main entry point, focus on <code class=\"language-plaintext highlighter-rouge\">http_init_worker()<\/code> initialization order and <code class=\"language-plaintext highlighter-rouge\">http_access_phase()<\/code> request flow<\/li>\n<\/ol>\n\n<h3 id=\"phase-2-core-modules-understand-the-infrastructure\">Phase 2: Core Modules (Understand the Infrastructure)<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/core.lua<\/code><\/strong> \u2014 Core module aggregation entry, understand available core capabilities<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/core\/ctx.lua<\/code><\/strong> \u2014 Request context, understand <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> creation\/release mechanism<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/core\/config_etcd.lua<\/code><\/strong> \u2014 etcd config provider, understand how config is read and hot-reloaded<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/core\/lrucache.lua<\/code><\/strong> \u2014 Caching mechanism<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/core\/request.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/core\/response.lua<\/code><\/strong> \u2014 Request\/response operation wrappers<\/li>\n<\/ol>\n\n<h3 id=\"phase-3-core-engine-understand-key-pipelines\">Phase 3: Core Engine (Understand Key Pipelines)<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/router.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/http\/router\/radixtree_uri.lua<\/code><\/strong> \u2014 Route matching mechanism<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/plugin.lua<\/code><\/strong> \u2014 Plugin engine, understand plugin loading, filtering, and execution lifecycle<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/upstream.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/balancer.lua<\/code><\/strong> \u2014 Upstream management and load balancing<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/http\/service.lua<\/code><\/strong> \u2014 Route \u2192 Service config inheritance logic<\/li>\n<\/ol>\n\n<h3 id=\"phase-4-admin-api-understand-the-control-plane\">Phase 4: Admin API (Understand the Control Plane)<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/init.lua<\/code><\/strong> \u2014 Admin API route dispatch<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/resource.lua<\/code><\/strong> \u2014 Generic CRUD base class<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/routes.lua<\/code><\/strong> \u2014 Use Route CRUD as an example to understand specific resource implementation<\/li>\n<\/ol>\n\n<h3 id=\"phase-5-deep-dive-into-plugins-learn-by-doing\">Phase 5: Deep Dive into Plugins (Learn by Doing)<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/plugins\/example-plugin.lua<\/code><\/strong> \u2014 Plugin development template<\/li>\n  <li>Pick a simple plugin you\u2019re interested in (recommended: <code class=\"language-plaintext highlighter-rouge\">key-auth.lua<\/code> or <code class=\"language-plaintext highlighter-rouge\">limit-count.lua<\/code>)<\/li>\n  <li>Read <strong><code class=\"language-plaintext highlighter-rouge\">apisix\/plugins\/ai-proxy.lua<\/code><\/strong> \u2014 Understand complex plugin structure and AI gateway capabilities<\/li>\n<\/ol>\n\n<h3 id=\"phase-6-extended-topics\">Phase 6: Extended Topics<\/h3>\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/stream\/<\/code><\/strong> \u2014 Layer 4 proxy subsystem<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/discovery\/<\/code><\/strong> \u2014 Service discovery (consul\/nacos\/eureka, etc.)<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">apisix\/secret\/<\/code><\/strong> \u2014 Secret management<\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">t\/<\/code><\/strong> \u2014 Test writing, understand features in reverse through tests<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"12-key-design-patterns-summary\">12. Key Design Patterns Summary<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>Pattern<\/th>\n      <th>Where It Appears<\/th>\n      <th>Description<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><strong>Facade<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix\/core.lua<\/code><\/td>\n      <td>Aggregates all core submodules, unified access point<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Template Method<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix\/admin\/resource.lua<\/code><\/td>\n      <td>Generic CRUD base class, submodules inject differentiated config<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Strategy<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix\/router.lua<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">apisix\/balancer.lua<\/code><\/td>\n      <td>Pluggable routing\/load balancing implementations<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Plugin Lifecycle<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">apisix\/plugin.lua<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/plugins\/*.lua<\/code><\/td>\n      <td>Sorted by priority, executed by phase<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Observer<\/strong><\/td>\n      <td>etcd watch in <code class=\"language-plaintext highlighter-rouge\">apisix\/core\/config_etcd.lua<\/code><\/td>\n      <td>Config changes auto-trigger hot reload<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Object Pool<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">tablepool<\/code> + <code class=\"language-plaintext highlighter-rouge\">apisix\/core\/ctx.lua<\/code><\/td>\n      <td>Reuse <code class=\"language-plaintext highlighter-rouge\">api_ctx<\/code> tables to reduce GC pressure<\/td>\n    <\/tr>\n    <tr>\n      <td><strong>Provider Abstraction<\/strong><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">core\/config_etcd.lua<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">core\/config_yaml.lua<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">core\/config_xds.lua<\/code><\/td>\n      <td>Unified config interface, swappable backends<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"13-development-environment-setup-quick-reference\">13. Development Environment Setup (Quick Reference)<\/h2>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\"># Install dependencies<\/span>\nmake deps\n\n<span class=\"c\"># Start APISIX<\/span>\nmake run\n\n<span class=\"c\"># Stop<\/span>\nmake stop\n\n<span class=\"c\"># Run tests<\/span>\nmake <span class=\"nb\">test<\/span>\n\n<span class=\"c\"># Run specific tests<\/span>\nprove <span class=\"nt\">-I<\/span> t\/ t\/plugin\/key-auth.t\n\n<span class=\"c\"># Code linting<\/span>\nmake lint\n<\/code><\/pre><\/div><\/div>\n\n<hr \/>\n\n<blockquote>\n  <p>It is recommended to read alongside the <a href=\"https:\/\/apisix.apache.org\/docs\/apisix\/getting-started\/\">Apache APISIX Official Documentation<\/a> and in-source comments. When you encounter problems, the test cases in the <code class=\"language-plaintext highlighter-rouge\">t\/<\/code> directory are the best reference material for understanding each feature.<\/p>\n<\/blockquote>\n","category":{"@attributes":{"term":"APISIX"}}},{"title":"Nginx \u6e90\u7801\u9605\u8bfb\u6307\u5357","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/2026-07-23\/nginx-source-code-guide.html"}},"updated":"2026-07-23T23:45:00+08:00","id":"https:\/\/wy471x.github.io\/2026-07-23\/nginx-source-code-guide.html","content":"<h1 id=\"nginx-\u6e90\u7801\u9605\u8bfb\u6307\u5357\">Nginx \u6e90\u7801\u9605\u8bfb\u6307\u5357<\/h1>\n\n<h2 id=\"\u4e00\u8bfb\u524d\u51c6\u5907\">\u4e00\u3001\u8bfb\u524d\u51c6\u5907<\/h2>\n\n<h3 id=\"11-\u5fc5\u5907\u77e5\u8bc6\">1.1 \u5fc5\u5907\u77e5\u8bc6<\/h3>\n\n<ul>\n  <li><strong>C \u8bed\u8a00<\/strong>\uff1a\u719f\u6089\u6307\u9488\u3001\u51fd\u6570\u6307\u9488\u3001\u5b8f\u3001\u4f4d\u8fd0\u7b97\u3001\u7ed3\u6784\u4f53\u5185\u5b58\u5e03\u5c40\uff08<code class=\"language-plaintext highlighter-rouge\">offsetof<\/code>\uff09\u3001\u53d8\u957f\u53c2\u6570<\/li>\n  <li><strong>\u7f51\u7edc\u7f16\u7a0b<\/strong>\uff1aTCP\/IP\u3001HTTP\/1.1 \u534f\u8bae\u3001socket API\uff08<code class=\"language-plaintext highlighter-rouge\">accept<\/code>\/<code class=\"language-plaintext highlighter-rouge\">recv<\/code>\/<code class=\"language-plaintext highlighter-rouge\">send<\/code>\/<code class=\"language-plaintext highlighter-rouge\">setsockopt<\/code>\uff09\u3001\u975e\u963b\u585e I\/O<\/li>\n  <li><strong>\u64cd\u4f5c\u7cfb\u7edf<\/strong>\uff1a\u8fdb\u7a0b\u6a21\u578b\uff08fork\uff09\u3001\u4fe1\u53f7\uff08signal\uff09\u3001\u5171\u4eab\u5185\u5b58\u3001epoll\/kqueue \u7b49\u591a\u8def\u590d\u7528\u673a\u5236<\/li>\n  <li><strong>\u7f16\u8bd1\u5de5\u5177<\/strong>\uff1a\u80fd\u8bfb\u61c2 shell \u811a\u672c\u548c Makefile<\/li>\n<\/ul>\n\n<h3 id=\"12-\u73af\u5883\u642d\u5efa\">1.2 \u73af\u5883\u642d\u5efa<\/h3>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\"># \u7f16\u8bd1\u5e26\u8c03\u8bd5\u4fe1\u606f\u7684 nginx<\/span>\n.\/auto\/configure <span class=\"nt\">--with-debug<\/span> <span class=\"nt\">--prefix<\/span><span class=\"o\">=<\/span><span class=\"si\">$(<\/span><span class=\"nb\">pwd<\/span><span class=\"si\">)<\/span>\/build\nmake <span class=\"nt\">-j<\/span><span class=\"si\">$(<\/span><span class=\"nb\">nproc<\/span><span class=\"si\">)<\/span>\n\n<span class=\"c\"># \u7528 GDB \u8c03\u8bd5<\/span>\ngdb .\/objs\/nginx\n<span class=\"o\">(<\/span>gdb<span class=\"o\">)<\/span> b ngx_process_events_and_timers\n<span class=\"o\">(<\/span>gdb<span class=\"o\">)<\/span> r\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"13-\u5173\u952e\u5b8f\u4e0e\u60ef\u4f8b\u901f\u67e5\">1.3 \u5173\u952e\u5b8f\u4e0e\u60ef\u4f8b\u901f\u67e5<\/h3>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u5b8f\/\u6a21\u5f0f<\/th>\n      <th>\u542b\u4e49<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_OK<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_ERROR<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_AGAIN<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_DECLINED<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_DONE<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_BUSY<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_ABORT<\/code><\/td>\n      <td>\u6807\u51c6\u8fd4\u56de\u503c\uff0c\u5206\u522b\u5bf9\u5e94 0\/-1\/-2\/-5\/-4\/-3\/-6<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_string(\"foo\")<\/code><\/td>\n      <td>\u7f16\u8bd1\u671f\u4ece\u5b57\u9762\u91cf\u6784\u9020 <code class=\"language-plaintext highlighter-rouge\">ngx_str_t<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_queue_data(q, type, link)<\/code><\/td>\n      <td>\u4ece\u4fb5\u5165\u5f0f\u961f\u5217\u8282\u70b9\u53cd\u67e5\u5305\u542b\u5b83\u7684\u7ed3\u6784\u4f53<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_rbtree_data(node, type, link)<\/code><\/td>\n      <td>\u540c\u4e0a\uff0c\u9488\u5bf9\u7ea2\u9ed1\u6811\u8282\u70b9<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_log_debug<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">ngx_log_error<\/code><\/td>\n      <td>\u5206\u7ea7\u65e5\u5fd7\u5b8f\uff0c\u5e26 <code class=\"language-plaintext highlighter-rouge\">--with-debug<\/code> \u624d\u4f1a\u8f93\u51fa debug \u7ea7\u522b<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">offsetof(type, member)<\/code><\/td>\n      <td>\u8ba1\u7b97\u6210\u5458\u5728\u7ed3\u6784\u4f53\u4e2d\u7684\u504f\u79fb\u91cf\uff0c\u4fb5\u5165\u5f0f\u6570\u636e\u7ed3\u6784\u7684\u57fa\u77f3<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"\u4e8c\u63a8\u8350\u9605\u8bfb\u8def\u7ebf\">\u4e8c\u3001\u63a8\u8350\u9605\u8bfb\u8def\u7ebf<\/h2>\n\n<h3 id=\"\u7b2c-0-\u6b65\u7406\u89e3\u6784\u5efa\u7cfb\u7edf30-\u5206\u949f\">\u7b2c 0 \u6b65\uff1a\u7406\u89e3\u6784\u5efa\u7cfb\u7edf\uff0830 \u5206\u949f\uff09<\/h3>\n\n<p>\u4ece <code class=\"language-plaintext highlighter-rouge\">auto\/<\/code> \u76ee\u5f55\u5f00\u59cb\uff0c\u4e0d\u5fc5\u7ec6\u8bfb\u6bcf\u4e2a\u811a\u672c\uff0c\u91cd\u70b9\u662f\u7406\u89e3\u6d41\u7a0b\uff1a<\/p>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">auto\/configure<\/code><\/strong> \u2014 \u5165\u53e3\uff0c\u987a\u5e8f\u8c03\u7528 <code class=\"language-plaintext highlighter-rouge\">auto\/options<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">auto\/init<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">auto\/cc\/*<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">auto\/os\/*<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">auto\/feature<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">auto\/modules<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">auto\/sources<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">auto\/make<\/code><\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">auto\/modules<\/code><\/strong> \u2014 \u6700\u5173\u952e\u7684\u6587\u4ef6\u4e4b\u4e00\u3002\u5b83\u51b3\u5b9a\u54ea\u4e9b\u6a21\u5757\u88ab\u7f16\u8bd1\u8fdb <code class=\"language-plaintext highlighter-rouge\">ngx_modules[]<\/code> \u6570\u7ec4\uff0c<strong>\u6a21\u5757\u7684\u6392\u5217\u987a\u5e8f\u51b3\u5b9a\u4e86\u521d\u59cb\u5316\u987a\u5e8f\u548c\u5904\u7406\u4f18\u5148\u7ea7\uff0c\u4e0d\u53ef\u968f\u610f\u6539\u52a8<\/strong><\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">auto\/sources<\/code><\/strong> \u2014 \u5b9a\u4e49\u4e86\u6240\u6709\u6e90\u6587\u4ef6\u5217\u8868\u7684 shell \u53d8\u91cf\uff08<code class=\"language-plaintext highlighter-rouge\">CORE_SRCS<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">HTTP_SRCS<\/code> \u7b49\uff09\uff0c\u6700\u7ec8\u8f93\u51fa\u5230 <code class=\"language-plaintext highlighter-rouge\">objs\/Makefile<\/code><\/li>\n<\/ol>\n\n<p>\u6784\u5efa\u4ea7\u7269\uff1a<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">objs\/ngx_auto_config.h<\/code> \u2014 \u6240\u6709 <code class=\"language-plaintext highlighter-rouge\">#define<\/code> \u5b8f\uff08\u7f16\u8bd1\u7279\u6027\u5f00\u5173\uff09<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">objs\/ngx_modules.c<\/code> \u2014 \u81ea\u52a8\u751f\u6210\u7684 <code class=\"language-plaintext highlighter-rouge\">ngx_modules[]<\/code> \u548c <code class=\"language-plaintext highlighter-rouge\">ngx_module_names[]<\/code><\/li>\n<\/ul>\n\n<h3 id=\"\u7b2c-1-\u6b65\u6838\u5fc3\u6570\u636e\u7ed3\u67842-3-\u5c0f\u65f6\">\u7b2c 1 \u6b65\uff1a\u6838\u5fc3\u6570\u636e\u7ed3\u6784\uff082-3 \u5c0f\u65f6\uff09<\/h3>\n\n<p><strong>\u8fd9\u662f\u6700\u91cd\u8981\u7684\u57fa\u7840\uff0c\u52a1\u5fc5\u5403\u900f\u3002<\/strong> \u6309\u4f9d\u8d56\u5173\u7cfb\u5efa\u8bae\u987a\u5e8f\uff1a<\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>ngx_str_t  \u2192  ngx_pool_t  \u2192  ngx_array_t  \u2192  ngx_list_t  \u2192  ngx_queue_t  \u2192  ngx_buf_t \/ ngx_chain_t  \u2192  ngx_rbtree_t\n<\/code><\/pre><\/div><\/div>\n\n<p>\u9010\u4e2a\u9605\u8bfb\u6587\u4ef6\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u9605\u8bfb\u6587\u4ef6<\/th>\n      <th>\u91cd\u70b9\u7406\u89e3<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_string.h<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_str_t<\/code> \u4e0d\u662f C \u5b57\u7b26\u4e32\uff0c<code class=\"language-plaintext highlighter-rouge\">len<\/code> + <code class=\"language-plaintext highlighter-rouge\">data<\/code> \u4e8c\u5143\u7ec4\uff1b<code class=\"language-plaintext highlighter-rouge\">ngx_vslprintf<\/code> \u7b49\u683c\u5f0f\u5316\u51fd\u6570<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_palloc.h<\/code> + <code class=\"language-plaintext highlighter-rouge\">ngx_palloc.c<\/code><\/td>\n      <td>\u6c60\u5206\u914d\u5668\uff1a\u5c0f\u5757\u4ece\u6c60\u4e2d\u5207\uff0c\u5927\u5757\u8d70 malloc\uff1b<code class=\"language-plaintext highlighter-rouge\">ngx_palloc<\/code> vs <code class=\"language-plaintext highlighter-rouge\">ngx_pnalloc<\/code>\uff08\u5bf9\u9f50 vs \u4e0d\u5bf9\u9f50\uff09\uff1bcleanup \u56de\u8c03\u673a\u5236<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_array.h<\/code><\/td>\n      <td>\u52a8\u6001\u6570\u7ec4\uff0c\u5143\u7d20\u8fde\u7eed\u5b58\u50a8\uff0c<code class=\"language-plaintext highlighter-rouge\">ngx_array_push<\/code> \u8fd4\u56de\u65b0\u5143\u7d20\u7684\u6307\u9488<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_list.h<\/code><\/td>\n      <td>\u94fe\u8868+\u6570\u7ec4\u7684\u6df7\u5408\u4f53\uff0c\u6bcf\u4e2a <code class=\"language-plaintext highlighter-rouge\">part<\/code> \u5b58\u653e <code class=\"language-plaintext highlighter-rouge\">nalloc<\/code> \u4e2a\u5143\u7d20<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_queue.h<\/code><\/td>\n      <td><strong>\u7eaf\u7cb9\u7684\u5b8f<\/strong>\uff0c\u4fb5\u5165\u5f0f\u53cc\u5411\u5faa\u73af\u94fe\u8868\uff0c\u6838\u5fc3\u5b8f <code class=\"language-plaintext highlighter-rouge\">ngx_queue_data<\/code> \u7528 <code class=\"language-plaintext highlighter-rouge\">offsetof<\/code> \u53cd\u67e5\u5bb9\u5668<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_buf.h<\/code> + <code class=\"language-plaintext highlighter-rouge\">ngx_buf.c<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_buf_t<\/code> \u7edf\u4e00\u4e86\u5185\u5b58\u6570\u636e\u548c\u6587\u4ef6\u6570\u636e\uff1b<code class=\"language-plaintext highlighter-rouge\">ngx_chain_t<\/code> \u6784\u6210\u6570\u636e\u6d41\u6c34\u7ebf<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_rbtree.h<\/code> + <code class=\"language-plaintext highlighter-rouge\">ngx_rbtree.c<\/code><\/td>\n      <td>\u7ea2\u9ed1\u6811\uff0c\u54e8\u5175\u8282\u70b9\u4ee3\u66ff NULL\uff0c\u81ea\u5b9a\u4e49\u63d2\u5165\u51fd\u6570\uff0c<code class=\"language-plaintext highlighter-rouge\">ngx_rbtree_data<\/code> \u53cd\u67e5\u5bb9\u5668<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"\u7b2c-2-\u6b65\u8fdb\u7a0b\u6a21\u578b\u4e0e\u4e8b\u4ef6\u5faa\u73af2-3-\u5c0f\u65f6\">\u7b2c 2 \u6b65\uff1a\u8fdb\u7a0b\u6a21\u578b\u4e0e\u4e8b\u4ef6\u5faa\u73af\uff082-3 \u5c0f\u65f6\uff09<\/h3>\n\n<p>\u8fd9\u662f\u7406\u89e3 nginx \u8fd0\u884c\u65f6\u884c\u4e3a\u7684\u6838\u5fc3\u3002<\/p>\n\n<p><strong>\u9605\u8bfb\u987a\u5e8f<\/strong>\uff1a<\/p>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/os\/unix\/ngx_process_cycle.c<\/code><\/strong> \u2014 <code class=\"language-plaintext highlighter-rouge\">main()<\/code> \u4e4b\u540e\u7684\u771f\u6b63\u5165\u53e3\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_master_process_cycle()<\/code> \u2014 master \u8fdb\u7a0b\u5faa\u73af\uff08\u4fe1\u53f7\u5904\u7406\u3001worker \u7ba1\u7406\uff09<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_single_process_cycle()<\/code> \u2014 \u5355\u8fdb\u7a0b\u6a21\u5f0f\uff08\u8c03\u8bd5\u7528\uff09<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_worker_process_cycle()<\/code> \u2014 <strong>worker \u8fdb\u7a0b\u7684\u4e3b\u5faa\u73af<\/strong>\uff08\u6700\u5173\u952e\u7684\u9605\u8bfb\u76ee\u6807\uff09<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_start_worker_processes()<\/code> \u2014 \u5982\u4f55 fork worker<\/li>\n      <li>\u91cd\u70b9\u5173\u6ce8\uff1a\u70ed\u66f4\u65b0\uff08HUP \u4fe1\u53f7\uff09\u65f6\u65b0\u65e7 worker \u7684\u5207\u6362\u903b\u8f91<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event.c<\/code><\/strong> \u2014 \u4e8b\u4ef6\u5b50\u7cfb\u7edf\u6838\u5fc3\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_event_process_init()<\/code> \u2014 worker \u542f\u52a8\u65f6\u7684\u4e8b\u4ef6\u521d\u59cb\u5316\uff08\u521b\u5efa\u8fde\u63a5\u6c60\u3001\u4e8b\u4ef6\u6c60\uff09<\/li>\n      <li><strong><code class=\"language-plaintext highlighter-rouge\">ngx_process_events_and_timers()<\/code><\/strong> \u2014 \u4e8b\u4ef6\u5faa\u73af\u7684\u5fc3\u810f\uff0c\u6bcf\u6b21\u5faa\u73af\u6267\u884c\u56db\u4e2a\u6b65\u9aa4\uff1a\n        <div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>\u2460 ngx_event_find_timer()       -- \u4ece\u7ea2\u9ed1\u6811\u627e\u51fa\u6700\u8fd1\u5230\u671f\u7684\u5b9a\u65f6\u5668\n\u2461 ngx_process_events()         -- \u8c03\u7528 epoll_wait \/ kqueue \u7b49\n\u2462 ngx_event_expire_timers()    -- \u5904\u7406\u5230\u671f\u5b9a\u65f6\u5668\n\u2463 ngx_event_process_posted()   -- \u5904\u7406\u5ef6\u8fdf\u6267\u884c\u7684 posted \u4e8b\u4ef6\n<\/code><\/pre><\/div>        <\/div>\n      <\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_timer.h<\/code><\/strong> \u2014 \u5b9a\u65f6\u5668\u7ba1\u7406\n    <ul>\n      <li>\u5168\u5c40\u7ea2\u9ed1\u6811 <code class=\"language-plaintext highlighter-rouge\">ngx_event_timer_rbtree<\/code>\uff0c\u952e\u503c\u4e3a <code class=\"language-plaintext highlighter-rouge\">\u5230\u671f\u65f6\u95f4 = ngx_current_msec + delay<\/code><\/li>\n      <li>\u60f0\u6027\u5ef6\u8fdf\u4f18\u5316\uff1a\u9608\u503c 300ms\uff0c\u907f\u514d\u9891\u7e41\u66f4\u65b0\u7ea2\u9ed1\u6811<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_posted.h<\/code><\/strong> \u2014 \u5ef6\u8fdf\u4e8b\u4ef6\u673a\u5236\n    <ul>\n      <li>\u4e09\u4e2a\u5168\u5c40\u961f\u5217\uff1a<code class=\"language-plaintext highlighter-rouge\">ngx_posted_accept_events<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">ngx_posted_events<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">ngx_posted_next_events<\/code><\/li>\n      <li>\u7528\u4e8e\u907f\u514d\u91cd\u5165\u548c\u6279\u91cf\u5316\u5904\u7406<\/li>\n    <\/ul>\n  <\/li>\n<\/ol>\n\n<h3 id=\"\u7b2c-3-\u6b65\u8fde\u63a5\u7ba1\u74061-2-\u5c0f\u65f6\">\u7b2c 3 \u6b65\uff1a\u8fde\u63a5\u7ba1\u7406\uff081-2 \u5c0f\u65f6\uff09<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_connection.h<\/code><\/strong> \u2014 \u4e24\u4e2a\u6838\u5fc3\u7ed3\u6784\u4f53\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_connection_t<\/code>\uff1a\u6bcf\u6761\u8fde\u63a5\u4e00\u4e2a\u5b9e\u4f8b\uff0c\u5305\u542b fd\u3001\u8bfb\u5199\u4e8b\u4ef6\u3001I\/O \u51fd\u6570\u6307\u9488\uff08\u88ab SSL\/QUIC \u66ff\u6362\uff09\u3001\u72b6\u6001\u4f4d<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_listening_t<\/code>\uff1a\u6bcf\u4e2a\u76d1\u542c socket \u4e00\u4e2a\u5b9e\u4f8b\uff0c\u5305\u542b\u63a5\u53d7\u56de\u8c03\u3001SSL\/QUIC \u6807\u8bb0<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_connection.c<\/code><\/strong>\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_open_listening_sockets()<\/code> \u2014 \u6253\u5f00\u6240\u6709\u76d1\u542c\u7aef\u53e3<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_get_connection()<\/code> \u2014 \u4ece\u9884\u5206\u914d\u6570\u7ec4\u4e2d\u53d6\u7a7a\u95f2\u8fde\u63a5<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_close_connection()<\/code> \u2014 \u5f52\u8fd8\u8fde\u63a5\u5230\u7a7a\u95f2\u5217\u8868<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_accept.c<\/code><\/strong>\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_event_accept()<\/code> \u2014 accept \u5904\u7406\u5668\uff0caccept \u4e92\u65a5\u9501\u903b\u8f91<\/li>\n    <\/ul>\n  <\/li>\n<\/ol>\n\n<p>\u5173\u952e\u8bbe\u8ba1\uff1a<strong>instance \u4f4d<\/strong>\u89e3\u51b3 stale event \u95ee\u9898<\/p>\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>\u6bcf\u6b21\u8fde\u63a5\u590d\u7528\u65f6\uff0cinstance \u4f4d\u7ffb\u8f6c\u3002\n\u5f53 epoll\/kqueue \u8fd4\u56de\u4e00\u4e2a\u8fc7\u65f6\u7684\u4e8b\u4ef6\u65f6\uff0c\n\u901a\u8fc7\u6bd4\u5bf9 instance \u4f4d\u53d1\u73b0\u4e0d\u5339\u914d \u2192 \u4e22\u5f03\u8be5\u4e8b\u4ef6\u3002\n\u8fd9\u907f\u514d\u4e86\u989d\u5916\u7cfb\u7edf\u8c03\u7528\u6765\u9a8c\u8bc1\u4e8b\u4ef6\u6709\u6548\u6027\u3002\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"\u7b2c-4-\u6b65\u914d\u7f6e\u7cfb\u7edf2-\u5c0f\u65f6\">\u7b2c 4 \u6b65\uff1a\u914d\u7f6e\u7cfb\u7edf\uff082 \u5c0f\u65f6\uff09<\/h3>\n\n<p>nginx \u7684\u914d\u7f6e\u89e3\u6790\u5668\u662f\u4e00\u4e2a<strong>\u9012\u5f52\u4e0b\u964d\u89e3\u6790\u5668<\/strong>\uff0c\u662f\u6574\u4e2a\u6a21\u5757\u7cfb\u7edf\u8fd0\u8f6c\u7684\u57fa\u7840\u3002<\/p>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_conf_file.h<\/code><\/strong> \u2014 \u6838\u5fc3\u7c7b\u578b\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_command_t<\/code>\uff1a\u6bcf\u4e2a\u914d\u7f6e\u6307\u4ee4\u7684\u5b9a\u4e49\uff08\u540d\u79f0\u3001\u53c2\u6570\u89c4\u5219\u3001set \u51fd\u6570\u3001\u504f\u79fb\u91cf\uff09<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_conf_t<\/code>\uff1a\u89e3\u6790\u4e0a\u4e0b\u6587<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_conf_file.c<\/code><\/strong>\n    <ul>\n      <li><strong><code class=\"language-plaintext highlighter-rouge\">ngx_conf_parse()<\/code><\/strong> \u2014 \u9012\u5f52\u89e3\u6790\u5165\u53e3\uff0c\u9047\u5230 block \u6307\u4ee4\u4f1a\u9012\u5f52\u8c03\u7528\u81ea\u8eab<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_conf_handler()<\/code> \u2014 \u5206\u53d1\u5230\u6a21\u5757\u7684 set \u51fd\u6570<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong>\u53c2\u6570\u7c7b\u578b\u6807\u5fd7\u901f\u67e5<\/strong>\uff1a\n    <div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>NGX_CONF_NOARGS         -- \u65e0\u53c2\u6570\uff08\u5982 \"accept_mutex off;\" \u4e2d\u7684 off \u662f flag\uff0c\u4e0d\u662f\u53c2\u6570\uff09\nNGX_CONF_TAKE1~7        -- \u6b63\u597d N \u4e2a\u53c2\u6570\nNGX_CONF_TAKE12         -- 1 \u6216 2 \u4e2a\u53c2\u6570\nNGX_CONF_FLAG           -- \u5e03\u5c14\u503c\uff08on\/off\uff09\nNGX_CONF_BLOCK          -- \u540e\u9762\u8ddf\u7740 {} \u5757\nNGX_CONF_1MORE          -- \u81f3\u5c11 1 \u4e2a\u53c2\u6570\n<\/code><\/pre><\/div>    <\/div>\n  <\/li>\n  <li>\n    <p><strong>Setter \u51fd\u6570\u65cf<\/strong>\uff1a<code class=\"language-plaintext highlighter-rouge\">ngx_conf_set_flag_slot<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">ngx_conf_set_str_slot<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">ngx_conf_set_num_slot<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">ngx_conf_set_size_slot<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">ngx_conf_set_msec_slot<\/code> \u7b49\uff0c\u8fd9\u4e9b\u662f\u914d\u7f6e\u89e3\u6790\u7684\u57fa\u7840\u7ec4\u4ef6\u3002<\/p>\n  <\/li>\n  <li><strong>\u914d\u7f6e\u5408\u5e76\u5b8f<\/strong>\uff1a\n    <div class=\"language-c highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"n\">ngx_conf_merge_value<\/span><span class=\"p\">(<\/span><span class=\"n\">conf<\/span><span class=\"p\">,<\/span> <span class=\"n\">prev<\/span><span class=\"p\">,<\/span> <span class=\"k\">default<\/span><span class=\"p\">)<\/span>   <span class=\"c1\">\/\/ \u6570\u503c\uff1a\u5f53\u524d \u2192 \u7236\u7ea7 \u2192 \u9ed8\u8ba4<\/span>\n<span class=\"n\">ngx_conf_merge_str_value<\/span><span class=\"p\">(<\/span><span class=\"n\">conf<\/span><span class=\"p\">,<\/span> <span class=\"n\">prev<\/span><span class=\"p\">,<\/span> <span class=\"k\">default<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">ngx_conf_merge_msec_value<\/span><span class=\"p\">(<\/span><span class=\"n\">conf<\/span><span class=\"p\">,<\/span> <span class=\"n\">prev<\/span><span class=\"p\">,<\/span> <span class=\"k\">default<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>    <\/div>\n    <p>\u4f53\u73b0\u4e86 nginx \u914d\u7f6e\u7ee7\u627f\u7684\u4e09\u7ea7 fallback \u673a\u5236\u3002<\/p>\n  <\/li>\n<\/ol>\n\n<h3 id=\"\u7b2c-5-\u6b65\u6a21\u5757\u7cfb\u7edf1-2-\u5c0f\u65f6\">\u7b2c 5 \u6b65\uff1a\u6a21\u5757\u7cfb\u7edf\uff081-2 \u5c0f\u65f6\uff09<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_module.h<\/code><\/strong> \u2014 <code class=\"language-plaintext highlighter-rouge\">ngx_module_t<\/code> \u7ed3\u6784\u4f53\n    <ul>\n      <li>\u5168\u5c40\u7d22\u5f15 <code class=\"language-plaintext highlighter-rouge\">index<\/code> \u548c\u7c7b\u578b\u5185\u7d22\u5f15 <code class=\"language-plaintext highlighter-rouge\">ctx_index<\/code><\/li>\n      <li>\u7c7b\u578b\u7279\u5b9a\u7684 <code class=\"language-plaintext highlighter-rouge\">ctx<\/code> \u6307\u9488<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">commands<\/code> \u6570\u7ec4\uff08\u914d\u7f6e\u6307\u4ee4\u5b9a\u4e49\uff09<\/li>\n      <li>\u751f\u547d\u5468\u671f\u94a9\u5b50\uff1a<code class=\"language-plaintext highlighter-rouge\">init_master<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">init_module<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">init_process<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">exit_process<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">exit_master<\/code><\/li>\n    <\/ul>\n  <\/li>\n  <li><strong>\u6a21\u5757\u7c7b\u578b<\/strong>\uff1a\n    <div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>NGX_CORE_MODULE    -- \u6838\u5fc3\u6a21\u5757\uff08\u5982 ngx_core_module\u3001ngx_events_module\u3001ngx_http_module\uff09\nNGX_EVENT_MODULE   -- \u4e8b\u4ef6\u6a21\u5757\uff08\u5982 ngx_epoll_module\u3001ngx_kqueue_module\uff09\nNGX_HTTP_MODULE    -- HTTP \u6a21\u5757\nNGX_MAIL_MODULE    -- Mail \u6a21\u5757\nNGX_STREAM_MODULE  -- Stream \u6a21\u5757\n<\/code><\/pre><\/div>    <\/div>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_module.c<\/code><\/strong>\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_cycle_modules()<\/code> \u2014 \u590d\u5236\u6a21\u5757\u6570\u7ec4\u5230 cycle<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_init_modules()<\/code> \u2014 \u8c03\u7528\u6bcf\u4e2a\u6a21\u5757\u7684 <code class=\"language-plaintext highlighter-rouge\">init_module<\/code><\/li>\n    <\/ul>\n  <\/li>\n  <li><strong>HTTP \u6a21\u5757\u7684\u7279\u6b8a\u4e0a\u4e0b\u6587<\/strong> <code class=\"language-plaintext highlighter-rouge\">ngx_http_module_t<\/code>\uff1a\n    <div class=\"language-c highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">typedef<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">ngx_int_t<\/span>   <span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">preconfiguration<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">);<\/span>\n    <span class=\"n\">ngx_int_t<\/span>   <span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">postconfiguration<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">void<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">create_main_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">char<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">init_main_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">,<\/span> <span class=\"kt\">void<\/span> <span class=\"o\">*<\/span><span class=\"n\">conf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">void<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">create_srv_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">char<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">merge_srv_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">,<\/span> <span class=\"kt\">void<\/span> <span class=\"o\">*<\/span><span class=\"n\">prev<\/span><span class=\"p\">,<\/span> <span class=\"kt\">void<\/span> <span class=\"o\">*<\/span><span class=\"n\">conf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">void<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">create_loc_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">char<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">merge_loc_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">,<\/span> <span class=\"kt\">void<\/span> <span class=\"o\">*<\/span><span class=\"n\">prev<\/span><span class=\"p\">,<\/span> <span class=\"kt\">void<\/span> <span class=\"o\">*<\/span><span class=\"n\">conf<\/span><span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span> <span class=\"n\">ngx_http_module_t<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre><\/div>    <\/div>\n    <p><strong>\u8fd9\u662f\u7406\u89e3 HTTP \u6a21\u5757\u5982\u4f55\u5de5\u4f5c\u7684\u5173\u952e<\/strong>\uff1amain \u2192 srv \u2192 loc \u4e09\u7ea7\u914d\u7f6e\u7684\u521b\u5efa\u548c\u5408\u5e76\u90fd\u5728\u8fd9\u91cc\u3002<\/p>\n  <\/li>\n<\/ol>\n\n<h3 id=\"\u7b2c-6-\u6b65http-\u8bf7\u6c42\u5904\u7406\u5168\u94fe\u8def4-5-\u5c0f\u65f6-\u6838\u5fc3\">\u7b2c 6 \u6b65\uff1aHTTP \u8bf7\u6c42\u5904\u7406\u5168\u94fe\u8def\uff084-5 \u5c0f\u65f6\uff09\u2b50 \u6838\u5fc3<\/h3>\n\n<p>\u8fd9\u662f nginx \u6e90\u7801\u4e2d\u6700\u91cd\u8981\u3001\u6700\u590d\u6742\u7684\u90e8\u5206\uff0c\u5efa\u8bae\u53cd\u590d\u9605\u8bfb\u3002<\/p>\n\n<h4 id=\"61-http-\u6846\u67b6\u521d\u59cb\u5316\">6.1 HTTP \u6846\u67b6\u521d\u59cb\u5316<\/h4>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http.c<\/code><\/strong><\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_http_block()<\/code> \u2014 <code class=\"language-plaintext highlighter-rouge\">http {}<\/code> \u5757\u7684\u89e3\u6790\u51fd\u6570\n    <ul>\n      <li>\u521b\u5efa main\/srv\/loc \u4e09\u7ea7\u914d\u7f6e<\/li>\n      <li>\u521d\u59cb\u5316 phase engine\uff08\u9636\u6bb5\u5f15\u64ce\uff09<\/li>\n      <li>\u8c03\u7528\u5404\u6a21\u5757\u7684 <code class=\"language-plaintext highlighter-rouge\">postconfiguration<\/code>\uff08\u6b64\u65f6\u6ce8\u518c handler\u3001filter\uff09<\/li>\n      <li>\u521d\u59cb\u5316\u8bf7\u6c42\u5934\u89e3\u6790\u8868\u3001\u53d8\u91cf\u7cfb\u7edf<\/li>\n    <\/ul>\n  <\/li>\n<\/ul>\n\n<h4 id=\"62-11-\u4e2a\u5904\u7406\u9636\u6bb5\">6.2 11 \u4e2a\u5904\u7406\u9636\u6bb5<\/h4>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_core_module.h<\/code><\/strong><\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>NGX_HTTP_POST_READ_PHASE       -- \u8bfb\u5b8c\u8bf7\u6c42\u5934\u4e4b\u540e\uff08realip \u6a21\u5757\u5728\u6b64\uff09\nNGX_HTTP_SERVER_REWRITE_PHASE  -- server \u7ea7\u522b\u7684 rewrite\nNGX_HTTP_FIND_CONFIG_PHASE     -- \u5339\u914d location\nNGX_HTTP_REWRITE_PHASE         -- location \u7ea7\u522b\u7684 rewrite\nNGX_HTTP_POST_REWRITE_PHASE    -- rewrite \u4e4b\u540e\uff08\u68c0\u67e5\u91cd\u5b9a\u5411\u5faa\u73af\uff09\nNGX_HTTP_PREACCESS_PHASE       -- \u8bbf\u95ee\u9650\u5236\uff08limit_conn\u3001limit_req\uff09\nNGX_HTTP_ACCESS_PHASE          -- \u6743\u9650\u68c0\u67e5\uff08allow\/deny\u3001auth_basic\u3001auth_request\uff09\nNGX_HTTP_POST_ACCESS_PHASE     -- access \u4e4b\u540e\uff08\u5904\u7406 satisfy all\/any\uff09\nNGX_HTTP_PRECONTENT_PHASE      -- \u5185\u5bb9\u4ea7\u751f\u4e4b\u524d\uff08mirror\u3001try_files\uff09\nNGX_HTTP_CONTENT_PHASE         -- \u4ea7\u751f\u54cd\u5e94\u5185\u5bb9\uff08proxy_pass\u3001fastcgi_pass\u3001static\uff09\nNGX_HTTP_LOG_PHASE             -- \u8bb0\u5f55\u65e5\u5fd7\uff08\u8bf7\u6c42\u5904\u7406\u5b8c\u6210\u4e4b\u540e\uff09\n<\/code><\/pre><\/div><\/div>\n\n<p>\u6bcf\u4e2a\u9636\u6bb5\u7531 <strong>checker \u51fd\u6570<\/strong> \u9a71\u52a8\uff0c\u4f9d\u6b21\u8c03\u7528\u6ce8\u518c\u5230\u8be5\u9636\u6bb5\u7684 handler\u3002\u5173\u952e checker\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Checker<\/th>\n      <th>\u9636\u6bb5<\/th>\n      <th>\u884c\u4e3a<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_http_core_generic_phase<\/code><\/td>\n      <td>rewrite \u7b49<\/td>\n      <td>\u987a\u5e8f\u6267\u884c\uff0cDECLINED \u5219\u4e0b\u4e00\u4e2a<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_http_core_find_config_phase<\/code><\/td>\n      <td>find_config<\/td>\n      <td>\u5339\u914d location\uff0c\u53ea\u6267\u884c\u4e00\u6b21<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_http_core_access_phase<\/code><\/td>\n      <td>access<\/td>\n      <td>\u652f\u6301 satisfy all\/any<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_http_core_content_phase<\/code><\/td>\n      <td>content<\/td>\n      <td>\u627e\u5230\u7b2c\u4e00\u4e2a\u8fd4\u56de OK \u7684 handler<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>\u9605\u8bfb\u5165\u53e3\uff1a<strong><code class=\"language-plaintext highlighter-rouge\">ngx_http_core_run_phases()<\/code><\/strong><\/p>\n\n<h4 id=\"63-\u8bf7\u6c42\u751f\u547d\u5468\u671f\">6.3 \u8bf7\u6c42\u751f\u547d\u5468\u671f<\/h4>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_request.h<\/code><\/strong> \u2014 <code class=\"language-plaintext highlighter-rouge\">ngx_http_request_t<\/code> \u7ed3\u6784\u4f53\uff08\u5f88\u5927\uff0c\u7ea6 60+ \u5b57\u6bb5\uff09<\/p>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_request.c<\/code><\/strong> \u2014 \u6309\u987a\u5e8f\u9605\u8bfb\u4ee5\u4e0b\u51fd\u6570\uff1a<\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>\u65b0\u8fde\u63a5\u5230\u8fbe\uff1a\n  ngx_http_init_connection()\n    \u2192 ngx_http_wait_request_handler()      -- \u7b49\u5f85\u5b8c\u6574\u7684\u8bf7\u6c42\u5934\u5230\u8fbe\n\n\u8bf7\u6c42\u5934\u89e3\u6790\u5b8c\u6210\uff1a\n  ngx_http_process_request_line()\n    \u2192 ngx_http_process_request_headers()\n      \u2192 ngx_http_process_request()\n        \u2192 ngx_http_process_request_headers()  -- \u89e3\u6790 Host\u3001Content-Length \u7b49\n        \u2192 ngx_http_handler()                  -- \u8bbe\u7f6e r-&gt;phase_handler = 0\n          \u2192 ngx_http_core_run_phases(r)       -- \u9a71\u52a8\u9636\u6bb5\u5f15\u64ce\n\n\u54cd\u5e94\u53d1\u9001\uff1a\n  ngx_http_writer()                         -- \u5f02\u6b65\u53d1\u9001\u54cd\u5e94\u4f53\n\n\u8bf7\u6c42\u7ed3\u675f\uff1a\n  ngx_http_finalize_request()\n    \u2192 ngx_http_free_request()\n      \u2192 ngx_destroy_pool(r-&gt;pool)          -- \u9500\u6bc1\u8bf7\u6c42\u5185\u5b58\u6c60\n<\/code><\/pre><\/div><\/div>\n\n<h4 id=\"64-\u8fc7\u6ee4\u5668\u94fe\">6.4 \u8fc7\u6ee4\u5668\u94fe<\/h4>\n\n<p>nginx \u7684\u8f93\u51fa\u4e0d\u662f\u7531\u5355\u4e2a\u6a21\u5757\u4e00\u6b21\u6027\u5b8c\u6210\u7684\uff0c\u800c\u662f\u901a\u8fc7<strong>\u8fc7\u6ee4\u5668\u94fe<\/strong>\uff08\u8d23\u4efb\u94fe\u6a21\u5f0f\uff09\u534f\u4f5c\u4ea7\u751f\u7684\u3002<\/p>\n\n<p><strong>\u5934\u8fc7\u6ee4\u5668\u94fe<\/strong>\uff1a<\/p>\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>ngx_http_top_header_filter\n  \u2192 ngx_http_not_modified_header_filter\n  \u2192 ...\n  \u2192 ngx_http_gzip_header_filter\n  \u2192 ...\n  \u2192 ngx_http_header_filter          -- \u6700\u7ec8\u5e8f\u5217\u5316 HTTP \u5934\u4e3a\u5b57\u8282\u6d41\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>\u4f53\u8fc7\u6ee4\u5668\u94fe<\/strong>\uff1a<\/p>\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>ngx_http_top_body_filter\n  \u2192 ngx_http_range_body_filter\n  \u2192 ngx_http_copy_filter            -- \u5fc5\u8981\u65f6\u5c06 in_file buf \u590d\u5236\u5230\u5185\u5b58\n  \u2192 ngx_http_gzip_body_filter\n  \u2192 ngx_http_chunked_body_filter\n  \u2192 ngx_http_write_filter           -- \u6700\u7ec8\u8c03\u7528 c-&gt;send_chain() \u53d1\u9001\n<\/code><\/pre><\/div><\/div>\n\n<p>\u8fc7\u6ee4\u5668\u6ce8\u518c\u6a21\u5f0f\uff1a<\/p>\n<div class=\"language-c highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">\/\/ \u5728 postconfiguration \u4e2d\u6ce8\u518c\uff1a<\/span>\n<span class=\"k\">static<\/span> <span class=\"n\">ngx_int_t<\/span>\n<span class=\"nf\">ngx_http_my_init<\/span><span class=\"p\">(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"n\">ngx_http_next_header_filter<\/span>  <span class=\"o\">=<\/span> <span class=\"n\">ngx_http_top_header_filter<\/span><span class=\"p\">;<\/span>\n    <span class=\"n\">ngx_http_top_header_filter<\/span>   <span class=\"o\">=<\/span> <span class=\"n\">ngx_http_my_header_filter<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"n\">ngx_http_next_body_filter<\/span>    <span class=\"o\">=<\/span> <span class=\"n\">ngx_http_top_body_filter<\/span><span class=\"p\">;<\/span>\n    <span class=\"n\">ngx_http_top_body_filter<\/span>     <span class=\"o\">=<\/span> <span class=\"n\">ngx_http_my_body_filter<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">NGX_OK<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n<p>\u6ce8\u610f\uff1a<strong>\u540e\u6ce8\u518c\u7684\u5148\u6267\u884c<\/strong>\uff08\u56e0\u4e3a\u6bcf\u6b21\u63d2\u5728\u94fe\u5934\uff09\u3002<\/p>\n\n<h4 id=\"65-location-\u5339\u914d\">6.5 Location \u5339\u914d<\/h4>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_core_module.c<\/code><\/strong><\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">ngx_http_core_find_config_phase()<\/code> \u4e2d\u7684\u5339\u914d\u7b97\u6cd5\uff1a<\/p>\n<ol>\n  <li>\u7528 <code class=\"language-plaintext highlighter-rouge\">ngx_hash_lookup()<\/code> \u5728 <code class=\"language-plaintext highlighter-rouge\">locations<\/code> \u54c8\u5e0c\u8868\u4e2d\u505a<strong>\u524d\u7f00\u5339\u914d<\/strong><\/li>\n  <li>\u5982\u679c\u5339\u914d\u5230\u7684 location \u6709\u5d4c\u5957\uff0c\u9012\u5f52\u67e5\u627e<\/li>\n  <li>\u6700\u540e\u7528 <code class=\"language-plaintext highlighter-rouge\">regex_locations<\/code> \u961f\u5217\u505a<strong>\u6b63\u5219\u5339\u914d<\/strong>\uff08\u4f18\u5148\u7ea7\u6700\u9ad8\uff0c\u4f7f\u7528 <code class=\"language-plaintext highlighter-rouge\">=~<\/code> \u6216 <code class=\"language-plaintext highlighter-rouge\">~*<\/code>\uff09<\/li>\n<\/ol>\n\n<p><strong>\u914d\u7f6e\u5408\u5e76\u7684\u8def\u5f84<\/strong>\uff1a\u5339\u914d\u5230\u67d0\u4e2a location \u540e\uff0c\u5176 <code class=\"language-plaintext highlighter-rouge\">loc_conf[module_index]<\/code> \u5df2\u5728\u89e3\u6790\u9636\u6bb5\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">merge_loc_conf<\/code> \u6b63\u786e\u5730\u7ee7\u627f\u81ea server \u548c main \u7ea7\u522b\u7684\u914d\u7f6e\u3002<\/p>\n\n<h4 id=\"66-upstream-\u673a\u5236\">6.6 Upstream \u673a\u5236<\/h4>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_upstream.h<\/code><\/strong> + <strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_upstream.c<\/code><\/strong><\/p>\n\n<p>upstream \u7684\u72b6\u6001\u673a\uff1a<\/p>\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>ngx_http_upstream_init()\n  \u2192 ngx_http_upstream_connect()           -- \u5efa\u7acb\u5230\u540e\u7aef\u7684\u8fde\u63a5\n    \u2192 ngx_http_upstream_send_request()    -- \u53d1\u9001\u8bf7\u6c42\u4f53\n      \u2192 ngx_http_upstream_process_header()  -- \u89e3\u6790\u54cd\u5e94\u5934\n        \u2192 ngx_http_upstream_process_body_in_memory() \u6216 sendfile\/pipe -- \u8f6c\u53d1\u54cd\u5e94\u4f53\n          \u2192 ngx_http_upstream_finalize_request()\n<\/code><\/pre><\/div><\/div>\n\n<p>\u8d1f\u8f7d\u5747\u8861\u662f<strong>\u53ef\u63d2\u62d4<\/strong>\u7684\uff0c\u901a\u8fc7 <code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_peer_t<\/code> \u63a5\u53e3\uff1a<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_round_robin.c<\/code> \u2014 \u52a0\u6743\u8f6e\u8be2\uff08\u9ed8\u8ba4\uff09<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_hash_module.c<\/code> \u2014 \u4e00\u81f4\u6027\u54c8\u5e0c<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_least_conn_module.c<\/code> \u2014 \u6700\u5c0f\u8fde\u63a5\u6570<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_random_module.c<\/code> \u2014 \u968f\u673a\u9009\u62e9<\/li>\n<\/ul>\n\n<h3 id=\"\u7b2c-7-\u6b65\u8865\u5145\u9605\u8bfb\u6309\u9700\">\u7b2c 7 \u6b65\uff1a\u8865\u5145\u9605\u8bfb\uff08\u6309\u9700\uff09<\/h3>\n\n<ol>\n  <li><strong>\u65e5\u5fd7\u7cfb\u7edf<\/strong>\uff1a<code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_log.h<\/code> + <code class=\"language-plaintext highlighter-rouge\">ngx_log.c<\/code> \u2014 <code class=\"language-plaintext highlighter-rouge\">ngx_log_t<\/code> \u5206\u7ea7\u65e5\u5fd7\uff0c\u94fe\u5f0f\u65e5\u5fd7\u5bf9\u8c61<\/li>\n  <li><strong>\u53d8\u91cf\u7cfb\u7edf<\/strong>\uff1a<code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_variables.c<\/code> \u2014 <code class=\"language-plaintext highlighter-rouge\">$remote_addr<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">$host<\/code> \u7b49\u53d8\u91cf\u5982\u4f55\u6ce8\u518c\u548c\u6c42\u503c<\/li>\n  <li><strong>\u6b63\u5219\u5f15\u64ce<\/strong>\uff1a<code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_regex.c<\/code> \u2014 \u5bf9 PCRE \u7684\u5c01\u88c5\uff08nginx \u81ea\u5df1\u4e0d\u505a\u6b63\u5219\u5f15\u64ce\uff09<\/li>\n  <li><strong>\u5171\u4eab\u5185\u5b58\u4e0e Slab \u5206\u914d\u5668<\/strong>\uff1a<code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_slab.c<\/code> \u2014 \u7528\u4e8e\u591a\u8fdb\u7a0b\u5171\u4eab\u6570\u636e\u7684 slab \u5206\u914d\u5668<\/li>\n  <li><strong>SSL\/TLS<\/strong>\uff1a<code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_openssl.c<\/code> \u2014 \u5982\u4f55\u901a\u8fc7\u66ff\u6362 <code class=\"language-plaintext highlighter-rouge\">c-&gt;recv\/send<\/code> \u51fd\u6570\u6307\u9488\u5b9e\u73b0 SSL<\/li>\n  <li><strong>HTTP\/2<\/strong>\uff1a<code class=\"language-plaintext highlighter-rouge\">src\/http\/v2\/<\/code> \u2014 HTTP\/2 \u5e27\u7684\u89e3\u6790\u548c\u591a\u8def\u590d\u7528<\/li>\n  <li><strong>QUIC\/HTTP\/3<\/strong>\uff1a<code class=\"language-plaintext highlighter-rouge\">src\/event\/quic\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">src\/http\/v3\/<\/code> \u2014 QUIC \u4f20\u8f93\u5c42\u548c HTTP\/3 \u7684\u5b9e\u73b0<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"\u4e09\u8d2f\u7a7f\u59cb\u7ec8\u7684\u8bbe\u8ba1\u6a21\u5f0f\u4e0e\u601d\u7ef4\u65b9\u5f0f\">\u4e09\u3001\u8d2f\u7a7f\u59cb\u7ec8\u7684\u8bbe\u8ba1\u6a21\u5f0f\u4e0e\u601d\u7ef4\u65b9\u5f0f<\/h2>\n\n<h3 id=\"31-\u4fb5\u5165\u5f0f\u6570\u636e\u7ed3\u6784\">3.1 \u4fb5\u5165\u5f0f\u6570\u636e\u7ed3\u6784<\/h3>\n\n<p>nginx \u4e0d\u5355\u72ec\u5206\u914d\u94fe\u8868\u8282\u70b9\u6216\u6811\u8282\u70b9\uff0c\u800c\u662f\u5c06 <code class=\"language-plaintext highlighter-rouge\">ngx_queue_t<\/code> \u548c <code class=\"language-plaintext highlighter-rouge\">ngx_rbtree_node_t<\/code> <strong>\u76f4\u63a5\u5d4c\u5165<\/strong>\u5728\u4f7f\u7528\u5b83\u4eec\u7684\u7ed3\u6784\u4f53\u4e2d\u3002\u96f6\u989d\u5916\u5206\u914d\uff0c\u6781\u81f4\u6548\u7387\u3002<\/p>\n\n<div class=\"language-c highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">\/\/ \u4e0d\u662f\uff1alist&lt;Item*&gt; items\uff08\u6bcf\u6b21\u63d2\u5165\u8981 malloc \u4e00\u4e2a\u8282\u70b9\uff09<\/span>\n<span class=\"c1\">\/\/ \u800c\u662f\uff1aItem \u91cc\u5305\u542b ngx_queue_t queue\uff0c\u76f4\u63a5\u94fe\u5165<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"32-\u9884\u5206\u914d--\u91cd\u7528\">3.2 \u9884\u5206\u914d + \u91cd\u7528<\/h3>\n\n<p>\u8fde\u63a5\u3001\u4e8b\u4ef6\u3001\u5185\u5b58\u6c60\u2014\u2014\u5728\u542f\u52a8\u65f6\u9884\u5206\u914d\u597d\uff0c\u8fd0\u884c\u65f6\u4e0d\u518d <code class=\"language-plaintext highlighter-rouge\">malloc<\/code>\u3002nginx \u7684\u54f2\u5b66\u662f\uff1a<strong>\u201c\u6211\u80fd\u5728\u542f\u52a8\u65f6\u7b97\u6e05\u695a\u7684\u6700\u5927\u8d44\u6e90\u91cf\uff0c\u5c31\u9884\u5206\u914d\u597d\u201d<\/strong>\u3002<\/p>\n\n<h3 id=\"33-io-\u51fd\u6570\u6307\u9488\u7684\u591a\u6001\">3.3 I\/O \u51fd\u6570\u6307\u9488\u7684\u591a\u6001<\/h3>\n\n<div class=\"language-c highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"n\">c<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">recv<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ngx_ssl_recv<\/span><span class=\"p\">;<\/span>   <span class=\"c1\">\/\/ SSL \u6a21\u5757\u5077\u5077\u6362\u4e86<\/span>\n<span class=\"n\">c<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">send<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ngx_ssl_send<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre><\/div><\/div>\n<p>\u9ad8\u5c42\u4ee3\u7801\uff08HTTP \u6846\u67b6\uff09\u5b8c\u5168\u4e0d\u611f\u77e5\u5e95\u5c42\u662f TCP \u8fd8\u662f SSL \u8fd8\u662f QUIC\uff0c\u8fd9\u662f nginx \u5b9e\u73b0\u534f\u8bae\u5347\u7ea7\u548c SSL \u900f\u660e\u7684\u5173\u952e\u624b\u6bb5\u3002<\/p>\n\n<h3 id=\"34-\u8fd4\u56de\u503c\u9a71\u52a8\u7684\u63a7\u5236\u6d41\">3.4 \u8fd4\u56de\u503c\u9a71\u52a8\u7684\u63a7\u5236\u6d41<\/h3>\n\n<p>nginx \u4e0d\u4f7f\u7528\u5f02\u5e38\u6216 <code class=\"language-plaintext highlighter-rouge\">goto<\/code>\uff0c\u800c\u662f\u901a\u8fc7\u8fd4\u56de\u503c\u8868\u8fbe\u63a7\u5236\u610f\u56fe\uff1a<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u8fd4\u56de\u503c<\/th>\n      <th>\u8bed\u4e49<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_OK<\/code><\/td>\n      <td>\u5b8c\u6210\uff0c\u8c03\u7528\u8005\u7ee7\u7eed<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_ERROR<\/code><\/td>\n      <td>\u51fa\u9519\uff0c\u7ec8\u6b62<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_AGAIN<\/code><\/td>\n      <td>\u8d44\u6e90\u4e0d\u8db3\uff08\u7f13\u51b2\u6ee1\u4e86\u3001\u6570\u636e\u672a\u5230\uff09\uff0c\u6682\u505c\u7b49\u5f85\u4e0b\u6b21\u4e8b\u4ef6\u89e6\u53d1<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_DECLINED<\/code><\/td>\n      <td>\u6211\u4e0d\u5904\u7406\uff0c\u627e\u4e0b\u4e00\u4e2a\uff08handler \u5355\u94fe\u8868\u904d\u5386\u7684\u6838\u5fc3\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_DONE<\/code><\/td>\n      <td>\u5df2\u5904\u7406\uff0c\u4f46\u8bf7\u6c42\u672a\u7ed3\u675f\uff08\u5f02\u6b65\u64cd\u4f5c pending\uff09<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_BUSY<\/code><\/td>\n      <td>\u5fd9\uff0c\u7a0d\u540e\u518d\u8bd5<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>\u7406\u89e3 <code class=\"language-plaintext highlighter-rouge\">NGX_AGAIN<\/code> \u548c <code class=\"language-plaintext highlighter-rouge\">NGX_DECLINED<\/code> \u7684\u533a\u522b\u7279\u522b\u91cd\u8981\u2014\u2014\u524d\u8005\u662f\u201d\u7b49\u4e00\u4f1a\u513f\u6211\u91cd\u8bd5\u201d\uff0c\u540e\u8005\u662f\u201d\u6362\u4e0b\u4e00\u4e2a\u201d\u3002<\/p>\n\n<h3 id=\"35-\u4f18\u96c5\u7684\u96f6\u505c\u673a\">3.5 \u4f18\u96c5\u7684\u96f6\u505c\u673a<\/h3>\n\n<p>\u914d\u7f6e\u91cd\u8f7d\uff08<code class=\"language-plaintext highlighter-rouge\">nginx -s reload<\/code>\uff09\u7684\u6838\u5fc3\u903b\u8f91\uff1a<\/p>\n\n<ol>\n  <li>Master \u6536\u5230 <code class=\"language-plaintext highlighter-rouge\">SIGHUP<\/code> \u2192 \u521b\u5efa\u65b0 <code class=\"language-plaintext highlighter-rouge\">ngx_cycle_t<\/code>\uff0cfork \u65b0 worker<\/li>\n  <li>\u65e7 worker \u6536\u5230 <code class=\"language-plaintext highlighter-rouge\">SIGQUIT<\/code> \u2192 \u4f18\u96c5\u5173\u95ed\uff08\u5904\u7406\u5b8c\u73b0\u6709\u8fde\u63a5\u518d\u9000\u51fa\uff09<\/li>\n  <li>\u65b0\u65e7 worker \u77ed\u6682\u5171\u5b58\uff0c\u65e7 worker \u5173\u95ed\u540e\u65b0 cycle \u63a5\u7ba1<\/li>\n<\/ol>\n\n<p>\u8fd9\u4f9d\u8d56\u4e8e <code class=\"language-plaintext highlighter-rouge\">cycle-&gt;old_cycle<\/code> \u7684\u8bbe\u8ba1\uff1a\u65b0 cycle \u6301\u6709\u65e7 cycle \u5f15\u7528\uff0c\u7b49\u65e7 worker \u9000\u51fa\u540e\u91ca\u653e\u3002<\/p>\n\n<hr \/>\n\n<h2 id=\"\u56db\u8c03\u8bd5\u6280\u5de7\">\u56db\u3001\u8c03\u8bd5\u6280\u5de7<\/h2>\n\n<h3 id=\"41-debug-\u65e5\u5fd7\">4.1 Debug \u65e5\u5fd7<\/h3>\n\n<p>\u7f16\u8bd1\u65f6\u5e26 <code class=\"language-plaintext highlighter-rouge\">--with-debug<\/code>\uff0c\u7136\u540e\u5728\u914d\u7f6e\u4e2d\u8bbe\u7f6e\uff1a<\/p>\n<div class=\"language-nginx highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">error_log<\/span> <span class=\"n\">\/var\/log\/nginx\/debug.log<\/span> <span class=\"s\">debug<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"42-gdb-\u5e38\u7528\u65ad\u70b9\">4.2 GDB \u5e38\u7528\u65ad\u70b9<\/h3>\n\n<pre><code class=\"language-gdb\"># \u4e8b\u4ef6\u5faa\u73af\u5165\u53e3\nb ngx_process_events_and_timers\n\n# \u8bf7\u6c42\u5904\u7406\u5165\u53e3\nb ngx_http_process_request\n\n# \u9636\u6bb5\u5f15\u64ce\nb ngx_http_core_run_phases\n\n# \u8fde\u63a5\u5206\u914d\nb ngx_get_connection\n\n# upstream \u8fde\u63a5\nb ngx_http_upstream_connect\n\n# \u4e00\u4e2a\u8fde\u63a5\u4e0a\u7684\u6240\u6709 recv\/send \u8c03\u7528\nb ngx_unix_recv\nb ngx_unix_send\n<\/code><\/pre>\n\n<h3 id=\"43-\u6253\u5370-ngx_str_t\">4.3 \u6253\u5370 ngx_str_t<\/h3>\n\n<pre><code class=\"language-gdb\"># ngx_str_t \u4e0d\u662f C \u5b57\u7b26\u4e32\uff0c\u5728 GDB \u4e2d\u9700\u8981\u81ea\u5b9a\u4e49\u6253\u5370\ndefine print_ngx_str\n  set $s = (ngx_str_t*)$arg0\n  printf \"%.*s\\n\", $s-&gt;len, $s-&gt;data\nend\n<\/code><\/pre>\n\n<h3 id=\"44-\u8ffd\u8e2a\u5185\u5b58\u5206\u914d\">4.4 \u8ffd\u8e2a\u5185\u5b58\u5206\u914d<\/h3>\n\n<p>\u5728 <code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_palloc.c<\/code> \u7684\u5173\u952e\u51fd\u6570\u6253\u65ad\u70b9\uff1a<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_create_pool<\/code> \u2014 \u6c60\u521b\u5efa<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_palloc<\/code> \u2014 \u5c0f\u5757\u5206\u914d<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_palloc_block<\/code> \u2014 \u5206\u914d\u65b0\u6c60\u5757<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_pfree<\/code> \u2014 \u5927\u5757\u91ca\u653e<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_destroy_pool<\/code> \u2014 \u6c60\u9500\u6bc1<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"\u4e94\u5efa\u8bae\u7684\u9605\u8bfb\u5b9e\u8df5\">\u4e94\u3001\u5efa\u8bae\u7684\u9605\u8bfb\u5b9e\u8df5<\/h2>\n\n<ol>\n  <li><strong>\u4e0d\u8981\u8bd5\u56fe\u6309\u6587\u4ef6\u5e8f\u53f7\u4ece\u5934\u8bfb\u5230\u5c3e<\/strong>\u3002nginx \u7684\u9759\u6001\u51fd\u6570\u548c\u5168\u5c40\u53d8\u91cf\u5f88\u591a\uff0c\u6309\u5934\u6587\u4ef6\u4f9d\u8d56\u5173\u7cfb\u53bb\u8bfb\u3002<\/li>\n  <li><strong>\u6bcf\u6b21\u53ea\u8ffd\u8e2a\u4e00\u4e2a\u529f\u80fd\u94fe\u8def<\/strong>\u3002\u6bd4\u5982 \u201c\u4e00\u4e2a HTTP GET \u8bf7\u6c42\u4ece\u63a5\u6536\u5230\u8fd4\u56de\u7684\u5b8c\u6574\u8def\u5f84\u201d\uff0c\u53ea\u5173\u6ce8\u8fd9\u6761\u7ebf\u4e0a\u7684\u51fd\u6570\uff0c\u5ffd\u7565\u65c1\u8def\u3002<\/li>\n  <li><strong>\u753b\u56fe<\/strong>\u3002nginx \u6e90\u7801\u4e2d\u7684\u7ed3\u6784\u4f53\u5d4c\u5957\u5f88\u6df1\uff0c\u624b\u7ed8\u4ee5\u4e0b\u5173\u7cfb\u56fe\u4f1a\u5f88\u6709\u5e2e\u52a9\uff1a\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_cycle_t<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">conf_ctx<\/code> \u2192 \u5404\u6a21\u5757\u914d\u7f6e\u7684\u7d22\u5f15\u5173\u7cfb<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_connection_t<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">read<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">write<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">ngx_event_t<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">handler<\/code> \u7684\u8c03\u7528\u94fe<\/li>\n      <li>HTTP \u9636\u6bb5\u5f15\u64ce\u4e2d checker \u2192 handler \u2192 next \u7684\u8df3\u8f6c\u5173\u7cfb<\/li>\n      <li>\u8fc7\u6ee4\u5668\u94fe\u4e2d <code class=\"language-plaintext highlighter-rouge\">ngx_http_top_header_filter<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">next<\/code> \u2192 \u2026 \u7684\u987a\u5e8f<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong>\u4ece\u7b80\u5355\u7684\u7b2c\u4e09\u65b9\u6a21\u5757\u5165\u624b<\/strong>\u3002\u9605\u8bfb <code class=\"language-plaintext highlighter-rouge\">src\/http\/modules\/ngx_http_echo_module.c<\/code> \u7ea7\u522b\u7684\u7b80\u5355\u6a21\u5757\uff0c\u7406\u89e3 handler \u548c filter \u600e\u4e48\u5199\u3002<\/li>\n  <li><strong>\u5bf9\u6bd4\u9605\u8bfb<\/strong>\u3002\u5728 <code class=\"language-plaintext highlighter-rouge\">src\/http\/modules\/<\/code> \u4e0b\u627e\u4e24\u4e2a\u7c7b\u4f3c\u529f\u80fd\u7684\u6a21\u5757\u5bf9\u6bd4\uff08\u5982 proxy vs fastcgi\uff09\uff0c\u7406\u89e3\u5dee\u5f02\u5728\u54ea\u91cc\u3002<\/li>\n  <li><strong>\u91cd\u590d\u8bfb\u6838\u5fc3\u51fd\u6570<\/strong>\u3002<code class=\"language-plaintext highlighter-rouge\">ngx_process_events_and_timers()<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">ngx_http_core_run_phases()<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">ngx_conf_parse()<\/code>\u3001<code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_connect()<\/code> \u8fd9\u51e0\u4e2a\u51fd\u6570\u503c\u5f97\u53cd\u590d\u8bfb\uff0c\u6bcf\u6b21\u90fd\u4f1a\u53d1\u73b0\u65b0\u7ec6\u8282\u3002<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"\u516d\u6838\u5fc3\u6587\u4ef6\u7d22\u5f15\">\u516d\u3001\u6838\u5fc3\u6587\u4ef6\u7d22\u5f15<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u6587\u4ef6<\/th>\n      <th style=\"text-align: center\">\u9605\u8bfb\u4f18\u5148\u7ea7<\/th>\n      <th>\u6838\u5fc3\u5185\u5bb9<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/nginx.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">main()<\/code> \u5165\u53e3<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_cycle.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_init_cycle()<\/code> \u5faa\u73af\u521d\u59cb\u5316<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_palloc.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>\u5185\u5b58\u6c60\u5b9e\u73b0<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_buf.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>buffer \u548c chain \u64cd\u4f5c<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_connection.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>\u8fde\u63a5\u9884\u5206\u914d\u548c\u7ba1\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_conf_file.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>\u914d\u7f6e\u89e3\u6790\u5668<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_module.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>\u6a21\u5757\u52a0\u8f7d\u548c\u521d\u59cb\u5316<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_string.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>\u5b57\u7b26\u4e32\u5de5\u5177\u51fd\u6570\u96c6<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_array.h<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>\u52a8\u6001\u6570\u7ec4<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_list.h<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>\u94fe\u8868+\u6570\u7ec4\u6df7\u5408<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_queue.h<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>\u4fb5\u5165\u5f0f\u53cc\u5411\u94fe\u8868<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_rbtree.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>\u7ea2\u9ed1\u6811<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_hash.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>\u9759\u6001\u54c8\u5e0c\u8868<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_log.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>\u65e5\u5fd7\u7cfb\u7edf<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/os\/unix\/ngx_process_cycle.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>master\/worker \u8fdb\u7a0b\u7ba1\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>\u4e8b\u4ef6\u5faa\u73af\u6838\u5fc3<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_accept.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>accept \u4e0e\u60ca\u7fa4\u5904\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_timer.h<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>\u5b9a\u65f6\u5668\u7ba1\u7406<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/event\/modules\/ngx_epoll_module.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>epoll \u4e8b\u4ef6\u6a21\u5757<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>HTTP \u6846\u67b6\u521d\u59cb\u5316<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_request.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>\u8bf7\u6c42\u751f\u547d\u5468\u671f<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_core_module.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>\u6838\u5fc3\u6307\u4ee4\u3001phase checker<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_upstream.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>upstream \u4ee3\u7406\u673a\u5236<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_variables.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>\u53d8\u91cf\u7cfb\u7edf<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_header_filter.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>\u54cd\u5e94\u5934\u5e8f\u5217\u5316<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_write_filter.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>\u6700\u7ec8\u53d1\u9001\u5230 socket<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/modules\/ngx_http_proxy_module.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>\u5178\u578b HTTP \u4ee3\u7406\u6a21\u5757<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/modules\/ngx_http_static_module.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2606\u2606<\/td>\n      <td>\u6700\u7b80\u5355\u7684 content handler<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<blockquote>\n  <p><strong>\u6700\u540e\u5efa\u8bae<\/strong>\uff1a\u8bfb nginx \u6e90\u7801\u662f\u4e00\u573a\u9a6c\u62c9\u677e\uff0c\u4e0d\u662f\u77ed\u8dd1\u3002\u6838\u5fc3\u4ee3\u7801\u5927\u7ea6 10 \u4e07\u884c\uff0c\u4f46\u8bbe\u8ba1\u9ad8\u5ea6\u4e00\u81f4\uff0c\u4e00\u65e6\u638c\u63e1\u4e86\u524d 30% \u7684\u6a21\u5f0f\uff0c\u5269\u4e0b\u7684 70% \u4f1a\u63d0\u901f\u5f88\u5feb\u3002\u795d\u9605\u8bfb\u987a\u5229\u3002<\/p>\n<\/blockquote>\n","category":{"@attributes":{"term":"Nginx"}}},{"title":"Nginx Source Code Reading Guide","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/en\/2026-07-23\/nginx-source-code-guide.html"}},"updated":"2026-07-23T23:45:00+08:00","id":"https:\/\/wy471x.github.io\/en\/2026-07-23\/nginx-source-code-guide.html","content":"<h1 id=\"nginx-source-code-reading-guide\">Nginx Source Code Reading Guide<\/h1>\n\n<h2 id=\"1-preparation\">1. Preparation<\/h2>\n\n<h3 id=\"11-prerequisites\">1.1 Prerequisites<\/h3>\n\n<ul>\n  <li><strong>C Language<\/strong>: pointers, function pointers, macros, bitwise operations, struct memory layout (<code class=\"language-plaintext highlighter-rouge\">offsetof<\/code>), variadic arguments<\/li>\n  <li><strong>Network Programming<\/strong>: TCP\/IP, HTTP\/1.1 protocol, socket API (<code class=\"language-plaintext highlighter-rouge\">accept<\/code>\/<code class=\"language-plaintext highlighter-rouge\">recv<\/code>\/<code class=\"language-plaintext highlighter-rouge\">send<\/code>\/<code class=\"language-plaintext highlighter-rouge\">setsockopt<\/code>), non-blocking I\/O<\/li>\n  <li><strong>Operating Systems<\/strong>: process model (fork), signals, shared memory, epoll\/kqueue multiplexing mechanisms<\/li>\n  <li><strong>Build Tools<\/strong>: ability to read shell scripts and Makefiles<\/li>\n<\/ul>\n\n<h3 id=\"12-environment-setup\">1.2 Environment Setup<\/h3>\n\n<div class=\"language-bash highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c\"># Build nginx with debug info<\/span>\n.\/auto\/configure <span class=\"nt\">--with-debug<\/span> <span class=\"nt\">--prefix<\/span><span class=\"o\">=<\/span><span class=\"si\">$(<\/span><span class=\"nb\">pwd<\/span><span class=\"si\">)<\/span>\/build\nmake <span class=\"nt\">-j<\/span><span class=\"si\">$(<\/span><span class=\"nb\">nproc<\/span><span class=\"si\">)<\/span>\n\n<span class=\"c\"># Debug with GDB<\/span>\ngdb .\/objs\/nginx\n<span class=\"o\">(<\/span>gdb<span class=\"o\">)<\/span> b ngx_process_events_and_timers\n<span class=\"o\">(<\/span>gdb<span class=\"o\">)<\/span> r\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"13-key-macros-and-conventions-quick-reference\">1.3 Key Macros and Conventions Quick Reference<\/h3>\n\n<table>\n  <thead>\n    <tr>\n      <th>Macro\/Pattern<\/th>\n      <th>Meaning<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_OK<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_ERROR<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_AGAIN<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_DECLINED<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_DONE<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_BUSY<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">NGX_ABORT<\/code><\/td>\n      <td>Standard return values: 0\/-1\/-2\/-5\/-4\/-3\/-6<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_string(\"foo\")<\/code><\/td>\n      <td>Compile-time construction of <code class=\"language-plaintext highlighter-rouge\">ngx_str_t<\/code> from a literal<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_queue_data(q, type, link)<\/code><\/td>\n      <td>Retrieve the containing struct from an intrusive queue node<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_rbtree_data(node, type, link)<\/code><\/td>\n      <td>Same as above, for rbtree nodes<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_log_debug<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">ngx_log_error<\/code><\/td>\n      <td>Leveled logging macros; debug level only output with <code class=\"language-plaintext highlighter-rouge\">--with-debug<\/code><\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">offsetof(type, member)<\/code><\/td>\n      <td>Calculate the offset of a member within a struct \u2014 the cornerstone of intrusive data structures<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<h2 id=\"2-recommended-reading-roadmap\">2. Recommended Reading Roadmap<\/h2>\n\n<h3 id=\"step-0-understand-the-build-system-30-min\">Step 0: Understand the Build System (30 min)<\/h3>\n\n<p>Start from the <code class=\"language-plaintext highlighter-rouge\">auto\/<\/code> directory. No need to read every script in detail \u2014 focus on understanding the flow:<\/p>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">auto\/configure<\/code><\/strong> \u2014 Entry point, sequentially calls <code class=\"language-plaintext highlighter-rouge\">auto\/options<\/code>, <code class=\"language-plaintext highlighter-rouge\">auto\/init<\/code>, <code class=\"language-plaintext highlighter-rouge\">auto\/cc\/*<\/code>, <code class=\"language-plaintext highlighter-rouge\">auto\/os\/*<\/code>, <code class=\"language-plaintext highlighter-rouge\">auto\/feature<\/code>, <code class=\"language-plaintext highlighter-rouge\">auto\/modules<\/code>, <code class=\"language-plaintext highlighter-rouge\">auto\/sources<\/code>, <code class=\"language-plaintext highlighter-rouge\">auto\/make<\/code><\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">auto\/modules<\/code><\/strong> \u2014 One of the most critical files. It determines which modules are compiled into the <code class=\"language-plaintext highlighter-rouge\">ngx_modules[]<\/code> array. <strong>The ordering of modules determines initialization order and processing priority \u2014 never change it casually<\/strong><\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">auto\/sources<\/code><\/strong> \u2014 Defines shell variables listing all source files (<code class=\"language-plaintext highlighter-rouge\">CORE_SRCS<\/code>, <code class=\"language-plaintext highlighter-rouge\">HTTP_SRCS<\/code>, etc.), ultimately output to <code class=\"language-plaintext highlighter-rouge\">objs\/Makefile<\/code><\/li>\n<\/ol>\n\n<p>Build artifacts:<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">objs\/ngx_auto_config.h<\/code> \u2014 All <code class=\"language-plaintext highlighter-rouge\">#define<\/code> macros (compile-time feature switches)<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">objs\/ngx_modules.c<\/code> \u2014 Auto-generated <code class=\"language-plaintext highlighter-rouge\">ngx_modules[]<\/code> and <code class=\"language-plaintext highlighter-rouge\">ngx_module_names[]<\/code><\/li>\n<\/ul>\n\n<h3 id=\"step-1-core-data-structures-2-3-hours\">Step 1: Core Data Structures (2-3 hours)<\/h3>\n\n<p><strong>This is the most important foundation \u2014 master it thoroughly.<\/strong> Suggested order by dependency:<\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>ngx_str_t  \u2192  ngx_pool_t  \u2192  ngx_array_t  \u2192  ngx_list_t  \u2192  ngx_queue_t  \u2192  ngx_buf_t \/ ngx_chain_t  \u2192  ngx_rbtree_t\n<\/code><\/pre><\/div><\/div>\n\n<p>Read file by file:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>File<\/th>\n      <th>Key Focus<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_string.h<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_str_t<\/code> is not a C string \u2014 it\u2019s a <code class=\"language-plaintext highlighter-rouge\">len<\/code> + <code class=\"language-plaintext highlighter-rouge\">data<\/code> pair; <code class=\"language-plaintext highlighter-rouge\">ngx_vslprintf<\/code> and other formatting functions<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_palloc.h<\/code> + <code class=\"language-plaintext highlighter-rouge\">ngx_palloc.c<\/code><\/td>\n      <td>Pool allocator: small blocks carved from pool, large blocks via malloc; <code class=\"language-plaintext highlighter-rouge\">ngx_palloc<\/code> vs <code class=\"language-plaintext highlighter-rouge\">ngx_pnalloc<\/code> (aligned vs unaligned); cleanup callback mechanism<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_array.h<\/code><\/td>\n      <td>Dynamic array, elements stored contiguously; <code class=\"language-plaintext highlighter-rouge\">ngx_array_push<\/code> returns a pointer to the new element<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_list.h<\/code><\/td>\n      <td>Hybrid of linked list + array; each <code class=\"language-plaintext highlighter-rouge\">part<\/code> holds <code class=\"language-plaintext highlighter-rouge\">nalloc<\/code> elements<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_queue.h<\/code><\/td>\n      <td><strong>Pure macros<\/strong>, intrusive doubly-linked circular list; the core macro <code class=\"language-plaintext highlighter-rouge\">ngx_queue_data<\/code> uses <code class=\"language-plaintext highlighter-rouge\">offsetof<\/code> to retrieve the container<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_buf.h<\/code> + <code class=\"language-plaintext highlighter-rouge\">ngx_buf.c<\/code><\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_buf_t<\/code> unifies memory data and file data; <code class=\"language-plaintext highlighter-rouge\">ngx_chain_t<\/code> forms a data pipeline<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_rbtree.h<\/code> + <code class=\"language-plaintext highlighter-rouge\">ngx_rbtree.c<\/code><\/td>\n      <td>Red-black tree, sentinel node instead of NULL, custom insert function; <code class=\"language-plaintext highlighter-rouge\">ngx_rbtree_data<\/code> retrieves the container<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<h3 id=\"step-2-process-model-and-event-loop-2-3-hours\">Step 2: Process Model and Event Loop (2-3 hours)<\/h3>\n\n<p>This is the core of understanding nginx runtime behavior.<\/p>\n\n<p><strong>Reading order<\/strong>:<\/p>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/os\/unix\/ngx_process_cycle.c<\/code><\/strong> \u2014 The real entry point after <code class=\"language-plaintext highlighter-rouge\">main()<\/code>\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_master_process_cycle()<\/code> \u2014 Master process loop (signal handling, worker management)<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_single_process_cycle()<\/code> \u2014 Single process mode (for debugging)<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_worker_process_cycle()<\/code> \u2014 <strong>The main loop of a worker process<\/strong> (most critical reading target)<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_start_worker_processes()<\/code> \u2014 How workers are forked<\/li>\n      <li>Key focus: the switching logic between old and new workers during hot reload (HUP signal)<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event.c<\/code><\/strong> \u2014 Event subsystem core\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_event_process_init()<\/code> \u2014 Event initialization when a worker starts (creates connection pool, event pool)<\/li>\n      <li><strong><code class=\"language-plaintext highlighter-rouge\">ngx_process_events_and_timers()<\/code><\/strong> \u2014 The heart of the event loop, four steps per iteration:\n        <div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>\u2460 ngx_event_find_timer()       -- Find the soonest-expiring timer from the rbtree\n\u2461 ngx_process_events()         -- Call epoll_wait \/ kqueue etc.\n\u2462 ngx_event_expire_timers()    -- Process expired timers\n\u2463 ngx_event_process_posted()   -- Process deferred posted events\n<\/code><\/pre><\/div>        <\/div>\n      <\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_timer.h<\/code><\/strong> \u2014 Timer management\n    <ul>\n      <li>Global rbtree <code class=\"language-plaintext highlighter-rouge\">ngx_event_timer_rbtree<\/code>, keyed by <code class=\"language-plaintext highlighter-rouge\">expiry = ngx_current_msec + delay<\/code><\/li>\n      <li>Lazy delay optimization: 300ms threshold to avoid frequent rbtree updates<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_posted.h<\/code><\/strong> \u2014 Deferred event mechanism\n    <ul>\n      <li>Three global queues: <code class=\"language-plaintext highlighter-rouge\">ngx_posted_accept_events<\/code>, <code class=\"language-plaintext highlighter-rouge\">ngx_posted_events<\/code>, <code class=\"language-plaintext highlighter-rouge\">ngx_posted_next_events<\/code><\/li>\n      <li>Used to avoid reentrancy and enable batch processing<\/li>\n    <\/ul>\n  <\/li>\n<\/ol>\n\n<h3 id=\"step-3-connection-management-1-2-hours\">Step 3: Connection Management (1-2 hours)<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_connection.h<\/code><\/strong> \u2014 Two core structs\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_connection_t<\/code>: One instance per connection, contains fd, read\/write events, I\/O function pointers (swapped by SSL\/QUIC), status bits<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_listening_t<\/code>: One instance per listening socket, contains accept callback, SSL\/QUIC flags<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_connection.c<\/code><\/strong>\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_open_listening_sockets()<\/code> \u2014 Open all listening ports<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_get_connection()<\/code> \u2014 Get a free connection from the pre-allocated array<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_close_connection()<\/code> \u2014 Return a connection to the free list<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_accept.c<\/code><\/strong>\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_event_accept()<\/code> \u2014 Accept handler, accept mutex logic<\/li>\n    <\/ul>\n  <\/li>\n<\/ol>\n\n<p>Key design: <strong>instance bit<\/strong> solves the stale event problem<\/p>\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>Every time a connection is reused, the instance bit flips.\nWhen epoll\/kqueue returns a stale event,\nthe instance bit mismatch is detected \u2192 the event is discarded.\nThis avoids extra syscalls to verify event validity.\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"step-4-configuration-system-2-hours\">Step 4: Configuration System (2 hours)<\/h3>\n\n<p>nginx\u2019s configuration parser is a <strong>recursive descent parser<\/strong> \u2014 the foundation upon which the entire module system operates.<\/p>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_conf_file.h<\/code><\/strong> \u2014 Core types\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_command_t<\/code>: Definition of each configuration directive (name, argument rules, set function, offset)<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_conf_t<\/code>: Parse context<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_conf_file.c<\/code><\/strong>\n    <ul>\n      <li><strong><code class=\"language-plaintext highlighter-rouge\">ngx_conf_parse()<\/code><\/strong> \u2014 Recursive parse entry point; calls itself recursively for block directives<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_conf_handler()<\/code> \u2014 Dispatches to a module\u2019s set function<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong>Argument type flags quick reference<\/strong>:\n    <div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>NGX_CONF_NOARGS         -- No arguments (e.g., \"off\" in \"accept_mutex off;\" is a flag, not an argument)\nNGX_CONF_TAKE1~7        -- Exactly N arguments\nNGX_CONF_TAKE12         -- 1 or 2 arguments\nNGX_CONF_FLAG           -- Boolean (on\/off)\nNGX_CONF_BLOCK          -- Followed by a {} block\nNGX_CONF_1MORE          -- At least 1 argument\n<\/code><\/pre><\/div>    <\/div>\n  <\/li>\n  <li>\n    <p><strong>Setter function family<\/strong>: <code class=\"language-plaintext highlighter-rouge\">ngx_conf_set_flag_slot<\/code>, <code class=\"language-plaintext highlighter-rouge\">ngx_conf_set_str_slot<\/code>, <code class=\"language-plaintext highlighter-rouge\">ngx_conf_set_num_slot<\/code>, <code class=\"language-plaintext highlighter-rouge\">ngx_conf_set_size_slot<\/code>, <code class=\"language-plaintext highlighter-rouge\">ngx_conf_set_msec_slot<\/code>, etc. \u2014 the basic building blocks of configuration parsing.<\/p>\n  <\/li>\n  <li><strong>Configuration merge macros<\/strong>:\n    <div class=\"language-c highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"n\">ngx_conf_merge_value<\/span><span class=\"p\">(<\/span><span class=\"n\">conf<\/span><span class=\"p\">,<\/span> <span class=\"n\">prev<\/span><span class=\"p\">,<\/span> <span class=\"k\">default<\/span><span class=\"p\">)<\/span>   <span class=\"c1\">\/\/ Numeric: current \u2192 parent \u2192 default<\/span>\n<span class=\"n\">ngx_conf_merge_str_value<\/span><span class=\"p\">(<\/span><span class=\"n\">conf<\/span><span class=\"p\">,<\/span> <span class=\"n\">prev<\/span><span class=\"p\">,<\/span> <span class=\"k\">default<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">ngx_conf_merge_msec_value<\/span><span class=\"p\">(<\/span><span class=\"n\">conf<\/span><span class=\"p\">,<\/span> <span class=\"n\">prev<\/span><span class=\"p\">,<\/span> <span class=\"k\">default<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre><\/div>    <\/div>\n    <p>These embody nginx\u2019s three-level fallback mechanism for configuration inheritance.<\/p>\n  <\/li>\n<\/ol>\n\n<h3 id=\"step-5-module-system-1-2-hours\">Step 5: Module System (1-2 hours)<\/h3>\n\n<ol>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_module.h<\/code><\/strong> \u2014 The <code class=\"language-plaintext highlighter-rouge\">ngx_module_t<\/code> struct\n    <ul>\n      <li>Global index <code class=\"language-plaintext highlighter-rouge\">index<\/code> and type-specific index <code class=\"language-plaintext highlighter-rouge\">ctx_index<\/code><\/li>\n      <li>Type-specific <code class=\"language-plaintext highlighter-rouge\">ctx<\/code> pointer<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">commands<\/code> array (configuration directive definitions)<\/li>\n      <li>Lifecycle hooks: <code class=\"language-plaintext highlighter-rouge\">init_master<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">init_module<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">init_process<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">exit_process<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">exit_master<\/code><\/li>\n    <\/ul>\n  <\/li>\n  <li><strong>Module types<\/strong>:\n    <div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>NGX_CORE_MODULE    -- Core modules (e.g., ngx_core_module, ngx_events_module, ngx_http_module)\nNGX_EVENT_MODULE   -- Event modules (e.g., ngx_epoll_module, ngx_kqueue_module)\nNGX_HTTP_MODULE    -- HTTP modules\nNGX_MAIL_MODULE    -- Mail modules\nNGX_STREAM_MODULE  -- Stream modules\n<\/code><\/pre><\/div>    <\/div>\n  <\/li>\n  <li><strong><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_module.c<\/code><\/strong>\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_cycle_modules()<\/code> \u2014 Copy the module array into the cycle<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_init_modules()<\/code> \u2014 Call each module\u2019s <code class=\"language-plaintext highlighter-rouge\">init_module<\/code><\/li>\n    <\/ul>\n  <\/li>\n  <li><strong>HTTP module-specific context<\/strong> <code class=\"language-plaintext highlighter-rouge\">ngx_http_module_t<\/code>:\n    <div class=\"language-c highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">typedef<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">ngx_int_t<\/span>   <span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">preconfiguration<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">);<\/span>\n    <span class=\"n\">ngx_int_t<\/span>   <span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">postconfiguration<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">void<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">create_main_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">char<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">init_main_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">,<\/span> <span class=\"kt\">void<\/span> <span class=\"o\">*<\/span><span class=\"n\">conf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">void<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">create_srv_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">char<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">merge_srv_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">,<\/span> <span class=\"kt\">void<\/span> <span class=\"o\">*<\/span><span class=\"n\">prev<\/span><span class=\"p\">,<\/span> <span class=\"kt\">void<\/span> <span class=\"o\">*<\/span><span class=\"n\">conf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">void<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">create_loc_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">);<\/span>\n    <span class=\"kt\">char<\/span>       <span class=\"o\">*<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">merge_loc_conf<\/span><span class=\"p\">)(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">,<\/span> <span class=\"kt\">void<\/span> <span class=\"o\">*<\/span><span class=\"n\">prev<\/span><span class=\"p\">,<\/span> <span class=\"kt\">void<\/span> <span class=\"o\">*<\/span><span class=\"n\">conf<\/span><span class=\"p\">);<\/span>\n<span class=\"p\">}<\/span> <span class=\"n\">ngx_http_module_t<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre><\/div>    <\/div>\n    <p><strong>This is key to understanding how HTTP modules work<\/strong>: the creation and merging of main \u2192 srv \u2192 loc three-level configurations all happen here.<\/p>\n  <\/li>\n<\/ol>\n\n<h3 id=\"step-6-http-request-processing-pipeline-4-5-hours--core\">Step 6: HTTP Request Processing Pipeline (4-5 hours) \u2b50 Core<\/h3>\n\n<p>This is the most important and complex part of the nginx source code \u2014 read it repeatedly.<\/p>\n\n<h4 id=\"61-http-framework-initialization\">6.1 HTTP Framework Initialization<\/h4>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http.c<\/code><\/strong><\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_http_block()<\/code> \u2014 The parse function for the <code class=\"language-plaintext highlighter-rouge\">http {}<\/code> block\n    <ul>\n      <li>Creates main\/srv\/loc three-level configurations<\/li>\n      <li>Initializes the phase engine<\/li>\n      <li>Calls each module\u2019s <code class=\"language-plaintext highlighter-rouge\">postconfiguration<\/code> (handlers and filters are registered here)<\/li>\n      <li>Initializes request header parsing tables and the variable system<\/li>\n    <\/ul>\n  <\/li>\n<\/ul>\n\n<h4 id=\"62-the-11-processing-phases\">6.2 The 11 Processing Phases<\/h4>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_core_module.h<\/code><\/strong><\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>NGX_HTTP_POST_READ_PHASE       -- After reading request headers (realip module lives here)\nNGX_HTTP_SERVER_REWRITE_PHASE  -- Server-level rewrite\nNGX_HTTP_FIND_CONFIG_PHASE     -- Location matching\nNGX_HTTP_REWRITE_PHASE         -- Location-level rewrite\nNGX_HTTP_POST_REWRITE_PHASE    -- After rewrite (checks for redirect loops)\nNGX_HTTP_PREACCESS_PHASE       -- Access limits (limit_conn, limit_req)\nNGX_HTTP_ACCESS_PHASE          -- Authorization checks (allow\/deny, auth_basic, auth_request)\nNGX_HTTP_POST_ACCESS_PHASE     -- After access (handles satisfy all\/any)\nNGX_HTTP_PRECONTENT_PHASE      -- Before content generation (mirror, try_files)\nNGX_HTTP_CONTENT_PHASE         -- Generate response content (proxy_pass, fastcgi_pass, static)\nNGX_HTTP_LOG_PHASE             -- Logging (after request processing is complete)\n<\/code><\/pre><\/div><\/div>\n\n<p>Each phase is driven by a <strong>checker function<\/strong> that sequentially invokes the handlers registered for that phase. Key checkers:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Checker<\/th>\n      <th>Phase<\/th>\n      <th>Behavior<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_http_core_generic_phase<\/code><\/td>\n      <td>rewrite, etc.<\/td>\n      <td>Sequential execution, DECLINED \u2192 next handler<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_http_core_find_config_phase<\/code><\/td>\n      <td>find_config<\/td>\n      <td>Match location, executes only once<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_http_core_access_phase<\/code><\/td>\n      <td>access<\/td>\n      <td>Supports satisfy all\/any<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_http_core_content_phase<\/code><\/td>\n      <td>content<\/td>\n      <td>Finds the first handler that returns OK<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>Reading entry point: <strong><code class=\"language-plaintext highlighter-rouge\">ngx_http_core_run_phases()<\/code><\/strong><\/p>\n\n<h4 id=\"63-request-lifecycle\">6.3 Request Lifecycle<\/h4>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_request.h<\/code><\/strong> \u2014 <code class=\"language-plaintext highlighter-rouge\">ngx_http_request_t<\/code> struct (very large, ~60+ fields)<\/p>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_request.c<\/code><\/strong> \u2014 Read the following functions in order:<\/p>\n\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>New connection arrives:\n  ngx_http_init_connection()\n    \u2192 ngx_http_wait_request_handler()      -- Wait for the complete request header to arrive\n\nRequest header parsed:\n  ngx_http_process_request_line()\n    \u2192 ngx_http_process_request_headers()\n      \u2192 ngx_http_process_request()\n        \u2192 ngx_http_process_request_headers()  -- Parse Host, Content-Length, etc.\n        \u2192 ngx_http_handler()                  -- Set r-&gt;phase_handler = 0\n          \u2192 ngx_http_core_run_phases(r)       -- Drive the phase engine\n\nResponse sending:\n  ngx_http_writer()                         -- Asynchronously send the response body\n\nRequest finished:\n  ngx_http_finalize_request()\n    \u2192 ngx_http_free_request()\n      \u2192 ngx_destroy_pool(r-&gt;pool)          -- Destroy the request memory pool\n<\/code><\/pre><\/div><\/div>\n\n<h4 id=\"64-filter-chain\">6.4 Filter Chain<\/h4>\n\n<p>nginx output is not produced by a single module in one shot \u2014 it is collaboratively generated through a <strong>filter chain<\/strong> (Chain of Responsibility pattern).<\/p>\n\n<p><strong>Header filter chain<\/strong>:<\/p>\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>ngx_http_top_header_filter\n  \u2192 ngx_http_not_modified_header_filter\n  \u2192 ...\n  \u2192 ngx_http_gzip_header_filter\n  \u2192 ...\n  \u2192 ngx_http_header_filter          -- Ultimately serializes HTTP headers into a byte stream\n<\/code><\/pre><\/div><\/div>\n\n<p><strong>Body filter chain<\/strong>:<\/p>\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>ngx_http_top_body_filter\n  \u2192 ngx_http_range_body_filter\n  \u2192 ngx_http_copy_filter            -- Copies in_file bufs to memory when necessary\n  \u2192 ngx_http_gzip_body_filter\n  \u2192 ngx_http_chunked_body_filter\n  \u2192 ngx_http_write_filter           -- Ultimately calls c-&gt;send_chain() to send\n<\/code><\/pre><\/div><\/div>\n\n<p>Filter registration pattern:<\/p>\n<div class=\"language-c highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">\/\/ Register in postconfiguration:<\/span>\n<span class=\"k\">static<\/span> <span class=\"n\">ngx_int_t<\/span>\n<span class=\"nf\">ngx_http_my_init<\/span><span class=\"p\">(<\/span><span class=\"n\">ngx_conf_t<\/span> <span class=\"o\">*<\/span><span class=\"n\">cf<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">{<\/span>\n    <span class=\"n\">ngx_http_next_header_filter<\/span>  <span class=\"o\">=<\/span> <span class=\"n\">ngx_http_top_header_filter<\/span><span class=\"p\">;<\/span>\n    <span class=\"n\">ngx_http_top_header_filter<\/span>   <span class=\"o\">=<\/span> <span class=\"n\">ngx_http_my_header_filter<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"n\">ngx_http_next_body_filter<\/span>    <span class=\"o\">=<\/span> <span class=\"n\">ngx_http_top_body_filter<\/span><span class=\"p\">;<\/span>\n    <span class=\"n\">ngx_http_top_body_filter<\/span>     <span class=\"o\">=<\/span> <span class=\"n\">ngx_http_my_body_filter<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">NGX_OK<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre><\/div><\/div>\n<p>Note: <strong>the last registered executes first<\/strong> (because each is inserted at the head of the chain).<\/p>\n\n<h4 id=\"65-location-matching\">6.5 Location Matching<\/h4>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_core_module.c<\/code><\/strong><\/p>\n\n<p>The matching algorithm in <code class=\"language-plaintext highlighter-rouge\">ngx_http_core_find_config_phase()<\/code>:<\/p>\n<ol>\n  <li>Use <code class=\"language-plaintext highlighter-rouge\">ngx_hash_lookup()<\/code> on the <code class=\"language-plaintext highlighter-rouge\">locations<\/code> hash table for <strong>prefix matching<\/strong><\/li>\n  <li>If the matched location has nested locations, search recursively<\/li>\n  <li>Finally, use the <code class=\"language-plaintext highlighter-rouge\">regex_locations<\/code> queue for <strong>regex matching<\/strong> (highest priority, using <code class=\"language-plaintext highlighter-rouge\">=~<\/code> or <code class=\"language-plaintext highlighter-rouge\">~*<\/code>)<\/li>\n<\/ol>\n\n<p><strong>Configuration merge path<\/strong>: after matching a location, its <code class=\"language-plaintext highlighter-rouge\">loc_conf[module_index]<\/code> has already correctly inherited from server and main level configurations via <code class=\"language-plaintext highlighter-rouge\">merge_loc_conf<\/code> during the parsing phase.<\/p>\n\n<h4 id=\"66-upstream-mechanism\">6.6 Upstream Mechanism<\/h4>\n\n<p><strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_upstream.h<\/code><\/strong> + <strong><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_upstream.c<\/code><\/strong><\/p>\n\n<p>The upstream state machine:<\/p>\n<div class=\"language-plaintext highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code>ngx_http_upstream_init()\n  \u2192 ngx_http_upstream_connect()           -- Establish connection to backend\n    \u2192 ngx_http_upstream_send_request()    -- Send request body\n      \u2192 ngx_http_upstream_process_header()  -- Parse response header\n        \u2192 ngx_http_upstream_process_body_in_memory() or sendfile\/pipe -- Forward response body\n          \u2192 ngx_http_upstream_finalize_request()\n<\/code><\/pre><\/div><\/div>\n\n<p>Load balancing is <strong>pluggable<\/strong> via the <code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_peer_t<\/code> interface:<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_round_robin.c<\/code> \u2014 Weighted round-robin (default)<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_hash_module.c<\/code> \u2014 Consistent hashing<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_least_conn_module.c<\/code> \u2014 Least connections<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_random_module.c<\/code> \u2014 Random selection<\/li>\n<\/ul>\n\n<h3 id=\"step-7-supplementary-reading-as-needed\">Step 7: Supplementary Reading (as needed)<\/h3>\n\n<ol>\n  <li><strong>Logging System<\/strong>: <code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_log.h<\/code> + <code class=\"language-plaintext highlighter-rouge\">ngx_log.c<\/code> \u2014 <code class=\"language-plaintext highlighter-rouge\">ngx_log_t<\/code> leveled logging, chained log objects<\/li>\n  <li><strong>Variable System<\/strong>: <code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_variables.c<\/code> \u2014 How variables like <code class=\"language-plaintext highlighter-rouge\">$remote_addr<\/code>, <code class=\"language-plaintext highlighter-rouge\">$host<\/code> are registered and evaluated<\/li>\n  <li><strong>Regex Engine<\/strong>: <code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_regex.c<\/code> \u2014 Wrapper around PCRE (nginx does not implement its own regex engine)<\/li>\n  <li><strong>Shared Memory &amp; Slab Allocator<\/strong>: <code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_slab.c<\/code> \u2014 Slab allocator for multi-process shared data<\/li>\n  <li><strong>SSL\/TLS<\/strong>: <code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_openssl.c<\/code> \u2014 How SSL is implemented by swapping <code class=\"language-plaintext highlighter-rouge\">c-&gt;recv\/send<\/code> function pointers<\/li>\n  <li><strong>HTTP\/2<\/strong>: <code class=\"language-plaintext highlighter-rouge\">src\/http\/v2\/<\/code> \u2014 HTTP\/2 frame parsing and multiplexing<\/li>\n  <li><strong>QUIC\/HTTP\/3<\/strong>: <code class=\"language-plaintext highlighter-rouge\">src\/event\/quic\/<\/code> + <code class=\"language-plaintext highlighter-rouge\">src\/http\/v3\/<\/code> \u2014 QUIC transport layer and HTTP\/3 implementation<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"3-design-patterns-and-mindset-throughout\">3. Design Patterns and Mindset Throughout<\/h2>\n\n<h3 id=\"31-intrusive-data-structures\">3.1 Intrusive Data Structures<\/h3>\n\n<p>nginx does not separately allocate list nodes or tree nodes. Instead, <code class=\"language-plaintext highlighter-rouge\">ngx_queue_t<\/code> and <code class=\"language-plaintext highlighter-rouge\">ngx_rbtree_node_t<\/code> are <strong>directly embedded<\/strong> in the structs that use them. Zero extra allocation, extreme efficiency.<\/p>\n\n<div class=\"language-c highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"c1\">\/\/ Not: list&lt;Item*&gt; items (malloc a node for every insertion)<\/span>\n<span class=\"c1\">\/\/ Instead: Item contains ngx_queue_t queue, linked in directly<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"32-pre-allocation--reuse\">3.2 Pre-allocation + Reuse<\/h3>\n\n<p>Connections, events, memory pools \u2014 all pre-allocated at startup, no <code class=\"language-plaintext highlighter-rouge\">malloc<\/code> at runtime. nginx\u2019s philosophy: <strong>\u201cWhatever maximum resources I can calculate at startup, I pre-allocate.\u201d<\/strong><\/p>\n\n<h3 id=\"33-io-function-pointer-polymorphism\">3.3 I\/O Function Pointer Polymorphism<\/h3>\n\n<div class=\"language-c highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"n\">c<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">recv<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ngx_ssl_recv<\/span><span class=\"p\">;<\/span>   <span class=\"c1\">\/\/ SSL module silently swaps these<\/span>\n<span class=\"n\">c<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">send<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ngx_ssl_send<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre><\/div><\/div>\n<p>Higher-level code (the HTTP framework) is completely unaware whether the underlying transport is TCP, SSL, or QUIC. This is nginx\u2019s key technique for protocol upgrades and SSL transparency.<\/p>\n\n<h3 id=\"34-return-value-driven-control-flow\">3.4 Return-Value-Driven Control Flow<\/h3>\n\n<p>nginx does not use exceptions or <code class=\"language-plaintext highlighter-rouge\">goto<\/code>. Instead, control intent is expressed through return values:<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Return Value<\/th>\n      <th>Semantics<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_OK<\/code><\/td>\n      <td>Done, caller continues<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_ERROR<\/code><\/td>\n      <td>Error, abort<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_AGAIN<\/code><\/td>\n      <td>Insufficient resources (buffer full, data not arrived yet), pause and wait for the next event trigger<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_DECLINED<\/code><\/td>\n      <td>I won\u2019t handle this, try the next one (core of handler singly-linked list traversal)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_DONE<\/code><\/td>\n      <td>Handled, but the request is not finished (async operation pending)<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">NGX_BUSY<\/code><\/td>\n      <td>Busy, retry later<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>Understanding the difference between <code class=\"language-plaintext highlighter-rouge\">NGX_AGAIN<\/code> and <code class=\"language-plaintext highlighter-rouge\">NGX_DECLINED<\/code> is particularly important \u2014 the former means \u201cwait a bit and I\u2019ll retry\u201d, the latter means \u201cmove on to the next one.\u201d<\/p>\n\n<h3 id=\"35-graceful-zero-downtime\">3.5 Graceful Zero-Downtime<\/h3>\n\n<p>The core logic of configuration reload (<code class=\"language-plaintext highlighter-rouge\">nginx -s reload<\/code>):<\/p>\n\n<ol>\n  <li>Master receives <code class=\"language-plaintext highlighter-rouge\">SIGHUP<\/code> \u2192 creates a new <code class=\"language-plaintext highlighter-rouge\">ngx_cycle_t<\/code>, forks new workers<\/li>\n  <li>Old workers receive <code class=\"language-plaintext highlighter-rouge\">SIGQUIT<\/code> \u2192 graceful shutdown (finish existing connections before exiting)<\/li>\n  <li>Old and new workers briefly coexist; once old workers exit, the new cycle takes over<\/li>\n<\/ol>\n\n<p>This relies on the <code class=\"language-plaintext highlighter-rouge\">cycle-&gt;old_cycle<\/code> design: the new cycle holds a reference to the old cycle, releasing it after old workers exit.<\/p>\n\n<hr \/>\n\n<h2 id=\"4-debugging-tips\">4. Debugging Tips<\/h2>\n\n<h3 id=\"41-debug-logging\">4.1 Debug Logging<\/h3>\n\n<p>Build with <code class=\"language-plaintext highlighter-rouge\">--with-debug<\/code>, then set in the configuration:<\/p>\n<div class=\"language-nginx highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">error_log<\/span> <span class=\"n\">\/var\/log\/nginx\/debug.log<\/span> <span class=\"s\">debug<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h3 id=\"42-common-gdb-breakpoints\">4.2 Common GDB Breakpoints<\/h3>\n\n<pre><code class=\"language-gdb\"># Event loop entry\nb ngx_process_events_and_timers\n\n# Request processing entry\nb ngx_http_process_request\n\n# Phase engine\nb ngx_http_core_run_phases\n\n# Connection allocation\nb ngx_get_connection\n\n# Upstream connection\nb ngx_http_upstream_connect\n\n# All recv\/send calls on a connection\nb ngx_unix_recv\nb ngx_unix_send\n<\/code><\/pre>\n\n<h3 id=\"43-printing-ngx_str_t\">4.3 Printing ngx_str_t<\/h3>\n\n<pre><code class=\"language-gdb\"># ngx_str_t is not a C string \u2014 needs custom printing in GDB\ndefine print_ngx_str\n  set $s = (ngx_str_t*)$arg0\n  printf \"%.*s\\n\", $s-&gt;len, $s-&gt;data\nend\n<\/code><\/pre>\n\n<h3 id=\"44-tracing-memory-allocation\">4.4 Tracing Memory Allocation<\/h3>\n\n<p>Set breakpoints at key functions in <code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_palloc.c<\/code>:<\/p>\n<ul>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_create_pool<\/code> \u2014 Pool creation<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_palloc<\/code> \u2014 Small block allocation<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_palloc_block<\/code> \u2014 Allocate new pool block<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_pfree<\/code> \u2014 Large block free<\/li>\n  <li><code class=\"language-plaintext highlighter-rouge\">ngx_destroy_pool<\/code> \u2014 Pool destruction<\/li>\n<\/ul>\n\n<hr \/>\n\n<h2 id=\"5-recommended-reading-practices\">5. Recommended Reading Practices<\/h2>\n\n<ol>\n  <li><strong>Don\u2019t try to read sequentially by file number<\/strong>. nginx has many static functions and global variables. Read by header file dependency relationships.<\/li>\n  <li><strong>Trace one functional path at a time<\/strong>. For example, \u201cthe complete path of an HTTP GET request from reception to response\u201d \u2014 only focus on functions on this path, ignore side branches.<\/li>\n  <li><strong>Draw diagrams<\/strong>. Struct nesting in nginx source code is very deep. Hand-drawing the following relationship diagrams will be very helpful:\n    <ul>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_cycle_t<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">conf_ctx<\/code> \u2192 indexing relationships of each module\u2019s configuration<\/li>\n      <li><code class=\"language-plaintext highlighter-rouge\">ngx_connection_t<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">read<\/code> \/ <code class=\"language-plaintext highlighter-rouge\">write<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">ngx_event_t<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">handler<\/code> call chain<\/li>\n      <li>The checker \u2192 handler \u2192 next jump relationships in the HTTP phase engine<\/li>\n      <li>The <code class=\"language-plaintext highlighter-rouge\">ngx_http_top_header_filter<\/code> \u2192 <code class=\"language-plaintext highlighter-rouge\">next<\/code> \u2192 \u2026 order in the filter chain<\/li>\n    <\/ul>\n  <\/li>\n  <li><strong>Start from simple third-party modules<\/strong>. Read simple modules at the level of <code class=\"language-plaintext highlighter-rouge\">src\/http\/modules\/ngx_http_echo_module.c<\/code> to understand how handlers and filters are written.<\/li>\n  <li><strong>Comparative reading<\/strong>. Find two modules with similar functionality under <code class=\"language-plaintext highlighter-rouge\">src\/http\/modules\/<\/code> (e.g., proxy vs fastcgi) and understand where they differ.<\/li>\n  <li><strong>Re-read core functions<\/strong>. <code class=\"language-plaintext highlighter-rouge\">ngx_process_events_and_timers()<\/code>, <code class=\"language-plaintext highlighter-rouge\">ngx_http_core_run_phases()<\/code>, <code class=\"language-plaintext highlighter-rouge\">ngx_conf_parse()<\/code>, <code class=\"language-plaintext highlighter-rouge\">ngx_http_upstream_connect()<\/code> \u2014 these functions are worth reading repeatedly; you\u2019ll discover new details each time.<\/li>\n<\/ol>\n\n<hr \/>\n\n<h2 id=\"6-core-file-index\">6. Core File Index<\/h2>\n\n<table>\n  <thead>\n    <tr>\n      <th>File<\/th>\n      <th style=\"text-align: center\">Priority<\/th>\n      <th>Core Content<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/nginx.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">main()<\/code> entry point<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_cycle.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td><code class=\"language-plaintext highlighter-rouge\">ngx_init_cycle()<\/code> cycle initialization<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_palloc.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Memory pool implementation<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_buf.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Buffer and chain operations<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_connection.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Connection pre-allocation and management<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_conf_file.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Configuration parser<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_module.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Module loading and initialization<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_string.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>String utility function collection<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_array.h<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Dynamic array<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_list.h<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Linked list + array hybrid<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_queue.h<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Intrusive doubly-linked list<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_rbtree.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>Red-black tree<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_hash.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>Static hash table<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/core\/ngx_log.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>Logging system<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/os\/unix\/ngx_process_cycle.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Master\/worker process management<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Event loop core<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_accept.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>Accept and thundering herd handling<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/event\/ngx_event_timer.h<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>Timer management<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/event\/modules\/ngx_epoll_module.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>epoll event module<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>HTTP framework initialization<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_request.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Request lifecycle<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_core_module.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Core directives, phase checkers<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_upstream.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2605<\/td>\n      <td>Upstream proxy mechanism<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_variables.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>Variable system<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_header_filter.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>Response header serialization<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/ngx_http_write_filter.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>Final send to socket<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/modules\/ngx_http_proxy_module.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2605\u2606<\/td>\n      <td>Typical HTTP proxy module<\/td>\n    <\/tr>\n    <tr>\n      <td><code class=\"language-plaintext highlighter-rouge\">src\/http\/modules\/ngx_http_static_module.c<\/code><\/td>\n      <td style=\"text-align: center\">\u2605\u2606\u2606<\/td>\n      <td>Simplest content handler<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<hr \/>\n\n<blockquote>\n  <p><strong>Final advice<\/strong>: Reading the nginx source code is a marathon, not a sprint. The core code is about 100K lines, but the design is highly consistent. Once you master the patterns in the first 30%, the remaining 70% will go much faster. Happy reading!<\/p>\n<\/blockquote>\n","category":{"@attributes":{"term":"Nginx"}}},{"title":"Problem 177: \u7b2cN\u9ad8\u7684\u85aa\u6c34","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/2021-02-23\/problem-177-nth-highest-salary.html"}},"updated":"2021-02-23T08:05:02+08:00","id":"https:\/\/wy471x.github.io\/2021-02-23\/problem-177-nth-highest-salary.html","content":"<h2 id=\"177-\u7b2cn\u9ad8\u7684\u85aa\u6c34\"><a href=\"https:\/\/leetcode-cn.com\/problems\/nth-highest-salary\/\">177. \u7b2cN\u9ad8\u7684\u85aa\u6c34<\/a><\/h2>\n\n<p>\u7f16\u5199\u4e00\u4e2a SQL \u67e5\u8be2\uff0c\u83b7\u53d6 Employee \u8868\u4e2d\u7b2c n \u9ad8\u7684\u85aa\u6c34\uff08Salary\uff09\u3002<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Id<\/th>\n      <th>Salary<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>1<\/td>\n      <td>100<\/td>\n    <\/tr>\n    <tr>\n      <td>2<\/td>\n      <td>200<\/td>\n    <\/tr>\n    <tr>\n      <td>3<\/td>\n      <td>300<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>\u4f8b\u5982\u4e0a\u8ff0 Employee \u8868\uff0cn = 2 \u65f6\uff0c\u5e94\u8fd4\u56de\u7b2c\u4e8c\u9ad8\u7684\u85aa\u6c34 200\u3002\u5982\u679c\u4e0d\u5b58\u5728\u7b2c n \u9ad8\u7684\u85aa\u6c34\uff0c\u90a3\u4e48\u67e5\u8be2\u5e94\u8fd4\u56de null\u3002<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>getNthHighestSalary(2)<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>200<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>sql\u811a\u672c\uff1a<\/p>\n\n<div class=\"language-sql highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">Create<\/span> <span class=\"k\">table<\/span> <span class=\"n\">If<\/span> <span class=\"k\">Not<\/span> <span class=\"k\">Exists<\/span> <span class=\"n\">Employee<\/span> <span class=\"p\">(<\/span><span class=\"n\">Id<\/span> <span class=\"nb\">int<\/span><span class=\"p\">,<\/span> <span class=\"n\">Salary<\/span> <span class=\"nb\">int<\/span><span class=\"p\">);<\/span>\n<span class=\"k\">Truncate<\/span> <span class=\"k\">table<\/span> <span class=\"n\">Employee<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">insert<\/span> <span class=\"k\">into<\/span> <span class=\"n\">Employee<\/span> <span class=\"p\">(<\/span><span class=\"n\">Id<\/span><span class=\"p\">,<\/span> <span class=\"n\">Salary<\/span><span class=\"p\">)<\/span> <span class=\"k\">values<\/span> <span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">100<\/span><span class=\"p\">);<\/span>\n<span class=\"k\">insert<\/span> <span class=\"k\">into<\/span> <span class=\"n\">Employee<\/span> <span class=\"p\">(<\/span><span class=\"n\">Id<\/span><span class=\"p\">,<\/span> <span class=\"n\">Salary<\/span><span class=\"p\">)<\/span> <span class=\"k\">values<\/span> <span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">200<\/span><span class=\"p\">);<\/span>\n<span class=\"k\">insert<\/span> <span class=\"k\">into<\/span> <span class=\"n\">Employee<\/span> <span class=\"p\">(<\/span><span class=\"n\">Id<\/span><span class=\"p\">,<\/span> <span class=\"n\">Salary<\/span><span class=\"p\">)<\/span> <span class=\"k\">values<\/span> <span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">,<\/span> <span class=\"mi\">300<\/span><span class=\"p\">);<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h2 id=\"\u89e3\u7b54\">\u89e3\u7b54<\/h2>\n\n<p>\u89e3\u6cd5\u4e00\uff1a<\/p>\n\n<div class=\"language-sql highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">CREATE<\/span> <span class=\"k\">FUNCTION<\/span> <span class=\"n\">getNthHighestSalary<\/span><span class=\"p\">(<\/span><span class=\"n\">N<\/span> <span class=\"nb\">INT<\/span><span class=\"p\">)<\/span> <span class=\"k\">RETURNS<\/span> <span class=\"nb\">INT<\/span>\n<span class=\"k\">BEGIN<\/span>\n\t\t<span class=\"k\">SET<\/span> <span class=\"n\">N<\/span> <span class=\"p\">:<\/span><span class=\"o\">=<\/span> <span class=\"n\">N<\/span> <span class=\"o\">-<\/span> <span class=\"mi\">1<\/span><span class=\"p\">;<\/span>\n  <span class=\"k\">RETURN<\/span> <span class=\"p\">(<\/span>\n      <span class=\"o\">#<\/span> <span class=\"k\">Write<\/span> <span class=\"n\">your<\/span> <span class=\"n\">MySQL<\/span> <span class=\"n\">query<\/span> <span class=\"k\">statement<\/span> <span class=\"n\">below<\/span><span class=\"p\">.<\/span>\n      <span class=\"k\">SELECT<\/span> <span class=\"p\">(<\/span><span class=\"k\">SELECT<\/span> <span class=\"k\">DISTINCT<\/span> <span class=\"n\">Salary<\/span> <span class=\"k\">FROM<\/span> <span class=\"n\">Employee<\/span> <span class=\"k\">ORDER<\/span> <span class=\"k\">BY<\/span> <span class=\"n\">Salary<\/span> <span class=\"k\">DESC<\/span> <span class=\"k\">LIMIT<\/span> <span class=\"n\">N<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"k\">END<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p>MySQL\u76f4\u63a5\u6267\u884c\u4f1a\u9047\u5230\u62a5\u9519\u4fe1\u606f\uff0c\u89e3\u51b3\u65b9\u6848\u8bf7\u53c2\u8003\uff1a<a href=\"https:\/\/stackoverflow.com\/questions\/26015160\/deterministic-no-sql-or-reads-sql-data-in-its-declaration-and-binary-logging-i\">DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled<\/a><\/p>\n","category":{"@attributes":{"term":"LeetCode-DataBase"}}},{"title":"Problem 177: Nth Highest Salary","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/en\/2021-02-23\/nth-highest-salary.html"}},"updated":"2021-02-23T08:05:02+08:00","id":"https:\/\/wy471x.github.io\/en\/2021-02-23\/nth-highest-salary.html","content":"<h2 id=\"177-nth-highest-salary\"><a href=\"https:\/\/leetcode.com\/problems\/nth-highest-salary\/\">177. Nth Highest Salary<\/a><\/h2>\n\n<p>Write a SQL query to get the nth highest salary from the Employee table.<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Id<\/th>\n      <th>Salary<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>1<\/td>\n      <td>100<\/td>\n    <\/tr>\n    <tr>\n      <td>2<\/td>\n      <td>200<\/td>\n    <\/tr>\n    <tr>\n      <td>3<\/td>\n      <td>300<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>For example, given the above Employee table, the nth highest salary where n = 2 is 200. If there is no nth highest salary, the query should return null.<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>getNthHighestSalary(2)<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>200<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<p>SQL script:<\/p>\n\n<div class=\"language-sql highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">Create<\/span> <span class=\"k\">table<\/span> <span class=\"n\">If<\/span> <span class=\"k\">Not<\/span> <span class=\"k\">Exists<\/span> <span class=\"n\">Employee<\/span> <span class=\"p\">(<\/span><span class=\"n\">Id<\/span> <span class=\"nb\">int<\/span><span class=\"p\">,<\/span> <span class=\"n\">Salary<\/span> <span class=\"nb\">int<\/span><span class=\"p\">);<\/span>\n<span class=\"k\">Truncate<\/span> <span class=\"k\">table<\/span> <span class=\"n\">Employee<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">insert<\/span> <span class=\"k\">into<\/span> <span class=\"n\">Employee<\/span> <span class=\"p\">(<\/span><span class=\"n\">Id<\/span><span class=\"p\">,<\/span> <span class=\"n\">Salary<\/span><span class=\"p\">)<\/span> <span class=\"k\">values<\/span> <span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span> <span class=\"mi\">100<\/span><span class=\"p\">);<\/span>\n<span class=\"k\">insert<\/span> <span class=\"k\">into<\/span> <span class=\"n\">Employee<\/span> <span class=\"p\">(<\/span><span class=\"n\">Id<\/span><span class=\"p\">,<\/span> <span class=\"n\">Salary<\/span><span class=\"p\">)<\/span> <span class=\"k\">values<\/span> <span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">,<\/span> <span class=\"mi\">200<\/span><span class=\"p\">);<\/span>\n<span class=\"k\">insert<\/span> <span class=\"k\">into<\/span> <span class=\"n\">Employee<\/span> <span class=\"p\">(<\/span><span class=\"n\">Id<\/span><span class=\"p\">,<\/span> <span class=\"n\">Salary<\/span><span class=\"p\">)<\/span> <span class=\"k\">values<\/span> <span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">,<\/span> <span class=\"mi\">300<\/span><span class=\"p\">);<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h2 id=\"solution\">Solution<\/h2>\n\n<p>Solution 1:<\/p>\n\n<div class=\"language-sql highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">CREATE<\/span> <span class=\"k\">FUNCTION<\/span> <span class=\"n\">getNthHighestSalary<\/span><span class=\"p\">(<\/span><span class=\"n\">N<\/span> <span class=\"nb\">INT<\/span><span class=\"p\">)<\/span> <span class=\"k\">RETURNS<\/span> <span class=\"nb\">INT<\/span>\n<span class=\"k\">BEGIN<\/span>\n    <span class=\"k\">SET<\/span> <span class=\"n\">N<\/span> <span class=\"p\">:<\/span><span class=\"o\">=<\/span> <span class=\"n\">N<\/span> <span class=\"o\">-<\/span> <span class=\"mi\">1<\/span><span class=\"p\">;<\/span>\n  <span class=\"k\">RETURN<\/span> <span class=\"p\">(<\/span>\n      <span class=\"o\">#<\/span> <span class=\"k\">Write<\/span> <span class=\"n\">your<\/span> <span class=\"n\">MySQL<\/span> <span class=\"n\">query<\/span> <span class=\"k\">statement<\/span> <span class=\"n\">below<\/span><span class=\"p\">.<\/span>\n      <span class=\"k\">SELECT<\/span> <span class=\"p\">(<\/span><span class=\"k\">SELECT<\/span> <span class=\"k\">DISTINCT<\/span> <span class=\"n\">Salary<\/span> <span class=\"k\">FROM<\/span> <span class=\"n\">Employee<\/span> <span class=\"k\">ORDER<\/span> <span class=\"k\">BY<\/span> <span class=\"n\">Salary<\/span> <span class=\"k\">DESC<\/span> <span class=\"k\">LIMIT<\/span> <span class=\"n\">N<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"k\">END<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<p>If you encounter errors running this directly in MySQL, refer to: <a href=\"https:\/\/stackoverflow.com\/questions\/26015160\/deterministic-no-sql-or-reads-sql-data-in-its-declaration-and-binary-logging-i\">DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled<\/a><\/p>\n","category":{"@attributes":{"term":"LeetCode-DataBase"}}},{"title":"Git\u7b80\u6613\u6559\u7a0b","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/2021-02-21\/git-tutorial.html"}},"updated":"2021-02-21T21:51:18+08:00","id":"https:\/\/wy471x.github.io\/2021-02-21\/git-tutorial.html","content":"<blockquote>\n  <p>\u5c06\u6682\u5b58\u533a\u4e2d\u6587\u4ef6\u6062\u590d\u4e3a\u548cHEAD\u4e00\u6837<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git reset HEAD<\/code> \u5c06\u6682\u5b58\u533a\u4e2d\u6240\u6709\u6587\u4ef6\u6062\u590d\u4e3a\u548cHEAD\u4e00\u6837<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git reset HEAD -- [filename]<\/code> \u5c06\u6682\u5b58\u533a\u4e2d\u540d\u5b57\u4e3afilename\u7684\u6587\u4ef6\u6062\u590d\u4e3a\u548cHEAD\u4e00\u6837<\/p>\n\n<blockquote>\n  <p>\u6bd4\u8f83\u6682\u5b58\u533a\u548cHEAD\u6240\u542b\u6587\u4ef6\u5dee\u5f02<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git diff --cached<\/code><\/p>\n\n<blockquote>\n  <p>\u6bd4\u8f83\u5de5\u4f5c\u533a\u548c\u6682\u5b58\u533a\u6240\u542b\u6587\u4ef6\u5dee\u5f02<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git diff<\/code> \u9ed8\u8ba4\u6bd4\u8f83\u6682\u5b58\u533a\u548c\u5de5\u4f5c\u533a\u7684\u6587\u4ef6\u7684\u533a\u522b<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git diff -- [filename]<\/code> \u6bd4\u8f83\u5de5\u4f5c\u533a\u548c\u6682\u5b58\u533a\u4e2d\u540d\u5b57\u4e3afilename\u7684\u6587\u4ef6\u7684\u5185\u5bb9\u7684\u533a\u522b<\/p>\n\n<blockquote>\n  <p>\u5c06\u5de5\u4f5c\u533a\u4e2d\u6587\u4ef6\u5185\u5bb9\u6062\u590d\u4e3a\u548c\u6682\u5b58\u533a\u4e2d\u4e00\u6837<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git checkout -- [filename]<\/code> \u5c06\u5de5\u4f5c\u533a\u4e2d\u7684\u540d\u5b57\u4e3afilename\u7684\u6587\u4ef6\u6062\u590d\u4e3a\u548c\u6682\u5b58\u533a\u4e2d\u4e00\u6837<\/p>\n\n<blockquote>\n  <p>\u5c06\u6682\u5b58\u533a\u548c\u5de5\u4f5c\u533a\u7684\u5185\u5bb9\u6062\u590d\u81f3\u67d0\u6b21commit<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git reset --hard [commit code]<\/code> \u5c06\u5de5\u4f5c\u533a\u548c\u6682\u5b58\u533a\u4e2d\u7684\u5185\u5bb9\u6062\u590d\u81f3\u4e0e\u67d0\u6b21commit\u4e00\u6837\u3010\u614e\u7528\u3011<\/p>\n\n<blockquote>\n  <p>\u67e5\u770b\u4e0d\u540ccommit\u7684\u6307\u5b9a\u6587\u4ef6\u7684\u5dee\u5f02<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git diff [commit code 1] [commit code 2] -- [filename]<\/code><\/p>\n\n<blockquote>\n  <p>\u5220\u9664\u6682\u5b58\u533a\u548c\u5de5\u4f5c\u533a\u6307\u5b9a\u6587\u4ef6<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git rm [filename]<\/code><\/p>\n\n<blockquote>\n  <p>\u5c06\u53d8\u66f4\u8fdb\u884c\u5b58\u5165\u4e34\u65f6\u6808\u7a7a\u95f4<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git stash<\/code> \u5c06\u53d8\u66f4\u5b58\u5165\u6808\u7a7a\u95f4<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git stash apply<\/code> \u6808\u7a7a\u95f4\u4e2d\u7684\u5185\u5bb9\u4ecd\u5b58\u5728<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git stash pop<\/code> \u6808\u7a7a\u95f4\u4e2d\u7684\u5185\u5bb9\u88ab\u79fb\u9664<\/p>\n\n<blockquote>\n  <p>git\u4ed3\u5e93\u5907\u4efd<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git clone --bare [remote git repository] [local git repository]<\/code> \u54d1\u534f\u8bae\u65b9\u5f0f<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git clone --bare [file:\/\/\/&lt;remote git repository&gt;] [local git repository]<\/code> \u667a\u80fd\u534f\u8bae\u65b9\u5f0f<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git remote add [remote repository name] [file:\/\/\/&lt;remote git repository&gt;]<\/code><\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git push --set-upstream [remote repository name] [branch name]<\/code> \u5c06\u672c\u5730\u5206\u652f\u63a8\u9001\u81f3\u8fdc\u7a0b\u4ed3\u5e93<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git push [remote repository name] [branch name]<\/code> \u5c06\u672c\u5730\u5206\u652f\u63a8\u9001\u81f3\u8fdc\u7a0b\u4ed3\u5e93<\/p>\n","category":{"@attributes":{"term":"Git\u6559\u7a0b"}}},{"title":"Git Tutorial","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/en\/2021-02-21\/git-tutorial.html"}},"updated":"2021-02-21T21:51:18+08:00","id":"https:\/\/wy471x.github.io\/en\/2021-02-21\/git-tutorial.html","content":"<blockquote>\n  <p>Restore files in staging area to match HEAD<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git reset HEAD<\/code> restores all files in staging area to match HEAD<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git reset HEAD -- [filename]<\/code> restores the specified file in staging area to match HEAD<\/p>\n\n<blockquote>\n  <p>Compare differences between staging area and HEAD<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git diff --cached<\/code><\/p>\n\n<blockquote>\n  <p>Compare differences between working directory and staging area<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git diff<\/code> compares differences between staging area and working directory<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git diff -- [filename]<\/code> compares differences for the specified file<\/p>\n\n<blockquote>\n  <p>Restore working directory files to match staging area<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git checkout -- [filename]<\/code> restores the specified file in working directory to match staging area<\/p>\n\n<blockquote>\n  <p>Restore both staging area and working directory to a specific commit<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git reset --hard [commit code]<\/code> restores both staging area and working directory to match a specific commit [use with caution]<\/p>\n\n<blockquote>\n  <p>Compare differences for a specified file between different commits<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git diff [commit code 1] [commit code 2] -- [filename]<\/code><\/p>\n\n<blockquote>\n  <p>Remove a file from both staging area and working directory<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git rm [filename]<\/code><\/p>\n\n<blockquote>\n  <p>Stash changes to a temporary stack<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git stash<\/code> saves changes to the stack<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git stash apply<\/code> applies changes while keeping them in the stack<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git stash pop<\/code> applies changes and removes them from the stack<\/p>\n\n<blockquote>\n  <p>Git repository backup<\/p>\n<\/blockquote>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git clone --bare [remote git repository] [local git repository]<\/code> using dumb protocol<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git clone --bare [file:\/\/\/&lt;remote git repository&gt;] [local git repository]<\/code> using smart protocol<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git remote add [remote repository name] [file:\/\/\/&lt;remote git repository&gt;]<\/code><\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git push --set-upstream [remote repository name] [branch name]<\/code> push local branch to remote repository<\/p>\n\n<p><code class=\"language-plaintext highlighter-rouge\">git push [remote repository name] [branch name]<\/code> push local branch to remote repository<\/p>\n","category":{"@attributes":{"term":"Git-Tutorial"}}},{"title":"Problem 175: \u7ec4\u5408\u4e24\u4e2a\u8868","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/2021-02-17\/problem-175-combine-two-tables.html"}},"updated":"2021-02-17T22:02:22+08:00","id":"https:\/\/wy471x.github.io\/2021-02-17\/problem-175-combine-two-tables.html","content":"<h2 id=\"175-\u7ec4\u5408\u4e24\u4e2a\u8868\"><a href=\"https:\/\/leetcode-cn.com\/problems\/combine-two-tables\/\">175. \u7ec4\u5408\u4e24\u4e2a\u8868<\/a><\/h2>\n\n<p>\u88681: Person<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u5217\u540d<\/th>\n      <th>\u7c7b\u578b<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>PersonId<\/td>\n      <td>int<\/td>\n    <\/tr>\n    <tr>\n      <td>FirstName<\/td>\n      <td>varchar<\/td>\n    <\/tr>\n    <tr>\n      <td>LastName<\/td>\n      <td>varchar<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<blockquote>\n  <p><code class=\"language-plaintext highlighter-rouge\">PersonId<\/code> \u662f\u4e0a\u8868\u4e3b\u952e<\/p>\n<\/blockquote>\n\n<p>\u88682: Address<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>\u5217\u540d<\/th>\n      <th>\u7c7b\u578b<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>AddressId<\/td>\n      <td>int<\/td>\n    <\/tr>\n    <tr>\n      <td>PersonId<\/td>\n      <td>int<\/td>\n    <\/tr>\n    <tr>\n      <td>City<\/td>\n      <td>varchar<\/td>\n    <\/tr>\n    <tr>\n      <td>State<\/td>\n      <td>varchar<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<blockquote>\n  <p><code class=\"language-plaintext highlighter-rouge\">AddressId<\/code> \u662f\u4e0a\u8868\u4e3b\u952e<\/p>\n<\/blockquote>\n\n<p>\u7f16\u5199\u4e00\u4e2a SQL \u67e5\u8be2\uff0c\u6ee1\u8db3\u6761\u4ef6\uff1a\u65e0\u8bba person \u662f\u5426\u6709\u5730\u5740\u4fe1\u606f\uff0c\u90fd\u9700\u8981\u57fa\u4e8e\u4e0a\u8ff0\u4e24\u8868\u63d0\u4f9b person \u7684\u4ee5\u4e0b\u4fe1\u606f\uff1a<\/p>\n\n<p>FirstName, LastName, City, State<\/p>\n\n<p>sql\u811a\u672c\uff1a<\/p>\n\n<div class=\"language-sql highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">Create<\/span> <span class=\"k\">table<\/span> <span class=\"n\">Person<\/span> <span class=\"p\">(<\/span><span class=\"n\">PersonId<\/span> <span class=\"nb\">int<\/span><span class=\"p\">,<\/span> <span class=\"n\">FirstName<\/span> <span class=\"nb\">varchar<\/span><span class=\"p\">(<\/span><span class=\"mi\">255<\/span><span class=\"p\">),<\/span> <span class=\"n\">LastName<\/span> <span class=\"nb\">varchar<\/span><span class=\"p\">(<\/span><span class=\"mi\">255<\/span><span class=\"p\">));<\/span>\n<span class=\"k\">Create<\/span> <span class=\"k\">table<\/span> <span class=\"n\">Address<\/span> <span class=\"p\">(<\/span><span class=\"n\">AddressId<\/span> <span class=\"nb\">int<\/span><span class=\"p\">,<\/span> <span class=\"n\">PersonId<\/span> <span class=\"nb\">int<\/span><span class=\"p\">,<\/span> <span class=\"n\">City<\/span> <span class=\"nb\">varchar<\/span><span class=\"p\">(<\/span><span class=\"mi\">255<\/span><span class=\"p\">),<\/span> <span class=\"k\">State<\/span> <span class=\"nb\">varchar<\/span><span class=\"p\">(<\/span><span class=\"mi\">255<\/span><span class=\"p\">));<\/span>\n<span class=\"k\">Truncate<\/span> <span class=\"k\">table<\/span> <span class=\"n\">Person<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">insert<\/span> <span class=\"k\">into<\/span> <span class=\"n\">Person<\/span> <span class=\"p\">(<\/span><span class=\"n\">PersonId<\/span><span class=\"p\">,<\/span> <span class=\"n\">LastName<\/span><span class=\"p\">,<\/span> <span class=\"n\">FirstName<\/span><span class=\"p\">)<\/span> <span class=\"k\">values<\/span> <span class=\"p\">(<\/span><span class=\"s1\">'1'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'Wang'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'Allen'<\/span><span class=\"p\">);<\/span>\n<span class=\"k\">Truncate<\/span> <span class=\"k\">table<\/span> <span class=\"n\">Address<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">insert<\/span> <span class=\"k\">into<\/span> <span class=\"n\">Address<\/span> <span class=\"p\">(<\/span><span class=\"n\">AddressId<\/span><span class=\"p\">,<\/span> <span class=\"n\">PersonId<\/span><span class=\"p\">,<\/span> <span class=\"n\">City<\/span><span class=\"p\">,<\/span> <span class=\"k\">State<\/span><span class=\"p\">)<\/span> <span class=\"k\">values<\/span> <span class=\"p\">(<\/span><span class=\"s1\">'1'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'2'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'New York City'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'New York'<\/span><span class=\"p\">);<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h2 id=\"\u89e3\u7b54\">\u89e3\u7b54<\/h2>\n\n<p>\u89e3\u6cd5\u4e00\uff1a\u5de6\u8054\u7ed3\uff08LEFT JOIN\uff09<\/p>\n\n<div class=\"language-sql highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">SELECT<\/span>\n\t<span class=\"n\">FirstName<\/span><span class=\"p\">,<\/span>\n\t<span class=\"n\">LastName<\/span><span class=\"p\">,<\/span>\n\t<span class=\"n\">City<\/span><span class=\"p\">,<\/span>\n\t<span class=\"k\">State<\/span>\n<span class=\"k\">FROM<\/span>\n\t<span class=\"n\">Person<\/span>\n\t<span class=\"k\">LEFT<\/span> <span class=\"k\">JOIN<\/span>\n\t<span class=\"n\">Address<\/span> <span class=\"k\">ON<\/span> <span class=\"p\">(<\/span><span class=\"n\">Person<\/span><span class=\"p\">.<\/span><span class=\"n\">PersonId<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Address<\/span><span class=\"p\">.<\/span><span class=\"n\">PersonId<\/span><span class=\"p\">);<\/span>\n<\/code><\/pre><\/div><\/div>\n","category":{"@attributes":{"term":"LeetCode-Database"}}},{"title":"Problem 175: Combine Two Tables","link":{"@attributes":{"href":"https:\/\/wy471x.github.io\/en\/2021-02-17\/problem-175-combine-two-tables.html"}},"updated":"2021-02-17T22:02:22+08:00","id":"https:\/\/wy471x.github.io\/en\/2021-02-17\/problem-175-combine-two-tables.html","content":"<h2 id=\"175-combine-two-tables\"><a href=\"https:\/\/leetcode.com\/problems\/combine-two-tables\/\">175. Combine Two Tables<\/a><\/h2>\n\n<p>Table 1: Person<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Column Name<\/th>\n      <th>Type<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>PersonId<\/td>\n      <td>int<\/td>\n    <\/tr>\n    <tr>\n      <td>FirstName<\/td>\n      <td>varchar<\/td>\n    <\/tr>\n    <tr>\n      <td>LastName<\/td>\n      <td>varchar<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<blockquote>\n  <p><code class=\"language-plaintext highlighter-rouge\">PersonId<\/code> is the primary key for this table.<\/p>\n<\/blockquote>\n\n<p>Table 2: Address<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>Column Name<\/th>\n      <th>Type<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>AddressId<\/td>\n      <td>int<\/td>\n    <\/tr>\n    <tr>\n      <td>PersonId<\/td>\n      <td>int<\/td>\n    <\/tr>\n    <tr>\n      <td>City<\/td>\n      <td>varchar<\/td>\n    <\/tr>\n    <tr>\n      <td>State<\/td>\n      <td>varchar<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n<blockquote>\n  <p><code class=\"language-plaintext highlighter-rouge\">AddressId<\/code> is the primary key for this table.<\/p>\n<\/blockquote>\n\n<p>Write a SQL query that provides the following information for each person in the Person table, regardless of whether there is an address entry for that person:<\/p>\n\n<p>FirstName, LastName, City, State<\/p>\n\n<p>SQL script:<\/p>\n\n<div class=\"language-sql highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">Create<\/span> <span class=\"k\">table<\/span> <span class=\"n\">Person<\/span> <span class=\"p\">(<\/span><span class=\"n\">PersonId<\/span> <span class=\"nb\">int<\/span><span class=\"p\">,<\/span> <span class=\"n\">FirstName<\/span> <span class=\"nb\">varchar<\/span><span class=\"p\">(<\/span><span class=\"mi\">255<\/span><span class=\"p\">),<\/span> <span class=\"n\">LastName<\/span> <span class=\"nb\">varchar<\/span><span class=\"p\">(<\/span><span class=\"mi\">255<\/span><span class=\"p\">));<\/span>\n<span class=\"k\">Create<\/span> <span class=\"k\">table<\/span> <span class=\"n\">Address<\/span> <span class=\"p\">(<\/span><span class=\"n\">AddressId<\/span> <span class=\"nb\">int<\/span><span class=\"p\">,<\/span> <span class=\"n\">PersonId<\/span> <span class=\"nb\">int<\/span><span class=\"p\">,<\/span> <span class=\"n\">City<\/span> <span class=\"nb\">varchar<\/span><span class=\"p\">(<\/span><span class=\"mi\">255<\/span><span class=\"p\">),<\/span> <span class=\"k\">State<\/span> <span class=\"nb\">varchar<\/span><span class=\"p\">(<\/span><span class=\"mi\">255<\/span><span class=\"p\">));<\/span>\n<span class=\"k\">Truncate<\/span> <span class=\"k\">table<\/span> <span class=\"n\">Person<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">insert<\/span> <span class=\"k\">into<\/span> <span class=\"n\">Person<\/span> <span class=\"p\">(<\/span><span class=\"n\">PersonId<\/span><span class=\"p\">,<\/span> <span class=\"n\">LastName<\/span><span class=\"p\">,<\/span> <span class=\"n\">FirstName<\/span><span class=\"p\">)<\/span> <span class=\"k\">values<\/span> <span class=\"p\">(<\/span><span class=\"s1\">'1'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'Wang'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'Allen'<\/span><span class=\"p\">);<\/span>\n<span class=\"k\">Truncate<\/span> <span class=\"k\">table<\/span> <span class=\"n\">Address<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">insert<\/span> <span class=\"k\">into<\/span> <span class=\"n\">Address<\/span> <span class=\"p\">(<\/span><span class=\"n\">AddressId<\/span><span class=\"p\">,<\/span> <span class=\"n\">PersonId<\/span><span class=\"p\">,<\/span> <span class=\"n\">City<\/span><span class=\"p\">,<\/span> <span class=\"k\">State<\/span><span class=\"p\">)<\/span> <span class=\"k\">values<\/span> <span class=\"p\">(<\/span><span class=\"s1\">'1'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'2'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'New York City'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'New York'<\/span><span class=\"p\">);<\/span>\n<\/code><\/pre><\/div><\/div>\n\n<h2 id=\"solution\">Solution<\/h2>\n\n<p>Solution 1: LEFT JOIN<\/p>\n\n<div class=\"language-sql highlighter-rouge\"><div class=\"highlight\"><pre class=\"highlight\"><code><span class=\"k\">SELECT<\/span>\n    <span class=\"n\">FirstName<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">LastName<\/span><span class=\"p\">,<\/span>\n    <span class=\"n\">City<\/span><span class=\"p\">,<\/span>\n    <span class=\"k\">State<\/span>\n<span class=\"k\">FROM<\/span>\n    <span class=\"n\">Person<\/span>\n    <span class=\"k\">LEFT<\/span> <span class=\"k\">JOIN<\/span>\n    <span class=\"n\">Address<\/span> <span class=\"k\">ON<\/span> <span class=\"p\">(<\/span><span class=\"n\">Person<\/span><span class=\"p\">.<\/span><span class=\"n\">PersonId<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Address<\/span><span class=\"p\">.<\/span><span class=\"n\">PersonId<\/span><span class=\"p\">);<\/span>\n<\/code><\/pre><\/div><\/div>\n","category":{"@attributes":{"term":"LeetCode-Database"}}}]}