page contents

为什么基于 Swoole 驱动的 Laravel 应用性能更好?

我们来看看基于 Swoole 驱动的 Laravel 应用从哪些方面对传统的 PHP Web 请求处理流程进行了优化。 以 laravels 扩展包为例,它为我们提供了一个内置的基于 Swoole 的 HTTP 服务器,通过 php...


我们来看看基于 Swoole 驱动的 Laravel 应用从哪些方面对传统的 PHP Web 请求处理流程进行了优化。

以 laravels 扩展包为例,它为我们提供了一个内置的基于 Swoole 的 HTTP 服务器,通过 php bin/laravels start 命令启动,Nginx 会将 PHP 请求都发到这个服务器进行处理。

与 PHP-FPM 不同的是,这个 Swoole 服务器启动后,会开启多个 Worker 进程,在每个 Worker 进程中,Laravel 应用启动及之前的环境初始化工作只执行一次,请求结束后,Laravel 应用实例不会回收,后续发给该 Worker 进程处理的请求会复用之前已经启动的 Laravel 应用实例,再结合 MySQL、Redis 长连接,从而极大提高了 Laravel 应用的性能。


在 Laravel 中使用 Swoole 的注意事项

单例模式

如上所述,Laravel 应用实例位于 Swoole 的 Worker 进程中,并且常驻内存,这种模式提升了应用性能的同时,也引入了新的复杂性,因为 Laravel 底层的核心是一个 Application IoC 容器,所有服务都绑定在这个容器里,然后在应用的时候从里面解析,包括通过 singleton 方法以单例模式绑定的服务。

这在传统的每次请求重新初始化新的 Application 容器的开发模式中当然没有什么问题,但是现在问题来了,单例模式绑定的服务在整个应用生命周期内解析时返回的都是同一个对象实例,现在这个生命周期延生到整个 Worker 进程的生命周期,只要 Worker 进程还在,那么多个请求使用的可能都是同一个单例服务,这对不同请求可以复用单例的场景来说是好事,比如数据库连接,但是对另一些场景,不同请求不能复用同一个实例,比如用户认证,则是灾难了,所以在这种场景下,需要在一次请求完成后手动注销这些单例服务(或者在下次实例化先判断单例是否存在,如果存在将其销毁)。

还是以 laravels 扩展包为例,它为我们提供的针对这种场景的解决方案是在每次请求处理完成后调用清理器对这些单例服务进行请求,你可以通过在 laravels 配置文件中注释 cleaners 配置项来启用这些清理器:

'cleaners' => [
Hhxsv5\LaravelS\Illuminate\Cleaners\SessionCleaner::class, // If you use the session/authentication in your project, please uncomment this line
Hhxsv5\LaravelS\Illuminate\Cleaners\AuthCleaner::class, // If you use the authentication/passport in your project, please uncomment this line
Hhxsv5\LaravelS\Illuminate\Cleaners\JWTCleaner::class, // If you use the package "tymon/jwt-auth" in your project, please uncomment this line
// ...
],

上面三个都是用户认证相关的清理器,除此之外,该扩展包还提供了针对 Request 和 Cookie 的清理器,可以去源码中查看,如果你想要自定义清理器,也可以仿照这些自带的清理器实现来编写实现了 Hhxsv5\LaravelS\Illuminate\Cleaners\CleanerInterface 接口的清理器类并将其配置到 cleaners 配置项。

除了清理类之外,还可以像上面介绍的那样,在中间件或者服务提供者中处理新请求时销毁已存在的单例服务(laravels 配置文件中包含一个 register_providers 配置项,用于在每次请求处理时重新初始化服务绑定设置)。

同理,通过 static 定义的静态变量也要在必要的时候进行清理,通过 global 定义的全局变量则要慎用,因为它会在同一个 Worker 进程处理的多个请求中复用。

禁用函数

exit/die 相关

由于 Swoole 中禁用 exit/die 函数,所以在 Laravel 中也不能使用它们,以及与之相关的 dd 函数。

请求相关

不要使用 $_GET/$_POST/$_FILES/$_COOKIE/$_REQUEST/$_SESSION/$GLOBALS/$_ENV 之类的超全局变量,统一通过 Illuminate\Http\Request 对象获取请求数据。

另外,Swoole 限制 GET 请求头长度不能超过 2KB,POST 请求数据长度也会通过 package_max_length 配置进行限制,默认是 2M。

响应相关

统一通过 Illuminate\Http\Response 返回响应,不要使用 header()/setcookie()/http_response_code() 之类的函数,以免引起异常问题。

flush 相关

swoole_http_response 不支持 flush 函数,所以不要使用与之相关的 flush/ob_flush/ob_end_flush/ob_implicit_flush 等函数。


  • 发表于 2020-02-15 16:02
  • 阅读 ( 479 )
  • 分类:PHP开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

1135 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1312 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章