「网络架构」网络代理第二部分:Nginx作为转发HTTP代理

简介: 「网络架构」网络代理第二部分:Nginx作为转发HTTP代理

我刚开始使用OpenDNS时,我的首要任务是弄清楚Nginx的工作方式,并为其编写一个自定义C模块来处理一些业务逻辑。 Nginx将反向代理到Apache Traffic Server(ATS),它将执行实际的正向代理。 这是一个简化图:


事实证明,Nginx易于理解和使用。这与ATS相反,后者更大,更复杂,而且简直不好玩。结果,“为什么我们不整个使用Nginx?”成为一个流行的问题,尤其是在确定代理将不进行任何缓存之后。

正向代理尽管Nginx是旨在与明确定义的上游一起使用的反向代理:

http { upstream myapp1 { server srv1.example.com; server srv2.example.com; server srv3.example.com; }

server { listen 80; location / { proxy_pass http://myapp1; } }}

也可以将其配置为基于某些变量使用上游,例如Host标头:

http { server { listen 80; location / { proxy_pass http://$http_host$request_uri; } }}

这实际上工作得很好。主要警告是Host标头可以匹配配置中的预定义上游{}(如果存在):

http { ... upstream foo { server bar; } ... server { listen 80; location / { proxy_pass http://$http_host$request_uri; } }}

然后,这样的请求将匹配foo并被代理到bar:

GET / HTTP/1.1Accept: */*Host: foo

可以通过在自定义模块中使用新变量来扩展此方法,而不是使用内置的$ http_host和$ request_uri进行更好的目标控制,错误处理等。

一切工作都非常好-请注意,这是一个HTTP(端口80)代理,在此我们不考虑HTTPS情况。一方面,Nginx无法识别显式HTTPS代理中使用的CONNECT方法,因此将永远无法工作。正如我在之前的博客文章中提到的那样,我们的智能代理通常采用一种更加非常规的方法。

一个大问题是性能。我们使用ATS进行的初始负载测试得出的数据少于理想值。Nginx的“ hack”对其性能有没有影响?

负载测试


跳过更详细的信息,我们的设置使用wrk作为负载生成器,并使用自定义C程序作为上游。定制上游是非常基本的。它所做的就是接受连接,并通过静态二进制Blob响应任何看起来像HTTP的请求。永远不会显式关闭连接,以消除不必要的额外TCP会话导致的结果中的任何潜在偏差。

我们首先通过直接加载上游服务器来建立基准:

Running 30s test 10 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 3.27ms 680.48us 5.04ms 71.95% Req/Sec 3.21k 350.69 4.33k 69.67% 911723 requests in 30.00s, 3.19GB read 100 total connects (of which 0 were reconnects)Requests/sec: 30393.62Transfer/sec: 108.78MB

一切看起来都不错,wrk按预期创建了100个连接,并设法每秒挤出3万个请求。

现在,让我们通过Nginx转发代理(2个工作组)进行重复:

Running 30s test 10 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 6.42ms 14.37ms 211.84ms 99.50% Req/Sec 1.91k 245.53 2.63k 83.75% 552173 requests in 30.00s, 1.95GB read 5570 total connects (of which 5470 were reconnects)Requests/sec: 18406.39Transfer/sec: 66.53MB

这几乎使可能的吞吐量减半。

通过手动请求,我们发现通过Nginx并不会真正增加任何明显的延迟。Nginx工作人员在测试期间获得了接近100%的CPU使用率,但是增加工作人员人数并没有多大帮助。

上游情况如何,在两种情况下会看到什么?

快速更新以打印一些统计信息后,在直接情况下一切看起来都很好-wrk和上游服务器报告的数字符合预期。但是,在查看上游服务器统计信息时,我们在代理情况下发现了一些令人吃惊的事情:

status: 552263 connects, 552263 closes, 30926728 bytes, 552263 packets

看起来Nginx为往上游的每个请求创建了一个新连接,尽管wrk仅向下游进行了100个连接…

深入Nginx核心并更全面地阅读文档,事情开始变得有意义。Nginx是一个负载均衡器,其中“负载”等于请求,而不是连接。连接可以发出任意数量的请求,重要的是在后端之间平均分配这些请求。就目前而言,Nginx在每个请求之后关闭上游连接。上游keepalive模块尝试通过始终保持一定数量的持久连接保持打开状态来对此进行轻微补救。Nginx Plus提供了诸如会话持久性(Session Persistence)之类的额外功能(顺便说一句,还存在一个等效的开源模块)—使请求可以更一致地路由到相同的上游。

我们真正想要的是客户端及其各自上游之间的一对一持久连接映射。在我们的案例中,上游是完全任意的,我们要避免创建不必要的连接,更重要的是,不要以任何方式“共享”上游连接。我们的会议是整个客户连接本身。

补丁

该解决方案非常简单,我们已经在Github 上提供了该解决方案。

通过此更改重新运行负载测试,我们可以获得更好的结果,概述了保持TCP连接持久性并避免那些昂贵的打开/关闭操作的重要性:

Running 30s test 10 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 10.82ms 48.67ms 332.65ms 97.72% Req/Sec 3.00k 505.22 4.46k 95.81% 854946 requests in 30.00s, 3.02GB read 8600 total connects (of which 8500 were reconnects)Requests/sec: 28498.99Transfer/sec: 103.01MB

上游的数字与wrk的数字匹配:

status: 8600 connects, 8600 closes, 47882016 bytes, 855036 packets

但是,仍然存在问题。有8600个连接,而不仅仅是100个。Nginx决定关闭上游和下游的许多连接。当进行调试以查看原因时,我们最终追溯到“ lingering_close_handler”:

...nginx: _ngx_http_close_request(r=0000000000C260D0) from ngx_http_lingering_close_handler, L: 3218nginx: ngx_http_close_connection(00007FD41B057A48) from _ngx_http_close_request, L: 3358...

由于即使使用此行为,整体效果还是令人满意的,因此我暂时不这样做了。

收盘中

我们已经将Nginx作为生产中的正向HTTP代理运行了一段时间,几乎没有问题。我们希望继续扩展Nginx的功能,并推动新的界限。请留意未来的博客文章和代码片段/补丁。

*这是一个重写的补丁程序(原始补丁有点笨拙),这个新代码最近才投入生产。如果有任何问题,我将进行任何调整以更新公共补丁。

相关文章
|
15天前
|
监控 应用服务中间件 测试技术
确保正则表达式在 Nginx 代理中的准确性和稳定性
【10月更文挑战第19天】总之,正则表达式在 Nginx 代理中具有重要作用,但要确保其准确性和稳定性需要付出一定的努力和关注。通过以上方法的综合运用,我们可以提高正则表达式配置的可靠性,为用户提供更好的服务体验。
|
3天前
|
前端开发 应用服务中间件 定位技术
|
28天前
|
负载均衡 应用服务中间件 Linux
nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件,很全
这篇博客文章详细介绍了Nginx的下载、安装、配置以及使用,包括正向代理、反向代理、负载均衡、动静分离等高级功能,并通过具体实例讲解了如何进行配置。
133 4
nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件,很全
|
12天前
|
负载均衡 应用服务中间件 nginx
基于Nginx和Consul构建自动发现的Docker服务架构——非常之详细
通过使用Nginx和Consul构建自动发现的Docker服务架构,可以显著提高服务的可用性、扩展性和管理效率。Consul实现了服务的自动注册与发现,而Nginx则通过动态配置实现了高效的反向代理与负载均衡。这种架构非常适合需要高可用性和弹性扩展的分布式系统。
18 4
|
1月前
|
安全 网络协议 算法
HTTPS网络通信协议揭秘:WEB网站安全的关键技术
HTTPS网络通信协议揭秘:WEB网站安全的关键技术
141 4
HTTPS网络通信协议揭秘:WEB网站安全的关键技术
|
13天前
|
负载均衡 应用服务中间件 nginx
基于Nginx和Consul构建自动发现的Docker服务架构——非常之详细
通过使用Nginx和Consul构建自动发现的Docker服务架构,可以显著提高服务的可用性、扩展性和管理效率。Consul实现了服务的自动注册与发现,而Nginx则通过动态配置实现了高效的反向代理与负载均衡。这种架构非常适合需要高可用性和弹性扩展的分布式系统。
28 3
|
15天前
|
应用服务中间件 API nginx
使用正则表达式实现 Nginx 代理
【10月更文挑战第19天】在不断发展的互联网技术中,掌握正则表达式在 Nginx 代理中的应用是非常重要的。不断探索和实践,将有助于我们在实际工作中更好地运用这一技术,提升项目的质量和效率。
|
15天前
|
缓存 负载均衡 应用服务中间件
Nginx 实现一个端口代理多个前后端服务
【10月更文挑战第19天】Nginx 的强大功能不仅限于此,它还可以与其他技术和工具相结合,为我们的应用提供更强大的支持和保障。在不断发展的互联网时代,掌握 Nginx 的使用技巧将为我们的工作和生活带来更多的便利和效益。
|
1月前
|
存储 缓存 监控
|
1月前
|
存储 缓存 负载均衡
Nginx代理缓存机制
【10月更文挑战第2天】
62 4