nginx - 通过 Unix 域套接字连接 Nginx 和 Varnish 6 不起作用
问题描述
我在同一台机器上的 Varnish 6 前面使用 Nginx 作为 SSL 端点。这在使用 TCP 端口时效果很好。由于 Varnish 6 支持监听 Unix 域套接字,我将配置更改为使用套接字:
varnishd 以选项开头:(
-a /var/run/varnish.sock,PROXY,user=varnish,group=varnish,mode=666
以前是 -a :8080)在 Nginx 配置中,我
proxy_pass http://127.0.0.1:8080;
改为proxy_pass http://unix:/var/run/varnish.sock;
重新启动 Nginx 和 Varnish,没有显示错误。套接字文件 /var/run/varnish.sock 被创建并且是世界可写的(我知道,我知道......我只是想让它运行)。Netstat 说 varnishd 正在监听 /var/run/varnish.sock。
但它不起作用,对 nginx 的任何 Web 请求都会返回“502 Bad Gateway”。
Nginx 错误日志显示“从上游读取响应标头时上游过早关闭连接”。
Varnishlog 为每个请求显示如下条目:
* << Session >> 65578
- Begin sess 0 PROXY
- SessOpen 0.0.0.0 0 a0 0.0.0.0 0 1557937009.691636 21
- SessClose RX_JUNK 0.000
- End
知道出了什么问题吗?
Varnish 是 varnish-6.0.3 修订版 7d1ded3aa033a018317dbafc61587026ea2ef8a3,Nginx 是 nginx/1.14.0 (Ubuntu),在 Ubuntu 18.04 Bionic 上运行
解决方案
您让 Varnish 使用 PROXY 协议进行侦听,但 NGINX 正在与常规 HTTP 协议通信。因此它失败了。
准确地说,-a /var/run/varnish.sock,PROXY,user=varnish,group=varnish,mode=666
是指 Varnish 监听 UDS 套接字,只接受 PROXY 协议。没有什么神奇的开关可以让它同时接受常规的 HTTP 和 PROXY 协议。
在一个完美的世界中,您将有一种方法让 NGINX 将代理协议转发(对话)到 Varnish。但是你不能proxy_pass
在http {}
上下文中做到这一点。您可以在 NGINX 流中执行proxy_pass
+ proxy_protocol
,但这通常不是您想要的,因为这会破坏 HTTP/2 并将其降级为旧协议。
请务必阅读UDS 堆栈概念。具体来说,它提到了为什么 NGINX 不是 UDS 设置中 TLS 终止的错误选择:
NGINX 无法通过 http 代理模块转发 PROXY 协议。这意味着 server { proxy_pass .... } TLS 终止到侦听 PROXY 协议的 Varnish 将不起作用。
和
nginx SSL 流 + Varnish 监听 PROXY 协议将不支持 HTTP/2,因为 nginx SSL 流不知道如何协商 ALPN proto。
推荐阅读
- android - 在重新创建活动后以编程方式设置导航图时,显示错误的片段
- mysql - SQL:在字符串上触发子字符串?
- r - R Shiny 必填字段调查表
- pycharm - 在 PyCharm vs Jupyter Lab 中运行 exec()
- containers - 无法执行到容器中
- java - 如何使用 pandas 运行 Python 代码,从 Java 请求等依赖项?
- php - Symfony 如何加载端到端测试的测试环境?
- mysql - 如何在 django 中创建一个单独的数据库而不使用默认数据库?
- ssis - SSISDB 上的包执行失败,出现错误“无法创建名为 DynamicsCRM 的类型”
- java - Java 声音 API 混合器 TargetDataLines 与 Windows 10 中的现实不符