immusen 2019-03-01 14:55:37 6209次浏览 8条评论 8 5 0

https://github.com/immusen/yii2-swoole-websocket

支持通过websocket、http、redis publish发送JSONRPC触发swoole worker执行异步任务和即时通信

示例:

聊天室案例, 示例代码: /websocket/controllers/RoomController.php

发送消息:

{
        "jsonrpc":"2.0",
        "id":1,
        "method":"room/msg",
        "params":{
            "id":"100111",
            "content":{
                "text":"Hello world!"
            }
        }
    }

聊天室成员接收消息:

{
        "jsonrpc":"2.0",
        "id":1,
        "result":{
            "text":"Hello world!"
        }
    }

开发:

1, 在websocket/controllers目录下创建Controller, (也可以是其它路径, 只需修改config/main.php中controllerNamespace配置)

<?php
namespace websocket\controllers;

use immusen\websocket\src\Controller;

class FooController extends Controller
{
     public function actionBar($param_1, $param_2 = 0, $param_n = null)
     {
          #  addFds把当前客户端fd存储到一个集合, $param_1作为Key(其它字符串亦可)
          $this->joinGroup($this->fd, $param_1);
          
          # 向当前websocket客户端发送信息
          $this->publish($this->fd, ['p1' => $param_1, 'p2' => $param_2]);
          
          # 从集合中取出所有客户度fd
          $fds_array = $this->getFds($param_1);
          
          # 群发消息给集合中的客户端
          $this->publish($fds_array, ['p1' => $param_1, 'p2' => $param_2]);
          #或
          $this->sendToGroup(['p1' => $param_1, 'p2' => $param_2], $param_1);
          
          # 通过redis连接池操作redis
          $this->redis->set($param_1, 0)
     }
}

2, 发送JSONRPC, 并指定method为"foo/bar"即可调用上述action

    {
        "jsonrpc":"2.0",
        "id":1,
        "method":"foo/bar",
        "params":{
            "param_1":"client_01",
            "param_2":100,
            "param_n":{
                "time":1551408888,
                "type":"report"
            }
        }
    }

所有的客户端到服务器的RPC调用, 除用websocket客户端之外, 也可以使用HTTP或Redis Publish来投递, 该特性可以用于Yii Web应用向Swoole worker投递异步任务(例如发短信..), 在聊天室例子中, 可以这样操作:

HTTP 请求:

http://127.0.0.1:8721/rpc?p={"jsonrpc":"2.0","id":1,"method":"room/msg","params":{"id":"100111","content":{"text":"System warning!"}}}

或 redis-cli:

127.0.0.1:6379> publish rpc '{"jsonrpc":"2.0","id":1,"method":"room/msg","params":{"id":"100111","content":{"text":"System warning!"}}}'

或 在Yii web 应用中

Yii:$app->redis->publish('rpc', '{"jsonrpc":"2.0","id":1,"method":"room/msg","params":{"id":"100111","content":{"text":"System warning!"}}}')

或通过Hook(推荐方式), 支持runOnce, 确保任务即使在多Swoole实例/分布式的情况下只执行一次, 详见immusen/yii2-swoole-websocket/Hook.php

Yii::$app->hook->run('room/msg', ['id' => 100111, 'content' => ['text' => 'System warning!']]);

升级中, 可能继续新增http session, auth, 丰富配置, 以及简化web app向swoole worker投递异步任务机制...

觉得很赞
  • 评论于 2019-03-16 20:03 举报

    大佬今天我用了下,貌似这个是高级版的,没有基础版的吗。。
    启动服务就报错了

    想着注释掉,但是引用的太多了,都不知道路径,麻烦大佬出个基础版的吧,

    21.png

    123.png

  • 评论于 2019-03-16 23:10 举报

    没用基础版版测试,但简单来说,你可以这么干,把配置文件都挪出来放到启动脚本websocket-server里:

    #!/usr/bin/env php
    <?php
    
    defined('YII_DEBUG') or define('YII_DEBUG', true);
    defined('YII_ENV') or define('YII_ENV', 'dev');
    defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
    defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
    defined('STDERR') or define('STDERR', fopen('php://stderr', 'w'));
    
    require __DIR__ . '/vendor/autoload.php';
    require __DIR__ . '/vendor/yiisoft/yii2/Yii.php';
    
    //require __DIR__ . '/common/config/bootstrap.php';
    //require __DIR__ . '/websocket/config/bootstrap.php';
    //$config = yii\helpers\ArrayHelper::merge(
    //    require __DIR__ . '/common/config/main.php',
    //    require __DIR__ . '/common/config/main-local.php',
    //    require __DIR__ . '/websocket/config/main.php',
    //    require __DIR__ . '/websocket/config/main-local.php'
    //);
    
    Yii::setAlias('@immusen/websocket', __DIR__ . '/vendor/immusen/yii2-swoole-websocket');
    Yii::setAlias('@websocket', __DIR__ . '/websocket');
    $config = [
        'id' => 'websocket',
        'basePath' => __DIR__ . '/websocket',
        'bootstrap' => ['log'],
        'controllerNamespace' => 'websocket\controllers',
        'components' => [
            'errorHandler' => ['class' => 'yii\console\ErrorHandler'],
            'log' => [
                'targets' => [
                    [
                        'class' => 'yii\log\FileTarget',
                        'levels' => ['error', 'warning'],
                    ],
                ],
            ],
        ],
        'params' => [
            'listen' => 8721,
            'daemonize' => 0,
            'redis' => [
                'host' => '127.0.0.1',
                'port' => '6379',
    //        'auth' => 'passwd',
                'pool_size' => 10,
            ],
        ],
    ];
    
    $application = new immusen\websocket\Application($config);
    $exitCode = $application->run();
    exit($exitCode);
    
    
    1 条回复
    评论于 2019-03-17 06:40 回复

    谢谢回复。

  • 评论于 2019-03-31 22:07 举报

    新升级:启动脚本支持更多操作

    ./websocket-server {start|restart|reload|stop|status}
    
    ./websocket-server status
    master_pid=7404
    start_time=1554030075
    connection_num=130
    accept_count=1025767
    close_count=1025637
    tasking_num=123
    request_count=2051456
    worker_request_count=511103
    coroutine_num=2
    
  • 评论于 2019-04-26 12:23 举报

    感谢大神的解答,已经用此功能完成了一个小任务了,成就感满满,特此感谢!

    3 条回复
    评论于 2019-04-26 13:06 回复

    你就是最近经常邮件提问那位吧?任务成功了、技能提升了,很好!我也分享到了你的成就感...😄

    评论于 2019-04-26 15:08 回复

    是的,是我,是我~
    期待有机会继续跟您讨论技术问题,开心!~

    评论于 2019-04-26 18:07 回复

    Ok,没问题..

  • 评论于 2019-06-17 18:06 举报

    请问这个的应用场景是什么,是内部服务调用吗 比如分布式系统下的服务互相调用

    1 条回复
    评论于 2019-06-19 15:44 回复

    主要就是websocket服务端,其次是可以执行一些异步任务比如发短信, jsonrpc只是一个通用的约定,让其它应用可以轻易向这个应用发指令,然后通过将指令和参数反射到controller/action,简化业务开发。基本上GatewayWorker能干的事情,这个扩展也能干...

  • 评论于 2019-07-20 02:32 举报

    请问为什么找不到 use Swoole\Websocket\Server 这个类呢?Swoole 也安装了啊,谢谢🙏

    1 条回复
    评论于 2019-07-22 15:09 回复

    运行php --ri swoole 看下输出,确定swoole是否安装好,版本号是否4+, swoole.use_namespace => On是否开启了使用命名空间。

  • 评论于 2019-07-29 22:41 举报

    您好,请问一下,我在 Yii2 下使用,但是会导致服务器 CPU 爆表然后死机,请问是哪里需要特别设置吗?服务器 4核CPU 16GB 内存,谢谢🙏
    服务器内使用 docker, nginx-yii2 框架。
    请问这个 docker 的 web root 可以设置在 websocket 这个目录吗?

  • 评论于 2019-08-05 19:19 举报

    开始服务器后,内存会一直增加,然后服务器就挂了?
    短短显示出 #client closed 高达 100多亿,然后服务器就挂了...

    1 条回复
    评论于 2019-08-08 10:50 回复

    在什么环境下测试的呢? 确有那么多client连接嘛?

您需要登录后才可以评论。登录 | 立即注册