diff --git a/docs/advanced/custom-start.md b/docs/advanced/custom-start.md index 369edbc7..b92895b4 100644 --- a/docs/advanced/custom-start.md +++ b/docs/advanced/custom-start.md @@ -91,6 +91,18 @@ bin/start server # 通过源码模式启动框架 - `--watch`:监控 `src/` 目录下的文件变化,有变化则自动重新载入代码。开启监控需要安装 PHP 扩展:inotify。使用 pecl 就可以安装:`pecl install inotify`。 - `--env`:设置运行环境,设置运行环境后将优先加载指定环境的配置文件,支持 `--env=production`,`--env=staging`,`--env=development`,见 [基本配置](/guide/basic-config/#_2)。 +## 守护进程操作命令 + +守护进程在 2.2.0 版本开始,可以使用命令行快速操作,如重启、停止、查看状态等。 + +注意,这里的守护进程操作命令是指 **使用 `--daemon` 方式启动的框架**,如使用 Docker、screen、tmux 等方式挂后台跑则此命令不可用! + +```bash +vendor/bin/start daemon:status # 查看守护进程的状态 +vendor/bin/start daemon:reload # 重载框架 +vendor/bin/start daemon:stop # 停止运行守护进程的框架 +``` + ## 独立启动其他组件 框架默认不止启动框架的 `server` 命令,还有 `init` 命令和 `simple-http-server` 命令。`init` 命令在上方 Composer 依赖模式中提到过,就是初始化各个文件的。 diff --git a/docs/component/light-cache.md b/docs/component/light-cache.md index 50d44dfa..d2b5efdd 100644 --- a/docs/component/light-cache.md +++ b/docs/component/light-cache.md @@ -224,3 +224,97 @@ public function test() { 解决这一问题,就需要用到锁。这种情况下,我们首先考虑的是自旋锁,框架也因此内置了一个方便使用的自旋锁组件。详见下一章:自旋锁。 +## 如何临时缓存大变量 + +由于 LightCache 需要提前声明最大大小,所以在某些情况下,比如第三方 API 接口结果临时缓存,可能不太适合使用,这时对于 2.x 版本的多进程炸毛框架是一个新的问题。 + +解决方案有三种: + +- 将 `global.php` 中的 `swoole.worker_num` 调整为 `1` 即可,所有除所有主 handler 事件的用户类外其他类均可使用如 `Hello::$store` 类似的静态变量全局存取 +- 使用 WorkerCache(需要 2.2.0 以上版本) +- 使用 Redis(需要安装 `redis` 扩展) + +以上,WorkerCache 是为了弥补 LightCache 的不足而诞生的,以下就是 WorkerCache 的具体内容。 + +### WorkerCache 跨进程大缓存 + +WorkerCache 和 LightCache 几乎完全不同,WorkerCache 存储的方式说白了就是 PHP 的静态变量,不过框架支持使用封装好的进程间通信进行跨进程读取。但由于需要设置一个存储变量的进程,所以配置文件必须先指定要将数据存到哪个 Worker/TaskWorker 进程中。关于框架内多进程的说明,请见 [进阶 - 多进程 Hack](/advanced/multi-process/)。 + +定义:`ZM\Store\WorkerCache`。 + +#### 配置 + +见 [基本配置](/guide/basic-config/)。 + +#### WorkerCache::get() + +定义:`get($key)`。 + +`$key` 为指定要获取的键值对的值,如果不存在则返回 null。 + +#### WorkerCache::set() + +定义:`set($key, $value, $async = false)`。 + +设置变量,你懂的。 + +注意,`$value` 可以是被无损 `json_encode` 和 `json_decode` 的变量,闭包(Closure)、资源(resource)等类型不支持存储。 + +`$async` 默认为 false,当为 true 时候,不会返回是否成功设置与否,否则会协程等待是否目标进程存储成功。 + +#### WorkerCache::unset() + +定义:`unset($key, $async = false)` + +删除键对应的值。`$async` 的意义同上。 + +#### WorkerCache::add() + +定义:`add($key, int $value, $async = false)` + +给 int 类型的值加一,如果值不存在,则默认为 0 且加上目标的 `$value`。 + +#### WorkerCache::sub() + +定义:`sub($key, int $value, $async = false)` + +给 int 类型的值减一,如果值不存在,则默认为 0 且减去目标的 `$value`。 + +```php +getFullArg("请输入要设置的内容名称"); + $arg2 = ctx()->getFullArg("请输入要设置的内容"); + WorkerCache::set($arg1, $arg2); + return "成功!"; + } + + /** + * @CQCommand("get_store") + */ + public function getStorage() { + $arg1 = ctx()->getFullArg("请输入要获取的内容名称"); + $data = WorkerCache::get($arg1); + return $data ?? "内容不存在!"; + } +} +``` + + +) set_store hello world +( 成功! +) get_store hello +( world +) get_store foo +( 内容不存在! + + diff --git a/docs/event/framework-annotations.md b/docs/event/framework-annotations.md index 908ff9ed..e8a7acee 100644 --- a/docs/event/framework-annotations.md +++ b/docs/event/framework-annotations.md @@ -116,6 +116,44 @@ `$conn`: [ConnectionObject](/advanced/connect-ws-client/) 类型,返回一个当前 WS 连接的连接对象。 +## OnPipeMessageEvent() + +当有 其他 Worker 进程通信发来指令,激活响应。(2.2.0 版本可用) + +### 属性 + +| 类型 | 值 | +| ---------- | ------------------------------------------------------- | +| 名称 | `@OnPipeMessageEvent` | +| 触发前提 | 当有 WebSocket 连接接入框架后发送过来消息,触发注解事件 | +| 命名空间 | `ZM\Annotation\Swoole\OnPipeMessageEvent` | +| 适用位置 | 方法 | +| 返回值处理 | 无 | + +### 参数 + +| 参数名称 | 参数范围 | 用途 | 默认 | +| -------- | -------- | ------------ | ---- | +| action | `string` | 限定动作名称 | | + +### 用法 + +```java +@OnPipeMessageEvent("foo") +@OnPipeMessageEvent(action="bar") +``` + +### 事件绑定参数 + +`$data`: 数组,内容如下: + +```php +[ + "action" => "你的上面的名称", + ... //其他自己发送时随便定义,带什么都行 +] +``` + ## OnSwooleEvent() 绑定 Swoole 所相关的事件,例如 WebSocket 接入、收到 WS 消息、关闭 WS 连接,HTTP 请求到达等。这个是旧的统一的 Swoole 事件分发注解。**请尽量使用上面几个新的注解**。 diff --git a/docs/guide/basic-config.md b/docs/guide/basic-config.md index f0ee5cd1..7d8cc63f 100644 --- a/docs/guide/basic-config.md +++ b/docs/guide/basic-config.md @@ -20,6 +20,7 @@ | `crash_dir` | 存放崩溃和运行日志的目录 | `zm_data` 下的 `crash/` | | `swoole` | 对应 Swoole server 中 set 的参数,参考Swoole文档 | 见子表 `swoole` | | `light_cache` | 轻量内置 key-value 缓存 | 见字表 `light_cache` | +| `worker_cache` | 跨进程变量级缓存 | 见子表 `worker_cache` | | `sql_config` | MySQL 数据库连接信息 | 见子表 `sql_config` | | `redis_config` | Redis 连接信息 | 见子表 `redis_config` | | `access_token` | OneBot 客户端连接约定的token,留空则无 | 空 | @@ -82,6 +83,12 @@ | `document_root` | 静态文件的根目录 | `{WORKING_DIR}/resources/html` | | `document_index` | 默认索引的文件名列表 | `["index.html"]` | +### 子表 worker_cache + +| 配置名称 | 说明 | 默认值 | +| -------- | --------------------------- | ------ | +| `worker` | 跨进程缓存的存储工作进程 id | 0 | + ## 多环境下的配置文件 炸毛框架的配置文件模块支持不同环境下的配置文件,主要结构为 `global.{环境}.php`。在一般情况下,炸毛框架默认从教程引导方式根据指令 `vendor/bin/start server` 启动的框架是不带环境控制的。这章将讲述如何根据不同的环境(production / development / staging)来编写配置文件。 diff --git a/docs/index.md b/docs/index.md index 74ac20b5..87df4542 100644 --- a/docs/index.md +++ b/docs/index.md @@ -33,7 +33,7 @@ public function index() { 首先,你需要了解你需要知道哪些事情才能开始着手使用框架: -1. Linux 命令行基础 +1. Linux 命令行(会跑 Linux 程序) 2. php 7.2+ 开发环境 3. HTTP 协议(可选) 4. OneBot 机器人聊天接口标准(可选) diff --git a/docs/update/v2.md b/docs/update/v2.md index 7820da83..91a45205 100644 --- a/docs/update/v2.md +++ b/docs/update/v2.md @@ -1,5 +1,18 @@ # 更新日志(v2 版本) +## v2.2.0 + +> 更新时间:2021.1.29 + +- 新增:`@OnPipeMessageEvent` 注解 +- 新增:进程管理器 +- 新增:`--daemon` 守护进程化后查看状态以及一系列操作的命令行 +- 新增:WorkerCache +- 修复:路由问题 +- 修复:`http_header` 配置项不生效的 bug +- 优化:框架内部所有异常全部基于 `ZMException` +- 优化:SingletonTrait 支持扩展 + ## v2.1.6 > 更新时间:2021.1.18 diff --git a/mkdocs.yml b/mkdocs.yml index 8cec69eb..dd1c1c4b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -94,6 +94,7 @@ nav: - 从 v1 升级: advanced/to-v2.md - 内部类文件手册: advanced/inside-class.md - 接入 WebSocket 客户端: advanced/connect-ws-client.md + - 框架多进程: advanced/multi-process.md - FAQ: FAQ.md - 更新日志: - 更新日志(v2): update/v2.md diff --git a/src/Module/Example/Hello.php b/src/Module/Example/Hello.php index ba871a3d..6f6d8f6c 100644 --- a/src/Module/Example/Hello.php +++ b/src/Module/Example/Hello.php @@ -2,8 +2,6 @@ namespace Module\Example; -use Swoole\Coroutine; -use ZM\Annotation\Http\Controller; use ZM\Annotation\Http\Middleware; use ZM\Annotation\Swoole\OnCloseEvent; use ZM\Annotation\Swoole\OnOpenEvent; @@ -13,16 +11,12 @@ use ZM\Console\Console; use ZM\Annotation\CQ\CQCommand; use ZM\Annotation\Http\RequestMapping; use ZM\Event\EventDispatcher; -use ZM\Store\Lock\SpinLock; -use ZM\Store\WorkerCache; -use ZM\Utils\ProcessManager; use ZM\Utils\ZMUtil; /** * Class Hello * @package Module\Example * @since 2.0 - * @Controller("/sdd") */ class Hello { @@ -85,7 +79,6 @@ class Hello * @RequestMapping("/") */ public function index() { - Console::info("Called!!"); return "Hello Zhamao!"; } @@ -96,42 +89,7 @@ class Hello * @return string */ public function paramGet($param) { - //WorkerCache::set("ss_cnt", 0); - return json_encode(Coroutine::stats()); - } - - /** - * @param $param - * @RequestMapping("/wc/set/{key}/{value}") - * @return string - */ - public function wcSet($param) { - WorkerCache::set($param["key"], $param["value"], true); - //SpinLock::lock("ss"); - WorkerCache::add("ss_cnt", 1); - //SpinLock::unlock("ss"); - return json_encode(Coroutine::stats()); - } - - /** - * @param $param - * @return mixed|string - * @RequestMapping("/wc/get/{key}") - * @Middleware("timer") - */ - public function wcGet($param) { - $obj = WorkerCache::get($param["key"]); - if(is_string($obj)) return $obj; - return json_encode($obj); - } - - /** - * @return mixed - * @RequestMapping("/task") - */ - public function runTask() { - $r = ProcessManager::runOnTask(["class" => Hello::class, "method" => "index", "params" => []]); - return $r; + return "Hello, ".$param["name"]; } /**