内容来源:2018 年 5 月 20 日,腾讯企点开放平台技术负责人熊月在“PHPCon China 2018 技术峰会”进行《嵌入式PHP的探索实践》演讲分享。IT 大咖说(微信id:itdakashuo)做为独家视频合做方,经主办方和讲者审阅受权发布。php
阅读字数:2410 | 7分钟阅读编程
对于拥有不少复杂业务场景的tob领域,“开发效率”和“性能”经常是咱们考虑的两个主要问题,PHP做为脚本语言,自己适用于快速开发业务逻辑,同时为了解决PHP特定的性能瓶颈,通常将C++/PHP结合,在PHP代码里调用C/C++扩展。 此次咱们带来了不一样思路的探索:将php嵌入到高性能C/C++框架运行,将C/C++框架做为容器,完美结合php快速开发优点和C/C++高性能特色。Zend Engine提供了一种嵌入式开发模式,咱们利用这一特性使它能够在C/C++的环境中单独执行PHP脚本,而且支持多实例运行,能够在C/C++协程框架中运行。嵌入式PHP也为在任意C/C++协程框架结合带来无限可能,包括在C++的客户端上运行PHP。安全
做为一门后台开发语言PHP有着不一样的发展阶段。最开始是你们都比较熟悉的LAMP,接着是PHP-fpm和fastcgi,再日后是swoole,以后在swoole的基础上又新增了协程。微信
为了便于理解,在介绍嵌入式PHP以前要先讲下SAPI的概念。SAPI即后台应用程序编程接口,是PHP与其余应用程序交互的接口。常见的SAPI有cgi、fpm、cli、Apace2 hander,而嵌入式PHP(embed)也是其中一类。swoole
咱们最初的业务框架是基于TSF2.0,底层为Zend Engine和扩展,扩展最核心的部分是基于swoole。在此之上是TSF PHP层,包含协程调度器、微服务框架、监控管理进程、MVC模式。最上层才是真正的执行逻辑的PHP脚本。网络
这样一套框架存在几个问题。PHP原生的Generator协程须要配合yield使用,对开发来讲不怎么友好,由于yield的使用时机不太好肯定,尤为是对于新手。因为协程调度器是用原生PHP实现的,所以相对其余语言在性能上会差些,特别是在高并发场景下。还有就是低版本swoole不够稳定,问题最多的就是在内存泄露这块。你们都知道腾讯内部有不少公用组件,这些组件接口大可能是用C++实现的,为此咱们须要作的是用扩展对接PHP与其余组件,而问题就在于扩展没法使用上层的PHP协程。多线程
SNG中有个很是有名的C++后台框架SPP,它是一个高性能的网络框架,起始于2008年,被普遍的应用于SNG的各个业务线。众所周知开发效率一直是PHP的长处,性能方面则是短板。因此咱们就在想能不能将SPP和PHP结合起来兼顾高性能和开发效率,嵌入式PHP无疑是很好的结合方案。架构
SPP主要有5个模块。proxy用来处理新请求,内存队列是proxy和workgroup交互的内存区域,workgroup是和后台逻辑脚本交互的模块,controller做为控制核心来控制proxy和workgroup的运行状态,最后是最重要的协程模块。并发
SPP实际上是基于协程的框架,协程是一个用户态的多线程概念。在协程切换的时候会涉及内存管理的机制,而Zend没有这种切换内存资源的机制,只有全局变量和多线程资源隔离的方式。这样的话要想将SPP和Zend结合起来,就要对Zend进行改造。框架
Zend的源码大概有60万行,若是直接改动核心源码,不光实施起来很麻烦,对以后的升级也会形成问题。最好的办法是借助Zend自己的机制对入口进行改造,而不侵入内核。
Zend有多进程和多线程两种方式,在多线程模式下有一个线程安全的机制ZTS。ZTS本质实际上是对每一个线程的全局资源进行了隔离,与SPP协程的结合就须要用到ZTS,下面是具体步骤。
第一步固然是打开Zend内核ZTS开关,第二步为了知足协程上下文切换,须要将ZTS中的线程私有变量转化为全局数据元素,第三步增长资源入口切换API。作完这三步就完成了Zend和SPP的结合,虽然步骤很少但实际上在作的过程当中仍是会有不少挑战。
解决告终合问题以后,接下来为了将整个流程串起来须要有一个执行流程调度器。上图是整个执行流程,首先SPP经过SAPI进入到Zend中,而后Zend执行PHP脚本,先编译成OpCode,以后若是有网路IO就会用到协程。协程也能够基于SPP提供的API来运做,经过Tsrm的全局资源table能够进行协程切换。
在有这样一套执行流的状况下,扩展也能够依赖SPP的API实现协程调度。
上图是SPP结合PHP以后的总体架构。最底层是SPP,往上是PHP执行流调度器,中间是PHP内核和扩展,最上层是PHP脚本。这一整套架构以嵌入式的方式结合了SPP和PHP,让开发者既能够利用SPP提供的高性能网络框架,同时也能应用到上层PHP快速开发的特色。
这里展现的是压测时候的环境数据,包括机型、压测工具、压测方法以及框架的版本等。
这是压测后得到的实际数据对比,能够看到SPP-PHP框架相对旧的框架性能上大概有3倍的提高。