当前位置:首页 > 技术文章 > 正文内容

再谈负载均衡(负载均衡实现原理)

arlanguage3个月前 (01-31)技术文章27

上周发的一篇负载均衡的文章有一个点不少人(统计了下在其他平台及上篇文章留言中大概有 8 人留言不解)有疑问,所以我觉得有必要单独写篇文章解释一下,先看下上篇文章展示的架构图

这里一些朋友的疑问点是 Nginx 是否多此一举,能否能直接从 LVS 打到站点层?即改成下面的架构

答案是不行,为什么?其实我在上文中有提到一些点已经暗示了,只不过不那么明显而已,我再单独把这些点拎出来

  1. LVS 是四层负载均衡器
  2. Nginx 是七层负载均衡器,可以根据 url 来转发流量

首先我们需要明白为什么根据 url 转发请求这么重要,假设现在有「营销」,「运营中心」这两个集群,使用 Nginx 的话很简单,根据 url 来决定到底将请求转发到哪个集群即可

由于 LVS 不能根据 url 转发,那么请问 LVS 收到请求后该转给谁

那么 LVS 为什么不能根据 url 来转发呢,因为它是四层负载均衡器,什么是四层和七层,这里就要简单复习下 ISO 七层参考模型了

由此可知,七层对应着应用层,四层对应着传输层,如果从应用层发起一个请求会在「传输层」,「网络层」,「数据链路层」分别加上各自层的包头,比如现在 A 电脑要发一个「I'm Deepon」数据给 B 电脑,则在各层的转化流程如下图所示

但最终在互联网上要传输的包(数据链路层传输的包叫祯,统称为包)是有大小限制的,如下图所示

在互联网上传输的包不能超过 14 + 20 + 20 + 1460 + 4 = 1518 byte,其中包含的应用层(即 payload)数据一次性不能超过 1460 个 byte,也就是说如果一个 HTTP 请求有 2000 byte,那么它必须分成两个包发送才能在网络上传输,再来看看 HTTP 的格式

如果一个 HTTP POST 请求很大,超过了 1460 byte(一个包 payload 的最大值),那么它必须分成两个包才能传输,也就意味着一个包可能包含 URI,另一个包不包含 URI,既然包都不包含 URI,那么请问 LVS 如何根据 URL 来转发给相应的集群呢,所以理解了 TCP/IP 的工作机制相信你不难理解开头的问题:LVS 是四层负载均衡器,无法根据 URL 来转发请求。

其实最关键的原因是四层以下其实只负责包的转发,只要拿出包头查看一下 ip 地址就可知道该转发哪里,很高效,如果你还要根据 url 来匹配那么需要拿到应用层数据根据正则等做匹配,显然会消耗更多的性能,所以专业的人做专业的事,应该由 LVS 来负责承载所有流量,Nginx 负责根据 url 来转发给对应的集群,因为它是七层负载均衡器,与上下游各建立了一个 TCP 链接

所以如果有多个分包,由于 Nginx 与 client 建立了 TCP 连接,可以在 Nginx 先拿到 client 发出的所有的分包再组装成完整的报文, 然后根据 url 选择其中一台 server 与之建立 TCP 连接后将数据分批完整地传给上游 server

另外需要注意的是现在在大厂中如果只将 Nginx 作为转发之用是不够的,一般用的 OpenResty ,什么是 OpenResty 呢

“OpenResty(R) 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

OpenResty(R) 的目标是让你的 Web 服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。”

注意上面一句「提供了与 MySQL ,Redis 等的交互能力」这一点非常关键,我们之前不是说 Nginx 可以根据 url 来决定打向哪个集群吗,假设现在有一个这样的场景:所有包含 operation 的请求都转发到运营中心的集群,则需要写死类似如下的配置

upstream backend {
  server 192.168.1.10:8080
  server 192.168.1.11:8080
}

server {
  location /operation {
    proxy_pass http://backed
  }
}

在我们集团中类似这样的规则非常多,难道要像上面这样把所有的规则都一个个写死在 Nginx 的配置文件里吗?显然不可行,更合理的方式是把这些规则(哪个 url 对应哪些集群)保存在 MySQL 中,然后 Nginx 在启动的时候将这些规则从 MySQL 中取出并保存在 Redis 及本地缓存中,然后 Nginx 要根据 url 匹配的时候从本地缓存(如果没有从 redis 拿,redis 过期从 MySQL 拿)里拿这些规则再根据匹配项转发到相应的集群,Nginx 没有这样的能力,而 OpenResty 由于集成了 Lua,引入了与 MySQL, Redis 等交互的模块,所以用它是可行的,所以最终架构如下(将 Nginx 换成 OpenResty)

关于使用 OpenResty 作为接入层/网关的具体实践,我们之前写了一篇文章,有兴趣的可以看看^_^


原文链接:https://mp.weixin.qq.com/s/B1pqmFqeD0IkdqG9Hf9Vfg


扫描二维码推送至手机访问。

版权声明:本文由AR编程网发布,如需转载请注明出处。

本文链接:http://www.arlanguage.com/post/1333.html

分享给朋友:

“再谈负载均衡(负载均衡实现原理)” 的相关文章

给你的Nginx加个防火墙

引言朋友的一个 WordPress 站经常访问慢。看了一下日志,发现整天被扫描网站目录,如phpmyadmin 或者 SQL 文件,和被 CC攻击。找了一下,发现 ngx_lua_waf 是个不错的方案,但是太久不更新了,而且代码我看不懂,猝最后找到 oneinstack 一键包内置的 ngx_lu...

如何让Nginx后端服务收到真实的客户IP?

背景开发有一个服务部署在阿里云上,依赖阿里云的CLB(传统型负载均衡)暴露服务,因特殊要求,CLB和后端服务之间需要通过自建Nginx做代理,拓扑图如下,应用拓扑操作客户端的请求经过了两层代理,这里CLB和Nginx都要做配置。1,配置CLBCLB的配置比较简单,在配置“监听”时,要附加“X-For...

nginx支持跨域的方法 nginx配置支持跨域

在nginx的配置文件中添加允许跨域的响应头。参考nginx官方文档,添加响应头的方法如下:在conf文件的server作用域中添加如下响应头:server { listen 80; # 其他配置... # 允许跨域 add_header Access-Control-Allow-...

轻量级日志平台 Loki 2.3 发布:15 倍最近数据查询速度提升

一、前言Loki v2.3.0 中添加了出色的新功能,进行了 bug 修复。除此之外,性能也得到了提升。二、自定义保留规则Loki 中的保留对于集群来说一直是全局的,并推迟到底层对象存储。Loki 现在可以通过 Compactor 组件处理保留。 你可以配置每个租户和每个流的保留时间。 这些不同的保...

「Nginx」-一定要明白Nginx的七层代理与四层代理

代理是在服务器和客户端之间的一层服务器,代理将客户端的请求转发给服务器,然后将服务端的响应转发给客户端。常用的代理技术分为正向代理、反向代理。Nginx虽然主要是来解决反向代理的,但也能支持正向代理。正向代理:代理服务器替代访问者去访问目标服务器。访问者知道目标服务器,目标服务器只知道代理服务器。需...

01《Nginx 入门教程》Nginx 是什么?

关于 Nginx,百度百科的介绍如下:**Nginx (engine x)是一个开源、高性能的 HTTP 和反向代理 Web 服务器,同时也提供了 IMAP/POP3/SMTP 服务”。**首先,对 Web 服务器做一个简要说明:Web 服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序...