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 相关文章推荐
Mysql数据库操作类( 1127版,提供源码下载 )
Dec 02 PHP
php学习笔记 数组的常用函数
Jun 13 PHP
php实现单链表的实例代码
Mar 22 PHP
基于php验证码函数的使用示例
May 03 PHP
PHP内核探索:变量概述
Jan 30 PHP
php跨域cookie共享使用方法
Feb 20 PHP
php微信支付之APP支付方法
Mar 04 PHP
PHP中PDO连接数据库中各种DNS设置方法小结
May 13 PHP
深入理解php printf() 输出格式化的字符串
May 23 PHP
Yii数据模型中rules类验证器用法分析
Jul 15 PHP
PHP错误和异常处理功能模块示例
Nov 12 PHP
php使用正则表达式获取字符串中的URL
Dec 29 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
第十三节 对象串行化 [13]
2006/10/09 PHP
php递归函数中使用return的注意事项
2014/01/17 PHP
PHP中应该避免使用同名变量(拆分临时变量)
2015/04/03 PHP
PHP使用缓存即时输出内容(output buffering)的方法
2015/08/03 PHP
php5.3后静态绑定用法详解
2016/11/11 PHP
Web开发者必备的12款超赞jQuery插件
2010/12/03 Javascript
给Flash加一个超链接(推荐使用透明层)兼容主流浏览器
2013/06/09 Javascript
写得不错的jquery table鼠标经过变色代码
2013/09/27 Javascript
使用纯javascript实现放大镜效果
2015/03/18 Javascript
使用JavaScript 实现的人脸检测
2015/03/24 Javascript
jQuery实现的产品自动360度旋转展示特效源码分享
2015/08/21 Javascript
jquery 无限极下拉菜单的简单实例(精简浓缩版)
2016/05/31 Javascript
拖动时防止选中
2017/02/03 Javascript
JavaScript 数组的进化与性能分析
2017/09/18 Javascript
nodejs爬虫初试superagent和cheerio
2018/03/05 NodeJs
JS中的两种数据类型及实现引用类型的深拷贝的方法
2018/08/12 Javascript
JS实现换肤功能的方法实例详解
2019/01/30 Javascript
vue中uni-app 实现小程序登录注册功能
2019/10/12 Javascript
vue 实现特定条件下绑定事件
2019/11/09 Javascript
Python验证码识别的方法
2015/07/10 Python
从零开始学Python第八周:详解网络编程基础(socket)
2016/12/14 Python
在python3.5中使用OpenCV的实例讲解
2018/04/02 Python
Python模拟简单电梯调度算法示例
2018/08/20 Python
Python实现平行坐标图的两种方法小结
2019/07/04 Python
python中dict使用方法详解
2019/07/17 Python
Python环境Pillow( PIL )图像处理工具使用解析
2019/09/12 Python
Python生态圈图像格式转换问题(推荐)
2019/12/02 Python
TensorFlow学习之分布式的TensorFlow运行环境
2020/02/05 Python
详解基于Jupyter notebooks采用sklearn库实现多元回归方程编程
2020/03/25 Python
Python 炫技操作之合并字典的七种方法
2020/04/10 Python
Python3爬虫里关于识别微博宫格验证码的知识点详解
2020/07/30 Python
python快速安装OpenCV的步骤记录
2021/02/22 Python
使用Html5中的cavas画一面国旗
2019/09/25 HTML / CSS
Casetify官网:自制专属手机壳、iPad护壳和Apple Watch手表带
2018/05/09 全球购物
Travelstart沙特阿拉伯:廉价航班、豪华酒店和实惠的汽车租赁优惠
2019/04/06 全球购物
Python如何定义一个函数
2015/09/01 面试题