LNMP虽是传统的Web应用架构组合,无奈NginX + PHP-FPM的搭配运行效率实在太低;而Swoole HTTP服务器具有NginX级别的性能,且本身嵌入在PHP中,完全可以替代NginX + PHP-FPM。于是一直在探索用Swoole HTTP服务器运行传统PHP应用的途径。这里主要介绍一下Swoole HTTP服务器运行Lumen项目的实现方法:
Swoole HTTP服务器
Swoole1.7.7增加了内置HTTP服务器的支持,使用了跟NginX一样的IO多路复用机制epoll,可以达到NginX级别的性能,并且只需几行代码即可写出一个异步非阻塞多进程的HTTP服务器(epoll属于同步非阻塞,这里说“异步非阻塞”主要是因为“多进程”,单个进程内部依然是同步非阻塞)。
开启一个Swoole HTTP服务器的面向对象编程代码样板大致如下(具体参考Swoole官方文档HttpServer):
1 |
|
直接用php
命令执行以上代码,浏览器访问http://127.0.0.1:9080
,会得到:
1 | App is 1. Get null |
浏览器访问http://127.0.0.1:9080/?user=guest
,会得到:
1 | App is 1. Get {"user":"guest"} |
就是这么简单。
加载Lumen项目
Lumen项目的入口文件是项目路径下的public/index.php
,里面只有简单的两行代码:
1 |
|
第一行代码就是加载整个Lumen框架代码,第二行代码则是处理请求,生成响应。
所以,在Swoole HTTP服务器中加载Lumen项目,也很简单,只需修改onWorkerStart
方法:
1 |
|
处理用户请求
虽然可以加载Lumen框架,但是要怎样才能用Lumen框架来处理用户请求呢?
由于Lumen框架的解耦程度非常高,我们可以很轻松地将swoole_http_request
对象$request
,转换成Lumen框架熟悉的Illuminate\Http\Request
对象,这样Lumen框架就能处理用户请求了。
这里实现一个parseRequest
方法,接收swoole_http_request
类参数,返回\Illuminate\Http\Request
类结果:
1 |
|
生成请求响应
Lumen框架处理用户请求,十分方便,只需调用应用的dispatch
方法即可。不过dispatch
方法返回结果一般是Symfony\Component\HttpFoundation\Response
对象,需要做一些转化才能交由swoole_http_response
对象给用户输出响应。
这里实现一个makeResponse
方法:
1 |
|
有了parseRequest
方法和makeResponse
方法,要实现以Swoole HTTP服务器运行Lumen项目来处理用户请求只要几行代码。onRequest
方法这样修改:
1 |
|
最后
就这样,不需要修改Lumen项目原本任何代码,就能让其运行在Swoole HTTP服务器上。
当然,用户请求各种各样,有请求文件上传,有请求静态资源等等;响应类型也是各种各样,有Gzip压缩,有JSON格式,有设置Cookie等待。要实现一个健全的Swoole+Lumen
网关服务,以上代码还须更多优化,具体可以参考Service.php。
按照以上思路,要实现以Swoole HTTP服务器运行Laravel项目也不难,不过,为了效率选择Swoole,自然会为了效率选择Lumen而不是Laravel。
下一篇文章介绍如何在Lumen中使用异步MySQL客户端,减少IO阻塞。