php高级 TP+Redis实现发布订阅和消息推送案例实战

7 篇文章 0 订阅

Redis 的发布-订阅模型是一种消息通信模式,它允许客户端之间通过特定的频道进行通信。在这种模型中,有些客户端负责发布消息(发布者),而其他客户端则订阅它们感兴趣的频道并接收这些消息(订阅者)。

以下是 Redis 发布订阅的基本操作:

  1. SUBSCRIBE:订阅者使用此命令订阅一个或多个频道的消息。
  2. PUBLISH:发布者使用此命令向指定的频道发送消息。
  3. UNSUBSCRIBE:订阅者使用此命令取消订阅一个或多个频道的消息。
  4. PUNSUBSCRIBE:订阅者使用此命令取消订阅所有频道的消息。

这种模型非常适合实现实时应用,如实时通知、实时分析、实时数据更新等。

第一步: 在index/controller文件中创建个控制器 Publish.php 文件

<?php
namespace app\mainapp\controller;

use app\mainapp\BaseController;
use think\cache\driver\Redis;
class Publish extends BaseController
{		
		protected $redis;
		
		public function __construct(){
			$redis = new Redis(Config::get('cache.stores.redis'));
			$redis->connect('127.0.0.1',6379);
			$this->redis = $redis;
			
		}
		
		//发布消息的控制器方法
		public function index()
		{
			
			//$this->redis->publish('频道名称','发布内容');
			//定义一个频道方法,往这个频道发布消息,频道名称:中英文都可以
			$res = $this->redis->publish('sixStar:index','发布内容');
			var_dump('发布订阅消息成功,接受者数量为:'.$res);
			
			//关闭
			$this->redis->close();
		}



		//订阅多个频道:
		//api
		public function api()
		{
			$this->redis->publish('sixStar:api','api平台开发专栏');
		}
		
		//swoole
		public function swoole()
		{
			$this->redis->publish('sixStar:swoole','swoole网络编程专栏');
		}
}

第二步 在项目 application/command.php中 加入一条指令,可参考 TP 添加定时任务 - 自定义指令

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: dqh <dqh@163.com>
// +----------------------------------------------------------------------

// +----------------------------------------------------------------------
// | 控制台配置
// +----------------------------------------------------------------------
return [
    // 指令定义
    'commands' => [
		'hello' => 'app\command\Subscribe',
    ],
];
<?php
/**
 * 自定义指令 - tp+redis实现发布订阅和消息推送
 */
namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\cache\driver\Redis;


class Subscribe extends Command
{
    protected function configure()
    {
        $this->setName('subscribe')->setDescription('接收订阅消息');
    }

    protected function execute(Input $input, Output $output)
    {
		
		$redis = new Redis();
			$redis->connect('127.0.0.1', 6379);
			
			//订阅这个频道,获取频道消息
			/*$res = $redis->subscribe(['sixStar:index'],function($instance,$channel,$message){//实例,频道,消息
				//$res = $redis->subscribe(['sixStar:index',''],function($instance,$channel,$message){//实例,频道,消息
				var_dump($message);
				//业务逻辑:发送短信,推送给用户等等
			});
			*/
			
			//匹配适应规则的所有的频道消息
			$res = $redis->psubscribe(['sixStar:*'],function($instance,$rule,$channel,$message){//实例,规则,频道,消息
				var_dump($message);
				//业务逻辑:发送短信,推送给用户等等
			});
			
        $output->writeln( date('Y-m-d H:i:s'));//输出内容
    }
}

第二步  执行

php think

 会有一条 subscribe 指令的命令

 php think subscribe

这样就订阅成功了
用postman 请求 Publish/index 发布消息的控制器方法 就能收到一条订阅 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个比较复杂的功能,需要涉及到多个模块的编写。下面是一个简单的示例代码,供您参考。 1. 首先是WebSocket的部分,我们可以使用Python的tornado框架来实现: ```python import tornado.web import tornado.websocket import tornado.ioloop import redis r = redis.Redis(host='localhost', port=6379, db=0) class WebSocketHandler(tornado.websocket.WebSocketHandler): def open(self): # 获取用户信息,将其作为Redis的key值 user_id = self.get_secure_cookie('user_id').decode('utf-8') self.user_id = user_id def on_close(self): pass def check_origin(self, origin): return True def on_message(self, message): # 接收到消息后,将其存入Redis,key为用户ID,value为消息内容 r.rpush(self.user_id, message) def make_app(): return tornado.web.Application([ (r'/ws', WebSocketHandler), ]) if __name__ == '__main__': app = make_app() app.listen(8000) tornado.ioloop.IOLoop.current().start() ``` 2. 接下来是Redis的部分,我们需要实现一个消息的函数,同时也需要实现一个获取离线消息的函数: ```python import redis r = redis.Redis(host='localhost', port=6379, db=0) def push_message(user_id, message): # 将消息到当前用户的WebSocket连接中 for conn in WebSocketHandler.connections: if conn.user_id == user_id: conn.write_message(message) def get_offline_message(user_id): # 获取当前用户的离线消息,并返回一个列表 messages = r.lrange(user_id, 0, -1) r.delete(user_id) return messages ``` 3. 最后,我们需要在适当的位置调用这些函数,来实现消息和离线消息的获取。例如,在用户登录后,我们可以调用`get_offline_message()`函数,获取用户的离线消息: ```python class LoginHandler(tornado.web.RequestHandler): def post(self): user_id = self.get_argument('user_id') self.set_secure_cookie('user_id', user_id) # 获取用户的离线消息,并到当前用户的WebSocket连接中 offline_messages = get_offline_message(user_id) for msg in offline_messages: push_message(user_id, msg) ``` 当用户收到新消息时,我们可以调用`push_message()`函数,将消息到当前用户的WebSocket连接中: ```python class SendMessageHandler(tornado.web.RequestHandler): def post(self): user_id = self.get_secure_cookie('user_id').decode('utf-8') message = self.get_argument('message') # 将消息到当前用户的WebSocket连接中 push_message(user_id, message) # 将消息存入Redis,供离线使用 r.rpush(user_id, message) ``` 这样,我们就完成了WebSocket+Redis实现消息机制以及离线消息的功能。当用户收到新消息时,会立即到其当前的WebSocket连接中;当用户下线后,未读的消息会存入Redis中,等用户再次登录时,会将其离线消息给用户。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值