laravel整合workerman做消息推送系统
官方建议分离 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界面处于前台时,聊天消息和指 ...
- 我有 7种 实现web实时消息推送的方案,7种!
技术交流,公众号:程序员小富 大家好,我是小富- 我有一个朋友- 做了一个小破站,现在要实现一个站内信web消息推送的功能,对,就是下图这个小红点,一个很常用的功能. 不过他还没想好用什么方式做,这里 ...
- Android P正式版即将到来:后台应用保活、消息推送的真正噩梦
1.前言 对于广大Android开发者来说,Android O(即Android 8.0)还没玩热,Andriod P(即Andriod 9.0)又要来了. 下图上谷歌官方公布的Android P ...
随机推荐
- shell 批量检测远程端口
[DNyunwei@YZSJHL24-209 li]$ cat port.sh #!/bin/bash # ip=`cat iplist` for i in $ip;do port=`ssh -t $ ...
- Leetcode#70. Climbing Stairs(爬楼梯)
题目描述 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数. 示例 1: 输入: 2 输出: 2 解 ...
- day14 集合与函数
数据类型和变量总结 字符串.数字.列表.元组.字典 可变:列表,字典 不可变:修改变量的值ID变,字符串,数字,元组 访问顺序: 直接访问:数字 顺序访问:字符串,列表,元组 映射:字典 存放元素个数 ...
- JavaScript高级程序设计(读书笔记)(一)
本笔记汇总了作者认为“JavaScript高级程序设计”这本书的前七章知识重点,仅供参考. 第一章 JavaScript简介 JavaScript发展简史: 1995年,JavaScript诞生 19 ...
- 【原创】大叔问题定位分享(19)spark task在executors上分布不均
最近提交一个spark应用之后发现执行非常慢,点开spark web ui之后发现卡在一个job的一个stage上,这个stage有100000个task,但是绝大部分task都分配到两个execut ...
- git命令之git remote的用法
git remote git remote -v git init git add xxx git commit -m 'xxx' git remote add origin ssh://softw ...
- vue项目移植tinymce踩坑
转载:https://segmentfault.com/a/1190000012791569?utm_source=tag-newest 2019-2-18 貌似这篇文章帮了大家一些小忙最近tinym ...
- Java集合实现
set: public class BSTSet<E extends Comparable<E>> implements Set<E> { private BST& ...
- net core体系-web应用程序-4asp.net core2.0 项目实战(1)-13基于OnActionExecuting全局过滤器,页面操作权限过滤控制到按钮级
1.权限管理 权限管理的基本定义:百度百科. 基于<Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员.后台管理员同时登录>我们做过了登录认证, ...
- VMware虚拟机下安装ubuntu操作系统
安装tools: