💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 编程须知 这个频道内会详细介绍异步编程与同步编程的不同之处以及需要注意的事项。 注意事项 ----- * 不要在代码中执行`sleep`以及其他睡眠函数,这样会导致整个进程阻塞 * `exit/die`是危险的,会导致`Worker`进程退出 * 可通过`register_shutdown_function`来捕获致命错误,在进程异常退出时做一些清理工作,具体参考 [/wiki/page/305.html](https://wiki.swoole.com/wiki/page/305.html) * `PHP`代码中如果有异常抛出,必须在回调函数中进行`try/catch`捕获异常,否则会导致工作进程退出 * 不支持`set_exception_handler`,必须使用`try/catch`方式处理异常 * `Worker`进程不得共用同一个`Redis`或`MySQL`等网络服务客户端,`Redis/MySQL`创建连接的相关代码可以放到`onWorkerStart`回调函数中,具体参考 [/wiki/page/325.html](https://wiki.swoole.com/wiki/page/325.html) 异步编程 ----- * 异步程序要求代码中不得包含任何同步阻塞操作 * **异步与同步代码不能混用,一旦应用程序使用了任何同步阻塞的代码,程序即退化为同步模式** 协程编程 ---- 使用`Coroutine`特性,请认真阅读 [协程编程须知](https://wiki.swoole.com/wiki/page/851.html) 类/函数重复定义 ---- 新手非常容易犯这个错误,由于`Swoole`是常驻内存的,所以加载类/函数定义的文件后不会释放。因此引入类/函数的php文件时必须要使用`include_once`或`require_once`,否会发生`cannot redeclare function/class` 的致命错误。 内存管理 ---- PHP守护进程与普通Web程序的变量生命周期、内存管理方式完全不同。请参考 [swoole_server内存管理](https://wiki.swoole.com/wiki/page/p-zend_mm.html) 页面。__编写`swoole_server`或其他常驻进程时需要特别注意。__ 进程隔离 ---- 进程隔离也是很多新手经常遇到的问题。修改了全局变量的值,为什么不生效,原因就是全局变量在不同的进程,内存空间是隔离的,所以无效。所以使用`Swoole`开发`Server`程序需要了解`进程隔离`问题。 * 不同的进程中PHP变量不是共享,即使是全局变量,在A进程内修改了它的值,在B进程内是无效的 * 如果需要在不同的Worker进程内共享数据,可以用`Redis`、`MySQL`、`文件`、`Swoole\Table`、`APCu`、`shmget`等工具实现 * 不同进程的文件句柄是隔离的,所以在A进程创建的Socket连接或打开的文件,在B进程内是无效,即使是将它的fd发送到B进程也是不可用的 #### 实例: #### ```php $server = new Swoole\Http\Server('127.0.0.1', 9500); $i = 1; $server->on('Request', function ($request, $response) { global $i; $response->end($i++); }); $server->start(); ``` 在多进程的服务器中,`$i`变量虽然是全局变量(`global`),但由于进程隔离的原因。假设有`4`个工作进程,在`进程1`中进行`$i++`,实际上只有`进程1`中的`$i`变成`2`了,其他另外`3`个进程内`$i`变量的值还是`1`。 正确的做法是使用`Swoole`提供的`Swoole\Atomic`或`Swoole\Table`数据结构来保存数据。如上述代码可以使用`Swoole\Atomic`实现。 ```php $server = new Swoole\Http\Server('127.0.0.1', 9500); $atomic = new Swoole\Atomic(1); $server->on('Request', function ($request, $response) use ($atomic) { $response->end($atomic->add(1)); }); $server->start(); ``` * `Swoole\Atomic`数据是建立在共享内存之上的,使用`add`方法加`1`时,在其他工作进程内也是有效的