这是一个典型问题关于反向代理、其工作原理及其配置方式。
我如何使用同一个 Web 服务器来处理来自不同端口的服务或不同服务器的请求并通过 URL 进行区分?
答案1
如果您想要提供来自多个服务或来自同一域的多个服务器的内容,则可以将 Web 服务器配置为反向代理。这些服务(通常称为后端服务器或者应用程序服务器) 不一定需要从客户端直接访问,通常只有实际为客户端提供服务的 Web 服务器才是直接可访问的。客户端和服务器之间以及服务器和后端之间也可能有不同的方案或协议(http、https、ajp 等)。
Client ---[https]---> Server ---[http]---> backend:8080
|
|---[direct]---> files from document root
`---[http]---> localhost:4000
例子
- https://example.com/-> 直接由网络服务器提供
- https://example.com/jenkins/-> 通过代理连接到可从 Web 服务器访问的其他服务器
- https://api.example.com/-> 代理到同一主机上具有不同端口的服务
反向代理可以配置为虚拟目录或子域。
Apache 的示例配置
您需要加载必要的 Apache 模块才能将其用作反向代理。这些模块至少包括:
对于更多协议,您将需要启用更多模块。
您可以使用基于 Debian/Ubuntu 的发行版启用模块,如下所示:
sudo a2enmod proxy proxy_http
对于基于 RedHat/CentOS 的发行版,您将需要找到正确的配置文件/etc/httpd/
并手动启用模块。
上述示例的配置可能如下所示:
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/html
# SSL options left out for simplicity
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /jenkins/ http://192.168.42.18:8080/
ProxyPassReverse /jenkins/ http://192.168.42.18:8080/
</VirtualHost>
<VirtualHost *:443>
ServerName api.example.com
DocumentRoot /var/www/html
# SSL options left out for simplicity
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:4000/
ProxyPassReverse / http://localhost:4000/
</VirtualHost>
nginx 的示例配置
server {
listen 443;
server_name example.com;
root /var/www/html;
# SSL options left out for simplicity
location /jenkins/ {
proxy_pass http://192.168.42.18:8080/;
}
}
server {
listen 443;
server_name api.example.com;
# SSL options left out for simplicity
location / {
proxy_pass http://localhost:4000/;
}
}
后端配置
需要注意的一点是,后端服务器应进行相应配置。例如,如果 Jenkins 配置为使用 URL 来处理请求http://192.168.42.18:8080/
,它将使用此基本 URL 作为 CSS、JS 和图像文件的路径,从而导致大量 404 错误或超时以及服务器无法正常工作。它必须配置使用代理 URLhttps://example.com/jenkins/
作为基本 URL 来使其工作。
其他后端需要类似的配置。这是解决 URL 指向后端服务器而不是前端服务器的问题的首选方法。如果由于某种原因无法更改后端服务器的配置,您可以配置前端服务器在将 HTML 提供给客户端之前重写它。
然而,这应该被视为最后的手段,因为它给前端服务器增加了不必要的负载。
阿帕奇
使用 Apache 时,您可以使用模块mod_proxy_html
.该模块提供指令ProxyHTMLURLMap
,您可以使用它来重写响应。
ProxyPass /jenkins/ http://192.168.42.18:8080/
ProxyPassReverse /jenkins/ http://192.168.42.18:8080/
SetOutputFilter proxy-html # make sure the output is filtered by proxy-html
ProxyHTMLURLMap http://192.168.42.18:8080/ https://example.com/jenkins/
ProxyHTMLExtended On # by default only HTML output is filtered
这应该使用 publichostname URL 重写答案中所有出现的 localserver URL。
nginx
使用 nginx 可以实现类似的结果ngx_http_sub_module:
location /jenkins/ {
proxy_pass http://192.168.42.18:8080/;
sub_filter '<a href="http://192.168.42.18:8080/' '<a href="https://$host/jenkins/';
sub_filter_once on;
}