Yii2结合Workerman的websocket示例详解


Posted in PHP onSeptember 10, 2018

前言

本文主要给大家介绍了关于Yii2结合Workerman的websocket的相关内容,两者都是好东西,我就想着能不能结合起来,这样Yii2出现瓶颈的时候有些业务就可以平滑地迁移到Workerman中。下面话不多说了,来随着小编来一起看看详细的介绍吧

步骤如下

1、安装workerman

composer require workerman/workerman

2、启动workerman

创建commands/WorkermanWebSocketController.php文件

创建actionIndex()函数,用来启动,代码如下

public function actionIndex()
{
 if ('start' == $this->send) {
 try {
  $this->start($this->daemon);
 } catch (\Exception $e) {
  $this->stderr($e->getMessage() . "\n", Console::FG_RED);
 }
 } else if ('stop' == $this->send) {
 $this->stop();
 } else if ('restart' == $this->send) {
 $this->restart();
 } else if ('reload' == $this->send) {
 $this->reload();
 } else if ('status' == $this->send) {
 $this->status();
 } else if ('connections' == $this->send) {
 $this->connections();
 }
}

添加初始化模块

public function initWorker()
{
 $ip = isset($this->config['ip']) ? $this->config['ip'] : $this->ip;
 $port = isset($this->config['port']) ? $this->config['port'] : $this->port;
 $wsWorker = new Worker("websocket://{$ip}:{$port}");

 // 4 processes
 $wsWorker->count = 4;

 // Emitted when new connection come
 $wsWorker->onConnect = function ($connection) {
 echo "New connection\n";
 };

 // Emitted when data received
 $wsWorker->onMessage = function ($connection, $data) {
 // Send hello $data
 $connection->send('hello ' . $data);
 };

 // Emitted when connection closed
 $wsWorker->onClose = function ($connection) {
 echo "Connection closed\n";
 };
}

添加启动模块

/**
 * workman websocket start
 */
public function start()
{
 $this->initWorker();
 // 重置参数以匹配Worker
 global $argv;
 $argv[0] = $argv[1];
 $argv[1] = 'start';
 if ($this->daemon) {
 $argv[2] = '-d';
 }

 // Run worker
 Worker::runAll();
}

添加停止模块

/**
 * workman websocket stop
 */
public function stop()
{
 $this->initWorker();
 // 重置参数以匹配Worker
 global $argv;
 $argv[0] = $argv[1];
 $argv[1] = 'stop';
 if ($this->gracefully) {
 $argv[2] = '-g';
 }

 // Run worker
 Worker::runAll();
}

添加重启模块

/**
 * workman websocket restart
 */
public function restart()
{
 $this->initWorker();
 // 重置参数以匹配Worker
 global $argv;
 $argv[0] = $argv[1];
 $argv[1] = 'restart';
 if ($this->daemon) {
 $argv[2] = '-d';
 }

 if ($this->gracefully) {
 $argv[2] = '-g';
 }

 // Run worker
 Worker::runAll();
}

添加重载模块

/**
 * workman websocket reload
 */
public function reload()
{
 $this->initWorker();
 // 重置参数以匹配Worker
 global $argv;
 $argv[0] = $argv[1];
 $argv[1] = 'reload';
 if ($this->gracefully) {
 $argv[2] = '-g';
 }

 // Run worker
 Worker::runAll();
}

添加状态模块

/**
 * workman websocket status
 */
public function status()
{
 $this->initWorker();
 // 重置参数以匹配Worker
 global $argv;
 $argv[0] = $argv[1];
 $argv[1] = 'status';
 if ($this->daemon) {
 $argv[2] = '-d';
 }

 // Run worker
 Worker::runAll();
}

添加链接数模块

/**
 * workman websocket connections
 */
public function connections()
{
 $this->initWorker();
 // 重置参数以匹配Worker
 global $argv;
 $argv[0] = $argv[1];
 $argv[1] = 'connections';

 // Run worker
 Worker::runAll();
}

3、前端调用

<script>
 // Create WebSocket connection.
 const ws = new WebSocket('ws://{{ app.request.hostName }}:2347/'); // 这里是获取的网站的域名,测试的时候可以改为自己的本地的ip地址

 // Connection opened
 ws.addEventListener('open', function (event) {
 ws.send('Hello Server!');
 });

 // Listen for messages
 ws.addEventListener('message', function (event) {
 console.log('Message from server ', event.data);
 });

 setTimeout(function() {
 ws.send('ssssss');
 }, 10000);

</script>

4、config参数配置

修改console.php并添加如下代码

'controllerMap' => [
 'workerman-web-socket' => [
 'class' => 'app\commands\WorkermanWebSocketController',
 'config' => [
  'ip' => '127.0.0.1',
  'port' => '2346',
  'daemonize' => true,
 ],
 ],
],

5、nginx配置

为什么会用 nginx, 我们正常部署上线是不可能直接使用ip的,这个户存在安全隐患,最好是绑定一个域名

server {
 charset utf-8;
 client_max_body_size 128M;

 listen 2347;

 server_name www.gowhich.com; # 这里改为自己的域名

 access_log /xxx.workerman.access.log; # 换成自己服务器的nginx日志路径
 error_log /xxx.workerman.error.log; # 换成自己服务器的nginx日志路径

 location / {
 proxy_pass http://127.0.0.1:2346; # 代理2346 也可以根据项目配置为自己的端口

 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header Host $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

 proxy_http_version 1.1;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection "upgrade";
 }
}

重新nginx

nginx -s relad 或者 sudo nginx -s reload

然后将第3步的代码加入自己做的视图中,如果没有问题的话,websocket启动后就能正常通讯了。

6、启动workerman websocket

// 启动
./yii workerman-web-socket -s start -d

如果没有问题的话会得到类似如下的结果

$ ./yii workerman-web-socket -s start -d
Workerman[workerman-web-socket] start in DAEMON mode
----------------------- WORKERMAN -----------------------------
Workerman version:3.5.13   PHP version:7.1.16
------------------------ WORKERS -------------------------------
user   worker  listen      processes status
durban  none   websocket://127.0.0.1:2346 4   [OK] 
----------------------------------------------------------------
Input "php workerman-web-socket stop" to stop. Start success.

7、其他

commands/WorkermanWebSocketController.php 完整代码如下

<?php
/**
 * WorkmanWebSocket 服务相关
 */

namespace app\commands;

use Workerman\Worker;
use yii\console\Controller;
use yii\helpers\Console;

/**
 *
 * WorkermanWebSocket
 *
 * @author durban.zhang <durban.zhang@gmail.com>
 */

class WorkermanWebSocketController extends Controller
{
 public $send;
 public $daemon;
 public $gracefully;

 // 这里不需要设置,会读取配置文件中的配置
 public $config = [];
 private $ip = '127.0.0.1';
 private $port = '2346';

 public function options($actionID)
 {
  return ['send', 'daemon', 'gracefully'];
 }

 public function optionAliases()
 {
  return [
   's' => 'send',
   'd' => 'daemon',
   'g' => 'gracefully',
  ];
 }

 public function actionIndex()
 {
  if ('start' == $this->send) {
   try {
    $this->start($this->daemon);
   } catch (\Exception $e) {
    $this->stderr($e->getMessage() . "\n", Console::FG_RED);
   }
  } else if ('stop' == $this->send) {
   $this->stop();
  } else if ('restart' == $this->send) {
   $this->restart();
  } else if ('reload' == $this->send) {
   $this->reload();
  } else if ('status' == $this->send) {
   $this->status();
  } else if ('connections' == $this->send) {
   $this->connections();
  }
 }

 public function initWorker()
 {
  $ip = isset($this->config['ip']) ? $this->config['ip'] : $this->ip;
  $port = isset($this->config['port']) ? $this->config['port'] : $this->port;
  $wsWorker = new Worker("websocket://{$ip}:{$port}");

  // 4 processes
  $wsWorker->count = 4;

  // Emitted when new connection come
  $wsWorker->onConnect = function ($connection) {
   echo "New connection\n";
  };

  // Emitted when data received
  $wsWorker->onMessage = function ($connection, $data) {
   // Send hello $data
   $connection->send('dddd hello ' . $data);
  };

  // Emitted when connection closed
  $wsWorker->onClose = function ($connection) {
   echo "Connection closed\n";
  };
 }

 /**
  * workman websocket start
  */
 public function start()
 {
  $this->initWorker();
  // 重置参数以匹配Worker
  global $argv;
  $argv[0] = $argv[1];
  $argv[1] = 'start';
  if ($this->daemon) {
   $argv[2] = '-d';
  }

  // Run worker
  Worker::runAll();
 }

 /**
  * workman websocket restart
  */
 public function restart()
 {
  $this->initWorker();
  // 重置参数以匹配Worker
  global $argv;
  $argv[0] = $argv[1];
  $argv[1] = 'restart';
  if ($this->daemon) {
   $argv[2] = '-d';
  }

  if ($this->gracefully) {
   $argv[2] = '-g';
  }

  // Run worker
  Worker::runAll();
 }

 /**
  * workman websocket stop
  */
 public function stop()
 {
  $this->initWorker();
  // 重置参数以匹配Worker
  global $argv;
  $argv[0] = $argv[1];
  $argv[1] = 'stop';
  if ($this->gracefully) {
   $argv[2] = '-g';
  }

  // Run worker
  Worker::runAll();
 }

 /**
  * workman websocket reload
  */
 public function reload()
 {
  $this->initWorker();
  // 重置参数以匹配Worker
  global $argv;
  $argv[0] = $argv[1];
  $argv[1] = 'reload';
  if ($this->gracefully) {
   $argv[2] = '-g';
  }

  // Run worker
  Worker::runAll();
 }

 /**
  * workman websocket status
  */
 public function status()
 {
  $this->initWorker();
  // 重置参数以匹配Worker
  global $argv;
  $argv[0] = $argv[1];
  $argv[1] = 'status';
  if ($this->daemon) {
   $argv[2] = '-d';
  }

  // Run worker
  Worker::runAll();
 }

 /**
  * workman websocket connections
  */
 public function connections()
 {
  $this->initWorker();
  // 重置参数以匹配Worker
  global $argv;
  $argv[0] = $argv[1];
  $argv[1] = 'connections';

  // Run worker
  Worker::runAll();
 }
}

workerman websocket支持的其他命令

重启

$ ./yii workerman-web-socket -s restart -d
Workerman[workerman-web-socket] restart 
Workerman[workerman-web-socket] is stopping ...
Workerman[workerman-web-socket] stop success
----------------------- WORKERMAN -----------------------------
Workerman version:3.5.13   PHP version:7.1.16
------------------------ WORKERS -------------------------------
user   worker  listen      processes status
durban  none   websocket://127.0.0.1:2346 4   [OK] 
----------------------------------------------------------------
Input "php workerman-web-socket stop" to stop. Start success.

重载

$ ./yii workerman-web-socket -s reload 
Workerman[workerman-web-socket] reload

状态

$ ./yii workerman-web-socket -s status -g
Workerman[workerman-web-socket] status 
----------------------------------------------GLOBAL STATUS----------------------------------------------------
Workerman version:3.5.13   PHP version:7.1.16
start time:2018-09-10 11:22:15 run 0 days 0 hours 
load average: 1.79, 2, 2   event-loop:\Workerman\Events\Swoole
1 workers  4 processes
worker_name exit_status  exit_count
none   0    12
----------------------------------------------PROCESS STATUS---------------------------------------------------
pid memory listening     worker_name connections send_fail timers total_request qps status
8283 4M  websocket://127.0.0.1:2346 none   0   0   0  0    0  [idle]
8284 4M  websocket://127.0.0.1:2346 none   0   0   0  0    0  [idle]
8285 4M  websocket://127.0.0.1:2346 none   0   0   0  0    0  [idle]
8286 4M  websocket://127.0.0.1:2346 none   0   0   0  0    0  [idle]
----------------------------------------------PROCESS STATUS---------------------------------------------------
Summary 16M  -       -   0   0   0  0    0  [Summary]

连接数

./yii workerman-web-socket -s connections
Workerman[workerman-web-socket] connections 
--------------------------------------------------------------------- WORKERMAN CONNECTION STATUS --------------------------------------------------------------------------------
PID  Worker   CID  Trans Protocol  ipv4 ipv6 Recv-Q  Send-Q  Bytes-R  Bytes-W  Status   Local Address   Foreign Address

我这里暂时连接的,所以没有连接的信息

停止

$ ./yii workerman-web-socket -s stop   
Workerman[workerman-web-socket] stop 
Workerman[workerman-web-socket] is stopping ...
Workerman[workerman-web-socket] stop success

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
PHP写的加密函数,支持私人密钥(详细介绍)
Jun 09 PHP
PHP处理SQL脚本文件导入到MySQL的代码实例
Mar 17 PHP
PHP启动windows应用程序、执行bat批处理、执行cmd命令的方法(exec、system函数详解)
Oct 20 PHP
CentOS下PHP安装Oracle扩展
Feb 15 PHP
学习php设计模式 php实现命令模式(command)
Dec 08 PHP
php提交过来的数据生成为txt文件
Apr 28 PHP
CI框架实现cookie登陆的方法详解
May 18 PHP
Yii框架数据模型的验证规则rules()被执行的方法
Dec 02 PHP
thinkPHP框架动态配置用法实例分析
Jun 14 PHP
ThinkPHP框架实现定时执行任务的两种方法分析
Sep 04 PHP
PHP利用pdo_odbc实现连接数据库示例【基于ThinkPHP5.1搭建的项目】
May 13 PHP
ThinkPHP6.0如何利用自定义验证规则规范的实现登陆
Dec 16 PHP
PHP按符号截取字符串的指定部分的实现方法
Sep 10 #PHP
php 中htmlentities导致中文无法查询问题
Sep 10 #PHP
使用PHPExcel导出Excel表
Sep 08 #PHP
thinkPHP5.0框架事务处理操作简单示例
Sep 07 #PHP
thinkPHP5.0框架验证码调用及点击图片刷新简单实现方法
Sep 07 #PHP
php curl优化下载微信头像的方法总结
Sep 07 #PHP
Yii1.1框架实现PHP极光推送消息通知功能
Sep 06 #PHP
You might like
基于php验证码函数的使用示例
2013/05/03 PHP
PHP封装分页函数实现文本分页和数字分页
2014/10/23 PHP
Laravel Eloquent分表方法并使用模型关联的实现
2019/11/25 PHP
javascript中$(function() {});写与不写有哪些区别
2015/08/10 Javascript
Javascript实现快速排序(Quicksort)的算法详解
2015/09/06 Javascript
基于jQuery通过jQuery.form.js插件实现异步上传
2015/12/13 Javascript
所见即所得的富文本编辑器bootstrap-wysiwyg使用方法详解
2016/05/27 Javascript
JS实现可编辑的后台管理菜单功能【附demo源码下载】
2016/09/13 Javascript
Javascript从数组中随机取出不同元素的两种方法
2016/09/22 Javascript
easyUI实现(alert)提示框自动关闭的实例代码
2016/11/07 Javascript
微信JS-SDK自定义分享功能实例详解【分享给朋友/分享到朋友圈】
2016/11/25 Javascript
JS正则匹配中文的方法示例
2017/01/06 Javascript
浅谈原生JS中的延迟脚本和异步脚本
2017/07/12 Javascript
js实现轮播图的完整代码
2020/10/26 Javascript
Vue中 v-if 和v-else-if页面加载出现闪现的问题及解决方法
2018/10/12 Javascript
elementui之el-tebs浏览器卡死的问题和使用报错未注册问题
2019/07/06 Javascript
利用Python获取赶集网招聘信息前篇
2016/04/18 Python
利用Python开发实现简单的记事本
2016/11/15 Python
python cx_Oracle的基础使用方法(连接和增删改查)
2017/11/19 Python
python pandas生成时间列表
2019/06/29 Python
PyQt5中向单元格添加控件的方法示例
2020/03/24 Python
Python使用扩展库pywin32实现批量文档打印实例
2020/04/09 Python
python中逻辑与或(and、or)和按位与或异或(&amp;、|、^)区别
2020/08/05 Python
PyTorch中clone()、detach()及相关扩展详解
2020/12/09 Python
python 利用百度API识别图片文字(多线程版)
2020/12/14 Python
HTML5 解析规则分析
2009/08/14 HTML / CSS
日本最大化妆品和美容产品的综合口碑网站:cosme shopping
2019/08/28 全球购物
大学生开西餐厅创业计划书
2014/02/01 职场文书
户外婚礼策划方案
2014/02/08 职场文书
动漫专业高职生职业生涯规划书
2014/02/15 职场文书
分层教学实施方案
2014/03/19 职场文书
会计核算科岗位职责
2014/03/19 职场文书
2015年办公室人员工作总结
2015/05/15 职场文书
2015年党小组工作总结
2015/05/26 职场文书
使用Selenium实现微博爬虫(预登录、展开全文、翻页)
2021/04/13 Python
正确使用MySQL update语句
2021/05/26 MySQL