介绍
反向代理 是一种代理服务器,它接受 HTTP(S) 请求并将它们透明地分发到一个或多个后端服务器。 反向代理非常有用,因为许多现代 Web 应用程序使用后端应用程序服务器处理传入的 HTTP 请求。 这些服务器并不意味着用户可以直接访问,并且通常只支持基本的 HTTP 功能。
您可以使用反向代理来防止这些底层应用程序服务器被直接访问。 它们还可用于将来自传入请求的负载分配到多个不同的应用程序服务器,从而大规模提高性能并提供故障安全性。 它们可以使用应用程序服务器不提供的功能来填补空白,例如缓存、压缩或 SSL 加密。
在本教程中,您将使用 mod_proxy
扩展将 Apache 设置为基本反向代理,以将传入连接重定向到在同一网络上运行的一个或多个后端服务器。 本教程使用使用 Flask Web 框架 编写的简单后端,但您可以使用任何您喜欢的后端服务器。
先决条件
要遵循本教程,您将需要:
- 使用 this initial server setup tutorial 设置一台 Ubuntu 16.04 服务器,包括 sudo 非 root 用户和防火墙。
- 按照如何在 Ubuntu 16.04 上安装 Linux、Apache、MySQL、PHP (LAMP) 堆栈的 步骤 1 在您的服务器上安装 Apache 2。
第 1 步 — 启用必要的 Apache 模块
Apache 捆绑了许多模块,这些模块在全新安装中可用但未启用。 首先,您需要启用将在本教程中使用的那些。
您需要的模块是 mod_proxy
本身和它的几个附加模块,它们扩展了它的功能以支持不同的网络协议。 具体来说,您将使用:
mod_proxy
,主要代理模块Apache模块,用于重定向连接; 它允许 Apache 充当通往底层应用程序服务器的网关。mod_proxy_http
,增加了对代理 HTTP 连接的支持。mod_proxy_balancer
和mod_lbmethod_byrequests
,为多个后端服务器添加负载平衡功能。
要启用这四个模块,请依次执行以下命令。
sudo a2enmod proxy sudo a2enmod proxy_http sudo a2enmod proxy_balancer sudo a2enmod lbmethod_byrequests
要使这些更改生效,请重新启动 Apache。
sudo systemctl restart apache2
Apache 现在已准备好充当 HTTP 请求的反向代理。 在下一步(可选)中,您将创建两个非常基本的后端服务器。 这些将帮助我们验证配置是否正常工作,但如果您已经拥有自己的后端应用程序,则可以跳到第 3 步。
第 2 步 — 创建后端测试服务器(推荐)
运行一些简单的后端服务器是测试 Apache 配置是否正常工作的简单方法。 在这里,您将创建两个测试服务器,它们通过打印一行文本来响应 HTTP 请求。 一台服务器会说 Hello world!,另一台服务器会说 Hello world!。 这将让我们测试多个服务之间的负载平衡。
注意: 在非测试设置中,后端服务器通常都返回相同类型的内容。 但是,特别是对于这个测试,让两台服务器返回不同的消息可以很容易地检查负载平衡机制是否同时使用了这两个服务器。
Flask 是一个用于构建 Web 应用程序的 Python 微框架。 您正在使用 Flask 创建测试服务器,因为基本应用程序只需要几行代码。 你不需要知道 Python 来设置这些,但是如果你想学习,你可以看看这些 Python 教程。
首先更新软件包列表。
sudo apt-get update
然后安装推荐的 Python 包管理器 Pip。
sudo apt-get install python3-pip
使用 Pip 安装 Flask。
sudo pip3 install Flask==1.1.4
现在已经安装了所有必需的组件,首先创建一个新文件,该文件将包含当前用户主目录中第一个后端服务器的代码。
nano ~/backend1.py
将以下代码复制到文件中,然后保存并关闭它。
~/backend1.py
from flask import Flask app = Flask(__name__) @app.route('/') def home(): return 'Hello world!'
前两行初始化 Flask 框架。 有一个函数 home()
,它返回一行文本 (Hello world!
)。 home()
函数定义上方的 @app.route('/')
行告诉 Flask 使用 home()
' 的返回值作为对指向 /
根的 HTTP 请求的响应应用程序的 URL。
第二个后端服务器与第一个完全相同,除了返回不同的文本行,因此首先复制第一个文件。
cp ~/backend1.py ~/backend2.py
打开新复制的文件。
nano ~/backend2.py
将要返回的消息从 Hello world! 更改为 Howdy world!,然后保存并关闭文件。 该脚本现在将如下所示:
~/backend2.py
from flask import Flask app = Flask(__name__) @app.route('/') def home(): return 'Howdy world!'
使用以下命令在端口 8080
上启动第一个后台服务器。 这也将 Flask 的输出重定向到 /dev/null
,因为它会使控制台输出进一步模糊。
FLASK_APP=~/backend1.py flask run --port=8080 >/dev/null 2>&1 &
在这里,您通过在同一行中设置 FLASK_APP
环境变量,在 flask
命令之前。 环境变量是一种将信息传递到从 shell 生成的进程的便捷方式。 您可以在如何在Linux VPS上读取和设置环境变量和Shell变量中了解更多关于环境变量的信息。
在这种情况下,使用环境变量可确保该设置仅适用于正在运行的命令,并且之后将不再可用,因为您将传递另一个文件名以告诉 flask
命令启动第二个服务器的相同方式
同样,使用此命令在端口 8081
上启动第二个服务器。 请注意 FLASK_APP
环境变量的不同值。
FLASK_APP=~/backend2.py flask run --port=8081 >/dev/null 2>&1 &
您可以使用 curl
测试两个服务器是否正在运行。 测试第一台服务器:
curl http://127.0.0.1:8080/
这将打印来自服务器的响应:
OutputHello world!
测试第二台服务器:
curl http://127.0.0.1:8081/
和以前一样,这将打印来自服务器的响应:
OutputHowdy world!
注意:在不再需要两个测试服务器后关闭它们,就像完成本教程一样,只需执行killall flask
即可。
在下一步中,您将修改 Apache 的配置文件以将其用作反向代理。
第 3 步 — 修改默认配置以启用反向代理
在本节中,您将设置默认的 Apache 虚拟主机作为单个后端服务器或负载平衡后端服务器阵列的反向代理。
注意:在本教程中,您将在虚拟主机级别应用配置。 在 Apache 的默认安装中,仅启用了一个默认虚拟主机。 但是,您也可以在其他虚拟主机中使用所有这些配置片段。 要了解有关 Apache 中虚拟主机的更多信息,您可以阅读此 如何在 Ubuntu 16.04 上设置 Apache 虚拟主机教程。
如果您的 Apache 服务器同时充当 HTTP 和 HTTPS 服务器,则您的反向代理配置必须同时放置在 HTTP 和 HTTPS 虚拟主机中。 要了解有关 Apache 的 SSL 的更多信息,您可以阅读此 如何在 Ubuntu 16.04 中为 Apache 创建自签名 SSL 证书教程。
使用 nano
或您喜欢的文本编辑器打开默认的 Apache 配置文件。
sudo nano /etc/apache2/sites-available/000-default.conf
在该文件中,您会发现从第一行开始的 <VirtualHost *:80>
块。 下面的第一个示例说明了如何将此块配置为单个后端服务器的反向代理,第二个示例为多个后端服务器设置负载平衡的反向代理。
示例 1 — 反向代理单个后端服务器
将 VirtualHost
块中的所有内容替换为以下内容,使您的配置文件如下所示:
/etc/apache2/sites-available/000-default.conf
<VirtualHost *:80> ProxyPreserveHost On ProxyPass / http://127.0.0.1:8080/ ProxyPassReverse / http://127.0.0.1:8080/ </VirtualHost>
如果您已按照步骤 2 中的示例服务器进行操作,请使用上面块中所写的 127.0.0.1:8080
。 如果您有自己的应用程序服务器,请改用它们的地址。
这里有三个指令:
ProxyPreserveHost
使 Apache 将原始的Host
标头传递给后端服务器。 这很有用,因为它使后端服务器知道用于访问应用程序的地址。ProxyPass
是主要的代理配置指令。 在这种情况下,它指定根 URL (/
) 下的所有内容都应映射到给定地址的后端服务器。 例如,如果 Apache 收到对/example
的请求,它将连接到http://your_backend_server/example
并将响应返回给原始客户端。ProxyPassReverse
应该与ProxyPass
具有相同的配置。 它告诉 Apache 修改来自后端服务器的响应标头。 这确保如果后端服务器返回位置重定向标头,客户端的浏览器将被重定向到代理地址而不是后端服务器地址,这将无法按预期工作。
要使这些更改生效,请重新启动 Apache。
sudo systemctl restart apache2
现在,如果您在 Web 浏览器中访问 http://your_server_ip
,您将看到后端服务器响应,而不是标准的 Apache 欢迎页面。 如果您按照第 2 步操作,这意味着您将看到 Hello world!。
示例 2 - 跨多个后端服务器的负载平衡
如果您有多个后端服务器,代理时在它们之间分配流量的一个好方法是使用 mod_proxy
的负载平衡功能。
将 VirtualHost
块中的所有内容替换为以下内容,使您的配置文件如下所示:
/etc/apache2/sites-available/000-default.conf
<VirtualHost *:80> <Proxy balancer://mycluster> BalancerMember http://127.0.0.1:8080 BalancerMember http://127.0.0.1:8081 </Proxy> ProxyPreserveHost On ProxyPass / balancer://mycluster/ ProxyPassReverse / balancer://mycluster/ </VirtualHost>
配置与前一个类似,但不是直接指定单个后端服务器,而是使用附加的 Proxy
块来定义多个服务器。 该块名为 balancer://mycluster
(名称可以自由更改),由一个或多个 BalancerMember
组成,它们指定底层后端服务器地址。 ProxyPass
和 ProxyPassReverse
指令使用名为 mycluster
的负载平衡器池而不是特定服务器。
如果您按照步骤 2 中的示例服务器进行操作,请使用 127.0.0.1:8080
和 127.0.0.1:8081
作为 BalancerMember
指令,如上块所述。 如果您有自己的应用程序服务器,请改用它们的地址。
要使这些更改生效,请重新启动 Apache。
sudo systemctl restart apache2
如果您在 Web 浏览器中访问 http://your_server_ip
,您将看到后端服务器的响应,而不是标准的 Apache 页面。 如果您按照第 2 步操作,多次刷新页面应该会显示 Hello world! 和 Howdy world!,这意味着反向代理正常工作并且正在两个服务器之间进行负载平衡。
结论
您现在知道如何将 Apache 设置为一个或多个底层应用程序服务器的反向代理。 mod_proxy
可以有效地用于为使用大量语言和技术(例如 Python 和 Django 或 Ruby 和 Ruby on Rails)编写的应用程序服务器配置反向代理。 它还可以用于为具有大量流量的站点平衡多个后端服务器之间的流量,通过多个服务器提供高可用性,或者为本地不支持 SSL 的后端服务器提供安全的 SSL 支持。
虽然 mod_proxy
与 mod_proxy_http
可能是最常用的模块组合,但还有其他几种支持不同的网络协议。 您在这里没有使用它们,但其他一些流行的模块包括:
mod_proxy_ftp
用于 FTP。mod_proxy_connect
用于 SSL 隧道。mod_proxy_ajp
用于 AJP(Apache JServ 协议),例如基于 Tomcat 的后端。mod_proxy_wstunnel
用于网络套接字。
要了解更多关于mod_proxy
的信息,您可以阅读官方Apache mod_proxy文档。