HTTP 持久连接

在 HTTP 持久连接或 HTTP 保持连接中,多个请求或响应使用一个 TCP/IP 连接。与普通连接相比,它的性能有很大提高,因为它只使用一个连接,而不是为每个请求或响应打开和关闭连接。HTTP 保持连接的一些优点如下:

  • 由于每次打开的 TCP 连接较少,CPU 和内存的负载也会减少,而且在使用这些 TCP 连接时,不会为后续请求和响应打开新的连接。

  • 减少 TCP 连接建立后后续请求的延迟。在建立 TCP 连接时,用户和 HTTP 服务器之间会进行三方握手通信。握手成功后,TCP 连接就建立了。在保持连接的情况下,只对建立 TCP 连接的初始请求进行一次握手,对后续请求不进行握手或 TCP 连接的打开/关闭。这就提高了请求/响应的性能。

  • 由于每次只向服务器打开几个 TCP 连接,网络拥塞现象也会减少。

除了这些优点外,keep-alive 也有一些副作用。每个服务器都有一个并发限制,当达到或消耗了这个并发限制时,应用程序的性能就会大大降低。为了解决这个问题,我们为每个连接定义了超时时间,超时后 HTTP keep-alive 连接会自动关闭。现在,让我们在 Apache 和 NGINX 上启用 HTTP keep-alive。

Apache

在 Apache 中,可以通过两种方式启用 keep-alive。可以在 .htaccess 文件或 Apache 配置文件中启用。

要在 .htaccess 文件中启用,请在 .htaccess 文件中设置以下配置:

<ifModule mod_headers.c>
  Header set Connection keep-alive
</ifModule>

在前面的配置中,我们在 .htaccess 文件中将连接头设置为 keep-alive。由于 .htaccess 配置优先于配置文件中的配置,因此无论 Apache 配置文件中的 keep-alive 配置如何,都将优先于该配置。

要在 Apache 配置文件中启用 keep-alive 连接,我们必须修改三个配置选项。搜索以下配置,并将其值设置为示例中的值:

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 100

在前面的配置中,我们将 KeepAlive 的值设置为 On,从而打开了保持连接配置。

其次是 MaxKeepAliveRequests,它定义了当时网络服务器的最大保持连接数。Apache 的默认值为 100,也可根据需要更改。为获得高性能,该值应保持较高水平。如果设置为 0,将允许无限制的保持连接,这是不推荐的。

最后一项配置是 KeepAliveTimeout,设置为 100 秒。这定义了在同一 TCP 连接上等待来自同一客户端的下一个请求的秒数。如果没有请求,则关闭连接。

NGINX

HTTP keep-alive 是 http_core 模块的一部分,默认情况下已启用。在 NGINX 配置文件中,我们可以编辑一些选项,例如超时。打开 nginx 配置文件,编辑以下配置选项,并将其值设置如下:

keepalive_requests 100
keepalive_timeout 100

keepalive_requests 配置定义了单个客户端在单个 HTTP 保持连接上可发出的最大请求数。

keepalive_timeout 配置是服务器在关闭 keep-alive 连接前等待下一个请求的秒数。

GZIP 压缩

内容压缩提供了一种减少 HTTP 服务器传输内容大小的方法。Apache 和 NGINX 都支持 GZIP 压缩,同样,大多数现代浏览器也支持 GZIP。启用 GZIP 压缩后,HTTP 服务器会发送压缩后的 HTML、CSS、JavaScript 和图像,这些内容的体积会变小。这样,内容就能快速加载。

只有当浏览器发送自身支持 GZIP 压缩的信息时,web 服务器才会通过 GZIP 压缩内容。通常,浏览器会在 Request 头中发送此类信息。

以下是 Apache 和 NGINX 启用 GZIP 压缩的代码。

Apache

可将以下代码放入 .htaccess 文件:

<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
#Add filters to different content types
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript
#Don't compress images
  SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dontvary
</IfModule>

在前面的代码中,我们使用 Apache deflate 模块启用了压缩功能。我们使用类型过滤器只压缩特定类型的文件,如 .html、纯文本、.xml.css.js。此外,在结束模块之前,我们还设置了不压缩图片的情况,因为压缩图片会导致图片质量下降。

NGINX

如前所述,您必须将以下代码放入 NGINX 的虚拟主机 conf 文件中:

gzip on;
gzip_vary on;
gzip_types text/plain text/xml text/css text/javascript application/xjavascript;
gzip_com_level 4;

在前面的代码中,通过 gzip on; 行激活了 GZIP 压缩。gzip_vary on; 行用于启用可变头。gzip_types 行用于定义要压缩的文件类型。根据需要,可以添加任何文件类型。gzip_com_level 4; 行用于设置压缩级别,但要注意不要设置过高。它的范围在 1 到 9 之间,所以要保持在中间值。

现在,让我们检查一下压缩是否真的有效。在下面的截图中,请求被发送到一个未启用 GZIP 压缩的服务器。最终下载或传输的 HTML 页面大小为 59 KB:

image 2023 11 05 11 23 52 731

在网络服务器上启用 GZIP 压缩后,传输的 HTML 页面大小减少到 9.95 KB,如下图所示:

image 2023 11 05 11 24 53 111

此外,加载内容的时间也会缩短。因此,内容的大小越小,页面的加载速度就越快。

使用 PHP 作为单独的服务

Apache 使用 mod_php 模块来处理 PHP。这样,PHP 解释器就集成到了 Apache 中,所有处理都由 Apache 模块完成,这会占用更多的服务器硬件资源。也可以在 Apache 中使用 PHP-FPM,它使用 FastCGI 协议并在单独的进程中运行。这样 Apache 就能处理 HTTP 请求,而 PHP 处理则由 PHP-FPM 完成。

另一方面,NGINX 没有为 PHP 处理提供任何内置支持或模块支持。因此,在 NGINX 中,PHP 总是在单独的服务中使用。

现在,让我们看看当 PHP 作为独立服务运行时会发生什么:网络服务器不知道如何处理动态内容请求,于是将请求转发给另一个外部服务,从而减少了网络服务器的处理负荷。

禁用未使用的模块

Apache 和 NGINX 都内置了大量模块。在大多数情况下,您并不需要其中的某些模块。禁用这些模块是个好办法。

好的做法是列出已启用模块的列表,逐个禁用这些模块,然后重启服务器。之后,检查应用程序是否正常运行。如果能正常工作,请继续;否则,请重新启用应用程序停止正常工作的模块。

这是因为你可能会发现,某个模块可能并不需要,但其他一些有用的模块却依赖于这个模块。因此,最好的做法是列出一个列表,然后如前所述启用或禁用模块。

Apache

要列出为 Apache 加载的所有模块,请在终端中发出以下命令:

sudo apachectl –M

该命令将列出所有加载的模块,如下截图所示:

image 2023 11 05 11 29 15 047

现在,分析所有加载的模块,检查应用程序是否需要它们,并按如下步骤禁用它们。

打开 Apache 配置文件,找到加载所有模块的部分。此处包含一个示例:

LoadModule access_compat_module modules/mod_access_compat.so
LoadModule actions_module modules/mod_actions.so
LoadModule alias_module modules/mod_alias.so
LoadModule allowmethods_module modules/mod_allowmethods.so
LoadModule asis_module modules/mod_asis.so
LoadModule auth_basic_module modules/mod_auth_basic.so
#LoadModule auth_digest_module modules/mod_auth_digest.so
#LoadModule auth_form_module modules/mod_auth_form.so
#LoadModule authn_anon_module modules/mod_authn_anon.so

前面有 号的模块不会加载。因此,要禁用完整列表中的某个模块,只需加上 号即可。# 号将注释掉该行,模块将不再加载。

NGINX

要检查 NGINX 编译时使用了哪些模块,请在终端中发出以下命令:

sudo Nginx –V

这将列出有关 NGINX 安装的完整信息,包括版本和编译 NGINX 的模块。请看下面的截图:

image 2023 11 05 11 32 12 069

通常,NGINX 只启用 NGINX 运行所需的模块。要启用任何其他与 NGINX 一起编译安装的模块,我们可以在 nginx.conf 文件中对其进行少量配置,但没有禁用任何 NGINX 模块的单一方法。因此,最好搜索一下该特定模块,并查看 NGINX 网站上的模块页面。在那里,我们可以找到有关该特定模块的信息,如果有的话,还可以找到有关如何禁用和配置该模块的信息。

Web 服务器资源

每个网络服务器都有自己的通用最佳设置。然而,这些设置对于您当前的服务器硬件来说可能并非最佳。网络服务器硬件的最大问题是内存。服务器的内存越大,网络服务器处理请求的能力就越强。

NGINX

NGINX 提供了两个变量来调整资源,即 worker_processesworker_connectionsworker_processes 设置决定了应该运行多少个 NGINX 进程。

现在,我们应该使用多少个 worker_processes 资源呢?这取决于服务器。通常情况下,每个处理器内核一个 Worker 进程。因此,如果您的服务器处理器有四个内核,那么这个值可以设置为 4。

Worker_connections 的值显示了每个 Worker_processes 每秒设置的连接数。简单地说,worker_connections 告诉 NGINX 可以同时处理多少个请求。worker_connections 的值取决于系统处理器内核。要了解 Linux 系统(Debian/Ubuntu)的核心限制,请在终端中执行以下命令:

# 进程最大可打开文件数
Ulimit –n

该命令将显示 Worker_connections 应使用的数字。

现在,假设我们的处理器有四个内核,每个内核的限制为 512。然后,我们可以在 NGINX 主配置文件中设置这两个变量的值。在 Debian/Ubuntu 上,它位于 /etc/nginx/nginx.conf

现在,找出这两个变量并按如下方式设置:

Worker_processes 4;
Worker_connections 512

前面提到的值可能会很高,特别是 worker_connections,因为服务器处理器内核有很高的限制。