大家好,
我是程序员小王。今天分享的是代理单点故障解决方法。
总耗时4个小时,累计3天时间查看了代理单点故障的解决方式。
2019-6-9
参考工业级产品 nginx,redis,twemproxy 并且对应优缺点。 说明:代理最终还是没有缓存数据,依然存在概率失败问题。
原则
思考一个问题
什么说 twemproxy 对平滑扩容、故障恢复不友好支持,nginx支持吗?
- Nginx 仅仅支持http功能代理模块。
- Twemproxy 仅仅支持tcp代理模块。
- 借助于 Twemproxy 来做二次开发,把 Nginx 的高性能、高可靠、高并发机制引入到 Twemproxy 中 代码地址: https://github.com/meitu/twemproxy(彩蛋)
1. 推特原生 Twemproxy 瓶颈
如今 Twemproxy 凭借其高性能的优势, 在很多互联网公司得到了广泛的应用,已经占据了不可动摇的地位,
然而在实际的生产环境中,Twemproxy 存在以下缺陷:(前方高能)
- 单进程单线程,无法充分发挥服务器多核 CPU 的性能。
- 当 Twemproxy QPS 短连接达到 8000 后,消耗 CPU 超过 70%,时延陡增。
- 大流量下造成 IO 阻塞,无法处理更多请求,QPS上不去,业务时延飙升。
- 维护成本高,如果想要充分发挥服务器的所有资源包括 CPU、 网络 IO 等,就必须建立多个 Twemproxy 实例,维护成本高。
- 扩容、升级不便。 目前成熟的 twemproxy 对平滑扩容、故障恢复和集群管理方面多做得不够
旁白:为什么这样说呢? 因为每次扩容,需要停止业务,迁移数据,重新加装配置上访
- 在原生的 twemproxy 里面是不支持 Redis 主从模式的 这个应该主要是因为 twemproxy 把 Redis/Memcached 当做是缓存而不是存储
原生 Twemproxy 进程呈现了下图现象:
一个人干活,多个人围观。多核服务器只有一个 CPU 在工作,资源没有得到充分利用。
Nginx 多进程高并发、低时延在滴滴缓存代理中的应用
2. Nginx
Nginx 是俄罗斯软件工程师 Igor Sysoev 开发的免费开源 Web 服务器软件,聚焦于高性能,高并发和低内存消耗问题,成为业界公认的高性能服务器,并逐渐成为业内主流的 Web 服务器。
.Nginx 主要特点有:
- 完全借助 Epoll 机制实现异步操作,避免阻塞。(epoll解决不了)
- 重复利用现有服务器的多核资源。
- 充分利用 CPU 亲和性(affinity),把每个进程与固定 CPU 绑定在一起,给定的 CPU 上尽量长时间地运行而不被迁移到其他处理器的倾向性,减少进程调度开销。
- 请求响应快。
- 支持模块化开发,扩展性好。
- Master 多 worker 进程方式,确保 worker 进程可靠工作。当 worker 进程出错时,可以快速拉起新的 worker 子进程来提供服务。
- 内存池、连接池等细节设计保障低内存消耗。
- 热部署支持,master 与 worker 进程分离设计模式,使其具有热部署功能。
- 升级方便,升级过程不会对业务造成任何伤害。
Nginx 多进程提供服务过程如下图所示:
Nginx 多进程高并发、低时延在滴滴缓存代理中的应用
3.为什么要选择 twemproxy
twemproxy 是一款由 twitter 开源的 Redis/Memcached 代理,主要目标是减少后端资源的连接数以及为缓存横向扩展能力。
twemproxy 支持多种 hash 分片算法,同时具备失败节点自动剔除的功能。除此之外,其他比较成熟的开源解决方案还有 codis,codis 具备在线的 auto-scale 以及友好的后台管理, 但整体的功能更接近于 Redis Cluster,而不是代理。
Twemproxy 是一个快速的单线程代理程序,支持 Memcached ASCII 协议和更新的 Redis 协议。它全部用 C 写成,使用 Apache 2.0 License 授权。
支持以下特性: 轻量级 维护持久的服务器连接 启用请求和响应的管道 支持代理到多个后端缓存服务器 !!!! 同时支持多个服务器池 多个服务器自动分享数据!!!! 可同时连接后端多个缓存集群 !!!! 实现了完整的 Memcached Ascii 和 Redis 协议. 服务器池配置简单,通过一个 YAML 文件即可 一致性 Hash 详细的监控统计信息 支持 Linux,* BSD,OS X and Solaris ( SmartOS ) 支持设置 HashTag 连接复用,内存复用,提高效率
需要的是一个 Redis 和 Memcached 协议类 PaaS 服务的代理(网关),所以我们最终选择了 twemproxy。
twemproxy 实现
twemproxy 主要的功能是解析用户请求后转发到后端的缓存资源,成功后在把响应转发回客户端。
代码实现的核心是三种连接对象:
- proxy connection, 用来监听用户建立连接的请求,建立连接成功后会对应产生一个客户端连接;
- client connection,由建连成功后产生,用户读写数据都是通过 client;connection 解析请求后,根据 key 和哈希规则选择一个 server 进行转发;
- server connection,转发用户请求到缓存资源并接收和解析响应数据转回 client connection,client connection 将响应返回到用户。
三种连接的数据流向如下图:
美图高性能twemproxy的改造之路
上图的 client connection 之所以没有 imsgq 是因为请求解析完可以直接进入 server 的 imsgq
- 用户通过 proxy connection 建立连接,产生一个 client connection;
- client connection 开始读取用户的请求数据,并将完整的请求根据 key 和设置的哈希规则选择 server, 然后将这个请求存放到 server 的 imsgq;
- 接着 server connection 发送 imsgq 请求到远程资源,发送完成之后(写 tcp buffer) 就会将 msg 从 imsgq 迁移到 omsgq,响应回来之后从 omsgq 队列里面找到这个对应的 msg 以及 client connection;
- 最后将响应内容放到 client connection 的 omsgq,由 client connection 将数据发送回客户端。
上面提到的用户请求和资源响应的数据都是在解析之后放到内存的 buf 里面,在 client 和 server 两种连接的内部流转也只是指针的拷贝(官网 README 里面提到的 Zero Copy)。
这也是 twemproxy 单线程模型在小包场景能够达到 10w qps 的原因之一,几乎不拷贝内存。
4.Nginx Master Worker 多进程机制在 Twemproxy 中的应用
- 4.1 为什么选择 Nginx 多进程机制做为参考?
Twemproxy 和 Nginx 都属于网络 IO 密集型应用,都属于七层转发应用,时延要求较高,应用场景基本相同。
Nginx 充分利用了多核 CPU 资源,性能好,时延低。 多进程模式
- 4.2 Master-Worker 多进程机制原理
Master-worker 进程机制采用一个 master 进程来管理多个 worker 进程。每一个 worker 进程都是繁忙的,它们在真正地提供服务,master 进程则很“清闲”,只负责监控管理worker进程。
- master 进程包含:接收来自外界的信号;
- 向各 worker 进程发送信号;
- 监控 worker 进程的运行状态;
- 当 worker 进程退出后 ( 异常情况下 ),会自动重新启动新的 worker 进程。
- Worker 进程负责处理客户端的网络请求,多个 worker 进程同时处理来自客户端的不同请求,worker 进程数可配置。
Nginx 多进程高并发、低时延在滴滴缓存代理中的应用
Nginx 多进程高并发、低时延在滴滴缓存代理中的应用
5说明 没有解决问题
- 如何实现资源缩容/扩容对业务无感? 扩容过程,proxy起到什么作用。我么想明白。
这依靠redis本身,用多进程之后可以分片重启。
1.是无感知,即对redis集群的用户来说服务ip和port保持不变 2.弹性扩容,指的是在需要时刻可以按照业务扩大redis存储容量。
正实现无感知弹性扩容方案 最终的方案新增了一个VIP,用这个VIP来解决无感知的问题,即扩容对客户端来说是无感知的。
- 无感知的解决类似”双buffer交换“的思路, 即上图的twemproxy-C和twemproxy-D, 当需要重启twemproxy代理时,
- 可以进行如下操作:
1.现假设vip只访问到twemproxy-C 2.更改twemproxy-D使用最新的配置,重启 3.vip切换服务到只访问twemproxy-D
当还需要重启代理时,以此循环。
- 单点故障,正在处理请求如何解决,我没看明白? 我理解是 这个无法解决,因为代理不缓存数据。
.6 Twemproxy 改造前后性能对比(时延、QPS 对比)
6.1 线上真实流量时延对比
6.1.1 改造前线上 Twemproxy 集群时延
线上集群完全采用开源 Twemproxy 做代理,架构如下:
Nginx 多进程高并发、低时延在滴滴缓存代理中的应用
未改造前线上 Twemproxy Memcache 集群,QPS=5000~6000,长连接,客户端时延分布如下图所示:
Nginx 多进程高并发、低时延在滴滴缓存代理中的应用
长连接
Nginx 多进程高并发、低时延在滴滴缓存代理中的应用
在 Twemproxy 机器上使用 tcprstat 监控到的网卡时延如下:
Nginx 多进程高并发、低时延在滴滴缓存代理中的应用
从上面两个图可以看出,采用原生 Twemproxy 时延高,同时抖动厉害。
6.2 参考 Nginx 多进程改造后的 Twemproxy 线下压测结果 ( 开启 Reuseport 功能 )
监听同一个端口,数据长度 100 字节,压测结果如下:
– Linux 内核版本:Linux-3.10
– 物理机机型: M10 ( 48 CPU
改正后的性能
7 总结: 参照 Nginx 改造后的 Twemproxy 特性
7.1 多进程、多线程机制选择
选择参照 Nginx 多进程机制,而不选择多线程实现原因主要有:
- 多进程机制无锁操作,实现更容易。
- 多进程的代理,整个 worker 进程无任何锁操作,性能更好。 如果是多线程方式,如果代码出现 Bug 段错误,则整个进程挂掉,整个服务不可用。而如果是多进程方式, 因为 Bug 触发某个 worker 进程段错误异常,其他工作进程不会受到如何影响,20 个 worker 进程,如果触发异常,同一时刻只有 1/20 的流量受到影响。 而如果是多线程模式,则 100% 的流量会受到影响。
- worker 进程异常退出后,master 进程立马感知拉起一个新进程提供服务,可靠性更高。
- 配置热加载、程序热升级功能实现更加容易。
7.2 参照 Nginx 改造后的 Twemproxy 特性
支持 Nginx 几乎所有的优秀特性,同时也根据自己实际情况新增加了自有特性:
- master 多 worker 进程机制
- 适配所有 Linux 内核版本,内核低版本惊群问题避免支持
- quic_ack 支持
- reuser_port 适配支持
- worker 进程异常,master 进程自动拉起功能支持 90%、95%、98%、100% 平均时延统计功能支持
- Memcache 单机版、集群版支持
- Redis 单机版、集群版支持
- 二进制协议、文本协议同时支持
- Redis、Memcache 集群在线扩容、缩容、数据迁移支持,扩缩容、数据迁移过程对业务无任何影响。【最关键地方,如何做到的】
- 多租户支持,一个代理可以接多个 Memcache、Redis 集群,并支持混部。
- mget、gets、sets 等批量处理命令优化处理
- 慢响应日志记录功能支持
- 内存参数实时修改支持
- 详细的集群监控统计功能
- CPU 亲缘性自添加
- 内存配置动态实时修改
信念会影响你的行为