戰(zhàn):Nginx反向代理與緩存策略優(yōu)化指南)
前陣子幫團(tuán)隊(duì)搭了一個(gè) GitHub 鏡像站起因很實(shí)際持續(xù)集成流水線每次拉第三方依賴都慢得讓人心慌release 里的大文件動(dòng)不動(dòng)就中斷同一份制品被十幾臺(tái)構(gòu)建機(jī)反復(fù)下載浪費(fèi)了不少時(shí)間。折騰了一周左右把 Nginx 緩存、主動(dòng)預(yù)熱、監(jiān)控告警這些環(huán)節(jié)都過(guò)了一遍總算穩(wěn)定下來(lái)。這篇把完整的搭建和優(yōu)化思路整理出來(lái)給和我一樣需要自建 GitHub 鏡像站的朋友做參考。自建鏡像站并不神秘核心就兩件事一是讓重復(fù)下載的流量盡可能打在本地二是讓跨地區(qū)訪問(wèn) GitHub 源站時(shí)常見(jiàn)的超時(shí)和中斷問(wèn)題得到緩解。換句話說(shuō)鏡像站 Nginx 反向代理 磁盤緩存 定時(shí)預(yù)熱 必要的保護(hù)措施。你可能不需要一上來(lái)就搞得很復(fù)雜但先想清楚自己的場(chǎng)景和資源邊界再動(dòng)手能少走很多彎路。1. 自建鏡像站前先想清楚這幾件事1.1 鏡像站解決的四個(gè)真實(shí)問(wèn)題很多人一想到 GitHub 鏡像站就默認(rèn)是為了“訪問(wèn)更快”。其實(shí)從實(shí)際運(yùn)維角度看真正值得用鏡像站解決的問(wèn)題更具體重復(fù)拉取代碼和依賴CI/CD 流水線里每次構(gòu)建都要從 GitHub 拉取同一個(gè)公共倉(cāng)庫(kù)或 release 包網(wǎng)絡(luò)一波動(dòng)就失敗。大文件下載中斷release 頁(yè)面里的二進(jìn)制安裝包動(dòng)輒幾百 MB直接從源站下載時(shí)常半路斷掉沒(méi)有斷點(diǎn)續(xù)傳就非常痛苦。API 速率限制自動(dòng)化腳本如果頻繁調(diào)用 GitHub API 獲取版本信息、下載列表很容易觸發(fā)限流影響業(yè)務(wù)。多機(jī)共享緩存團(tuán)隊(duì)里有多臺(tái)構(gòu)建機(jī)或開發(fā)機(jī)各自獨(dú)立下載相同資源白白消耗帶寬和時(shí)間。所以自建鏡像站的首要目標(biāo)不是什么“繞過(guò)限制”而是把重復(fù)流量就近攔截下來(lái)讓回源的次數(shù)降到最低。這個(gè)思路適用于任何網(wǎng)絡(luò)環(huán)境純粹從工程效率出發(fā)。1.2 三種落地方案的取舍動(dòng)手之前先選架構(gòu)。我見(jiàn)過(guò)三種主流方案各有取舍方案優(yōu)點(diǎn)缺點(diǎn)適合場(chǎng)景Nginx 反向代理 磁盤緩存配置靈活、完全可控、可以精確設(shè)計(jì)緩存策略需要自己處理 URL 映射、302 重定向等細(xì)節(jié)有運(yùn)維能力想要高可控性的團(tuán)隊(duì)開源專用工具如 ghproxy部署快、開箱即用URL 規(guī)則清晰功能固定二次開發(fā)空間小更新依賴上游個(gè)人或小團(tuán)隊(duì)快速上線倉(cāng)庫(kù)同步Gitee/Gitea/GitLab倉(cāng)庫(kù)完全復(fù)制clone 速度快非實(shí)時(shí)同步release 大文件支持弱只是需要固定倉(cāng)庫(kù)的代碼備份我最后選了 Nginx 反向代理方案原因很簡(jiǎn)單鏡像站需要同時(shí)滿足git clone、release 下載、API 請(qǐng)求轉(zhuǎn)發(fā)三件事Nginx 的緩存模塊和 rewrite 能力可以應(yīng)對(duì)所有這些場(chǎng)景后續(xù)調(diào)優(yōu)空間也大。如果你只是想要一個(gè)給同事用的簡(jiǎn)單下載加速入口ghproxy 這類工具會(huì)更省事但別指望它在流量變大后還能保持靈活。2. 服務(wù)器到域名證書準(zhǔn)備工作里的隱藏細(xì)節(jié)2.1 服務(wù)器配置怎么選才不浪費(fèi)鏡像站是典型的高帶寬、中低 CPU 應(yīng)用。它的大部分工作都在轉(zhuǎn)發(fā)流量和寫緩存真正吃資源的是磁盤 IO 和網(wǎng)絡(luò)帶寬。CPU2 核足夠起步。如果你不用 OpenResty/Lua 做復(fù)雜邏輯Nginx 對(duì) CPU 的要求不高。內(nèi)存4GB 起步。內(nèi)存主要被系統(tǒng)的 Page Cache 占用來(lái)加速磁盤讀取緩存文件越大內(nèi)存越有用。帶寬建議 5Mbps 以上。如果面向團(tuán)隊(duì)使用10Mbps 會(huì)更穩(wěn)。帶寬不是越高越好而是要根據(jù)實(shí)際的下載流量預(yù)算來(lái)配。磁盤這是最容易忽略的。release 大文件緩存和訪問(wèn)日志都落在磁盤上系統(tǒng)盤不能和緩存目錄共用否則日志一膨脹就把根分區(qū)塞滿。一句話磁盤容量和帶寬決定了鏡像站的上限CPU 內(nèi)存夠用就行。2.2 域名、DNS 與 HTTPS 證書的自動(dòng)化鏡像站必須用獨(dú)立域名不要用 IP 裸奔。獨(dú)立域名帶來(lái)的好處是后續(xù)接 CDN、做多區(qū)域分流、調(diào)整 DNS 都很方便。域名選好后DNS 記錄直接解析到服務(wù)器 IP 即可。如果服務(wù)器在國(guó)內(nèi)建議做好備案相關(guān)的合規(guī)檢查如果服務(wù)器在境外那訪問(wèn)延遲會(huì)受到地區(qū)影響需要結(jié)合團(tuán)隊(duì)分布選擇區(qū)域。HTTPS 證書我推薦用 Lets Encrypt 自動(dòng)簽發(fā)配合acme.sh或certbot配置一條 cron 或 systemd timer 做自動(dòng)續(xù)期。很多鏡像站事故不是源站出問(wèn)題而是證書過(guò)期導(dǎo)致全站不可用所以這一步一定要自動(dòng)化。2.3 磁盤掛載與目錄規(guī)劃我習(xí)慣把鏡像站所有數(shù)據(jù)放在一個(gè)獨(dú)立數(shù)據(jù)盤下命名清晰/data/github-mirror/cache /data/github-mirror/logs /data/github-mirror/tmp緩存目錄單獨(dú)掛載到數(shù)據(jù)盤并且掛載參數(shù)加上noatime可以減少不必要的磁盤寫入對(duì) IO 有一點(diǎn)幫助。文件系統(tǒng)用 ext4 或 xfs 都行。日志目錄和緩存目錄分開是因?yàn)槿罩据嗈D(zhuǎn)和緩存清理的觸發(fā)條件不同混在一起容易出現(xiàn)“日志把磁盤塞滿緩存寫不進(jìn)去”的連鎖故障。3. Nginx 核心配置從能用到好用的距離3.1 起步配置一個(gè)能用的反向代理先看一段最基礎(chǔ)的反向代理配置作用是讓github-mirror.example.com/owner/repo/...反向代理到github.com/owner/repo/...server { listen 443 ssl http2; server_name github-mirror.example.com; # SSL 證書配置省略 ssl_certificate /etc/letsencrypt/live/github-mirror.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/github-mirror.example.com/privkey.pem; location / { resolver 8.8.8.8 ipv6off; set $backend https://github.com; proxy_pass $backend$request_uri; proxy_set_header Host github.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }注意這里用resolver定義 DNS 解析地址是為了讓 Nginx 能夠根據(jù)變量動(dòng)態(tài)解析$backend避免proxy_pass配置中的固定域名在啟動(dòng)時(shí)解析一次后就不再更新。這個(gè)配置對(duì)普通的倉(cāng)庫(kù)頁(yè)面瀏覽沒(méi)問(wèn)題但距離“好用”還差很遠(yuǎn)因?yàn)?GitHub 的 release 下載會(huì)涉及 302 重定向到objects.githubusercontent.com必須單獨(dú)處理。3.2 處理 release 下載的 302 重定向GitHub 的 release 下載流程是這樣客戶端請(qǐng)求https://github.com/owner/repo/releases/download/v1.0.0/file.zipGitHub 服務(wù)器返回 302Location 指向https://objects.githubusercontent.com/...客戶端跟隨重定向從對(duì)象存儲(chǔ)下載文件。直接在 Nginx 里反向代理客戶端會(huì)在最外層就拿到 302 響應(yīng)于是它繞過(guò)你的鏡像站直連 GitHub 的對(duì)象存儲(chǔ)鏡像緩存完全失效。解決辦法是讓 Nginx 把對(duì)象存儲(chǔ)也代理了并改寫響應(yīng)頭里的 Location。這里我給出一個(gè)實(shí)用配置思路是將 release 下載路徑反向代理到github.com使用proxy_redirect把響應(yīng)頭里的https://objects.githubusercontent.com/改寫成自己的鏡像域名增加一個(gè) location 專門反向代理objects.githubusercontent.com并開啟緩存。# 處理 release 下載路徑 location / { proxy_pass https://github.com; proxy_set_header Host github.com; # 將 objects.githubusercontent.com 的重定向改寫為本站地址 proxy_redirect https://objects.githubusercontent.com/ /objects/; } # 代理 GitHub 對(duì)象存儲(chǔ) location /objects/ { resolver 8.8.8.8 ipv6off; set $backend https://objects.githubusercontent.com; proxy_pass $backend$request_uri; proxy_set_header Host objects.githubusercontent.com; # 開啟緩存 proxy_cache github_cache; proxy_cache_valid 200 7d; proxy_cache_key $scheme://$host$uri; }這樣客戶端實(shí)際下載路徑變成https://github-mirror.example.com/objects/...文件內(nèi)容會(huì)通過(guò)鏡像站回源到對(duì)象存儲(chǔ)然后被 Nginx 緩存下來(lái)。第一次請(qǐng)求會(huì)比較慢后續(xù)請(qǐng)求就直接命中本地緩存了。3.3 緩存策略與 Range 請(qǐng)求大文件下載最怕斷點(diǎn)續(xù)傳失效??蛻舳送ǔ?huì)攜帶Range: bytes0-或一個(gè)具體的區(qū)間去請(qǐng)求Nginx 需要把 Range 頭透?jìng)鹘o上游同時(shí)保證緩存命中。Nginx 的proxy_cache默認(rèn)會(huì)緩存完整響應(yīng)但如果你直接讓客戶端和源站之間做 Range 請(qǐng)求Nginx 的緩存行為需要額外配置。關(guān)鍵參數(shù)proxy_cache github_cache; proxy_cache_valid 200 7d; proxy_cache_valid 206 1h; proxy_cache_key $scheme://$host$uri; proxy_set_header Range $http_range; proxy_ignore_headers Cache-Control Expires Set-Cookie;這里的proxy_ignore_headers是常見(jiàn)的必備項(xiàng)。GitHub 對(duì)象存儲(chǔ)返回的響應(yīng)頭里可能帶有Set-Cookie或Cache-Control: private如果不忽略Nginx 會(huì)因?yàn)椤安辉试S緩存”而放棄緩存導(dǎo)致所有請(qǐng)求都回源。3.4 用 OpenResty 提升緩存命中率如果直接用 Nginx 官方版緩存 key 匹配規(guī)則比較死板。GitHub 的很多 URL 帶有查詢參數(shù)例如?raw1、?tokenxxx這些參數(shù)沒(méi)有實(shí)際意義卻會(huì)讓緩存 key 變化導(dǎo)致同一份文件被緩存多份命中率直線下降。用 OpenResty 可以更靈活地處理。例如動(dòng)態(tài)去除無(wú)意義的 query 參數(shù)location / { set_by_lua $cache_key local uri ngx.var.uri local args ngx.req.get_uri_args() -- 只保留有限參數(shù) return uri ; proxy_cache_key $scheme://$host$cache_key; proxy_pass https://github.com; }這樣即使客戶端請(qǐng)求/owner/repo?tokenabc和/owner/repo?tokenxyz最終緩存 key 都是/owner/repo命中率明顯提升。OpenResty 的 LuaJIT 性能很強(qiáng)這步操作對(duì)整體吞吐影響很小。4. 緩存命中率優(yōu)化與主動(dòng)預(yù)熱4.1 日志里的三個(gè)關(guān)鍵數(shù)字配好之后第一件事不是繼續(xù)調(diào)配置而是看日志。我在 Nginx 日志格式里加了一個(gè)變量$upstream_cache_status用來(lái)記錄每次請(qǐng)求的緩存狀態(tài)HIT、MISS、EXPIRED、BYPASS 等。log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_range cache:$upstream_cache_status;通過(guò)日志你需要關(guān)注三個(gè)數(shù)字緩存命中率統(tǒng)計(jì) HIT / 總請(qǐng)求正常應(yīng)在 60% 以上。如果長(zhǎng)期低于 30%說(shuō)明緩存策略有問(wèn)題或者請(qǐng)求 URL 中的隨機(jī)參數(shù)太多。MISS 請(qǐng)求的 top URL找到回源最多的路徑優(yōu)先做預(yù)熱。5xx 和 429 狀態(tài)碼數(shù)量如果源站開始返回 429說(shuō)明回源請(qǐng)求太頻繁可能觸發(fā)了限流。統(tǒng)計(jì)命令可以用awk快速處理awk {print $NF} /data/github-mirror/logs/access.log | sort | uniq -c | sort -rn | head4.2 寫一個(gè)預(yù)熱腳本被動(dòng)緩存有個(gè)缺點(diǎn)新文件第一次被請(qǐng)求時(shí)依然要回源如果這個(gè)文件體積很大第一個(gè)下載者會(huì)等很久。為了避免“冷啟動(dòng)慢”可以針對(duì)熱門倉(cāng)庫(kù)做主動(dòng)預(yù)熱。預(yù)熱腳本的邏輯很簡(jiǎn)單定期請(qǐng)求你關(guān)心的 release 下載 URL強(qiáng)制 Nginx 緩存。比如用 Python 腳本拉取 GitHub API 獲取某個(gè)倉(cāng)庫(kù)的最新 release 下載地址然后依次請(qǐng)求鏡像站 URL。#!/usr/bin/env python3 import requests import time GITHUB_API https://api.github.com/repos/{owner}/{repo}/releases/latest MIRROR_BASE https://github-mirror.example.com repos [ (owner, repo), (owner2, repo2), ] for owner, repo in repos: try: r requests.get(GITHUB_API.format(ownerowner, reporepo), timeout10) if r.status_code ! 200: continue for asset in r.json().get(assets, []): url asset[browser_download_url] mirror_url MIRROR_BASE url.replace(https://github.com, ) print(Warm up:, mirror_url) requests.get(mirror_url, timeout30, streamTrue) time.sleep(1) except Exception as e: print(Error:, e)注意預(yù)熱請(qǐng)求最好限制并發(fā)和頻率否則源站可能認(rèn)為你在攻擊它反而把 IP 封掉。我通常在每次請(qǐng)求之間加 1-2 秒間隔。4.3 限流與超時(shí)保護(hù)鏡像站一旦公開出去就會(huì)面臨各種突發(fā)流量。Nginx 本身有很好的防護(hù)能力關(guān)鍵是用起來(lái)# 限制客戶端請(qǐng)求速率平均每秒 5 個(gè)請(qǐng)求突增不超過(guò) 10 limit_req_zone $binary_remote_addr zonemirror_limit:10m rate5r/s; location / { limit_req zonemirror_limit burst10 nodelay; proxy_connect_timeout 10s; proxy_send_timeout 60s; proxy_read_timeout 60s; }proxy_connect_timeout要短一點(diǎn)避免客戶端等待太久proxy_read_timeout要足夠長(zhǎng)因?yàn)榇笪募螺d可能持續(xù)幾分鐘。這個(gè)平衡需要根據(jù)實(shí)際業(yè)務(wù)調(diào)整。5. 實(shí)戰(zhàn)中遇到的網(wǎng)絡(luò)怪問(wèn)題5.1 release 路徑 404一個(gè) rewrite 的鍋我第一次配置時(shí)下載release文件一直返回 404但倉(cāng)庫(kù)首頁(yè)能訪問(wèn)。排查了很久最后發(fā)現(xiàn)是 Nginx 的location ~正則寫得太激進(jìn)把/owner/repo/releases/download/...里的/releases匹配掉了一段。優(yōu)化前l(fā)ocation ~ ^/([^/])/([^/])/releases/download/(.*)$ { proxy_pass https://github.com/$1/$2/releases/download/$3; }這看起來(lái)沒(méi)問(wèn)題但如果是多層目錄的情況$3可能不完整。GitHub 的 release download 路徑實(shí)際上就是/{owner}/{repo}/releases/download/{tag}/{filename}如果 tag 里包含斜杠或文件名被 URL 編碼簡(jiǎn)單的正則就會(huì)漏。我的經(jīng)驗(yàn)是能用前綴匹配就盡量用前綴匹配少用復(fù)雜正則。直接location / { proxy_pass https://github.com$request_uri; }簡(jiǎn)單的透?jìng)鞣炊畈蝗菀壮鲥e(cuò)。只有當(dāng)需要特殊改寫時(shí)才用 rewrite并且改完之后必須實(shí)測(cè)幾個(gè)典型路徑。5.2 403 權(quán)限問(wèn)題緩存目錄的“隱形權(quán)限”有段時(shí)間鏡像站經(jīng)常隨機(jī)出現(xiàn) 403但刷新一下又好了。查看錯(cuò)誤日志發(fā)現(xiàn)是 Nginx 的proxy_cache寫緩存失敗因?yàn)榫彺婺夸泴僦鞑皇?Nginx 工作進(jìn)程。Nginx 的 master 進(jìn)程一般是 root但 worker 進(jìn)程通常以www-data或nginx用戶運(yùn)行。如果你手工把緩存目錄mkdir在/data下屬主是 rootworker 進(jìn)程沒(méi)有寫權(quán)限自然無(wú)法寫入緩存文件于是請(qǐng)求直接失敗返回 403。解決方法是把緩存目錄屬主改成 Nginx worker 用戶sudo chown -R www-data:www-data /data/github-mirror/cache sudo chmod -R 755 /data/github-mirror/cache這個(gè)坑很容易被忽略因?yàn)槁?Nginx 代理不配緩存時(shí)完全正常一旦開緩存就間歇性報(bào)錯(cuò)。5.3 緩存穿透與回源風(fēng)暴惡意請(qǐng)求如何拖垮源站有次我發(fā)現(xiàn)源站突然開始返回大量 429查看鏡像站訪問(wèn)日志后發(fā)現(xiàn)有人在用掃描工具探測(cè)路徑生成大量隨機(jī) URL比如/owner/nonexistent/releases/download/v1.0.0/random.zip。這些請(qǐng)求全部回源導(dǎo)致 GitHub API 和對(duì)象存儲(chǔ)限流。解決方案有兩個(gè)前置校驗(yàn)如果 URL 路徑不符合/{owner}/{repo}/releases/download/的格式直接返回 404不進(jìn)行反向代理。緩存鎖開啟proxy_cache_lock on避免多個(gè)相同請(qǐng)求同時(shí)回源。這樣即使有熱點(diǎn)流量也只有一個(gè)請(qǐng)求會(huì)真正回源。proxy_cache_lock on; proxy_cache_lock_timeout 10s;配合limit_req基本能抵御常見(jiàn)掃描流量。5.4 大文件緩存不完整Nginx 臨時(shí)文件上限大文件下載到一半就斷明明已經(jīng)緩存過(guò)但每次請(qǐng)求還是回源。查了 Nginx 文檔發(fā)現(xiàn)是proxy_max_temp_file_size限制導(dǎo)致的。Nginx 緩存文件時(shí)會(huì)先把上游響應(yīng)寫入臨時(shí)文件如果臨時(shí)文件的大小超過(guò)某個(gè)閾值Nginx 就決定不緩存直接流式轉(zhuǎn)發(fā)給客戶端。默認(rèn)的proxy_max_temp_file_size是 1024m如果你的 release 包超過(guò) 1GB超出了這個(gè)值緩存就不會(huì)生效。解決辦法是調(diào)大這個(gè)參數(shù)并確保臨時(shí)目錄proxy_temp_path所在磁盤有足夠空間proxy_temp_path /data/github-mirror/tmp; proxy_max_temp_file_size 8192m;大文件緩存對(duì)磁盤 IO 的要求比較高建議臨時(shí)目錄和緩存目錄放在同一塊高速磁盤上避免多次跨盤拷貝。6. 安全加固與日常運(yùn)維6.1 防盜鏈與限速控制流量成本鏡像站公開后很容易被第三方網(wǎng)站直接引用。如果有別人在熱門頁(yè)面嵌入你的下載鏈接你的帶寬成本會(huì)瞬間飆升??梢酝ㄟ^(guò)valid_referers限制來(lái)源location /objects/ { valid_referers none blocked github-mirror.example.com *.example.com; if ($invalid_referer) { return 403; } }但要注意很多下載命令行工具wget/curl不會(huì)帶 Referer所以none要保留否則會(huì)誤傷正常用戶。只針對(duì)瀏覽器請(qǐng)求做防盜鏈命令行工具一般不需要。同時(shí)可以限制單個(gè) IP 的下載速率location /objects/ { limit_conn addr 4; limit_rate 5m; }這里limit_conn addr需要先在http層定義 zonelimit_conn_zone $binary_remote_addr zoneaddr:10m;6.2 日志輪轉(zhuǎn)與緩存清理訪問(wèn)日志增長(zhǎng)很快尤其是大文件下載場(chǎng)景每行日志雖然小但量一多就會(huì)占滿磁盤。我用logrotate按天切分保留 30 天/data/github-mirror/logs/access.log { daily rotate 30 compress delaycompress missingok notifempty create 0640 www-data www-data sharedscripts postrotate /usr/sbin/nginx -s reopen endscript }對(duì)于 Nginx 緩存目錄依靠proxy_cache_path自帶的 manager 機(jī)制定期清理proxy_cache_path /data/github-mirror/cache levels1:2 keys_zonegithub_cache:10m max_size50g inactive30d use_temp_pathoff;max_size50g表示緩存總量超過(guò) 50GB 時(shí)manager 進(jìn)程會(huì)自動(dòng)清理不活躍文件inactive30d表示 30 天沒(méi)有被訪問(wèn)的緩存會(huì)被清掉。這個(gè)配置能保證緩存目錄不會(huì)無(wú)限膨脹。6.3 監(jiān)控告警的整體思路鏡像站在沒(méi)有告警的情況下運(yùn)行是很危險(xiǎn)的。你可能登錄服務(wù)器才發(fā)現(xiàn)磁盤滿了或者緩存命中率已經(jīng)掉到 30% 以下。我用的方案是 Prometheus nginx_exporter暴露 Nginx Stub Status 數(shù)據(jù)再配合node_exporter采集磁盤、CPU、內(nèi)存指標(biāo)。在 Nginx 配置里開啟 status 需要在編譯時(shí)帶--with-http_stub_status_module一般發(fā)行版都默認(rèn)帶了location /stub_status { stub_status; allow 127.0.0.1; deny all; }然后nginx_exporter會(huì)定期抓取stub_status把連接數(shù)、請(qǐng)求數(shù)等轉(zhuǎn)成 Prometheus 指標(biāo)。告警規(guī)則我這里給幾個(gè)重點(diǎn)5xx 響應(yīng)占比超過(guò) 1%緩存命中率HIT 占比低于 50%/data/github-mirror磁盤使用率超過(guò) 80%Nginx 進(jìn)程關(guān)閉或無(wú)法探活有了這幾個(gè)告警鏡像站的基本健康狀態(tài)就能實(shí)時(shí)掌握。最后說(shuō)幾句自建 GitHub 鏡像站最大的感受是“配好只是開始”。緩存策略要觀察真實(shí)請(qǐng)求來(lái)調(diào)整重定向規(guī)則要根據(jù)源站行為變化來(lái)維護(hù)磁盤和帶寬消耗要持續(xù)監(jiān)控。如果你沒(méi)有真實(shí)流量建議先用測(cè)試腳本模擬幾輪下載再切正式域名不然一上線就被存量請(qǐng)求打爆緩存目錄是很常見(jiàn)的事。一個(gè)小技巧把所有 location、緩存策略寫在獨(dú)立的配置片段里用include引入主配置。這樣每次調(diào)整只需要改一個(gè)文件還能方便地做 A/B 對(duì)比。鏡像站這種服務(wù)簡(jiǎn)單透明比花哨重要得多。