今天我们从流量调度谈起,聊了几种典型的调度手段和负载均衡的方式。
从流量调度角度来说,负载均衡的最大价值是让多个业务服务器的压力均衡。这里面隐含的一个前提是负载均衡软件的抗压能力往往比业务服务器强很多(为什么?欢迎留言讨论)。
这表现在:其一,负载均衡的实例数/业务服务器的实例数往往大大小于1;其二,DNS 的调度不均衡,所以负载均衡的不同实例的压力不均衡,有的实例可能压力很大。
当然,负载均衡的价值并不只是做流量的均衡调度,它也让我们的业务服务器优雅升级成为可能。
如果你对今天的内容有什么思考与解读,欢迎给我留言,我们一起讨论。下一讲我们将聊聊存储中间件。
相比桌面程序而言,服务端程序依赖的基础软件不只是操作系统和编程语言,还多了两类:
- 负载均衡(Load Balance);
- 数据库或其他形式的存储(DB/Storage)。
- 连接数;
- IOPS;
- 流量,入向流量和出向流量。
- 平均每秒收到的请求包(Request)数量
*
请求包平均大小。
- 平均每秒返回的应答包(Response)数量
*
应答包平均大小。
- 入向流量 ≈ IOPS
*
请求包平均大小 - 出向流量 ≈ IOPS
*
应答包平均大小
DNS 流量调度
最基础的方式,是通过 DNS,如下图所示。网络层负载均衡
第一种做法,是在网络层(IP 层)做负载均衡。 章文嵩博士发起的负载均衡软件 LVS(Linux Virtual Server)就工作在这一层。我们以 LVS 为代表介绍一下工作原理。 LVS 支持三种调度模式。- VS/NAT:通过网络地址转换(NAT)技术做调度。请求和响应都会经过调度器中转,性能最差。
- VS/TUN:把请求报文通过 IP 隧道转发至真实服务器,而真实服务器将响应直接返回给客户,所以调度器只处理请求报文。这种做法性能比 VS/NAT 好很多。
- VS/DR:通过改写请求报文的MAC地址,将请求发送到真实服务器,真实服务器将响应直接返回给客户。这种做法相比 VS/TUN 少了 IP 隧道的开销,性能最好。
应用层负载均衡
有办法避免出现这种请求失败的情况吗? 可以。答案是:服务端重试。 怎么做服务端重试?应用层负载均衡。有时候我们也把它叫做应用网关。 HTTP 协议是应用最为广泛的应用层协议。当前应用网关,绝大多数都是 HTTP 应用网关。 Nginx 和 Apache 都是大家最为耳熟能详的 HTTP 应用网关。因为知道应用层协议的细节,所以 HTTP 应用网关的能力通常非常强大。这一点我们后面还会进一步进行探讨,今天我们先聊负载均衡(Load Balance)相关的内容。 HTTP 网关收到一个 HTTP 请求(Request)后,根据一定调度算法把请求转发给后端真实的业务服务器实例 RS(Real Server),收到 RS 的应答(Response)后,再把它转发给客户端。 整个过程的逻辑非常简单,而且重试也非常好做。 在发现某个 RS 实例挂了后,HTTP 网关可以将同一个 HTTP 请求(Request)重新发给其他 RS 实例。 当然一个重要的细节是为了能够支持重试,HTTP 请求(Request)需要被保存起来。不保存 HTTP 请求做重试是有可能的,但是只能支持业务实例完全挂掉 HTTP 请求一个字节都没发过去的场景。但在断电或异常崩溃等情况,显然会有很多进行中的请求是不符合这个前提的,它们就没法做重试。 大部分 HTTP 请求不大,直接在内存中存储即可,保存代价不高。但是文件上传型的请求,由于请求包中包含文件内容,可能就需要依赖临时文件或其他手段来保存 HTTP 请求。优雅升级
有了负载均衡,不只是可以实现了流量的均衡调度,连带业务服务器的升级也会方便多了。 对于前端是 LVS 这种网络层负载均衡的场景,升级的核心步骤为:- 升级系统通知 LVS 调度器(Director Server)下线要升级的业务服务器(Real Server)实例。
- LVS 调度器(Director Server)将该实例从 RS 集合中去除,这样就不再调度新流量到它。
- 升级系统通知要升级的 RS 实例退出。
- 要升级的 RS 实例处理完所有处理中的请求,然后主动退出。
- 升级系统更新 RS 实例到新版本,并重启。
- 升级系统将 RS 实例重新加回 RS 集合参与调度。
- 升级系统通知升级的业务服务器(Real Server)实例退出。
- 要升级的 RS 实例进入退出状态,这时新请求进来直接拒绝(返回一个特殊的 Status Code);处理完所有处理中的请求后,RS 实例主动退出。
- 升级系统更新 RS 实例到新版本,并重启。