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扩展函数
Oct 09 PHP
php面向对象全攻略 (七) 继承性
Sep 30 PHP
Linux下实现PHP多进程的方法分享
Aug 16 PHP
浅析PKI加密解密 OpenSSL
Jul 01 PHP
smarty模板引擎基础知识入门
Mar 30 PHP
discuz图片顺序混乱解决方案
Jul 29 PHP
CI框架常用经典操作类总结(路由,伪静态,分页,session,验证码等)
Nov 21 PHP
php 运算符与表达式详细介绍
Nov 30 PHP
老生常谈PHP位运算的用途
Mar 12 PHP
CI框架(CodeIgniter)操作redis的方法详解
Jan 25 PHP
微信支付之JSAPI公众号支付详解
May 15 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
Apr 05 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
虫族 ZERG 概述
2020/03/14 星际争霸
jQuery 源码分析笔记
2011/05/25 PHP
ThinkPHP查询中的魔术方法简述
2014/06/25 PHP
ThinkPHP做文字水印时提示call an undefined function exif_imagetype()解决方法
2014/10/30 PHP
PHP中的表达式简述
2016/05/29 PHP
js 加载并解析XML字符串的代码
2009/12/13 Javascript
js 多种变量定义(对象直接量,数组直接量和函数直接量)
2010/05/24 Javascript
javascript instanceof 内部机制探析
2010/10/15 Javascript
一个简单的JavaScript数据缓存系统实现代码
2010/10/24 Javascript
再论Javascript的类继承
2011/03/05 Javascript
JQuery入门——用one()方法绑定事件处理函数(仅触发一次)
2013/02/05 Javascript
js设置cookie过期及清除浏览器对应名称的cookie
2013/10/24 Javascript
jquery显示loading图片直到网页加载完成的方法
2015/06/25 Javascript
CSS中position属性之fixed实现div居中
2015/12/14 Javascript
JavaScript模拟鼠标右键菜单效果
2020/12/08 Javascript
JavaScript的this关键字的理解
2016/06/18 Javascript
使用jquery/js获取iframe父子级、同级获取元素的方法
2016/08/05 Javascript
微信小程序之页面拦截器的示例代码
2017/09/07 Javascript
js+css3实现简单时钟特效
2020/09/13 Javascript
Python进阶-函数默认参数(详解)
2017/05/18 Python
Python实现向服务器请求压缩数据及解压缩数据的方法示例
2017/06/09 Python
Python处理中文标点符号大集合
2018/05/14 Python
python实现人机猜拳小游戏
2020/02/03 Python
Python GUI库PyQt5图形和特效样式QSS介绍
2020/02/25 Python
python如何随机生成高强度密码
2020/08/19 Python
Pycharm的Available Packages为空的解决方法
2020/09/18 Python
python re的findall和finditer的区别详解
2020/11/15 Python
ivx平台开发之不用代码实现一个九宫格抽奖功能
2021/01/27 HTML / CSS
欧洲最大的笔和书写专家:The Pen Shop
2017/03/19 全球购物
Meli Melo官网:名媛们钟爱的英国奢侈手包品牌
2017/04/17 全球购物
园林专业毕业生自荐信
2014/07/04 职场文书
学校党风廉政建设调研报告
2015/01/01 职场文书
服务员岗位职责
2015/02/03 职场文书
乡镇安全生产月活动总结
2015/05/08 职场文书
2015年社区精神文明工作总结
2015/05/26 职场文书
Nginx本地配置SSL访问的实例教程
2022/05/30 Servers