ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

BIND解析、nginx虚拟主机与Squid缓存配置:从域名到后端的完整链路实战

BIND解析、nginx虚拟主机与Squid缓存配置:从域名到后端的完整链路实战 最近在整理一套线上环境的访问链路顺手把几台新机器的解析从公共 DNS 迁到了自建 BIND后面挂着 nginx 虚拟主机跑不同业务再在 nginx 和后端应用之间塞了一层 Squid 做缓存加速。这套组合不新鲜BIND 管解析、nginx 管路由分流、Squid 管缓存每个环节单独看都是非常成熟的东西但真把它们串起来的时候你会发现域名对不对、虚拟主机有没有命中、缓存到底是被谁消费的每一个环节理解不到位整条请求链路都会给你颜色看。这篇文章就是围绕“BIND 解析 nginx 虚拟主机域名 Squid 缓存配置”这套组合来写的。我不会只贴配置而是把请求从浏览器发出后经过 DNS、nginx、Squid 再到后端应用的完整路径讲透。适合正在搭中小型站点、想把静态资源缓存层做起来、又不想一上来就上 CDN 的运维和开发者参考。里面的配置我都用本地环境验证过坑也踩了不少你应该能直接抄作业。1. 三件套的分工与请求链路BIND、nginx、Squid 到底谁先干活1.1 一次完整访问的链路拆解很多人在配置的时候容易犯一个毛病就是分别把 BIND、nginx、Squid 三份配置都捣鼓好了却搞不清它们之间的先后关系。先把这个想清楚后面排错会省一大半时间。以我这次的部署为例最外层是 nginx所有 HTTP/HTTPS 流量先进 nginxnginx 根据server_name判断访问的是哪个虚拟主机如果命中的是静态资源或需要缓存的路径就把请求转发给本机的 SquidSquid 检查自己的缓存目录有就直接返回没有才回源到后端应用服务器。而 BIND 在这条链路里管的是最前面的“域名到 IP”的转换用户浏览器访问www.example.com时第一步是向 DNS 服务器问这个域名对应哪台服务器。所以整条链路是这样的浏览器 - BIND域名解析 - nginx虚拟主机分流 - Squid缓存层 - 后端应用每次访问的时间消耗大部分其实发生在 DNS 解析和后端回源上。DNS 一旦解析慢用户还没碰到 nginx 就已经卡住了后端一旦每次都回源Squid 就形同虚设。链路里每一层都有自己独立的日志这也是我喜欢这套组合的原因——每一层都能单独验证出了问题可以一层一层往下剥。1.2 为什么选 Squid 而不是 nginx 自带的 proxy_cache这是每次聊到这个架构时都会被问的问题。nginx 的proxy_cache确实能缓存配置也不复杂对于简单站点完全够用。但真实跑起来我会更倾向把缓存单独拆给 Squid。原因有三点。第一Squid 的缓存策略比 nginx 细致得多refresh_pattern可以按 URL 后缀、目录、是否带参数来分别定义刷新规则而 nginx 的 proxy_cache 主要依赖proxy_cache_valid和上游响应头控制粒度相对粗。第二Squid 有完整的缓存命中率统计、内存对象管理、替换算法配置你可以通过squidclient mgr:info直接看到当前缓存对象数量、内存占用、命中率这些数据nginx 自带模块这方面弱一些。第三当流量涨上来之后Squid 可以独立拆分到专门的缓存服务器上nginx 只需要通过proxy_pass指过去就行架构演进很平滑。当然这不是说 Squid 就一定比 nginx 缓存好而是这个标题下的组合里Squid 作为独立缓存层更合理。如果你的场景只是几个静态文件nginx 自带缓存足够没必要多加一层。1.3 两种部署拓扑Squid 前置与 nginx 前置的区别这个点我在不同项目里都见过有人搞混。Squid 和 nginx 的先后顺序直接影响配置方式。Squid 前置用户请求先到 SquidSquid 缓存未命中时回源到后端的 nginx。这种模式下 Squid 是入口域名解析直接指向 Squid 所在服务器带宽控制、访问控制都在这层做。nginx 前置用户请求先到 nginxnginx 做 TLS 终止和虚拟主机分流再把需要缓存的请求转发给 Squid。Squid 在后端做缓存回源目标是应用服务器或者再往后的另一层 nginx。我实际采用并推荐的是“nginx 前置”。原因很现实现在绝大多数站点都上了 HTTPSTLS 证书挂在 nginx 上比挂在 Squid 上方便太多而且 nginx 作为入口虚拟主机分流能力比 Squid 的 vhost 模式灵活多站点共用一个 IP 时特别好使。Squid 在纯 HTTP 缓存上很专业但让它处理大规模虚拟主机路由配置复杂度和可维护性都不如 nginx。所以本文的拓扑固定为“BIND 解析 - nginx 虚拟主机 - Squid 缓存 - 后端应用”。下面每个配置块都按这个链路来写。2. BIND 域名解析配置从 zone 声明到 TTL 调优2.1 区域声明与 named.conf 的常见坑BIND 的核心思路是“区域zone”管理。你要解析的每一个域名都需要在 named.conf 里声明一个 zone并指定对应的 zone 文件。很多人第一次配 BIND 时把named.conf.options改得一团糟却忘了加 zone 声明结果永远解析不出来。以 Debian/Ubuntu 系的 BIND 9 为例我的区域配置写在/etc/bind/named.conf.local里zone example.com { type master; file /etc/bind/zones/db.example.com; };如果是新的子域或单独域名也可以直接复制这段。有两个细节值得注意。一是 zone 类型主域名服务器用master如果将来要做高可用从服务器用slave并加一句masters指到主服务器。二是区块名末尾的域名不能带wwwwww.example.com是主机记录不是区域它的解析记录写在 zone 文件里。在named.conf.options里我一般做这几项设置options { directory /var/cache/bind; listen-on port 53 { 127.0.0.1; 192.0.2.10; }; listen-on-v6 { any; }; allow-query { any; }; recursion yes; allow-recursion { trusted; }; forwarders { 223.5.5.5; 119.29.29.29; }; };listen-on决定了 BIND 监听哪些网卡的 53 端口如果你只有内网地址就把私网 IP 写上去。allow-query控制谁能来查通常any表示对所有人提供解析服务如果只服务内网就写内网网段。forwarders是递归转发用的对于外部域名比如用户请求里混了其他网站的域名BIND 会转发给这些公共 DNS 去递归查询。2.2 一个可用的 zone 文件写法zone 文件是 BIND 里最容易写错的地方。我提供一个参考模板$TTL 600 IN SOA ns1.example.com. admin.example.com. ( 2026051501 ; serial 7200 ; refresh 3600 ; retry 1209600 ; expire 300 ) ; negative cache TTL ; 名称服务器记录 IN NS ns1.example.com. ns1 IN A 192.0.2.10 ; A 记录指向 nginx 入口服务器 IN A 192.0.2.11 www IN A 192.0.2.11 static IN A 192.0.2.11很多新手犯的第一个错误是 SOA 记录里域名末尾少写了一个点。ns1.example.com.最后这个点代表“绝对域名”如果省略BIND 会自动补上当前的 zone 名结果变成ns1.example.com.example.com.整个解析就废了。第二个错误是修改 zone 文件后忘了把serial序列号加一从服务器比对序列号判断是否更新主服务器如果不递增序列号改了等于没改。写完 zone 文件后用named-checkzone验证语法named-checkzone example.com /etc/bind/zones/db.example.com输出类似OK就说明语法没问题。然后执行named-checkconf rndc reloadnamed-checkconf检查的是 named.conf 整体语法rndc reload在不中断服务的情况下重新加载配置。这套命令组合我每次改完配置都会跑一遍它救了我很多次。2.3 TTL 的选择DNS 缓存与业务切换速度的平衡TTLTime To Live是 DNS 记录在客户端或递归 DNS 服务器上缓存的秒数。TTL 设得太小比如 60好处是域名换 IP 后很快生效坏处是每一个访问者都要频繁回源到你的 BIND 查询BIND 压力大一点公共 DNS 也可能限流TTL 设得太大比如 86400一天解析压力小了但你想把www从一台 nginx 切到另一台时用户可能要等一天才能访问到新服务器。我的建议是平时把 TTL 设在 300 到 600 之间既不会给 BIND 太大压力也不会让切换等太久如果已经确定要做一次 IP 变更可以在变更前 24 小时把 TTL 临时降到 60让旧记录尽快过期变更完成后再调回 600。这个技巧在标题这种“解析 nginx Squid”组合下尤其有用因为 Squid 本身也会缓存页面DNS 层如果切得慢用户请求会长时间指向旧节点Squid 缓存再一叠加整个切换周期会被拖得很长。还有一个容易被忽略的点是negative cache TTL也就是 zone 文件 SOA 记录里最后那个300。它表示当客户端查询一个不存在的记录时这个“查不到”的结果可以缓存多久。设得太长的话你新加一条 A 记录后客户端要等很久才能查到这个域名存在。所以我把默认负缓存也控制在 300 秒以内。3. nginx 虚拟主机server_name 匹配顺序与反代到 Squid 的细节3.1 server_name 的匹配优先级与默认站点nginx 的虚拟主机机制本质上是根据 HTTP 请求头里的Host字段去匹配配置里的server_name。理解匹配顺序特别重要因为它决定了你的请求到底进入哪个 server 块。匹配优先级从高到低是精确匹配比如server_name www.example.com通配符起始匹配比如server_name *.example.com通配符结尾匹配比如server_name www.*正则表达式匹配比如server_name ~^www\d\.example\.com$如果全部没匹配上则使用默认 server默认 server 是什么呢在多个 server 块里nginx 会选第一个监听了相同端口的 server 作为默认或者你显式在listen里加default_server标记。我在配置虚拟主机时习惯把入口站点写成默认server { listen 80 default_server; listen [::]:80 default_server; server_name _; return 444; }这个return 444是直接断开连接专门用来拒绝那些没带正确 Host 头的扫描请求。再往下才是真正的业务站点server { listen 80; server_name www.example.com; location / { proxy_pass http://127.0.0.1:3128; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }这里proxy_pass http://127.0.0.1:3128就是把请求转发给本机 Squid端口 3128 是 Squid 默认监听端口。3.2 让不同 location 分别走 Squid 和后端并不是所有请求都应该经过 Squid。动态接口如果被 Squid 缓存很容易出现脏数据。我一般用 location 做路径分离比如/api/动态请求直接反代到后端静态资源和页面走 Squid 缓存server { listen 80; server_name www.example.com; location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; } location / { proxy_pass http://127.0.0.1:3128; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }location /api/以斜杠结尾这个路径前缀严格匹配location /是所有没被/api/捕获的请求都会进来。判断请求路径时 nginx 会先找最长前缀匹配所以/api/的优先级高于/不用担心被覆盖。如果你想让不同域名访问不同的后端比如static.example.com全部走 Squidwww.example.com动态接口多可以拆成两个完整 server 块。虚拟主机的好处就是同一个 nginx 进程可以承载多个域名互不干扰。3.3 proxy_pass 带不带 URI 的区别这个细节我觉得是 nginx 配置里最容易被忽略、又最容易导致线上事故的地方。proxy_pass http://127.0.0.1:3128这种写法不带 URInginx 会把客户端原始请求的完整 URI 原样转发给后端但如果你写成proxy_pass http://127.0.0.1:3128/末尾多了个斜杠nginx 就会用这个 URI 去替换掉 location 中匹配到的部分。举例说明。配置location /static/ { proxy_pass http://127.0.0.1:3128/; }当用户访问/static/images/logo.png时nginx 会把/static/前缀去掉然后拼接上代理地址后面的/最终发给后端的是/images/logo.png。这往往不是你想要的结果尤其是 Squid 作为缓存层时它要知道原始 URL 才能正确计算缓存 key。所以反代到 Squid 时我永远写成不带尾部斜杠的proxy_pass http://127.0.0.1:3128;。顺带一提如果proxy_pass后面跟的是带路径的 upstream比如proxy_pass http://backend/foo;同样会触发路径替换逻辑。这个规则适用于所有 nginx 反代场景而不仅是标题里的 Squid。3.4 启用 resolver 的场景当 proxy_pass 目标是域名大多数情况下proxy_pass后面写的是 IPnginx 启动时会解析一次并缓存结果这没问题。但有时候后端是动态域名比如云上负载均衡的域名或者你想通过变量拼接出请求地址nginx 就强制要求配置一个 resolver。一个典型例子location /api/ { resolver 192.0.2.10 valid30s; set $backend http://api.internal.example.com; proxy_pass $backend; }这里重点有两个。第一resolver必须写一个能正常解析域名的 DNS 服务器地址通常可以写自建 BIND 的地址正好把标题里的两套东西也关联起来了——nginx 的动态转发内容也要依赖 BIND 的解析结果。第二proxy_pass的 target 必须写在变量里比如set $backend ...如果你直接写proxy_pass http://api.internal.example.com;而没有 resolvernginx 启动时就会报错。我之前在看到这个报错时第一反应是防火墙出问题了排查了一圈回来发现只是缺 resolver印象特别深。valid30s表示 nginx 对域名的解析结果缓存 30 秒如果你在 BIND 里改了这条域名对应的 IP最迟 30 秒后 nginx 就会用上新地址。注意这个 TTL 和 BIND zone 文件里的 TTL 是两个独立的东西BIND 的 TTL 影响客户端resolver 的valid影响 nginx 自身。4. Squid 缓存配置加速模式下最容易忽略的参数4.1 最小可用 squid.confSquid 的配置文件默认就在/etc/squid/squid.conf我每次从零开始配时都先清掉默认配置里大量用不到的示例只留一个最小可用的骨架再逐步加参数。骨架如下http_port 3128 accel vhost vport cache_peer 127.0.0.1 parent 8080 0 no-query originserver cache_mem 256 MB maximum_object_size_in_memory 512 KB memory_replacement_policy heap GDSF cache_replacement_policy heap LFUDA cache_dir ufs /var/spool/squid 10000 16 256 minimum_object_size 0 KB maximum_object_size 100 MB access_log /var/log/squid/access.log squid cache_log /var/log/squid/cache.log pid_filename /var/run/squid.pid acl all src all http_access allow all refresh_pattern -i (/cgi-bin/|\?) 0 0% 0 refresh_pattern -i \.(gif|png|jpg|jpeg|css|js|ico|svg|woff2)$ 1440 90% 43200 override-expire ignore-no-cache ignore-private refresh_pattern . 0 20% 4320先别急着跑这个配置已经够跑通一条完整链路了下面我把每个关键字段拆开讲。4.2 http_port 的 accel 模式与 cache_peer 的含义http_port 3128 accel vhost vport这一行值得单独解释。accel表示 Squid 工作在 Web 加速器模式也就是反向代理模式这时候 Squid 不会像传统转发代理一样要求客户端设置代理地址而是直接接收外部请求。vhost让 Squid 根据请求头中的 Host 选择对应的后端虚拟主机这个参数在 nginx 前置的架构里必须加因为 nginx 转发过来的请求头里带着Host: www.example.comSquid 需要识别它。vport表示保留原始请求端口如果后端要区分 HTTP 和 HTTPS 回源端口这个有用。cache_peer 127.0.0.1 parent 8080 0 no-query originserver是回源配置。parent表示这是一个父节点Squid 在缓存未命中时会向这个地址发起请求。8080是后端服务的端口在这个链路里是后端应用或者其他中转 nginx 的监听端口具体看你的业务部署。0是 ICP 端口号现在不用了就填 0。no-query表示不通过 ICP 协议查询父节点直接转发。originserver表示这个父节点就是真正的原始服务器Squid 会把它当作后端源站来看待这是加速模式平时最容易漏掉的参数没有它 Squid 可能把请求当作普通代理转发而不是回源请求。这里要注意拓扑nginx 把需要缓存的请求转发给 SquidSquid 再回源到 127.0.0.1:8080 的后端应用。如果你只有一台 nginx 和一台后端这个链路完全够用。4.3 refresh_pattern 为什么决定一切refresh_pattern是 Squid 缓存策略的灵魂。它的基本逻辑是Squid 收到源站的响应后会根据响应头里的过期信息、Last-Modified、以及 refresh_pattern 里的参数决定一个对象是否缓存、缓存多久。第一行refresh_pattern -i (/cgi-bin/|\?) 0 0% 0这是很多默认配置里都会带的规则。-i表示匹配时忽略大小写后面的正则匹配/cgi-bin/或带?的 URL参数0 0% 0表示这类请求不缓存。这就是为什么你发现不管怎么配带问号的动态请求就是无法缓存因为这条规则在最前面而且匹配的是?这个字符。如果你确实要缓存带参数的静态请求比如图片处理接口或带版本号的静态文件需要在上面那一条之前加更宽泛的规则比如refresh_pattern -i \.(jpg|jpeg|png|gif|css|js)\? 1440 90% 43200 override-expire ignore-no-cache ignore-private注意正则的顺序Squid 的 refresh_pattern 按配置文件出现的顺序匹配先匹配到的规则生效所以更具体的规则要写在前面。第二行是常见的静态资源规则1440 90% 43200这三个数字分别代表min age最小缓存时间 1440 秒、percentage如果响应头没有明确过期时间按 Last-Modified 距今时间的一定百分比计算缓存时长、max age最大缓存时间 43200 秒即 12 小时。override-expire表示忽略源站响应头里的 Expires 字段ignore-no-cache表示忽略响应头里的 Cache-Control: no-cacheignore-private表示忽略 Cache-Control: private。这三个开关加上去之后静态资源的缓存能力会明显增强但也要注意它可能把原本不该缓存的响应也缓存了使用前要确认后端返回这些资源时头信息是否安全。4.4 缓存目录初始化与 reload配置里这一行cache_dir ufs /var/spool/squid 10000 16 256ufs是存储类型/var/spool/squid是缓存目录10000是缓存最大容量 MB 数约 10GB16是一级子目录数量256是二级子目录数量。Squid 的缓存不会单文件平铺存储而是散落在多层目录里避免单个目录文件过多导致磁盘性能下降。刚配好之后缓存目录还是空的Squid 无法直接使用你需要在启动前先执行一次初始化squid -z-z参数的作用就是创建缓存目录结构。如果忘记这一步启动 Squid 时日志里会报错说缓存目录不存在或权限不足。修改 squid.conf 后先检查语法squid -k parse确认没问题再平滑重载配置squid -k reconfigure很多新手会在修改配置后直接重启 Squid导致正在处理的请求全部断开。reconfigure是在不影响现有请求的情况下加载新配置适合线上环境。如果改了 cache_dir 这种需要重建缓存的参数才考虑完整的重启。5. 三件套联调用 dig、curl 和日志验证整条链路5.1 先验证 DNS别让排查从开始就走偏配置全部落地之后第一件事不是 curl 站点而是验证域名解析。这一步如果错了后面全是白费。在任意一台内网机器上执行dig www.example.com 192.0.2.10指定192.0.2.10是强制向你的 BIND 服务器查询而不是走系统默认 DNS。观察返回结果中的ANSWER SECTION如果能看到www.example.com. 600 IN A 192.0.2.11说明解析链路是通的。注意这里的600就是你在 zone 文件里配置的 TTL。如果查询无结果按顺序检查BIND 服务是否在运行、named-checkconf是否报错、zone 文件的域名是否拼写正确、防火墙是否放行了 UDP/TCP 53 端口。当初我第一次搭好 BIND 后 dig 迟迟不出结果最后发现是 cloud 防火墙没放行 53 端口印象特别深。5.2 curl 请求头里的 X-Cache 与 Via 怎么读DNS 通了之后再测 nginx 和 Squid。我常用的命令是这样的curl -sI --resolve www.example.com:80:127.0.0.1 http://www.example.com/--resolve参数让 curl 直接跳过 DNS把www.example.com解析到 127.0.0.1这样可以在本机测试不用依赖外部网络。注意如果你的 nginx 没有监听 80 端口而是 443需要把端口和参数改成https://。重点关注响应头里的两个字段Via: 1.1 squid-3.5 X-Cache: MISS from squidVia说明这个响应的确经过了 Squid。X-Cache: MISS表示缓存未命中Squid 回源拿了一次第二次再执行同样的 curl如果看到X-Cache: HIT from squid说明缓存已经生效。一个常见的问题是为什么第二次还是MISS这就要结合第 6 章里的排查思路去看了大多数情况出在 refresh_pattern 或源站响应头上。5.3 分角色看日志nginx access_log、squid access.log、后端访问日志整条链路配好之后诊断问题最有效的方法就是“三层日志对时间”。我们在请求同一个 URL 时分别看 nginx access log、Squid access log、后端服务日志里的记录就能定位请求到底在哪一层被处理了。nginx access log 默认路径是/var/log/nginx/access.log里面能看到谁在什么时间访问了哪个虚拟主机的哪个 URL状态码是多少。Squid 的 access.log 格式比较有辨识度一行里会包含这些信息时间 响应耗时 客户端IP TCP_HIT/200 传输字节 请求方法 URL 用户TCP_HIT表示缓存命中TCP_MISS表示未命中回源了TCP_REFRESH_HIT表示缓存对象已经过期但条件请求后确认源站没变也算一种命中。看这个字段是最快判断 Squid 是否在干活的方式。后端服务日志更简单如果第一次请求后日志里出现了一条访问记录第二次请求后没有新增说明第二次是缓存命中的如果每次都新增说明缓存没有生效请求每次都穿透到了后端。这个三层对日志的方法几乎可以解决 80% 以上的“页面能访问但速度不理想”类问题。6. 我踩过的坑解析、虚拟主机与缓存各在哪一层翻车6.1 域名解析正常但 nginx 就是进错虚拟主机这个坑是标题里最容易出现的。BIND 解析明明是正常的手动访问 IP 也能通但用域名一访问掉进了另一个站点或直接 404。问题通常出在 nginx 的server_name匹配上。最常见的是同一份配置里有两个 server 块都监听了 80 端口一个server_name _默认拦截了所有请求另一个server_name www.example.com永远匹配不到。解决方法是优先检查默认 server 的配置把它调整成只拒绝未知 Host而不是把默认页面返回给所有请求。另一个是我踩过的同一个页面同时配置了 HTTP 和 HTTPS 两套虚拟主机但我只给 HTTPS 的 server 块写了server_nameHTTP 的 server 块没写导致 HTTP 请求全部进了默认 server。解决办法很简单每个 server 块都要有明确的server_name并确定好谁是默认的。6.2 访问 URL 带问号导致 Squid 永远 MISS我实际遇到过一个场景站点里大量静态资源请求带版本号比如/static/app.css?v20260515后台日志显示每次请求都回源Squid 完全没有缓存压力。排查思路是这样的先看 curl 响应头里的X-Cache: MISS确认一直在 miss再去看 Squid access.log发现请求行里的 URL 带?v20260515最后回到 squid.conf发现第一行 refresh_pattern 就是refresh_pattern -i (/cgi-bin/|\?) 0 0% 0把带问号的请求全部排除了。修复方式是调整 refresh_pattern 的顺序给带查询参数的静态资源单独加一条规则写在上面的通用静态资源规则里让它优先于排掉问号那条规则生效。这类问题不仔细看日志根本发现不了因为浏览器能打开、服务也正常就是慢。6.3 请求头保留不当Squid 回源拿错站点nginx 转发请求到 Squid 时如果没把Host头传干净Squid 在vhost模式下会根据 Host 判断应该回源到哪个后端或者干脆把请求当作错误处理。所以我每一处反代都会显式设置proxy_set_header Host $host;$host在 nginx 里取的是请求头里的 Host 字段对于标准请求来说就是用户访问的域名。如果你漏掉这一行nginx 默认会用proxy_pass地址里的 host也就是127.0.0.1:3128作为 Host 头Squid 收到后看到的 Host 是127.0.0.1:3128自然无法正确匹配虚拟主机回源请求也会出错。另外一个和请求头相关的坑是X-Forwarded-For。如果你的后端应用要根据客户端真实 IP 做访问统计或风控nginx 转发时一定要加proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr;否则后端看到的 IP 都是 nginx 或 Squid 的本地回环地址。6.4 conf 语法检查通过但缓存目录没初始化这个坑可以说是最隐蔽的。我一度在squid -k parse没报错、squid -k reconfigure也执行成功的情况下发现缓存始终 miss最后翻/var/log/squid/cache.log才看到告警说缓存存储目录不可写或者尚未初始化导致拒绝缓存。原因是重启前没有执行squid -z-z就是初始化缓存目录结构。如果目录不存在Squid 不会主动创建而是静默把缓存功能禁用掉只做转发导致所有请求看起来都正常但永远 miss。更隐蔽的是如果这个目录的属主不是 Squid 运行用户通常是proxy用户即使目录存在也无法写缓存。所以我在刚配置完或迁移过数据之后都会执行一遍squid -z chown -R proxy:proxy /var/spool/squid service squid restart再回到前面用 curl 确认 X-Cache 状态一条链路就彻底通了。如果你也想把这套“BIND 解析 nginx 虚拟主机 Squid 缓存”的链路搭起来建议严格按照上面的顺序来先把 BIND 的解析跑通并验证再配 nginx 虚拟主机并确认server_name匹配正常最后才是 Squid 的缓存参数调优。每一步都用 dig、curl、日志这三个手段验证过再进入下一步。我自己的经验是大多数排查时间其实都花在了“觉得配置没问题”但实际链路某一环根本没在工作上所以宁可每一步多花两分钟验证也不要最后一次性面对一堆未知错误。
返回列表