workerman5.0 和 swoole5.0 实现一键协程

概述

在现代的互联网应用开发中,性能和实时性是衡量一个应用成功的关键指标。Workerman 和 Swoole 作为 PHP 社区中流行的高性能通信库,它们的结合使用为开发者提供了强大的异步网络通信能力。本文将深入探索如何利用 Workerman 5.0 结合 Swoole 5.0 来实现一键协程。

🥁 问: workerman5.0为什么要使用swoole5.0,原因很简单:workerman5.0 全面支持Swoole驱动。更多了解:https://github.com/walkor/workerman/releases/tag/v5.0.0-beta.1

workerman5.0 和 swoole5.0 实现一键协程

使用

强烈建议看看这个作为入门:webman如何使用swoole事件驱动和协程?

为了方便开发和部署,这里直接使用docker容器

docker pull tinywan/docker-php-webman:8.2.17-swoole5.1

更多使用方法可以参考这里 https://github.com/Tinywan/docker-php-webman。该容器支持swoole扩展5.1.1

# pecl info swoole
About pecl.php.net/swoole-5.1.1
===============================
Release Type          PECL-style PHP extension (source code)
Name                  swoole
Channel               pecl.php.net
Summary               Event-driven asynchronous and concurrent
                      networking engine with high performance for PHP.
Description           Event-driven asynchronous and concurrent
                      networking engine with high performance for PHP.
                       - event-driven
                       - coroutine
                       - asynchronous non-blocking
                       - multi-thread reactor
                       - multi-process worker
                       - multi-protocol
                       - millisecond timer
                       - built-in tcp/http/websocket/http2 server
                       - coroutine tcp/http/websocket client
                       - coroutine mysql client
                       - coroutine redis client
                       - coroutine read/write file system
                       - coroutine dns lookup
                       - support IPv4/IPv6/UnixSocket/TCP/UDP
                       - support SSL/TLS encrypted transmission
Maintainers           Tianfeng Han <rango@swoole.com> (lead)
                      Twosee <twosee@php.net> (developer)
                      Shen Zhe <shenzhe163@gmail.com> (developer,
                      inactive)
                      Lu Fei <lufei@php.net> (developer)
                      Bruce Dou <doubaokun@php.net> (developer)
Release Date          2023-11-26 14:25:25
Release Version       5.1.1 (stable)
API Version           5.0 (stable)
License               Apache2.0
                      (http://www.apache.org/licenses/LICENSE-2.0.html)
Release Notes         - Fixed memory leak issue in HTTP coroutine
                      client
                      - Fixed the issue of can not hook pdo_odbc
                      - Fixed the error in executing
                      socket_import_stream()
                      - Fixed the issue with
                      Context::parse_multipart_data() unable to handle
                      empty request body
                      - Fixed the issue with PostgreSQL coroutine
                      client where the parameters are not working
                      - Fixed the bug where curl crashes during
                      destruction
                      - Fixed the compatibility issue between Swoole
                      5.x and the latest version of xdebug
                      - Fixed the problem of class not found error
                      caused by coroutine switching during the process
                      of class autoloading
                      - Fixed the issue of not being able to compile
                      Swoole on OpenBSD
Required Dependencies PHP version 8.0.0
                      PEAR installer version 1.4.0 or newer
package.xml version   2.0
Last Modified         2024-04-21 10:05
Previous Installed    - None -
Version

开启swoole事件驱动

webman框架中开启swoole事件驱动特别简单,只有配置一下就可以了。修改配置文件config/server.php服务配置文件

'event_loop' => WorkermanEventsSwoole::class

Docker 启动webman

$ docker run --rm -it -p 8887:8787 -v d:/dnmp/www/webman2024:/app tinywan/docker-php-webman:8.2.17-swoole5.1
2024-04-21 14:13:53,255 INFO Set uid to user 0 succeeded
2024-04-21 14:13:53,266 INFO supervisord started with pid 1
2024-04-21 14:13:54,272 INFO spawned: 'webman' with pid 7
Workerman[/app/start.php] start in DEBUG mode
-------------------------------------------------- WORKERMAN --------------------------------------------------
Workerman version:5.0.0    PHP version:8.2.17     Event-loop:WorkermanEventsSwoole
--------------------------------------------------- WORKERS ---------------------------------------------------
proto   user            worker                       listen                      processes    state
tcp     root            webman                       http://0.0.0.0:8787         8             [OK]
tcp     root            monitor                      none                        1             [OK]
tcp     root            push_chart                   none                        1             [OK]
tcp     root            plugin.webman.push.server    websocket://0.0.0.0:8788    1             [OK]
---------------------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.

swoole实现协程

协程伪代码

<?php
/**
 * @desc Swoole 协程入门
 * @author Tinywan(ShaoBo Wan)
 * @date 2024/4/22 19:27
 */

declare(strict_types=1);

function task1(){
    for ($i=0;$i<=5;$i++){
        //写入文件,大概要3000微秒
        usleep(3000);
        echo '[x] [写入文件] ['.$i.'] ' . date('Y-m-d H:i:s') . PHP_EOL;
        Co::sleep(0.001);//挂起当前协程,0.001秒后恢复//相当于切换协程
    }
}
function task2(){
    for ($i=0;$i<=10;$i++){
        //发送邮件给500名会员,大概3000微秒
        usleep(3000);
        echo '[x] [发送邮件] ['.$i.'] ' . date('Y-m-d H:i:s') . PHP_EOL;
        Co::sleep(0.001);//挂起当前协程,0.001秒后恢复//相当于切换协程
    }
}
function task3(){
    for ($i=0;$i<=15;$i++){
        //模拟插入100条数据,大概3000微秒
        usleep(3000);
        echo '[x] [插入数据] ['.$i.'] ' . date('Y-m-d H:i:s') . PHP_EOL;
        Co::sleep(0.001);//挂起当前协程,0.001秒后恢复//相当于切换协程
    }
}
$pid1 = go('task1'); //go函数是swoole的开启协程函数,用于开启一个协程
$pid2 = go('task2');
$pid3 = go('task3');

执行结果

[x] [写入文件] [02024-04-21 13:31:37
[x] [发送邮件] [02024-04-21 13:31:37
[x] [插入数据] [02024-04-21 13:31:37
[x] [写入文件] [12024-04-21 13:31:37
[x] [发送邮件] [12024-04-21 13:31:37
[x] [插入数据] [12024-04-21 13:31:37
[x] [写入文件] [22024-04-21 13:31:37
[x] [发送邮件] [22024-04-21 13:31:37
[x] [插入数据] [22024-04-21 13:31:37
[x] [写入文件] [32024-04-21 13:31:37
[x] [发送邮件] [32024-04-21 13:31:37
[x] [插入数据] [32024-04-21 13:31:37
[x] [写入文件] [42024-04-21 13:31:37
[x] [发送邮件] [42024-04-21 13:31:37
[x] [插入数据] [42024-04-21 13:31:37
[x] [写入文件] [52024-04-21 13:31:37
[x] [发送邮件] [52024-04-21 13:31:37
[x] [插入数据] [52024-04-21 13:31:37
[x] [发送邮件] [62024-04-21 13:31:37
[x] [插入数据] [62024-04-21 13:31:37
[x] [发送邮件] [72024-04-21 13:31:37
[x] [插入数据] [72024-04-21 13:31:37
[x] [发送邮件] [82024-04-21 13:31:37
[x] [插入数据] [82024-04-21 13:31:37
[x] [发送邮件] [92024-04-21 13:31:37
[x] [插入数据] [92024-04-21 13:31:37
[x] [发送邮件] [102024-04-21 13:31:37
[x] [插入数据] [102024-04-21 13:31:37
[x] [插入数据] [112024-04-21 13:31:37
[x] [插入数据] [122024-04-21 13:31:37
[x] [插入数据] [132024-04-21 13:31:37
[x] [插入数据] [142024-04-21 13:31:37
[x] [插入数据] [152024-04-21 13:31:37

为什么要用sleep挂起协程实现切换呢?因为swoole的协程是自动的,当协程内遇上I/O操作(mysql,redis)等时,swoole的协程会自动切换,运行到下一个协程任务中(切换后,I/O继续执行),直到下一个协程任务完成或者被切换(遇上I/O),如此反复,直到所有协程任务完成,则任务完成。

MySQL 一键协程化

<?php

use function SwooleCoroutinerun;
use function SwooleCoroutinego;

run(function () {
    go(function () {
        $pdo = new PDO('mysql:host=192.168.3.29;port=3308;dbname=nacos;charset=utf8''root''123456');
        $statement = $pdo->prepare('SELECT * FROM `users`');
        $statement->execute();
        var_dump($statement->fetchAll());
    });
    go(function () {
        $mysqli = new mysqli('192.168.3.29''root''123456''webman-admin'3308);
        $mysqli->set_charset('utf8mb4');
        var_dump($mysqli);
    });
});

执行结果

array(1) {
  [0]=>
  array(6) {
    ["username"]=>
    string(5) "nacos"
    [0]=>
    string(5) "nacos"
    ["password"]=>
    string(60) "$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu"
    [1]=>
    string(60) "$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu"
    ["enabled"]=>
    int(1)
    [2]=>
    int(1)
  }
}
object(mysqli)#6 (18) {
  ["affected_rows"]=>
  int(0)
  ["client_info"]=>
  string(14) "mysqlnd 8.2.17"
  ["client_version"]=>
  int(80217)
  ["connect_errno"]=>
  int(0)
  ["connect_error"]=>
  NULL
  ["errno"]=>
  int(0)
  ["error"]=>
  string(0) ""
  ["error_list"]=>
  array(0) {
  }
  ["field_count"]=>
  int(0)
  ["host_info"]=>
  string(23) "192.168.3.29 via TCP/IP"
  ["info"]=>
  NULL
  ["insert_id"]=>
  int(0)
  ["server_info"]=>
  string(6) "5.7.36"
  ["server_version"]=>
  int(50736)
  ["sqlstate"]=>
  string(5) "00000"
  ["protocol_version"]=>
  int(10)
  ["thread_id"]=>
  int(104)
  ["warning_count"]=>
  int(0)
}

致谢: 感谢 Workerman 和 Swoole 开发团队为 PHP 社区带来的创新和卓越贡献,让我们共同期待 PHP 在实时应用领域的更多突破。

参考

  • https://www.easyswoole.com/NoobCourse/coroutine.html
  • https://wiki.swoole.com/#/runtime


原文始发于微信公众号(开源技术小栈):workerman5.0 和 swoole5.0 实现一键协程

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/284575.html

(0)
李, 若俞的头像李, 若俞

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!