内容纲要

一、面向人群
如果你的站点架构满足以下几点,那么本文的优化方案会非常适合你:
1)使用 php 等脚本语言作为开发语言
2)需要连接后端服务,例如 RPC 服务、memcache 或 redis 等
3)流量非常大

二、解决的问题

常见的 web 架构如上:
1)最前端是 APP 或者 web 页面
2)服务器上层是 web-server 进行接入
3)php 脚本语言调用后端数据,完成业务逻辑,拼接页面
4)最后端是服务、缓存、数据库
我们都知道,php 是一种脚本语言,不像 C++/Java 那样进程能够常驻,所以它连接后端的服务都是使用短连接:

上图是一种典型场景,站点 php 部署在机器 A 上,缓存 memcache 部署在机器 B 上,之间通过短连接通信,过程为:
1)php 建立 tcp 短连接
2)按照 memcache 协议发送数据
3)接收 memcache 返回的数据
4)php 关闭 tcp 短连接
在站点流量小时,上述过程没有任何问题,当站点流量非常大,QPS 很高的情况下,php 对 memcache 的 tcp 建立 + 关闭 tcp 短连接的开销便不能忽略了,有可能成为性能的瓶颈,如何进行优化是本文即将讨论的核心。

三、UNIX Domain Socket 技术介绍
话锋一转,先一起来看看 UNIX Domain Socket 技术。
UNIX Domain Socket 是一种进程间 IPC 通讯机制,它不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。它可以用于同一台主机上两个没有亲缘关系的进程,并且是全双工的,提供可靠消息传递(消息不丢失、不重复、不错乱)的 IPC 机制。

四、优化方案
可以看到,UNIX Domain Socket 的效率会远高于 tcp 短连接,但它只能用于同一台主机间的进程通讯,而我们的 php 应用和后端服务往往是部署在不同的机器上的,此时我们能否利用它来进行优化呢,答案是肯定的。

优化后的简易架构图如上,我们在 php 应用服务器上部署一个 local-proxy,php 与 local-proxy 之间使用 UNIX Domain Socket 来通讯,而 local-proxy 与后端服务进行 TCP 长连接通讯,这样就大大提升了通讯效率,免除了每次请求都要进行的建立 + 关闭 tcp 短连接的开销。

五、local-proxy 要点
要实现上述优化方案,local-proxy 是实现要点,在实现 local-proxy 时,有这么几点需要注意
1)协议设计:local-proxy 本身没有任何业务逻辑,只负责请求转发,上游发送过来 memcache 协议,透传给后端的 memchace,这样的话,上游客户端不需要进行任何代码的修改
2)通讯方式:如上文所述,local-proxy 与上游使用 UNIX Domain Socket 进行通讯,与下游使用 tcp 长连接进行通信
3)高效框架:这种方案是为了解决 tcp 短连接的效率损耗,这样对 local-proxy 的效率要求就非常高,可以选用成熟高效的网络框架(例如 libevent)和 tcp 长连接连接池技术来实现
4)请求映射:需要将上游发过来的请求与发往下游的请求一一映射起来,这样才能正确的对应上请求包与响应包

六、具体应用
优酷内部的 Memcached Agent 项目已经应用了这种方案。

发表评论

电子邮件地址不会被公开。 必填项已用*标注