Nginx,为什么依旧这么“香”?

百家 作者:51CTO技术栈 2020-09-25 19:02:08

Nginx 很好用,几乎每个公司都在用,它的功能主要有反向代理、 负载均衡、 动静分离等,其中最主要的就是反向代理。


图片来自 Pexels


它的主要架构图如下:

客户端是无法直接访问后端的 Server 的,因为 Server 资源高高在上,Client 并没有权限。


这个时候,就需要有一个 Proxy,进行代理,将客户端的请求进行转发,然后把结果返回给 Client。


为什么不能直接让 Client 访问 Server 呢?这就涉及到资源隔离问题。Server 的一些真实意图,是不想要 Client 知晓的,比如一些受安全保护的敏感资源。


也就是说,通过 Proxy,Server 想让 Client 看到啥,Client 也只能看到啥。对 Client 来说,功能总是阉割的!甚至是篡改的!


我们将图中的元素替换一下,奇妙的事情发生了。

我们把 Client 换成可怜的普通码农,把 Server 换成牛 X 的领导,可以看到 6 条绿色的箭头,带着呼啸的山风,无情的指向了 Proxy。


Proxy 成为了关键的资源。这个 Proxy 要求可不简单,需要五弊三缺,上承天命,下召九幽。这么牛 X 的存在,当之无愧称之为 Nginx 工程师。


Nginx 工程师不需要有自己的想法,但他必须记住领导的每一句话,领会领导的真实意图。


传导领导想法的时候,也知道轻重,知道过滤,能够快狠准的将领导的想法广播出去。不服不行,这还真不是一般人能做的。


哪些人能够成为 Nginx 工程师呢?在奴隶社会,无论一个奴隶(Slave)工作多么的卖力,能力多么的出众,都没有出头之日。


反而是那些拿着鞭子的监工们,更容易获得主人们的赞赏,喝酒吃肉的时候都能够想到他们。


更加奇妙的是,如果把监工们和奴隶们的工作调换一下。奴隶有可能会胜任监工的工作,而监工绝无可能胜任奴隶的工作。


这是为什么呢?总结下来可以有这么几点:

  • 监工知道更多的内幕资源,更容易投主人所好。

  • 监工的工作属性是管理,可操作空间大。

  • 监工离权利中心更近,耳边风吹的频率要高一些。


你可能会说,这是社会性质使然,现在的社会肯定没这问题。你答对了一半,问题就出在这里。


由于每个公司的进化程度不一,程序员在不同的公司,获得的感受和受到的待遇,也是非常大的。你甚至会产生图中爸爸的心态。

监工一般都不是一线,离生产是比较远的,对于 Client 的想法,只能领会一点点。这一点点传导到 Server 那里的,正确性更难以保证。


而且,监工由于领会领导意图和汇总 Excel,耗费了大量的精力,花在真正有意义的事上的时间,就少的可怜。那怎么办呢?只好拿 Client 的成果当作自己的成果。


所以,闷头写代码的程序员,可能会发现自己做了很多工作,经过 Proxy 的一加工一转达,到了领导那里就是个屁。


Proxy 做的没错,996 的 Client 深夜也需要调代码,Proxy 只需要在一旁刷 TikTok 就可以了。工作强度不一样,工时自然就没有衡量对比的价值。


我们可以再看 Proxy 的 3 种传导场景。


场景 1:
server:要加强员工文化建设。
proxy:周六、周末去团建,AA
client: WCNM

场景 2:
server:公司要勤俭节约。
proxy:从明天开始不提供厕纸和开水
client: WCNM

场景 3:
server:王xx同学拼搏奋斗,是公司的楷模。
proxy:开启狼性文化,明起996
client: WCNM

可以看到,这一层的 Proxy 素质尤其重要。如果你不巧碰见了一个水货 Proxy,你的悲惨程度可想而知。


但如果你遇到一个 Nice 的 Proxy,那就珍惜他,因为所有的压力,都需要由他传导。


那一般的 Nginx 工程师是怎么做的呢?为了让驴拉磨,人们想出四招:蒙眼睛、捂嘴巴、堵耳朵、抽鞭子。


同样,要想 Proxy 顺利推行,Proxy 就可以不让你看到某些事情;你想要发表意见的时候,使用暴力手段堵住你的嘴;当你想要聆听领导真实意图,堵住你的耳朵;当你有所懈怠的时候,使用鞭子督促你完成工作。


很多公司由于人员众多,结构复杂,就存在着多层 Proxy 的拓扑。这种公司非常的精彩,一个 Proxy,可以作为另一个 Proxy 的 Client,很多时候,竟然会发生 Server 的数量比 Client 的数量多的情况。


我很可怜这些 Proxy 们,他们活的太累了。但由于 Proxy 的工作特性,只需要进行完整的转发即可完成工作,不需要思考--自然有一头乌黑油亮的秀发。


加上 Nginx 工程师可以很容易打破 35 岁魔咒,所以这个职业依然让人趋之若鹜。你也想做一枚 Nginx 工程师么?


如何保证 Nginx 的高可用?


目前 HTTP 协议,乃至 WebSocket 协议,乃至采用了 MQTT 协议的 WebSocket 协议,都不可避免的使用了 Nginx。


所谓病从口入,祸从口出。作为入口,Nginx 承担的责任非常的重要。假如某个时刻不能用了,那可真是灾难。


如何保证 Nginx 的高可用呢?这是个问题。不论你用什么样的方案,到最后总是要归为单一,很让人苦恼。

所谓的高可用,无非两种方式:

  • 一种方式就是在组件自身上做文章。

  • 另外一种方式,就是加入一个中间层。


我们通常希望在高可用的时候,同时还能够负载均衡,典型的猫和狗都想要,贪婪的很。


每当解决不了问题的时候,我们都会加入一个中间层,然后把希望寄托在这个新生的组件上。


如果这个中间层解决不了问题,我们就可以加入另外一个中间层。就这样一层套一层,到最后系统高可用架构就会变得非常复杂。


DNS 保证高可用


第一种方式当然是要在 DNS 上做文章了。通过在 DNS 上,绑定多个 Nginx 的 IP 地址,即可完成高可用。不仅能够完成高可用,还能顺便完成负载均衡。

但这玩意有一个致命的问题,那就是故障的感知时间。


我们的浏览器在访问到真正的 Nginx 之前,需要把域名转化为真正的 IP 地址,DNS 就是干解析这个动作的,每次需要耗费 20-20ms 不等。


为了加快解析速度,一般都会有多级的缓存。比如浏览器就有 DNS 的缓存;你使用的 PC 机上也有这样的缓存;IPS 服务提供商,也会有缓存;再加上有的企业为了加速访问所自建的 DNS 服务器,中间的缓存层就更多了。


只有所有的缓存都不命中的情况下,DNS 才会查询真正的 IP 地址。所以,如果有一台 Nginx 宕机了,这个故障的感知能力就会特别的差。总有一部分用户的请求,会落在这台已经死亡的机器上。


硬件保证高可用


我们前面说了。解决不了的问题,就可以加中间层,即使这个中间层是硬件,比如 F5。

这种架构一般的企业玩不起,只有那些采购有回扣有油水的公司,才会喜欢这个。互联网中用的很少,就不过多介绍了。


当然,F5 同样有单点的问题。虽然硬件肯定要比软件稳定上一点,但是总归是一个隐患。


就像 Oracle 无论再厉害,它还是有出问题的时候,到时候备机是必须的。有的厂商在卖硬件的时候,推荐你一次买 3 个!为啥呢?这也有理由。


你的一台硬件正在服务,有两台备份机器。当你服务的这台机器出现问题时,就可以选取备份机中的其中一台作为主机,另一台依然是备机,集群还是高可用的。


这理由真让人陶醉。按照这个逻辑,碰到傻子,我可以卖出 100 台!


①主备模式


硬的不行,就要来软的。采用主备的模式,使用软件来完成切换过程。

如图,使用 Keepalived 组件,通过 VRRP 协议,即可完成最简单的高可用配置。


我们把 DNS 的地址绑定在 VIP 上,当正在服务的 Nginx 发生问题,VIP 会发生漂移,转移到另外一台 Nginx 上。


可以看到,备份的 Nginx,正常情况下是无法进行服务的,它也叫做影子节点,只有主 Nginx 发生问题的时候才有用。如果你的节点非常多,这种模式下,会有非常大的浪费。


除了浪费,还有一个非常大的问题。那就是,单台 Nginx 无论性能多么牛 X,总是有上限的。当网卡的流量达到顶峰,接下来何去何从呢?


这种模式肯定是不满足需求的。


②简单组合模式


这个时候,我们就可以配合 DNS 解析,以及主备模式做文章了。如下图,DNS 解析到两个 VIP 上,VIP 本身也做了高可用。


这样就能够缩短故障时间,同时也能够保证每个组件的高可用。

这种架构模式思路是非常清晰的,但依然存在影子节点的浪费。


③LVS+KeepAlived+Nginx


LVS 是 Linux Virtual Server 的简称,也就是 Linux 虚拟服务器。


现在 LVS 已经是 Linux 标准内核的一部分,从 Linux2.4 内核以后,已经完全内置了 LVS 的各个功能模块,无需给内核打任何补丁,可以直接使用 LVS 提供的各种功能。

LVS 工作在 OSI 模型的第四层:传输层,比如 TCP/UDP,所以像七层网络的 HTTP 协议,它是识别不出来的。


也就是说,我们不能拿 HTTP 协议的一些内容来控制路由,它的路由切入层次更低一些。


如下图,LVS 架设的服务器集群系统有三个部分组成:

  • 最前端的负载均衡层,用 Load Balancer 表示。

  • 中间的服务器集群层,用 Server Array 表示。

  • 最底端的数据共享存储层,用 Shared Storage 表示。

DR(直接路由)模式可将响应数据包直接返回给用户浏览器,避免负载均衡服务器网卡带宽成为瓶颈,是目前采用最为广泛的方式(数据不详,Fullnat 模式使用也比较广泛)。


所以,配合 DNS 的负载均衡,加上 LVS 的负载均衡,可以实现双层的负载均衡和高可用。


如图,DNS 可以将请求绑定在 VIP 上。由于 LVS DR 模式的效率非常高,网卡要达到瓶颈也需要非常大的请求量(只有入口流量才走 LVS),所以一般通过 LVS 做 Nginx 的负载均衡就足够了。


如果 LVS 还有瓶颈,那么就可以在 DNS 上再做文章。

还有哪些挑战?其实,我们上面谈到的这些方案,大多数是在同机房的。如果在多个机房,如何让用户选择最快的节点、如何保证负载均衡,又是一个大的问题。


另外,你可以看到数据包经过层层的转发和协调,还有多种负载均衡算法参与其中,如何保持会话,也是一个挑战。


一般的,四层会话会通过 IP 地址去实现,七层会话会通过 Cookie 或者头信息等去实现。


开发人员一般情况下接触不到这么入口级的东西,但一旦遇到了,可能会受忙脚乱。


本文是我根据一些即有的经验进行整理,希望你在公司需要一些高可用方案的时候,能够助你一臂之力。


PS:什么叫方案?你只需要当时把你的领导哄好,让他感觉很认同的样子就行了。至于要不要做,具体怎么做,那都是后面的事。


君不见,扯了这么半天,很多企业其实一个 Nginx,就可以走天下。


作者:小姐姐味道

简介:聚焦基础架构和 Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。

编辑:陶家龙

出处:转载自公众号小姐姐味道(ID:xjjdog)

精彩文章推荐:

就是要让你搞懂Nginx,这篇就够了!
被“推荐系统”虐的日子,太惨了...
一口气说出“分布式追踪系统”原理!

关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接