当前位置: 首页 > news >正文

Hyperf中的其它事项

Hyperf中的其它事项

关于 Hyperf 其它的内容我们就不多说了,毕竟框架这东西用得多了自然也就熟悉了。最重要的是——我的水平还不足以去深入地分析这个框架!

好吧,其它的功能大家可以去官方文档详细了解,毕竟国人自己做的框架,文档和服务支持还是非常方便的。今天,我们就来再简单讲讲其它的一些配置。

Nginx部署

第一个就是 Nginx 部署问题,Nginx 做为现在顶流级别的应用服务器,可以非常方便地实现 HTTP 服务、绑定域名、负载均衡等功能。在传统的 PHP-FPM 时代,我们只需要指定 FastCGI ,也就是那个 9000 端口或者 unixSocket 就可以了。其实也可以看出,fastcgi_pass 这个词本身就是通过什么什么来执行的意思。fastcgi_pass 就是通过 fastcgi 来执行 PHP-FPM 程序从而实现应用程序的代理。

Swoole 本身启动的就是一个服务应用,这种情况最方便的当然就是来一个反向代理搞定啦。

# 至少需要一个 Hyperf 节点,多个配置多行
upstream hyperf {# Hyperf HTTP Server 的 IP 及 端口server 127.0.0.1:9501;server 127.0.0.1:9502;
}
​
server {# 监听端口listen 80; # 绑定的域名,填写您的域名server_name www.testswoole.com;
​location / {# 将客户端的 Host 和 IP 信息一并转发到对应节点  proxy_set_header Host $http_host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# 转发Cookie,设置 SameSiteproxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";# 执行代理访问真实服务器proxy_pass http://hyperf;}
}

这是官网的例子,配置都比较简单,也没什么多说的,不过需要注意的是,一定要配置 IP 的转发,要不你在程序中获得的 IP 就是 127.0.0.1 那个了。这个只要配置过反向代理的应该都清楚,也不多做解释了哦。

Supervisor部署

除了 Nginx 之外,还推荐一个工具,那就是 Supervisor 。它是一个进程管理工具,本身 PHP-FPM 就可以自动管理进程,同时我们之前也讲过在 Swoole 中如何管理进程。但是,Supervisor 相对来说更加强大一些,可以很方便地启动、监听和重启一个或多个进程。当一个进程意外被 kill 时,它就会自动再把它重启或者拉起新的进程,从而达到进程自动恢复的目的。

# 安装 epel 源,如果此前安装过,此步骤跳过
yum install -y epel-release
yum install -y supervisor  

CentOS 的话直接运行上面两个命令行就可以安装 Supervisor 了。如果你有使用过 宝塔面板 之类的面板工具的话,那就更方便了,里面可以直接选择安装 Supervisor 并且能够图形界面化的管理。

如果你不爱使用面板类的工具的话,那就还是跟着我一起向下配置吧。先来创建一个配置文件。

vim /etc/supervisord.d/hyperf.ini

在这个 .ini 文件中添加下面的内容。

# 新建一个应用并设置一个名称,这里设置为 hyperf
[program:hyperf]
# 设置命令在指定的目录内执行
directory=/home/www/6.框架/hyperf-skeleton/
# 这里为您要管理的项目的启动命令
command=php ./bin/hyperf.php start
# 以哪个用户来运行该进程
user=root
# supervisor 启动时自动该应用
autostart=true
# 进程退出后自动重启进程
autorestart=true
# 进程持续运行多久才认为是启动成功
startsecs=1
# 重试次数
startretries=3
# stderr 日志输出位置
stderr_logfile=/home/www/6.框架/hyperf-skeleton/runtime/stderr.log
# stdout 日志输出位置
stdout_logfile=/home/www/6.框架/hyperf-skeleton/runtime/stdout.log

注意上面路径相关的内容,要修改成你的项目路径哦。然后就可以启动 Supervisor 了。

supervisord -c /etc/supervisord.d/supervisord.conf

这一行的意思是以配置文件启动 Supervisor 主程序,同时之前我们配置过的 .ini 文件中的程序都会运行起来。

[root@localhost supervisord.d]# ps -ef | grep skeleton
root     32162 32161  0 07:25 ?        00:00:00 skeleton.Master
root     32170 32162  0 07:25 ?        00:00:00 skeleton.Manager
root     32172 32170  0 07:25 ?        00:00:00 skeleton.TaskWorker.1
root     32173 32170  0 07:25 ?        00:00:00 skeleton.TaskWorker.2
root     32174 32170  0 07:25 ?        00:00:00 skeleton.TaskWorker.3
root     32175 32170  0 07:25 ?        00:00:00 skeleton.TaskWorker.4
root     32176 32170  0 07:25 ?        00:00:00 skeleton.TaskWorker.5
root     32177 32170  0 07:25 ?        00:00:00 skeleton.TaskWorker.6
root     32178 32170  0 07:25 ?        00:00:00 skeleton.TaskWorker.7
root     32179 32170  0 07:25 ?        00:00:00 skeleton.TaskWorker.8
root     32180 32170  0 07:25 ?        00:00:00 skeleton.Worker.0

不对呀,我们程序名字怎么是 skeleton ,而且 gerp php 也看不到内容。没错,同时也不要慌张,进入项目目录,修改一下 .env 中 APP_NAME ,我就修改成了 MNLZ 。接着重启一下 Supervisor 应用服务。

[root@localhost hyperf-skeleton]# supervisorctl restart hyperf
hyperf: stopped
hyperf: started
[root@localhost hyperf-skeleton]# ps -ef | grep MNLZ
root     32213 32161  1 07:29 ?        00:00:00 MNLZ.Master
root     32221 32213  0 07:29 ?        00:00:00 MNLZ.Manager
root     32223 32221  0 07:29 ?        00:00:00 MNLZ.TaskWorker.1
root     32224 32221  0 07:29 ?        00:00:00 MNLZ.TaskWorker.2
root     32225 32221  0 07:29 ?        00:00:00 MNLZ.TaskWorker.3
root     32226 32221  0 07:29 ?        00:00:00 MNLZ.TaskWorker.4
root     32227 32221  0 07:29 ?        00:00:00 MNLZ.TaskWorker.5
root     32228 32221  0 07:29 ?        00:00:00 MNLZ.TaskWorker.6
root     32229 32221  0 07:29 ?        00:00:00 MNLZ.TaskWorker.7
root     32230 32221  0 07:29 ?        00:00:00 MNLZ.TaskWorker.8
root     32231 32221  0 07:29 ?        00:00:00 MNLZ.Worker.0

现在你可以试试 kill 一下,不管是 TaskWorker 还是 Master ,kill 之后都会重新拉起新的进程。但是注意,如果 Manager 出现问题了,那可就拉不起任何子进程了。毕竟,Manager 是整个 Swoole 中的管理进程。还记得我们之前讲过的进程模式相关的内容吗?如果不记得了,可以回去看看哦 【Swoole系列3.2】Swoole异步进程服务系统【Swoole系列3.2】Swoole 异步进程服务系统 。

最后,为什么要使用 Supervisor 呢?之前其实我们也讲过,Swoole 中的一个异常或者错误就会导致进程被关闭,为了保证有足够的子进程来处理请求,Supervisor 就是非常好的选择,特别是预防 Master 进程的突然中断。下面的一些命令行命令大家也可以了解一下。

# 启动 hyperf 应用
supervisorctl start hyperf
# 重启 hyperf 应用
supervisorctl restart hyperf
# 停止 hyperf 应用
supervisorctl stop hyperf  
# 查看所有被管理项目运行状态
supervisorctl status
# 重新加载配置文件
supervisorctl update
# 重新启动所有程序
supervisorctl reload

Hyperf 核心生命周期

Hyperf 的生命周期其实分两个部分,在官方文档上也就两段说明。我带着大家去翻源码再看一下。

在 Hyperf 中,它没有像 Laravel 一样的 public/index.php 这样的请求入口文件。因为它是需要自己启动服务的,所以它的全部入口都是 bin/hyperf.php 这个命令行文件。

框架生命周期

当我们执行 php bin/hyperf.php start 的时候,实际上是 vendor/hyperf/server/src/Command/StartServer.php 这个文件中的命令被执行了。这一系列操作我们之前在学习 Laravel 命令行时也接触过。

protected function execute(InputInterface $input, OutputInterface $output){$this->checkEnvironment($output);$serverFactory = $this->container->get(ServerFactory::class)->setEventDispatcher($this->container->get(EventDispatcherInterface::class))->setLogger($this->container->get(StdoutLoggerInterface::class));$serverConfig = $this->container->get(ConfigInterface::class)->get('server', []);if (! $serverConfig) {throw new InvalidArgumentException('At least one server should be defined.');}$serverFactory->configure($serverConfig);Coroutine::set(['hook_flags' => swoole_hook_flags()]);$serverFactory->start();return 0;}

在这个对象的 execute() 中,我们就可以非常清楚地看到读取到了配置文件 config/autoload/server.php 中的内容,然后交给一个 $serverFactory 对象去启动。

$serverFactory 的 configure() 方法会根据配置文件信息,返回实际的原生 Swoole 服务对象。

public function configure(array $config)
{$this->config = new ServerConfig($config);$this->getServer()->init($this->config);
}
public function getServer(): ServerInterface
{if (! $this->server instanceof ServerInterface) {$serverName = $this->config->getType();$this->server = new $serverName($this->container,$this->getLogger(),$this->getEventDispatcher());}return $this->server;
}

ServerConfig 对象会根据我们的配置文件生成一个格式化的配置对象。然后在下面的 getServer() 方法中,根据 ServerConfig 对象的 getType() 返回值获得一个指定的 Server 对象。注意,这个 getType() 返回的不是我们配置文件中的那个 type 属性哦。

class ServerConfig implements Arrayable
{// ......public function __construct(array $config = []){// ......$this->setType($config['type'] ?? Server::class)->setMode($config['mode'] ?? 0)->setServers($servers)->setProcesses($config['processes'] ?? [])->setSettings($config['settings'] ?? [])->setCallbacks($config['callbacks'] ?? []);}// ......
}

注意看这里的 setType() 它要拿的是整个 server.php 配置文件中最外层的 type 属性,我们并没有定义这个值,所以返回的就是 vendor/hyperf/server/src/Server.php 这个对象。接下来我们顺着这个对象的 init() 方法向下摸,在 initServers() 方法中发现了一个 makeServer() 方法的调用,感觉离胜利不远了哦。

protected function makeServer(int $type, string $host, int $port, int $mode, int $sockType)
{switch ($type) {case ServerInterface::SERVER_HTTP:return new SwooleHttpServer($host, $port, $mode, $sockType);case ServerInterface::SERVER_WEBSOCKET:return new SwooleWebSocketServer($host, $port, $mode, $sockType);case ServerInterface::SERVER_BASE:return new SwooleServer($host, $port, $mode, $sockType);}throw new RuntimeException('Server type is invalid.');
}

我擦,不对呀,SwooleHttpServer 又是什么鬼,再进去看看,我们就选第一个 SwooleHttpServer 。点过去之后总算真象大白了,SwooleHttpServer 是一个命名空间别名,真实的就是 Swoole 下面的各种服务器。

// vendor/swoole/ide-helper/src/swoole/Swoole/Http/Server.php
class Server extends \Swoole\Server
{
}

这一条线大家摸清楚了吧,这就是我们说的第一个生命周期,也就是整个框架运行起 Swoole 应用服务的生命周期。

请求与协程生命周期

另一个就是请求与协程的生命周期,这里我就搬官方原话了,其实这部分内容我们之前讲过。

Swoole 在处理每个连接时,会默认创建一个协程去处理,主要体现在 onRequest、onReceive、onConnect 事件,所以可以理解为每个请求都是一个协程,由于创建协程也是个常规操作,所以一个请求协程里面可能会包含很多个协程,同一个进程内协程之间是内存共享的,但调度顺序是非顺序的,且协程间本质上是相互独立的没有父子关系,所以对每个协程的状态处理都需要通过 协程上下文 来管理。

总结

到这里,我们整个 Hyperf 框架的学习就结束了,同时,整个 Swoole 系列也就告一段落了。这里先不煽情了,毕竟后面还有一篇大总结,大家有收获吗?不管怎么样,一步一步跟着我走下来,相信多少都会有一点感悟和成长。更重要的,如果有机会,不如尝试在实战中运用一下,这才是真正成长的最佳机会。

测试代码:

https://github.com/zhangyue0503/swoole/tree/main/6.%E6%A1%86%E6%9E%B6/hyperf-skeleton

参考文档:

Hyperf

Hyperf

Hyperf

相关文章:

Hyperf中的其它事项

Hyperf中的其它事项 关于 Hyperf 其它的内容我们就不多说了,毕竟框架这东西用得多了自然也就熟悉了。最重要的是——我的水平还不足以去深入地分析这个框架! 好吧,其它的功能大家可以去官方文档详细了解,毕竟国人自己做的框架&a…...

【技术选型】Elasticsearch 和Solr那个香?

我们为什么在这里?我存在的目的是什么?我应该运动还是休息并节省能量?早起上班或晚起并整夜工作?我应该将炸薯条和番茄酱或蛋黄酱一起吃吗? 这些都是古老的问题,可能有也可能没有答案。其中一些是非常困难或…...

4面美团测试工程师,因为这个小细节,直接让我前功尽弃.....

说一下我面试别人时候的思路 反过来理解,就是面试时候应该注意哪些东西;用加粗部分标注了 一般面试分为这么几个部分: 一、自我介绍 这部分一般人喜欢讲很多,其实没必要。大约5分钟内说清楚自己的职业经历,自己的核…...

数据恢复软件EasyRecovery16下载安装步骤教程

EasyRecovery16是一款专业好用的数据恢复软件,软件提供了向导式的操作向导,可以有效地恢复电脑或者移动存储设备中丢失的各种文件,包括删除的文件、格式化丢失的文件和清空回收站的数据!千呼万唤始出来,大家期盼许久的EasyRecover…...

Springboot 自定义缓存配置 CacheManager 及redis集成

目录 前言 集成 maven依赖 CacheManagerConfig配置 redis配置 使用 Springboot 集成使用缓存 Cacheable CacheEvict 前言 现有项目中经常遇到的缓存集成问题,Springboot提供了统一的接口抽象与缓存管理器,可集成多种缓存类型,如 Co…...

JS 中七个改变原数组的方法

目录 一、push 二、pop 三、unshift 四、shift 五、splice 六、sort 七、reverse 一、push 在数组的尾部添加元素,并返回新的长度。 let arr [1] arr.push(2) console.log(arr) // [1, 2] 二、pop 删除数组最后面一个元素、并返回删除的元素。 let arr [1, …...

【笔试强训选择题】Day7.习题(错题)解析

作者简介:大家好,我是未央; 博客首页:未央.303 系列专栏:笔试强训选择题 每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!! 文章目录…...

Vue电商项目--axios二次封装

postman测试接口 刚刚经过postman工具测试,发现接口果然发生了改变。 新的接口为http://gmall-h5-api.atguigu.cn 如果服务器返回的数据code字段200,代表服务器返回数据成功 整个项目,接口前缀都有/api字样 axios二次封装 XmlHttpRequ…...

人生四维度

人生四维度 不是有钱了就成功,你知道;人生的成功不止一种,你也知道。但成功还有哪种?你知道吗? 如果把人生的体验展开,我们可以得到四个维度,高度、深度、宽度和温度。 财富、权力、影响力 构…...

Python 调用 MessageBeep 播放系统音效

Python 调用 MessageBeep 播放 Windows 系统提示声音 Windows API 函数 "MessageBeep" 介绍 "Windows API MessageBeep"是一个用于发出系统提示音效的函数。它可以向用户发出一种预定义的声音,以指示事件的发生或某个条件的满足。例如&#xf…...

废物,我TMD一个985却斗不过专科生(大厂自动化测试2年被裁)

前言 看到标题,可能很多读者朋友恐怕又要骂我了,985这个特殊的字眼也确实异常晃眼,实际上现在985,211也越来越多,它能代表你能够进入到更高的平台,拿到“高级工厂”的入场券,但并不意味着你会成…...

p70 内网安全-域横向内网漫游 Socks 代理隧道技术(NPS、FRP、CFS 三层内网漫游)

数据来源 本文仅用于信息安全学习,请遵守相关法律法规,严禁用于非法途径。若观众因此作出任何危害网络安全的行为,后果自负,与本人无关。 ​ 必要基础知识点: 内外网简单知识内网 1 和内网 2 通信问题正向反向协议通…...

第三十二章 Unity Mecanim动画系统(上)

在上一章节中,我们介绍了Unity的旧版动画系统,本章节来介绍新版的Mecanim动画系统。新版的Mecanim动画系统实际是对旧版动画系统的升级。新版的Mecanim动画系统仍然是建立在动画片段的基础上的,只不过它给我们提供了一个可视化的窗口来编辑动…...

第二章 集合

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目…...

这一篇Databinding应该可以帮助迅速上手吧

Databinding使用篇(迅速上手) 使用前需要在模块级别的build.gradle里面的android闭包里添加: dataBinding{enabled true}接着在layout文件中按下Alt 回车, 将布局转换成data binding layout即可,此时编译就会生成对…...

【PHP在线定制商城网站源码V3.0】开源的DIY在线定制商城系统+在线礼品定制

源码下载:https://download.csdn.net/download/m0_66047725/87637177 PHP在线定制商城网站源码,免费开源、免费下载。本商城基于mycncart开发。安装成功后即可浏览,你可以在后台->安装扩展功能上传安装插件,在代码调整中点击刷…...

cout源码浅析

目录 cout源码浅析 那么对于没有定义在这之中的要怎么办呢? 实际使用 结语 首先来看我从cplusplus中截取的这张图: 注意最下面这一行字。cout其实是ostream的一个标准对象object。而上面则演示了一些继承关系。 好的,理解了之后&#xf…...

发送Ajax get请求详解

发送AJAX get请求&#xff0c;前端代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>ajax get请求</title> </head> <body> <script type"text/java…...

SQL语句

创建及删除数据库和表 CREATE DATABASE 数据库名; CREATE DATABASE school; 创建新的表 CREATE TABLE 表名(字段1 数据类型,字段2 数据类型[,...] [,PRIMARY KEY (主键名)]); #主键一般选择能代表唯一性的字段&#xff0c;不允许取空值(NULL)&#xff0c;值也不允许重复&…...

Mysql 学习(八)单表查询方法二

复杂查询 上一节说了5种访问类型的查询&#xff0c;这一节就来说说关于这些比较复杂的查询 情况一&#xff1a;多个二级索引查询 sql&#xff1a;SELECT * FROM index_value_table WHERE value1 abc AND value2 > 1000;搜索条件&#xff1a; value1 等于 abcvalue2 大于…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...