图图
发布于 2024-09-05 / 144 阅读 / 0 评论 / 0 点赞

hyperf的使用和理解

框架简介

Hyperf 是 PHP 领域中少有的原生支持协程的框架,基于 Swoole 扩展。Swoole 是一个为 PHP 提供异步、协程支持的底层库,Hyperf 利用它实现了 PHP 原生无法实现的异步 IO、多任务处理以及高并发能力。Hyperf 引入了许多现代开发框架的特性,如依赖注入(DI)、中间件、AOP(面向切面编程)等,使得开发者可以以更清晰、可维护的方式进行开发,如果写过Java的伙伴会发现有很多 Spring 的影子。Hyperf 提供了自动生成代码、依赖注入、路由自动注册等工具,减少了重复的手动操作,提升了开发效率。

高性能

Hyperf 放弃了传统的 FastCGI 模式,采用 Swoole 来重写 PHP 的服务。这是 Hyperf 高性能的核心原因之一。传统的 PHP 应用通常通过 FastCGI 或 FPM(FastCGI Process Manager)与 Web 服务器(如 Nginx、Apache)交互,而 Hyperf 则通过 Swoole 提供的底层功能实现常驻内存的方式运行,从而大幅提升了性能。传统 PHP 是串行化执行的,每个请求在单独的进程中处理,无法利用多核 CPU 进行并发计算,Swoole 为 PHP 提供了并发执行的能力,并且通过多进程利用多核 CPU。可以说swoole是划时代的产品,而同一家公司出品的框架hyperf是php为php开创了一个新的时代,给php提供了更多的可能。

  • Swoole 协程的性能依赖于 Swoole 扩展的实现,通过异步 I/O 和用户态的调度机制实现协程。PHP 本身是单线程阻塞的语言,而 Swoole 协程允许异步执行多个任务,从而在并发处理上大大提升了性能。

  • Swoole 的协程相对较轻量,单个 PHP 进程可以运行成千上万个协程。不过,由于底层语言(PHP)的限制,PHP 的协程调度在效率和资源占用上相比 Go 还是有所差距。

Swoole 与 Go GMP 模型的比较

特点

Swoole 协程模型

Go GMP 模型

并发执行单元

协程(Coroutine),由 Swoole 调度

Goroutine,由 Go 运行时自动调度

调度器

用户态调度器,由 Swoole 提供

Go 运行时自带 GMP 调度器,自动分配 Goroutines

事件模型

基于事件循环,类似于 Node.js 的事件驱动

GMP 模型直接在内存中调度,不依赖事件循环

轻量级

协程非常轻量,性能较好

Goroutine 非常轻量,性能极佳

上下文切换

用户态的协程切换,成本低

用户态 Goroutine 切换,成本低

多线程支持

通过协程池支持并发任务,可以手动配置线程数

Goroutine 通过 M 绑定操作系统线程自动调度

自动负载均衡

没有 Go 那样的自动负载均衡

GMP 模型自动调度 Goroutine,支持负载均衡

应用场景

适合高并发 I/O 密集型任务(WebSocket、HTTP)

适合大规模并发任务,支持 CPU 密集和 I/O 密集型

总的来说,Swoole 的协程模型 为 PHP 提供了强大的并发能力,并且在高并发 I/O 场景中表现优异,但 Go 的 GMP 模型 更加轻量、高效,特别是在处理大规模并发任务时表现更为出色。

开始使用

本文尽量不赘述或者照搬文档内容,只希望对文档内容进行一些提炼或者没提到的内容进行一些补充。文档地址跳转

环境

hyperf提供了docker镜像的环境,无需自行搭建环境还比较方便,强烈建议使用这种方式进行开发,如果需要宿主机自行安装可以去文档查看环境要求。以下是docker方式

docker run --name hyperf -it \ 
-v /Users/zhenyang/codes/hyperf-docker:/data/project \ 
-w /data/project \ 
-p 9501:9501 \ 
--net local_compose_env \ 
--privileged -u root \ 
--entrypoint /bin/sh \ 
hyperf/hyperf:7.4-alpine-v3.12-swoole-v4.6.4

phpstorm中通过镜像启动

两种方式都可以。

安装使用

// 创建项目,可选参数,test-local指定创建的文件名
composer create-project hyperf/hyperf-skeleton test-local

// 所有命令
php bin/hyperf.php list
// 启动框架
php bin/hyperf.php start

Options:
  -h, --help            显示指定命令的帮助信息。如果没有指定命令,则显示列表命令的帮助
  -q, --quiet           不输出任何信息
  -V, --version         显示当前应用程序的版本
      --ansi|--no-ansi  强制启用或禁用 ANSI 输出
  -n, --no-interaction  不进行任何交互式询问
  -v|vv|vvv, --verbose  增加消息的详细程度:1 为普通输出,2 为更详细的输出,3 为调试模式

Available commands:
  completion          输出 shell 自动补全脚本
  help                显示指定命令的帮助信息
  info                输出服务器信息
  list                列出所有命令
  migrate             
  start               启动 Hyperf 服务器
 cmd
  cmd:test            Hyperf 演示命令
 db
  db:seed             数据库填充命令,用于插入测试或初始数据
 describe
  describe:aspects    描述 AOP 切面类
  describe:listeners  描述事件和监听器
  describe:routes     描述路由信息
 gen
  gen:amqp-consumer        // 生成 AMQP 消费者,用于处理消息队列中的消息
  gen:amqp-producer        // 生成 AMQP 生产者,用于发送消息到消息队列
  gen:aspect               // 生成 AOP 切面类,常用于日志、事务等横切逻辑
  gen:command              // 生成自定义命令行工具类,方便在命令行中执行任务
  gen:constant             // 生成常量类枚举类,通常用于定义全局常量
  gen:controller           // 生成控制器类,用于处理 HTTP 请求
  gen:job                  // 生成异步任务类,用于后台处理耗时任务
  gen:kafka-consumer       // 生成 Kafka 消费者类,用于处理 Kafka 消息
  gen:listener             // 生成事件监听器类,用于响应触发的事件
  gen:middleware           // 生成中间件类,用于在请求处理流程中执行特定逻辑
  gen:migration            // 生成数据库迁移文件,用于修改数据库表结构
  gen:model                // 生成 Eloquent 模型类,用于操作数据库记录
  gen:nats-consumer        // 生成 NATS 消费者类,用于处理 NATS 消息
  gen:nsq-consumer         // 生成 NSQ 消费者类,用于处理 NSQ 消息
  gen:process              // 生成进程类,用于创建常驻进程或后台任务
  gen:request              // 生成请求验证类,用于验证 HTTP 请求的输入参数
  gen:resource             // 生成资源类,用于将模型转换为 API 资源响应
  gen:seeder               // 生成数据库填充类,用于插入测试或初始数据
 migrate
  migrate:fresh       重置并运行所有数据库迁移
  migrate:install     安装迁移表
  migrate:refresh     回滚并重新执行所有迁移
  migrate:reset       回滚所有迁移
  migrate:rollback    回滚最近的迁移
  migrate:status      显示已执行的迁移状态
 vendor
  vendor:publish      发布供应商包中的可发布配置文件

踩坑

process多次执行

hyperf提供autoload和注释注册多种方式,我使用的2.2的hyperf版本生成的时候已经自动添加了注释进行注册了,所以如果是手动创建的可以选择autoload或者注释注册,通过命令gen生成的文件无需再通过autoload进行注册,否则会出现多次注册的问题。例如process就是多次运行。

文档搜索不到

如果使用的版本文档中没有写某个功能的使用说明,可以向下搜索,例如2.2可以去看一下2.0的文档。

gen命令丢失

上述指令list可以列出所有指令,但是我创建一个监听文件一个,不确定是不是我的文件中有语法错误或者没有完成,倒是我的list列出的gen指令只有三个,且其他指令也无法使用,报错如下:

Command "gen:process" is not defined.

Did you mean one of these?

gen:migration

gen:model

gen:seeder

解决方案是删除那个监听文件即可。

定时任务注册

在使用定时任务组件之前,需要先在 config/autoload/processes.php 内注册一下 Hyperf\Crontab\Process\CrontabDispatcherProcess 这里并不是让你使用gen:process去生成,只要composer require hyperf/crontab成功导入,就按照要求去配置即可。当然如果有重载这个类的需求可以选择生成。

依赖注入

直接去文档看例子

依赖注入提供了非常方便和简单的调用方式,通过di组件自动的帮我们完成类的引入调用,提高了开发生产效率。建议通过注解方式,更简单更快速。

关于process,listener,job的应用场景分析

  1. Job(任务)

    • 主动触发Job 更适合用于主动触发的异步任务。通常用于处理耗时操作,避免在请求过程中阻塞响应。例如,发送邮件、处理队列、生成报告等。

    • 使用场景

      • 异步处理复杂的逻辑任务。

      • 高并发下延迟执行任务,减轻主线程负担。

  2. Listener(事件监听器)

    • 被动触发Listener 适用于响应某些事件的异步任务。当某个特定事件被触发时,Listener 会自动响应并执行相关逻辑。事件监听器往往用于解耦代码,通过事件驱动的方式执行任务。

    • 使用场景

      • 监听用户注册事件并发送欢迎邮件。

      • 在某个数据操作完成后自动执行相关后续操作(如清理缓存、发送通知等)。

  3. Process(进程)

    • 常驻进程Process 适用于需要长时间运行的任务或守护进程。它通常用于持续监听某些资源或状态,处理常驻任务,类似于守护进程(Daemon)。

    • 使用场景

      • 持续监听队列、Socket、或者文件系统。

      • 处理长时间运行的任务(如 WebSocket 服务器、Crontab 分发器、任务调度器等)。