当我启用 https 时,Nginx 性能显著下降(比仅使用 http 慢 30 倍),比 Apache https 慢 12 倍

当我启用 https 时,Nginx 性能显著下降(比仅使用 http 慢 30 倍),比 Apache https 慢 12 倍

我有一个 Angular 网站,其中静态资产大约有 1.5 mb,gzip 压缩后大约有 400 kb,我使用 nginx 作为我的 Web 服务器和 API 服务器的反向代理,当我使用 Apache 基准测试工具测试 nginx 时,我发现如果我测试 https 网站,与 http 相比,性能会大幅下降(https 慢 10 倍),并且 CPU 利用率和内存一点也不高(CPU 30% 内存只有 1 mb!!)

我已经搜索了几个小时并尝试了所有可能的增强功能,但都没有起作用,据我所知 https 在现代 Web 服务器上不会慢那么多(http 大约 1500 个请求/秒,https 对于 nginx 是 46 个请求/秒),这主要是因为 Nginx https 连接时间非常长,但我不知道如何解决这个问题。

有人可以建议如何改善这种情况吗?

(同样令我惊讶的是,Apache 在两种情况下的表现都更好,但如果我将并发连接数设置为超过 200,它就不会响应)并且这不是 nginx 与 apache 的比较,我只是陈述我的情况。

重要的提示:

我并不是在比较这两台网络服务器,这不是本网站的重点,但总体而言,它们的性能相当因此,如果 nginx 中的 https 比 Apache 慢 10 倍,我感觉我的 Nginx 配置有问题,我想修复它。

所有测试都在我的 Windows 机器 i7 和 16 GB RAM 上进行。

仅限 Nginx http:

C:\Apache24\bin>ab -n 5000 -c 200 http://localhost:8100/abc/index.html?param=abc
This is ApacheBench, Version 2.3 <$Revision: 1826891 $>

Server Software:        nginx/1.15.4
Server Hostname:        localhost
Server Port:            8100

Document Path:          /abc/index.html?param=abc
Document Length:        1099 bytes

Concurrency Level:      200
Time taken for tests:   3.246 seconds
Complete requests:      5000
Failed requests:        0
Total transferred:      6665000 bytes
HTML transferred:       5495000 bytes
Requests per second:    1540.32 [#/sec] (mean)
Time per request:       129.843 [ms] (mean)
Time per request:       0.649 [ms] (mean, across all concurrent requests)
Transfer rate:          2005.12 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.3      0      16
Processing:    31   87  12.8     94     124
Waiting:        0   87  13.7     94     124
Total:         31   87  12.8     94     124

Percentage of the requests served within a certain time (ms)
  50%     94
  66%     94
  75%     94
  80%     94
  90%     99
  95%    109
  98%    109
  99%    113
 100%    124 (longest request)

Nginx https(启用 http2)

C:\Apache24\bin>abs -n 5000 -c 200 https://localhost:8200/abc/index.html?param=abc
This is ApacheBench, Version 2.3 <$Revision: 1826891 $>

Server Software:        nginx/1.15.4
Server Hostname:        localhost
Server Port:            8200
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256
TLS Server Name:        localhost

Document Path:          /abc/index.html?param=abc
Document Length:        1099 bytes

Concurrency Level:      200
Time taken for tests:   108.985 seconds
Complete requests:      5000
Failed requests:        0
Total transferred:      6780000 bytes
HTML transferred:       5495000 bytes
Requests per second:    45.88 [#/sec] (mean)
Time per request:       4359.386 [ms] (mean)
Time per request:       21.797 [ms] (mean, across all concurrent requests)
Transfer rate:          60.75 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       16 4201 506.8   4251    4755
Processing:     0   32  12.6     31      88
Waiting:        0   32  12.6     31      88
Total:         62 4232 506.9   4283    4800

Percentage of the requests served within a certain time (ms)
  50%   4283
  66%   4342
  75%   4413
  80%   4439
  90%   4484
  95%   4547
  98%   4694
  99%   4727
 100%   4800 (longest request)

与 Apache http 相比(此处 CPU 利用率约为 90% 到 100%)

C:\Apache24\bin>ab -n 5000 -c 200 http://localhost:6200/abc/index.html?param=abc
Server Software:        Apache/2.4.33
Server Hostname:        localhost
Server Port:            6200

Document Path:          /abc/index.html?param=abc
Document Length:        1099 bytes

Concurrency Level:      200
Time taken for tests:   1.781 seconds
Complete requests:      5000
Failed requests:        0
Total transferred:      6810000 bytes
HTML transferred:       5495000 bytes
Requests per second:    2806.99 [#/sec] (mean)
Time per request:       71.251 [ms] (mean)
Time per request:       0.356 [ms] (mean, across all concurrent requests)
Transfer rate:          3733.51 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.6      0      16
Processing:    16   69  16.0     63     125
Waiting:        0   57  16.0     63     125
Total:         16   69  16.0     63     125

Percentage of the requests served within a certain time (ms)
  50%     63
  66%     78
  75%     78
  80%     78
  90%     94
  95%     94
  98%     94
  99%    109
 100%    125 (longest request)

Apache https 如下(http 1.1)&请注意,nginx 中的 http 1.1 并没有提高其性能:

C:\Apache24\bin>abs -n 5000 -c 200 https://localhost:7200/abc/index.html?param=abc

This is ApacheBench, Version 2.3 <$Revision: 1826891 $>

Server Software:        Apache/2.4.33
Server Hostname:        localhost
Server Port:            7200
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256
TLS Server Name:        localhost

Document Path:          /abc/index.html?param=abc
Document Length:        1099 bytes

Concurrency Level:      200
Time taken for tests:   8.747 seconds
Complete requests:      5000
Failed requests:        0
Total transferred:      6810000 bytes
HTML transferred:       5495000 bytes
Requests per second:    571.60 [#/sec] (mean)
Time per request:       349.894 [ms] (mean)
Time per request:       1.749 [ms] (mean, across all concurrent requests)
Transfer rate:          760.27 [Kbytes/sec] received

Connection Times (ms)
            min  mean[+/-sd] median   max
Connect:        0  198  42.7    188     391
Processing:    62  145  39.1    140     385
Waiting:        0   76  28.3     78     250
Total:         62  343  63.0    331     615

Percentage of the requests served within a certain time (ms)
50%    331
66%    369
75%    380
80%    389
90%    422
95%    465
98%    500
99%    536
100%    615 (longest request)

我的 nginx 配置:

worker_processes auto;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       8100;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

    server {
    listen       8200 ssl http2;
    server_name  localhost;

    ssl_certificate      C:/nginx-1.13.12/conf/server.crt;
    ssl_certificate_key  C:/nginx-1.13.12/conf/server.key;

        ssl_session_cache   shared:SSL:10m;
        ssl_session_timeout 10m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

        gzip on;
        gzip_comp_level 1;
        gzip_vary on;
        gzip_types
            text/css
            text/javascript
            text/xml
            text/plain
            text/x-component
            application/javascript
            application/json
            application/xml
            application/rss+xml
            font/truetype
            font/opentype
            application/vnd.ms-fontobject
            image/svg+xml;

        gzip_static on;

    location /ipo_reits/ {

        root   html;
        index  index.html index.htm;
        ## here we redirect to the homepage in case of nginx 404 
        try_files $uri $uri/ /ipo_reits/index.html;
        #    error_page 404 =301 /;
    }

        location /api/ {
            proxy_pass  https://localhost:7001/;
        }
    }
}

更新

我已经按照 kworr 的建议在 Linux 上进行了测试,nginx 在 https 上的性能要好得多

Nginx http:17000 个请求/秒,https 大约 1200 个请求/秒,apache 的性能比类似,https 1150 个请求/秒,http 13000 个请求/秒

为什么两个 Web 服务器中的 http 和 https 有如此大的差异?

尽管许多参考文献都保证差异可以忽略不计,但 Http 比 https 快大约 12 倍?

答案1

对于这个简单的测试用例,HTTPS 将比 HTTP 慢得多。

HTTPS 意味着两件事:

  1. 您需要进行初始设置以同意加密参数(TLS 握手)。
  2. 您需要计算能力在发送之前加密每个请求并在接收之后解密每个请求。

现在,如果设置正确,对于大多数流量来说,第 2 点的影响可以忽略不计。流量大(例如,如果您主要提供 Netflix 或 YouTube 等视频)可能会注意到差异,但大多数网站不会注意到差异,除非使用非常陈旧的硬件或非常糟糕的设置。

但是第一点很有趣。您使用的 TLSv1.2 需要 2 次完整的往返才能建立 HTTPS 连接,此外 TCP 连接需要 1.5 次往返,实际 HTTP 请求需要 1 次往返。TLSv1.3 将此减少到一次往返(如果重新建立连接,甚至为零),这是人们对它感到兴奋的众多原因之一,现在它已开始在实施中可用。

因此,目前我预计 HTTPS 的速度至少会是 HTTP 的两倍。非常少- 完全忽略加密处理成本本身,并假设网页的下载量很小,因为您正在将 4.5 次往返与 2.5 次往返进行比较。

然而计算有成本。HTTPS 使用基于网站提供的 TLS 证书的公钥非对称加密。这是必要的,因为您没有一个可以用于世界上每个网站(尤其是尚未创建的网站!)的预先约定的密钥,因此您无法使用更快的对称加密。非对称加密非常慢,因此为了帮助抵消这一点,它仅用于建立对称密钥,然后用于其余加密。然而,这意味着初始握手将再次变得相当慢,因为它正在执行昂贵的公钥加密和解密。

说实话,我从来没有使用 ab 测量过差异,但与使用只需要建立 TCP 连接并发回页面的 HTTP 相比,由于这些原因,它慢了 10-13 倍,我并不完全感到惊讶。

那么为什么网站会使用 HTTPS,为什么大多数人都说对性能的影响并不大呢?!因为很少有网站只加载一个页面。网站通常由无数资源组成(平均 75) 并且每个域中只有第一个会受到该握手延迟的影响。

因此,您的ab测试不能代表真实情况(除非您的网站非常简单)。相反,您应该使用wget -p或类似工具下载网页和依赖项。然后计时,然后您才能看到差异是什么。我仍然希望有差异,但不会像您在简单ab测试中看到的那样大。

然而,这也不能代表全部,因为下载只是其中一部分。如果下载您的网站需要 1 秒钟,而浏览所有 JavaScript、广告跟踪等则需要 15 秒钟,那么即使将 1 秒钟的下载时间翻倍也不会产生实质性差异。因此,要进行真正准确的测试,您应该同时测量下载和渲染以获得真实成本。工具如网页测试可以帮助解决这个问题。

您还应确保您的HTTPS 设置已优化要使用更快的密码,请确保启用 TLS 恢复(这样任何后续连接都不会受到太大的性能损失)和其他设置。

最终,我们出于充分的理由转向 HTTPS 世界,虽然初始设置会对性能产生影响,但还有其他性能优势,例如 Brotli 压缩和 HTTP/2,这些优势仅通过 HTTPS 可用(出于理想和实际原因)。这些可能会让 HTTP 望尘莫及但说到性能,通常展示这一点的网站(比如我的那个)往往基于人工测试,这些测试并不真正代表大多数网站,所以大多数网站的性能不会有那么大的提升!

相关内容