「网络架构」网络代理第二部分: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的功能,并推动新的界限。请留意未来的博客文章和代码片段/补丁。

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

相关文章
|
8天前
|
应用服务中间件 Linux 网络安全
Centos 8.0中Nginx配置文件和https正书添加配置
这是一份Nginx配置文件,包含HTTP与HTTPS服务设置。主要功能如下:1) 将HTTP(80端口)请求重定向至HTTPS(443端口),增强安全性;2) 配置SSL证书,支持TLSv1.1至TLSv1.3协议;3) 使用uWSGI与后端应用通信(如Django);4) 静态文件托管路径设为`/root/code/static/`;5) 定制错误页面(404、50x)。适用于Web应用部署场景。
81 7
|
4天前
|
安全 网络协议 算法
HTTP/HTTPS与SOCKS5协议在隧道代理中的兼容性设计解析
本文系统探讨了构建企业级双协议隧道代理系统的挑战与实现。首先对比HTTP/HTTPS和SOCKS5协议特性,分析其在工作模型、连接管理和加密方式上的差异。接着提出兼容性架构设计,包括双协议接入层与统一隧道内核,通过协议识别模块和分层设计实现高效转换。关键技术部分深入解析协议转换引擎、连接管理策略及加密传输方案,并从性能优化、安全增强到典型应用场景全面展开。最后指出未来发展趋势将更高效、安全与智能。
22 1
|
4月前
|
网络协议 应用服务中间件 网络安全
Nginx,正向代理
本文介绍了Nginx作为HTTPS正向代理的两种方案:HTTP CONNECT隧道(7层)和NGINX stream(4层)。HTTP CONNECT隧道需要客户端手动配置代理,通过CONNECT请求建立隧道;而NGINX stream则更适合透明代理,利用SNI字段实现流量转发。文章详细讲解了两者的原理、环境搭建、使用场景及常见问题,并提供了配置示例和最佳实践建议。内容转载自阿里云开发者社区@怀知的文章,推荐读者参阅原文获取更多信息。感谢您的阅读!
541 80
Nginx,正向代理
|
3月前
|
缓存 安全 网络安全
代理协议解析:如何根据需求选择HTTP、HTTPS或SOCKS5?
本文详细介绍了HTTP、HTTPS和SOCKS5三种代理协议的特点、优缺点以及适用场景。通过对比和分析,可以根据具体需求选择最合适的代理协议。希望本文能帮助您更好地理解和应用代理协议,提高网络应用的安全性和性能。
164 17
|
4月前
|
缓存 负载均衡 应用服务中间件
Nginx七层(应用层)反向代理:HTTP反向代理proxy_pass篇
通过使用Nginx的反向代理功能,可以有效地提高Web应用的性能、安全性和可扩展性。配置过程中需要注意不同场景下的具体需求,如负载均衡、SSL终止和缓存策略等。正确配置和优化Nginx反向代理可以显著提升系统的整体表现。
814 20
|
7月前
|
监控 应用服务中间件 测试技术
确保正则表达式在 Nginx 代理中的准确性和稳定性
【10月更文挑战第19天】总之,正则表达式在 Nginx 代理中具有重要作用,但要确保其准确性和稳定性需要付出一定的努力和关注。通过以上方法的综合运用,我们可以提高正则表达式配置的可靠性,为用户提供更好的服务体验。
|
5月前
|
缓存 Java 应用服务中间件
nginx的正向代理和反向代理以及tomcat
Nginx的正向代理和反向代理功能在不同的场景中具有重要作用,正向代理主要用于客户端访问控制和匿名浏览,而反向代理则用于负载均衡和高可用性服务。Tomcat作为Java Web应用服务器,与Nginx结合使用,可以显著提升Web应用的性能和稳定性。通过合理配置Nginx和Tomcat,可以构建高效、稳定和可扩展的Web服务架构。
275 11
|
5月前
|
应用服务中间件 Linux 网络安全
nginx安装部署ssl证书,同时支持http与https方式访问
为了使HTTP服务支持HTTPS访问,需生成并安装SSL证书,并确保Nginx支持SSL模块。首先,在`/usr/local/nginx`目录下生成RSA密钥、证书申请文件及自签名证书。接着,确认Nginx已安装SSL模块,若未安装则重新编译Nginx加入该模块。最后,编辑`nginx.conf`配置文件,启用并配置HTTPS服务器部分,指定证书路径和监听端口(如20000),保存后重启Nginx完成部署。
2018 8
|
7月前
|
应用服务中间件 API nginx
使用正则表达式实现 Nginx 代理
【10月更文挑战第19天】在不断发展的互联网技术中,掌握正则表达式在 Nginx 代理中的应用是非常重要的。不断探索和实践,将有助于我们在实际工作中更好地运用这一技术,提升项目的质量和效率。
|
7月前
|
缓存 负载均衡 应用服务中间件
Nginx 实现一个端口代理多个前后端服务
【10月更文挑战第19天】Nginx 的强大功能不仅限于此,它还可以与其他技术和工具相结合,为我们的应用提供更强大的支持和保障。在不断发展的互联网时代,掌握 Nginx 的使用技巧将为我们的工作和生活带来更多的便利和效益。

热门文章

最新文章

OSZAR »