据说, PHP 是世界上最好的语言?
画外音: phper 说, 不服可以点赞来辩.
如果站点架构满足以下几点:
使用 PHP 这类脚本语言开发
需要连接后端服务, 例如 RPC 服务, memcache,Redis 等
流量非常大
此时, 通过短连接访问 RPC 服务, mc,Redis 会出现什么问题呢?
典型的 web 架构如上:(1) 最前端是 App 或者 Web 页面;(2) 服务器上层是 Web-server 进行接入;(3) PHP 调用后端, 完成业务逻辑, 拼接页面;(4) 最后端是服务, 缓存, 数据库;
PHP 作为脚本语言, 不像 C++/Java 那样进程常驻, 所以它连接后端的服务都是使用短连接.
画外音: 有朋友说, 可以用 C 写扩展?
上图是一种典型场景, 站点 PHP 部署在机器 A 上, 缓存 memcache 部署在机器 B 上, 之间通过短连接通信, 过程为:(1) PHP 建立 tcp 短连接;(2) 按照 memcache 协议发送数据;(3) 接收 memcache 返回的数据;(4) PHP 关闭 tcp 短连接;
在流量小时, 上述过程没有任何问题, 当网站流量非常大的情况下, 短连接可能会成为性能瓶颈, 有什么优化办法吗?
画外音: 建立连接, 销毁连接很耗时.
话锋一转, 什么是 UNIX Domain Socket? UNIX Domain Socket 是一种 IPC 机制, 它不需要经过网络协议栈, 不需要打包拆包, 计算校验和, 维护序号和应答等, 只是将应用层数据从一个进程拷贝到另一个进程.
画外音: IPC, Inter-Process Communication, 进程间通信.
它可以用于同一台主机上两个没有亲缘关系的进程, 并且是全双工的, 提供可靠消息传递 (消息不丢失, 不重复, 不错乱) 的 IPC 机制.
画外音: 亲缘关系是指, 父子进程或者兄弟进程这种 "特殊的" 进程关系.
可以看到, UNIX Domain Socket 的效率会远高于 tcp 短连接, 但它只能用于同一台主机间的进程通讯, 而 PHP 应用和后端服务往往是部署在不同的机器上的, 此时能否利用它来进行优化呢?
优化后的简易架构图如上:
(1) 在 PHP 应用服务器上部署一个 local-proxy;
(2) PHP 与 local-proxy 之间使用 UNIX Domain Socket 来通讯;
(3) local-proxy 与后端服务进行 TCP 长连接通讯;
这样就大大提升了通讯效率, 免除了每次请求都要进行的建立与关闭 tcp 短连接的开销.
实现 local-proxy 有什么要注意的?
local-proxy 非常注重通用性设计, 因为 PHP 有 RPC,mc,Redis 等多种后端:
协议设计: local-proxy 本身没有任何业务逻辑, 只负责请求转发, 上游发送过来 Redis 协议, 透传给后端的 Redis
画外音: 这样, 上游客户端不需要进行任何代码修改.
通讯方式: 如上文所述, local-proxy 与上游使用 UNIX Domain Socket 进行通讯, 与下游使用 tcp 长连接进行通信
高效框架: 这种方案是为了解决 tcp 短连接的效率损耗, 这样对 local-proxy 的效率要求就非常高, 可以选用成熟高效的网络框架和 tcp 长连接连接池技术来实现
画外音: 例如 libevent.
请求映射: 需要将上游发过来的请求与发往下游的请求一一映射起来, 这样才能正确的对应上请求包与响应包
思考过程比结论重要, 希望对你有启示.
架构师之路 - 分享可落地的技术文章
来源: https://juejin.im/entry/5c1f0f2f5188252d7c07aeec