From a7d5f768e952e86b173a97929ff8a5285e2ccc5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=93=AD=E6=98=95?= Date: Wed, 15 Dec 2021 16:18:55 +0800 Subject: [PATCH 1/3] Use `Swoole\Coroutine\Socket` in `Hyperf\Amqp\IO\SwooleIO`. (#4360) * No longer uses `Swoole\Coroutine\Client`, but uses `Swoole\Coroutine\Socket`, which is more stable and has better performance in `Hyperf\Amqp\IO\SwooleIO`. --- CHANGELOG-2.2.md | 1 + src/amqp/src/ConnectionFactory.php | 3 +- src/amqp/src/IO/SwooleIO.php | 52 ++++++++++++------------------ 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/CHANGELOG-2.2.md b/CHANGELOG-2.2.md index b6959d76c..c7ef1e097 100644 --- a/CHANGELOG-2.2.md +++ b/CHANGELOG-2.2.md @@ -12,6 +12,7 @@ ## Optimized - [#4350](https://github.com/hyperf/hyperf/pull/4350) Optimized the error message for `swoole.use_shortname`. +- [#4360](https://github.com/hyperf/hyperf/pull/4360) No longer uses `Swoole\Coroutine\Client`, but uses `Swoole\Coroutine\Socket`, which is more stable and has better performance in `Hyperf\Amqp\IO\SwooleIO`. # v2.2.20 - 2021-12-13 diff --git a/src/amqp/src/ConnectionFactory.php b/src/amqp/src/ConnectionFactory.php index c09c52b65..8f7222374 100644 --- a/src/amqp/src/ConnectionFactory.php +++ b/src/amqp/src/ConnectionFactory.php @@ -98,7 +98,8 @@ class ConnectionFactory $io = new SwooleIO( $host, $port, - $params->getConnectionTimeout() + $params->getConnectionTimeout(), + $params->getReadWriteTimeout(), ); $connection = new AMQPConnection( diff --git a/src/amqp/src/IO/SwooleIO.php b/src/amqp/src/IO/SwooleIO.php index acb7b0b8a..062baecb7 100644 --- a/src/amqp/src/IO/SwooleIO.php +++ b/src/amqp/src/IO/SwooleIO.php @@ -15,8 +15,7 @@ use PhpAmqpLib\Exception\AMQPConnectionClosedException; use PhpAmqpLib\Exception\AMQPRuntimeException; use PhpAmqpLib\Wire\AMQPWriter; use PhpAmqpLib\Wire\IO\AbstractIO; -use Swoole\Coroutine\Client; -use const SWOOLE_SOCK_TCP; +use Swoole\Coroutine\Socket; class SwooleIO extends AbstractIO { @@ -37,32 +36,34 @@ class SwooleIO extends AbstractIO */ protected $connectionTimeout; + /** + * @var int + */ + protected $readWriteTimeout; + /** * @var int */ protected $heartbeat; /** - * @var null|Client + * @var null|Socket */ private $sock; - /** - * @var string - */ - private $buffer = ''; - /** * @throws \InvalidArgumentException when readWriteTimeout argument does not 2x the heartbeat */ public function __construct( string $host, int $port, - int $connectionTimeout + int $connectionTimeout, + int $readWriteTimeout = 3 ) { $this->host = $host; $this->port = $port; $this->connectionTimeout = $connectionTimeout; + $this->readWriteTimeout = $readWriteTimeout; } /** @@ -77,34 +78,21 @@ class SwooleIO extends AbstractIO public function read($len) { - while (true) { - if ($len <= strlen($this->buffer)) { - $data = substr($this->buffer, 0, $len); - $this->buffer = substr($this->buffer, $len); - - return $data; - } - - if (! $this->sock->isConnected()) { - throw new AMQPConnectionClosedException('Broken pipe or closed connection. ' . $this->sock->errMsg); - } - - $buffer = $this->sock->recv(-1); - - if ($buffer === '') { - throw new AMQPConnectionClosedException('Connection is closed. The reason is ' . $this->sock->errMsg); - } - - $this->buffer .= $buffer; + $data = $this->sock->recvAll($len, $this->readWriteTimeout); + if ($data === false || strlen($data) !== $len) { + throw new AMQPConnectionClosedException('Read data failed, The reason is ' . $this->sock->errMsg); } + + return $data; } public function write($data) { - $buffer = $this->sock->send($data); + $len = $this->sock->sendAll($data, $this->readWriteTimeout); - if ($buffer === false) { - throw new AMQPConnectionClosedException('Error sending data'); + /* @phpstan-ignore-next-line */ + if ($data === false || strlen($data) !== $len) { + throw new AMQPConnectionClosedException('Send data failed, The reason is ' . $this->sock->errMsg); } } @@ -134,7 +122,7 @@ class SwooleIO extends AbstractIO protected function makeClient() { - $sock = new Client(SWOOLE_SOCK_TCP); + $sock = new Socket(AF_INET, SOCK_STREAM, 0); if (! $sock->connect($this->host, $this->port, $this->connectionTimeout)) { throw new AMQPRuntimeException( sprintf('Error Connecting to server: %s ', $sock->errMsg), From 10b23e60b7158aaa59020998be33b6d596abffbe Mon Sep 17 00:00:00 2001 From: codelin <494020937@qq.com> Date: Sat, 18 Dec 2021 12:01:27 +0800 Subject: [PATCH 2/3] Fixed the metadata generation error caused by switching coroutine for snowflake. (#4373) --- .github/workflows/test.yml | 2 +- CHANGELOG-2.2.md | 1 + src/snowflake/src/MetaGenerator.php | 3 +- src/snowflake/tests/MetaGeneratorTest.php | 60 +++++++++++++++++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/snowflake/tests/MetaGeneratorTest.php diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cb4f9bb27..04f4771bc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: matrix: os: [ ubuntu-latest ] php-version: [ '7.4', '8.0', '8.1' ] - sw-version: [ 'v4.5.11', 'v4.6.7', 'v4.7.1', 'v4.8.3', 'master' ] + sw-version: [ 'v4.5.11', 'v4.6.7', 'v4.7.1', 'v4.8.4', 'master' ] exclude: - php-version: '8.1' sw-version: 'v4.5.11' diff --git a/CHANGELOG-2.2.md b/CHANGELOG-2.2.md index c7ef1e097..6f4667e6d 100644 --- a/CHANGELOG-2.2.md +++ b/CHANGELOG-2.2.md @@ -3,6 +3,7 @@ ## Fixed - [#4347](https://github.com/hyperf/hyperf/pull/4347) Fixed bug that amqp io has been bound to more than one coroutine when out of buffer. +- [#4373](https://github.com/hyperf/hyperf/pull/4373) Fixed the metadata generation error caused by switching coroutine for snowflake. ## Added diff --git a/src/snowflake/src/MetaGenerator.php b/src/snowflake/src/MetaGenerator.php index 937bc930f..50c84dd8e 100644 --- a/src/snowflake/src/MetaGenerator.php +++ b/src/snowflake/src/MetaGenerator.php @@ -55,8 +55,9 @@ abstract class MetaGenerator implements MetaGeneratorInterface } $this->lastTimestamp = $timestamp; + $sequence = $this->sequence; - return new Meta($this->getDataCenterId(), $this->getWorkerId(), $this->sequence, $timestamp, $this->beginTimestamp); + return new Meta($this->getDataCenterId(), $this->getWorkerId(), $sequence, $timestamp, $this->beginTimestamp); } public function getBeginTimestamp(): int diff --git a/src/snowflake/tests/MetaGeneratorTest.php b/src/snowflake/tests/MetaGeneratorTest.php new file mode 100644 index 000000000..2c9daad91 --- /dev/null +++ b/src/snowflake/tests/MetaGeneratorTest.php @@ -0,0 +1,60 @@ +generate()->getSequence(); + }; + } + + $res = parallel($callbacks); + ksort($res); + $this->assertSame([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], $res); + } +} From b473732fbd6c951a34103c52568e444c6bcb8c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=93=AD=E6=98=95?= Date: Mon, 20 Dec 2021 09:14:02 +0800 Subject: [PATCH 3/3] Release v2.2.21 (#4375) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 沈唁 <52o@qq52o.cn> --- .github/workflows/test-components.yml | 7 +------ CHANGELOG-2.2.md | 4 +++- docs/zh-cn/changelog.md | 17 +++++++++++++++++ docs/zh-cn/quick-start/questions.md | 12 ++++++++++++ docs/zh-hk/changelog.md | 17 +++++++++++++++++ docs/zh-hk/quick-start/questions.md | 12 ++++++++++++ docs/zh-tw/changelog.md | 17 +++++++++++++++++ docs/zh-tw/quick-start/questions.md | 12 ++++++++++++ 8 files changed, 91 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test-components.yml b/.github/workflows/test-components.yml index 9a9cbe2d6..40241961a 100644 --- a/.github/workflows/test-components.yml +++ b/.github/workflows/test-components.yml @@ -6,8 +6,7 @@ on: schedule: - cron: '0 2 * * *' env: - SW_VERSION: 'v4.8.3' - YASD_VERSION: 'v0.3.9' + SW_VERSION: 'v4.8.4' jobs: database: name: Test for Database @@ -133,8 +132,6 @@ jobs: php link_env.phar show:name -N helloworld sudo chmod u+x link_env.phar ./link_env.phar show:name -N helloworld - - container: name: Test for Psr Container V2.0 runs-on: 'ubuntu-latest' @@ -157,8 +154,6 @@ jobs: coverage: none - name: Setup Swoole run: ./.travis/swoole.install.sh - - name: Setup Yasd - run: ./.travis/yasd.install.sh - name: Setup Packages run: | cp .travis/.env.example .env diff --git a/CHANGELOG-2.2.md b/CHANGELOG-2.2.md index 6f4667e6d..4d94201ea 100644 --- a/CHANGELOG-2.2.md +++ b/CHANGELOG-2.2.md @@ -1,4 +1,6 @@ -# v2.2.21 - TBD +# v2.2.22 - TBD + +# v2.2.21 - 2021-12-20 ## Fixed diff --git a/docs/zh-cn/changelog.md b/docs/zh-cn/changelog.md index fd9b7ab2e..a5341fb81 100644 --- a/docs/zh-cn/changelog.md +++ b/docs/zh-cn/changelog.md @@ -1,5 +1,22 @@ # 版本更新记录 +# v2.2.21 - 2021-12-20 + +## 修复 + +- [#4347](https://github.com/hyperf/hyperf/pull/4347) 修复使用 `AMQP` 组件时,如果连接缓冲区溢出,会导致连接被绑定到多个协程从而报错的问题。 +- [#4373](https://github.com/hyperf/hyperf/pull/4373) 修复使用 `Snowflake` 组件时,由于 `getWorkerId()` 中存在 `IO` 操作进而导致协程切换,最终导致元数据生成重复的问题。 + +## 新增 + +- [#4344](https://github.com/hyperf/hyperf/pull/4344) 新增事件 `Hyperf\Crontab\Event\FailToExecute`,此事件会在 `Crontab` 任务执行失败时触发。 +- [#4348](https://github.com/hyperf/hyperf/pull/4348) 支持使用 `gen:*` 命令创建文件时,自动吊起对应的 `IDE`,并打开当前文件。 + +## 优化 + +- [#4350](https://github.com/hyperf/hyperf/pull/4350) 优化了未开启 `swoole.use_shortname` 时的错误信息。 +- [#4360](https://github.com/hyperf/hyperf/pull/4360) 将 `Hyperf\Amqp\IO\SwooleIO` 进行重构,使用更加稳定和高效的 `Swoole\Coroutine\Socket` 而非 `Swoole\Coroutine\Client`。 + # v2.2.20 - 2021-12-13 ## 修复 diff --git a/docs/zh-cn/quick-start/questions.md b/docs/zh-cn/quick-start/questions.md index 86e2c446a..3f00b7bf9 100644 --- a/docs/zh-cn/quick-start/questions.md +++ b/docs/zh-cn/quick-start/questions.md @@ -169,3 +169,15 @@ http2 => enabled 如果没有,需要重新编译 Swoole 并增加 `--enable-http2` 参数。 2. 检查 [server.php](/zh-cn/config?id=serverphp-配置说明) 文件中 `open_http2_protocol` 选项是否为 `true`。 + +## Command 无法正常关闭 + +在 Command 中使用 AMQP 等多路复用技术后,会导致无法正常关闭,碰到这种情况只需要在执行逻辑最后增加以下代码即可。 + +```php +resume(); +``` diff --git a/docs/zh-hk/changelog.md b/docs/zh-hk/changelog.md index aa924f5bd..752ff475e 100644 --- a/docs/zh-hk/changelog.md +++ b/docs/zh-hk/changelog.md @@ -1,5 +1,22 @@ # 版本更新記錄 +# v2.2.21 - 2021-12-20 + +## 修復 + +- [#4347](https://github.com/hyperf/hyperf/pull/4347) 修復使用 `AMQP` 組件時,如果連接緩衝區溢出,會導致連接被綁定到多個協程從而報錯的問題。 +- [#4373](https://github.com/hyperf/hyperf/pull/4373) 修復使用 `Snowflake` 組件時,由於 `getWorkerId()` 中存在 `IO` 操作進而導致協程切換,最終導致元數據生成重複的問題。 + +## 新增 + +- [#4344](https://github.com/hyperf/hyperf/pull/4344) 新增事件 `Hyperf\Crontab\Event\FailToExecute`,此事件會在 `Crontab` 任務執行失敗時觸發。 +- [#4348](https://github.com/hyperf/hyperf/pull/4348) 支持使用 `gen:*` 命令創建文件時,自動吊起對應的 `IDE`,並打開當前文件。 + +## 優化 + +- [#4350](https://github.com/hyperf/hyperf/pull/4350) 優化了未開啟 `swoole.use_shortname` 時的錯誤信息。 +- [#4360](https://github.com/hyperf/hyperf/pull/4360) 將 `Hyperf\Amqp\IO\SwooleIO` 進行重構,使用更加穩定和高效的 `Swoole\Coroutine\Socket` 而非 `Swoole\Coroutine\Client`。 + # v2.2.20 - 2021-12-13 ## 修復 diff --git a/docs/zh-hk/quick-start/questions.md b/docs/zh-hk/quick-start/questions.md index eed468c6a..a264ba40a 100644 --- a/docs/zh-hk/quick-start/questions.md +++ b/docs/zh-hk/quick-start/questions.md @@ -169,3 +169,15 @@ http2 => enabled 如果沒有,需要重新編譯 Swoole 並增加 `--enable-http2` 參數。 2. 檢查 [server.php](/zh-hk/config?id=serverphp-配置説明) 文件中 `open_http2_protocol` 選項是否為 `true`。 + +## Command 無法正常關閉 + +在 Command 中使用 AMQP 等多路複用技術後,會導致無法正常關閉,碰到這種情況只需要在執行邏輯最後增加以下代碼即可。 + +```php +resume(); +``` diff --git a/docs/zh-tw/changelog.md b/docs/zh-tw/changelog.md index 229bc680f..66a86b8c2 100644 --- a/docs/zh-tw/changelog.md +++ b/docs/zh-tw/changelog.md @@ -1,5 +1,22 @@ # 版本更新記錄 +# v2.2.21 - 2021-12-20 + +## 修復 + +- [#4347](https://github.com/hyperf/hyperf/pull/4347) 修復使用 `AMQP` 元件時,如果連線緩衝區溢位,會導致連線被繫結到多個協程從而報錯的問題。 +- [#4373](https://github.com/hyperf/hyperf/pull/4373) 修復使用 `Snowflake` 元件時,由於 `getWorkerId()` 中存在 `IO` 操作進而導致協程切換,最終導致元資料生成重複的問題。 + +## 新增 + +- [#4344](https://github.com/hyperf/hyperf/pull/4344) 新增事件 `Hyperf\Crontab\Event\FailToExecute`,此事件會在 `Crontab` 任務執行失敗時觸發。 +- [#4348](https://github.com/hyperf/hyperf/pull/4348) 支援使用 `gen:*` 命令建立檔案時,自動吊起對應的 `IDE`,並開啟當前檔案。 + +## 優化 + +- [#4350](https://github.com/hyperf/hyperf/pull/4350) 優化了未開啟 `swoole.use_shortname` 時的錯誤資訊。 +- [#4360](https://github.com/hyperf/hyperf/pull/4360) 將 `Hyperf\Amqp\IO\SwooleIO` 進行重構,使用更加穩定和高效的 `Swoole\Coroutine\Socket` 而非 `Swoole\Coroutine\Client`。 + # v2.2.20 - 2021-12-13 ## 修復 diff --git a/docs/zh-tw/quick-start/questions.md b/docs/zh-tw/quick-start/questions.md index 882ddd665..643f04259 100644 --- a/docs/zh-tw/quick-start/questions.md +++ b/docs/zh-tw/quick-start/questions.md @@ -169,3 +169,15 @@ http2 => enabled 如果沒有,需要重新編譯 Swoole 並增加 `--enable-http2` 引數。 2. 檢查 [server.php](/zh-tw/config?id=serverphp-配置說明) 檔案中 `open_http2_protocol` 選項是否為 `true`。 + +## Command 無法正常關閉 + +在 Command 中使用 AMQP 等多路複用技術後,會導致無法正常關閉,碰到這種情況只需要在執行邏輯最後增加以下程式碼即可。 + +```php +resume(); +```