框架简介
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的应用场景分析
Job(任务):
主动触发:
Job
更适合用于主动触发的异步任务。通常用于处理耗时操作,避免在请求过程中阻塞响应。例如,发送邮件、处理队列、生成报告等。使用场景:
异步处理复杂的逻辑任务。
高并发下延迟执行任务,减轻主线程负担。
Listener(事件监听器):
被动触发:
Listener
适用于响应某些事件的异步任务。当某个特定事件被触发时,Listener
会自动响应并执行相关逻辑。事件监听器往往用于解耦代码,通过事件驱动的方式执行任务。使用场景:
监听用户注册事件并发送欢迎邮件。
在某个数据操作完成后自动执行相关后续操作(如清理缓存、发送通知等)。
Process(进程):
常驻进程:
Process
适用于需要长时间运行的任务或守护进程。它通常用于持续监听某些资源或状态,处理常驻任务,类似于守护进程(Daemon)。使用场景:
持续监听队列、Socket、或者文件系统。
处理长时间运行的任务(如 WebSocket 服务器、Crontab 分发器、任务调度器等)。