官方建议分离 workerman和mvc框架的结合,我去,这不是有点脑缺氧吗?
大量的业务逻辑,去独立增加方法和类库在写一次,实际业务中是不现实和不实际的
gateway增加一些这方面的工作,但是我看了源码之后,就发现还是只能自己做
先增加composer require workerman/workerman 或者walkor/workerman ,但是官方的github是 walkor/workerman,注意一下
可以去 https://packagist.org查看是否有包
首先结合Console做命令
建立一个Command
<?php namespace App\Console\Commands; use Illuminate\Console\Command;
use Workerman\Worker;
use App\Work\WorkermanWork; class Workerman extends Command { protected $taskserver;
/*
* 操作参数
* 注意只能在
* start 启动
* stop 停止
* relaod 只能重启逻辑代码,核心workerman_init无法重启,注意看官方文档
* status 查看状态
* connections 查看连接状态(需要Workerman版本>=3.5.0)
*
*/
protected $action = array('start', 'stop', 'reload', 'status', 'connections'); /**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'Workerman {action}'; /**
* The console command description.
*
* @var string
*/
protected $description = 'Workerman'; /**
* Create a new command instance.
*
* @return void
*/
public function __construct() {
parent::__construct();
} /**
* Execute the console command.
*
* @return mixed
*
* 注意
*
*/
public function handle() {
$action = $this->argument('action'); if (!in_array($action, $this->action)) {
$this->error('Error Action');
exit;
}
//初始化workerman
WorkermanWork::workerman_init($action);
} }
注册到Kernel
class Kernel extends ConsoleKernel { /**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [ \App\Console\Commands\Workerman::class,
];
WorkermanWork的内容
<?php namespace App\Work; use App\Work\BaseWork as Base;
use Illuminate\Support\Facades\DB;
use App\Work\CommonWork;
use Workerman\Worker;
use Workerman\Lib\Timer;
use App\Models\OperationLog;
use App\Models\Users; class WorkermanWork extends Base { static $connection_count = 0; public static function workerman_init($action = null) {
global $argv; $argv[0] = 'workerman:websocket';
$argv[1] = $action;
$argv[2] = '-d';
// 心跳
define('HEARTBEAT_TIME', 30);
//初始化
$worker = new Worker("websocket://172.17.1.247:9099");
$worker->name = 'MessagePushWorker';
//linux 用户线上是www
// $worker->user = 'www';
//守护模式信息输出文件地址
// $worker->stdoutFile = "./workerman.log";
//工作进程总数 测试环境4个
$worker->count = 4;
//正式环境
// $ws->count = 10;
//建立链接 处理逻辑
$worker->onConnect = function($connection) {
// 有新的客户端连接时,连接数+1
self::$connection_count++;
self::onConnect($connection);
};
//接受消息 处理逻辑
$worker->onMessage = function($connection, $data) { self::onMessage($connection, $data);
};
//关闭链接 处理逻辑
$worker->onClose = function($connection) {
// 客户端关闭时,连接数-1
self::$connection_count--;
self::onClose($connection);
}; // 进程启动后设置一个30秒运行一次的定时器
// $worker->onWorkerStart = function($worker) {
// Timer::add(30, function()use($worker) {
//
// });
// };
// 开始
Worker::runAll();
} //建立链接 处理逻辑
public static function onConnect($connection) {
//测试5秒一次 线上30秒一次
Timer::add(10, function() use($connection) { if (!empty($_SESSION['user_id'])) {
$Users = Users::where('id', $_SESSION['user_id'])->first();
if (!empty($Users)) {
$message_count = OperationLog::where('user_id', $_SESSION['user_id'])->where('is_read', 1)->count();
$message_list = OperationLog::where('user_id', $_SESSION['user_id'])->where('is_read', 1)->orderBy('id', 'desc')->get(['content', 'id', 'create_time'])->toArray(); if (!empty($message_list)) {
$connection->send(json_encode(['code' => 200, 'msg' => '请求成功', 'data' => $message_list, 'connections' => self::$connection_count, 'message_count' => $message_count]));
}
}
// else {
// $connection->send(json_encode(['code' => 201, 'msg' => '无效user_id', 'connections' => self::$connection_count]));
// }
}
// else {
// $retrun_data = json_encode(['code' => 201, 'msg' => 'session user_id不存在', 'connections' => self::$connection_count]);
// $connection->send($retrun_data);
// }
});
} //接受消息 处理逻辑
public static function onMessage($connection, $data) {
//解析数据,非合法的json数据不处理
if (!empty($data)) {
if (is_json($data)) {
$data = json_decode($data, true);
switch ($data['type']) {
// 客户端回应服务端的心跳
case 'ping':
$connection->send(json_encode(['code' => 200, 'msg' => '服务存活', 'data' => [], 'connections' => self::$connection_count]));
case 'login':
$Users = Users::where('id', $data['user_id'])->first();
if (empty($Users)) {
$connection->send(json_encode(['code' => 201, 'msg' => '用户ID无效或者错误', 'data' => [], 'connections' => self::$connection_count]));
} else {
$_SESSION['user_id'] = $data['user_id'];
$connection->send(json_encode(['code' => 200, 'msg' => '登录成功', 'data' => [], 'connections' => self::$connection_count]));
}
}
}
} else {
$connection->send(json_encode(['code' => 201, 'msg' => '数据请求为空', 'data' => [], 'connections' => self::$connection_count]));
} // $data = $data . '----总共有连接数:' . self::$connection_count;
// $connection->send("return_data: $data ");
} //关闭链接 处理逻辑
public static function onClose($connection) { } }
建立socket的时间设置一个10秒的定时器,这个基于session的控制,登录之后立即请求发送
{"type":"login","user_id":"24"}
因为如果登录,就检索OperationLog表里属于这个用户ID的消息,每10秒推送一次数据
运行 命令
php artisan Workerman start 启动
$argv[2] = '-d';
注释掉就是测试模式,加上就是守护模式,就是线上使用的
2019年7月12日09:43:56
注意:上面是临时测试代码。业务代码使用try catch处理异常和错误
laravel整合workerman做消息推送系统的更多相关文章
-
MPush开源消息推送系统:简洁、安全、支持集群
引言由于之前自己团队需要一个消息推送系统来替换JPUSH,一直找了很久基本没有真正可用的开源系统所有就直接造了个*,造*的时候就奔着开源做打算的,只是后来创业项目失败一直没时间整理这一套代码,最近 ...
-
开源实时消息推送系统 MPush
系统介绍 mpush,是一款开源的实时消息推送系统,采用java语言开发,服务端采用模块化设计,具有协议简洁,传输安全,接口流畅,实时高效,扩展性强,可配置化,部署方便,监控完善等特点.同时也是少有的 ...
-
laravel整合workerman做聊天室
测试工具 http://www.blue-zero.com/WebSocket/ 2018年8月6日17:28:24 <?php namespace App\Console\Commands; ...
-
【转】SpringMVC整合websocket实现消息推送及触发
1.创建websocket握手协议的后台 (1)HandShake的实现类 /** *Project Name: price *File Name: HandShake.java *Packag ...
-
laravel 5.8 实现消息推送
以下教程是基于5.6 的,在使用5.8实现时遇到一些问题,做一下记录 在我看来,实时通信才是 APP 应用的将来. Socket 服务通常不是那么容易实现,但是 Laravel Echo 服务改变了这 ...
-
netty-socketio整合springboot消息推送
netty-socketio整合springboot消息推送 1.netty-socketio消息推送 1)在项目中常常涉及到消息推送的情况,消息推送要求的实时性,使用传统的方式已经不能满足需求了: ...
-
了解iOS消息推送一文就够:史上最全iOS Push技术详解
本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表. 1.引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ.微信等IM界面处于前台时,聊天消息和指 ...
-
Android P正式版即将到来:后台应用保活、消息推送的真正噩梦
1.前言 对于广大Android开发者来说,Android O(即Android 8.0)还没玩热,Andriod P(即Andriod 9.0)又要来了. 下图上谷歌官方公布的Android P ...
-
基于APNs最新HTTP/2接口实现iOS的高性能消息推送(服务端篇)
1.前言 本文要分享的消息推送指的是当iOS端APP被关闭或者处于后台时,还能收到消息/信息/指令的能力. 这种在APP处于后台或关闭情况下的消息推送能力,通常在以下场景下非常有用: 1)IM即时通讯 ...
随机推荐
-
ORACLE解决登陆em状态暂挂方法
1.找到oracle安装目录中db_1/计算机名_orcl/sysman/config/emd.properties , 用记事本打开emd.properties,在emd.properties文件 ...
-
导hive表项目总结(未完待续)
shell里面对日期的操作 #!/bin/bash THIS_FROM=$(date +%Y%m%d -d "-7 day") THIS_TO=$(date +%Y-%m-%d - ...
-
剑指Offer 59. 按之字形顺序打印二叉树 (二叉树)
题目描述 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推. 题目地址 https://www.nowco ...
-
js类型----你所不知道的JavaScript系列(5)
ECMAScirpt 变量有两种不同的数据类型:基本类型,引用类型.也有其他的叫法,比如原始类型和对象类型等. 1.内置类型 JavaScript 有七种内置类型: • 空值(null) • 未定义( ...
-
epoll_wait 时 POLLERR 与 POLLIN 同时返回的现象解析(转)
今天code review时,同事B对我代码中的poll()的处理做法提出了异议.于是做了些研究,还发现了一些好玩的故事. 异议的代码 我的代码是参考manpage写的,类似下面的做法.同事B说没有处 ...
-
Loopback接口用途---用作管理地址。
Loopback接口的优点是永远不会down点,不管是链路断开还是网卡损坏.因而loopback接口有很高健壮性. 但是loopback并非实际网口,外部设备要与该口通信,必须经过实际口的路由实现. ...
-
【Ctsc2011】幸福路径
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2306 给定一张有向图,每个点有权值,蚂蚁从某个节点出发,初始体力值为$1$,每走一条边$体 ...
-
selenium-java,启动谷歌浏览器和火狐浏览器
selenium3.4.0-java,启动谷歌浏览器和火狐浏览器-------------------------------------------------------------------- ...
-
java 内存管理机制
垃圾收集算法 1.标记清理算法:效率不高(标记和清理过程效率都不高).会形成内存碎片 2.复制算法:把内存分为两部分,当进行回收时,把使用部分的存活对象复制到未使用部分,然后两部分内存角色互换(一个为 ...
-
arcgis jsapi接口入门系列(8):鼠标在地图画面
初始化,每个map执行一次 PS:画点也差不多,都是用SketchViewModel,因此本demo没有专门写画点的 drawPolygonInit: function () { //画几何对象初始化 ...