如何在 CentOS 7 上使用 Apache 作为带有 mod_proxy 的反向代理
介绍
反向代理 是一种代理服务器,它接受 HTTP(S) 请求并将它们透明地分发到一个或多个后端服务器。反向代理很有用,因为许多现代 Web 应用程序使用后端应用程序服务器处理传入的 HTTP 请求,这些服务器不打算由用户直接访问,并且通常只支持基本的 HTTP 功能。
您可以使用反向代理来防止这些底层应用服务器被直接访问。它们还可用于将传入请求的负载分配到多个不同的应用程序服务器,从而大规模提高性能并提供故障安全性。它们可以填补应用服务器不提供的功能的空白,例如缓存、压缩或 SSL 加密。
在本教程中,您将使用 mod_proxy
扩展将 Apache 设置为基本的反向代理,以将传入连接重定向到在同一网络上运行的一个或多个后端服务器。本教程使用使用 Flask Web 框架编写的简单后端,但您可以使用您喜欢的任何后端服务器。
先决条件
要学习本教程,您需要:
- 一台使用此初始服务器设置教程设置的 CentOS 7 服务器,包括一个 sudo 非根用户。
- 按照如何在 CentOS 7 上安装 Linux、Apache、MySQL、PHP (LAMP) 堆栈的第 1 步在您的服务器上安装 Apache 2。
- 可选地,
nano
文本编辑器随yum install nano
安装。 CentOS 默认带有vi
文本编辑器,但nano
可以更友好。
第 1 步 — 引入必要的 Apache 模块
使用 Apache 作为反向代理所需的模块包括 mod_proxy
本身和它的几个附加模块,这些模块扩展了它的功能以支持不同的网络协议。具体来说,我们将使用:
mod_proxy
,主要代理模块 Apache 模块,用于重定向连接;它允许 Apache 充当底层应用程序服务器的网关。mod_proxy_http
,添加了对代理 HTTP 连接的支持。mod_proxy_balancer
和mod_lbmethod_byrequests
,为多个后端服务器添加负载平衡功能。
在全新的 CentOS 7 安装中默认启用所有四个模块。您可以通过运行以下命令验证它们是否已启用:
- httpd -M
命令输出将列出所有启用的 Apache 模块。您要查找的四行是上述模块名称:
Output. . .
proxy_module (shared)
. . .
lbmethod_byrequests_module (shared)
. . .
proxy_balancer_module (shared)
. . .
proxy_http_module (shared)
. . .
如果模块未启用,您可以通过使用 nano
打开 /etc/httpd/conf.modules.d/00-proxy.conf
来启用它们:
- sudo nano /etc/httpd/conf.modules.d/00-proxy.conf
并通过从行开头删除 #
符号来取消注释包含必要模块的行,因此文件如下所示:
. . .
LoadModule proxy_module modules/mod_proxy.so
. . .
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
. . .
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
. . .
LoadModule proxy_http_module modules/mod_proxy_http.so
. . .
要使更改生效,请保存文件并重新启动 Apache。
- sudo systemctl restart httpd
Apache 现在已准备好充当 HTTP 请求的反向代理。在下一步中,我们将创建两个非常基本的后端服务器。这些将帮助我们验证配置是否正常工作,但如果您已经拥有自己的后端应用程序,则可以跳到第 3 步。
第 2 步 — 创建后端测试服务器
运行一些简单的后端服务器是测试 Apache 配置是否正常工作的简单方法。在这里,我们将制作两个测试服务器,它们通过打印一行文本来响应 HTTP 请求。一台服务器会说 Hello world!另一个会说你好世界!。
注意:在非测试设置中,后端服务器通常都返回相同类型的内容。然而,特别是对于这个测试,让两个服务器返回不同的消息可以很容易地检查负载平衡机制是否使用了两者。
Flask 是一个用于构建 Web 应用程序的 Python 微框架。我们使用 Flask 创建测试服务器,因为一个基本的应用程序只需要几行代码。您无需了解 Python 即可设置这些,但如果您想学习,可以查看这些 Python 教程。
让我们先安装 IUS 包存储库文件。 IUS(Inline with Upstream Stable)是一个社区项目,它为 CentOS 带来精选软件的最新版本,包括 Python 3。
- sudo yum -y install https://centos7.iuscommunity.org/ius-release.rpm
然后安装 Python 3 和 Pip,这是推荐的 Python 包管理器。
- sudo yum -y install python35u python35u-pip
使用 Pip 安装 Flask。
- sudo pip3.5 install flask
现在所有必需的组件都已安装,首先创建一个新文件,该文件将包含当前用户主目录中第一个后端服务器的代码。
- nano ~/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()
的返回值作为响应指向应用程序的 /
根 URL 的 HTTP 请求。
第二个后端服务器与第一个完全相同,只是返回不同的文本行,所以从复制第一个文件开始。
- cp ~/backend1.py ~/backend2.py
打开新复制的文件。
- nano ~/backend2.py
更改要从 Hello world! 返回的消息到 Howdy world!,然后保存并关闭文件。
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
命令之前通过在同一行中设置 FLASK_APP
环境变量。环境变量是一种将信息传递到从 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/
这将输出 Hello world!在终端。测试第二台服务器:
- curl http://127.0.0.1:8081/
这将输出 Howdy world!反而。
注意:要在不再需要这两个测试服务器后关闭它们,就像完成本教程时一样,您可以简单地执行 killall flask
。
在下一步中,我们将修改 Apache 的配置文件以使其能够用作反向代理。
第 3 步 — 修改默认配置以启用反向代理
在本节中,我们将设置默认的 Apache 虚拟主机作为单个后端服务器或一组负载平衡后端服务器的反向代理。
注意:在本教程中,我们在虚拟主机级别应用配置。在 Apache 的默认安装中,没有配置虚拟主机。我们将创建一个单一的默认虚拟主机来捕获所有流量。但是,您也可以在其他虚拟主机中使用所有这些配置片段。要了解有关 Apache 中虚拟主机的更多信息,您可以阅读此如何在 CentOS 7 上设置 Apache 虚拟主机教程。
如果您的 Apache 服务器同时充当 HTTP 和 HTTPS 服务器,则您的反向代理配置必须同时放置在 HTTP 和 HTTPS 虚拟主机中。要了解有关 Apache 的 SSL 的更多信息,您可以阅读此如何在 Apache 上为 CentOS 7 创建 SSL 证书教程。
通过使用 nano
或您喜欢的文本编辑器在 /etc/httpd/conf.d
目录中创建一个新的空 Apache 配置文件来创建新的默认虚拟主机。
- sudo nano /etc/httpd/conf.d/default-site.conf
下面的第一个示例解释了如何将默认虚拟主机配置为单个后端服务器的反向代理,第二个示例为多个后端服务器设置负载平衡反向代理。
示例 1 - 反向代理单个后端服务器
将以下内容粘贴到 default-site.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 httpd
现在,如果您在 Web 浏览器中访问 http://your_server_ip
,您将看到后端服务器响应,而不是标准的 Apache 欢迎页面。如果您执行了第 2 步,这意味着您将看到 Hellow world!。
示例 2 - 跨多个后端服务器的负载平衡
如果您有多个后端服务器,代理时在它们之间分配流量的一个好方法是使用 mod_proxy
的负载平衡功能。
将 VirtualHost
块中的所有内容替换为以下内容,因此您的配置文件如下所示:
<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 httpd
如果您在 Web 浏览器中访问 http://your_server_ip
,您将看到后端服务器的响应,而不是标准的 Apache 页面。如果您按照第 2 步操作,多次刷新页面应该会显示 Hello 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
文档。