Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

文档修改 #45

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 27 additions & 28 deletions public/zh-cn/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* [HTTP服务器](start/start_http_server.md)
* [WebSocket服务器](start/start_ws_server.md)
* [MQTT(物联网)服务器](start/start_mqtt.md)
* [执行异步任务(Task)](start/start_task.md)
* [执行异步任务](start/start_task.md)
* [协程初探](start/coroutine.md)

* [服务端(异步风格)](server/init.md)
Expand Down Expand Up @@ -41,46 +41,45 @@
* [MySQL客户端](coroutine_client/mysql.md)
* [Redis客户端](coroutine_client/redis.md)

* 进程管理 (Process)
* [创建进程](process/process.md)
* [进程池](process/process_pool.md)
* [进程管理器](process/process_manager.md)

* 线程管理 (Thread)
* [创建线程](thread/thread.md)
* [线程池](thread/pool.md)
* [方法与属性](thread/info)
* [并发Map](thread/map.md)
* [并发List](thread/arraylist.md)
* [并发Queue](thread/queue.md)
* [数据类型](thread/transfer.md)

* [协程 (Coroutine)](coroutine.md)
* [一键协程化](runtime.md)
* [核心API](coroutine/coroutine.md)
* [协程容器](coroutine/scheduler.md)
* [协程容器](coroutine/scheduler.md)
* [协程API](coroutine/coroutine.md)
* [系统API](coroutine/system.md)
* [进程API](coroutine/proc_open.md)
* [Channel](coroutine/channel.md)
* [WaitGroup](coroutine/wait_group.md)
* [Barrier](coroutine/barrier.md)
* [并发调用](coroutine/multi_call.md)
* [连接池](coroutine/conn_pool.md)
* [Library](library.md)
* [调试协程](coroutine/gdb.md)
* [编程须知](coroutine/notice.md)

* 进程/线程/协程同步
* [锁](memory/lock.md)
* [原子计数](memory/atomic.md)
* [同步屏障](thread/barrier.md)
* [高性能共享内存](memory/table.md)
* [Channel](coroutine/channel.md)
* [WaitGroup](coroutine/wait_group.md)

* 文件异步操作
* [实现](file/engine.md)
* [配置](file/setting.md)

* 线程管理 (Thread)
* [创建线程](thread/thread.md)
* [线程池(Thread\Pool)](thread/pool.md)
* [方法与属性](thread/info)
* [并发Map](thread/map.md)
* [并发List](thread/arraylist.md)
* [并发Queue](thread/queue.md)
* [同步屏障Barrier](thread/barrier.md)
* [数据类型](thread/transfer.md)

* 进程管理 (Process)
* [创建进程](process/process.md)
* [进程池(Process\Pool)](process/process_pool.md)
* [进程管理器(Process\Manager)](process/process_manager.md)
* [高性能共享内存(Table)](memory/table.md)

* 并发管理
* [锁(Lock)](memory/lock.md)
* [原子计数(Atomic)](memory/atomic.md)
* [事件循环(EventLoop)](event.md)
* [定时器(Timer)](timer.md)
* [事件循环(EventLoop)](event.md)
* [定时器(Timer)](timer.md)

* 其他
* [常量](consts.md)
Expand Down
30 changes: 29 additions & 1 deletion public/zh-cn/coroutine/barrier.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Coroutine\Barrier
# 协程同步执行屏障 Barrier

在 [Swoole Library](https://github.com/swoole/library) 中底层提供了一个更便捷的协程并发管理工具:`Coroutine\Barrier` 协程屏障,或者叫协程栅栏。基于 `PHP` 引用计数和 `Coroutine API` 实现。

相比于[Coroutine\WaitGroup](/coroutine/wait_group),`Coroutine\Barrier`使用更简单一些,只需通过参数传递或者闭包的`use`语法,引入子协程函数上即可。

!> Swoole 版本 >= v4.5.5 时可用。

!> 该协程屏障只能用于单进程或者单线程中的多协程同步,主要作用还是让主协程等待全部子协程完成任务后再退出。

## 使用示例

```php
Expand Down Expand Up @@ -33,6 +35,32 @@ run(function () {
});
```

## 方法

### make()
生成一个协程屏障。

```php
Coroutine\Barrier::make(): self
```

### wait()
在所有协程还未完成任务时,主协程在该函数等待所有协程完成任务。

```php
Coroutine\Barrier::wait(Barrier &$barrier, float $timeout = -1): void
```

* **参数**
* `int $barrier`
* 功能:由`Coroutine\Barrier::make()`返回的协程屏障。
* 默认值:无。
* 其它值:无。
* `float $timeout`
* 功能:超时时间。
* 默认值:-1,表示永不超时。
* 其它值:无。

## 执行流程

* 先使用`Barrier::make()`创建了一个新的协程屏障
Expand Down
2 changes: 1 addition & 1 deletion public/zh-cn/coroutine/channel.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Coroutine\Channel
# Channel

> 建议先查看[概览](/coroutine),了解一些协程基本概念后再看此节。

Expand Down
2 changes: 2 additions & 0 deletions public/zh-cn/coroutine/coroutine.md
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,8 @@ Swoole\Coroutine::getElapsed([$cid]): int

!> Swoole版本 >= `v4.7.0` 可用

!> 你无法取消正在进行文件IO的协程,因为此时内核正在进行文件读写操作,如果此时取消协程,会导致内核正在操作的内存被释放导致段错误。

```php
Swoole\Coroutine::cancel($cid): bool
```
Expand Down
7 changes: 7 additions & 0 deletions public/zh-cn/coroutine/notice.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@

!> `hook`这两个入口函数后,大部分情况下会把平坦的PHP指令调用变为`C`函数调用,增加C栈的消耗。

## 协程中创建进程

由于在协程空间内`fork`进程会带着其他协程上下文,因此底层禁止了在`Coroutine`中使用`Process`模块。可以使用

* `System::exec()`或`Runtime Hook`+`shell_exec`实现外面程序运行
* `Runtime Hook`+`proc_open`实现父子进程交互通信

## 退出协程

在Swoole低版本中,协程中使用`exit`强行退出脚本会导致内存错误导致不可预期的结果或`coredump`,在Swoole服务中使用`exit`会使整个服务进程退出且内部的协程全部异常终止导致严重问题,Swoole长期以来一直禁止开发者使用`exit`,但开发者可以使用抛出异常这种非常规的方式,在顶层`catch`来实现和`exit`相同的退出逻辑
Expand Down
122 changes: 69 additions & 53 deletions public/zh-cn/coroutine/scheduler.md
Original file line number Diff line number Diff line change
@@ -1,65 +1,29 @@
# Coroutine\Scheduler

?> 所有的[协程](/coroutine)必须在`协程容器`里面[创建](/coroutine/coroutine?id=create),`Swoole`程序启动的时候大部分情况会自动创建`协程容器`,用`Swoole`启动程序的方式一共有三种:
# 协程容器

所有的[协程](/coroutine)必须在`协程容器`里面[创建](/coroutine/coroutine?id=create),`Swoole`程序启动的时候大部分情况会自动创建`协程容器`,用`Swoole`启动程序的方式一共有三种:
- 调用[异步风格](/server/init)服务端程序的[start](/server/methods?id=start)方法,此种启动方式会在事件回调中创建`协程容器`,参考[enable_coroutine](/server/setting?id=enable_coroutine)。
- 调用`Swoole`提供的2个进程管理模块[Process](/process/process)和[Process\Pool](/process/process_pool)的[start](/process/process_pool?id=start)方法,此种启动方式会在进程启动的时候创建`协程容器`,参考这两个模块构造函数的`enable_coroutine`参数。
- 其他直接裸写协程的方式启动程序,需要先创建一个协程容器(`Coroutine\run()`函数,可以理解为java、c的`main`函数),例如:

* **启动一个全协程`HTTP`服务**

```php
use Swoole\Coroutine\Http\Server;
use function Swoole\Coroutine\run;

run(function () {
$server = new Server('127.0.0.1', 9502, false);
$server->handle('/', function ($request, $response) {
$response->end("<h1>Index</h1>");
});
$server->handle('/test', function ($request, $response) {
$response->end("<h1>Test</h1>");
});
$server->handle('/stop', function ($request, $response) use ($server) {
$response->end("<h1>Stop</h1>");
$server->shutdown();
});
$server->start();
});
echo 1;//得不到执行
```
- 其他直接裸写协程的方式启动程序,需要先创建一个协程容器`Coroutine\Scheduler`(可以理解为java、c的`main`函数),协程容器会初始化完毕运行协程所需的环境。

* **添加2个协程并发的做一些事情**
!> 在`Swoole v4.4+`版本可用。

## 使用示例
```php
use Swoole\Coroutine;
use function Swoole\Coroutine\run;

run(function () {
Coroutine::create(function() {
var_dump(file_get_contents("http://www.xinhuanet.com/"));
});
use Swoole\Coroutine\Scheduler;

Coroutine::create(function() {
Coroutine::sleep(1);
echo "done\n";
});
$scheduler = new Scheduler();
$scheduler->set(['hook_flags' => SWOOLE_HOOK_ALL]);
$scheduler->add(function() {
sleep(1);
});
echo 1;//可以得到执行
return $scheduler->start();
```

!> 在`Swoole v4.4+`版本可用。

!> 不可以嵌套`Coroutine\run()`。
`Coroutine\run()`里面的逻辑如果有未处理的事件在`Coroutine\run()`之后就进行[EventLoop](learn?id=什么是eventloop),后面的代码将得不到执行,反之,如果没有事件了将继续向下执行,可以再次`Coroutine\run()`。

上文的`Coroutine\run()`函数其实是对`Swoole\Coroutine\Scheduler`类(协程调度器类)的封装,想了解细节的同学可以看`Swoole\Coroutine\Scheduler`的方法:
## 方法

### set()

?> **设置协程运行时参数。**

?> 是`Coroutine::set`方法的别名。请参考 [Coroutine::set](/coroutine/coroutine?id=set) 文档
?> **设置协程运行时参数。** ,是`Coroutine::set`方法的别名。请参考 [Coroutine::set](/coroutine/coroutine?id=set) 文档。

```php
Swoole\Coroutine\Scheduler->set(array $options): bool
Expand All @@ -74,9 +38,7 @@ $sch->set(['max_coroutine' => 100]);

### getOptions()

?> **获取设置的协程运行时参数。** Swoole版本 >= `v4.6.0` 可用

?> 是`Coroutine::getOptions`方法的别名。请参考 [Coroutine::getOptions](/coroutine/coroutine?id=getoptions) 文档
?> **获取设置的协程运行时参数。** Swoole版本 >= `v4.6.0` 可用,是`Coroutine::getOptions`方法的别名。请参考 [Coroutine::getOptions](/coroutine/coroutine?id=getoptions) 文档。

```php
Swoole\Coroutine\Scheduler->getOptions(): null|array
Expand Down Expand Up @@ -177,4 +139,58 @@ Swoole\Coroutine\Scheduler->start(): bool
* **返回值**

* 启动成功,会执行所有添加的任务,所有协程退出时`start`会返回`true`
* 启动失败返回`false`,原因可能是已经启动了或者已经创建了其他调度器无法再次创建
* 启动失败返回`false`,原因可能是已经启动了或者已经创建了其他调度器无法再次创建


## 简化函数
为了简化创建协程容器的步骤,`Swoole`封装了一个`Coroutine\run()`函数。

### 使用示例
* **启动一个全协程`HTTP`服务**

```php
use Swoole\Coroutine\Http\Server;
use function Swoole\Coroutine\run;

run(function () {
$server = new Server('127.0.0.1', 9502, false);
$server->handle('/', function ($request, $response) {
$response->end("<h1>Index</h1>");
});
$server->handle('/test', function ($request, $response) {
$response->end("<h1>Test</h1>");
});
$server->handle('/stop', function ($request, $response) use ($server) {
$response->end("<h1>Stop</h1>");
$server->shutdown();
});
$server->start();
});
echo 1;//得不到执行
```

* **添加2个协程并发的做一些事情**

```php
use Swoole\Coroutine;
use function Swoole\Coroutine\run;

run(function () {
Coroutine::create(function() {
var_dump(file_get_contents("http://www.xinhuanet.com/"));
});

Coroutine::create(function() {
Coroutine::sleep(1);
echo "done\n";
});
});
echo 1;//可以得到执行
```

!> 使用`Coroutine\run()`函数需要确保`swoole.enable_library=On`(默认为On),因为该函数是通过`library`提供的。

!> 使用协程容器会默认设置一键协程化,使所有的PHP阻塞操作变成非阻塞操作。

!> 不可以嵌套`Coroutine\run()`。`Coroutine\run()`里面的逻辑如果有未处理的事件在`Coroutine\run()`之后就进行[EventLoop](learn?id=什么是eventloop),后面的代码将得不到执行,反之,如果没有事件了将继续向下执行,可以再次`Coroutine\run()`。

41 changes: 32 additions & 9 deletions public/zh-cn/coroutine/wait_group.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@

在`Swoole4`中可以使用[Channel](/coroutine/channel)实现协程间的通信、依赖管理、协程同步。基于[Channel](/coroutine/channel)可以很容易地实现`Golang`的`sync.WaitGroup`功能。

## 实现代码

> 此功能是使用PHP编写的功能,并不是C/C++代码,实现源代码在 [Library](https://github.com/swoole/library/blob/master/src/core/Coroutine/WaitGroup.php) 当中

* `add`方法增加计数
* `done`表示任务已完成
* `wait`等待所有任务完成恢复当前协程的执行
* `WaitGroup`对象可以复用,`add`、`done`、`wait`之后可以再次使用
!> `WaitGroup`只能用于单进程或者单线程中的多协程同步,主要作用还是让主协程等待全部子协程完成任务。

## 使用示例

Expand Down Expand Up @@ -69,4 +62,34 @@ run(function () {
//这里 $result 包含了 2 个任务执行结果
var_dump($result);
});
```
```

## 方法

### __construct
`WaitGroup`的构造函数。

```php
Swoole\Coroutine\WaitGroup->__construct()
```

### add
在子协程中使用,表示引用计数加1。

```php
Swoole\Coroutine\WaitGroup->add(): void
```

### done
在子协程中使用,表示任务已完成,引用计数减一。

```php
Swoole\Coroutine\WaitGroup->done(): void
```

### wait
在主协程中使用,主协程会等待子协程全部任务完成之后再退出。

```php
Swoole\Coroutine\WaitGroup->wait(): void
```
22 changes: 22 additions & 0 deletions public/zh-cn/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ pecl install -D 'enable-sockets="no" enable-openssl="yes" enable-http2="yes" ena
pecl install --configureoptions 'enable-sockets="no" enable-openssl="yes" enable-http2="yes" enable-mysqlnd="yes" enable-swoole-json="no" enable-swoole-curl="yes" enable-cares="yes"' swoole
```

## PIE

Swoole 项目支持由 PHP 全新的扩展安装工具 PIE 一键下载安装。

```shell
pie install swoole/swoole:5.1.5
```

通过 PIE 安装 Swoole 时,在安装过程中它会询问是否要启用某些功能,这也可以在运行安装之前提供,例如:

```shell
pie install swoole/swoole:5.1.5 --enable-socket --enable-swoole-curl
```

## 添加Swoole到php.ini

最后,编译安装成功后,修改`php.ini`加入
Expand Down Expand Up @@ -225,6 +239,14 @@ with-swoole-odbc="unixODBC,/usr"

>`v6.0`版本后可用,而且需要安装`liburing`依赖来支持此特性,如果磁盘性能够好的情况下两种模式性能相差不大,只有`I/O`压力较大的情况下,`iouring`模式性能会优于异步线程模式。

>`io_uring`对linux内核版本要求较高,建议在linux 5.12+,liburing 2.6+ 以上的系统使用。

#### --enable-zstd

添加这个编译选项后,`http`服务端和客户端之间可以使用高性能压缩工具`Zstd`压缩响应。

>`v6.0`版本后可用,而且需要安装`libzstd`依赖来支持此特性。

### 特殊参数

!> **如无历史原因不建议启用**
Expand Down
Loading