文档章节

swoole应答式消息发送重试功能实现

吾爱
 吾爱
发布于 01/28 16:15
字数 690
阅读 107
收藏 1

用swoole做了个长连接TCP服务器,server和多台client之间交互是发送/应答的形式,这里面需要做一个消息重试机制,比如:

Server 发送一条消息 message_1 给 ClientA ,约定5秒重发一次,最多尝试3次,期间server如果收到 message_2 则自动取消重试。

首先想到的是,在发送message_1后,启动一个 swoole_timer_tick 定时器,设定间隔时间为5秒,同时将$timerId 保存到全局变量 array $timers 中例如:

//... 假设 $msg1 是一个封装的Msg对象,包含消息标识,数据等信息
$server->send($fd, $msg1->data);
//创建一个定时器
$timerID = \swoole_timer_tick(5000, function() use ($server,$fd,$msg1) {
    $server->send($fd,$msg1->data);
});
//保存$timerID, key是由fd和消息标识组成,保证每个连接每条消息的定时器不重复
$key = $fd.'_'.$msg1->id; //假设 id=1
$timers[$key] = $timerID;

当接收到消息的时候,清除定时器

$server->on('receive',function($server,$fd){
    global $timers;
     //解析消息过程略
    $key = $fd.'_1';
    if (isset($timers[$key])) {
        $server->clearTimer($key);
        unset($timers[$key]);
    }    
});

看起来没啥问题,但是首先需要知道一个重要的点:

定时器是进程隔离的!在一个woker进程中创建的定时器,哪怕把timerID存放到redis或者其他共享内存中,也无法在其他进程中通过timerID清除,在哪个进程中创建的定时器就必须在哪个进程中销毁。

不过幸运的是,如果你没有特别配置,swoole默认一个fd固定在一个woker上的,这里的代码并不会有什么问题。

但是如果在其他worker中主动向fd发送了一条消息,比如在运维端口下面 (多端口监听)向指定的client发送指定的消息,这时候由于执行发送程序是在运维的TCP链路上,并不一定和fd在同一个worker中,如果此时启动了定时器,但是接收消息的时候是在fd的worker中,clearTimer就会报错,定时器不存在,因为定时器是在运维worker中创建的。

这个问题困扰了我一天,甚至想过换语言,用go重写整个服务,去TMD恶心的进程间通信,最终还是找到了解决方法,用的是 pipeMessage。

大致步骤如下:

$server对象中有一个 woker_id 属性,当client连上来的时候可以把 fd,worker_id保存到 swoole_table或redis中。

然后发送消息封装一下,发送之前先判断一下当前worker_id和指定fd的worker_id是否一致,不一致则通过 $server->sendMessage() 发送给fd绑定的worker处理。

算是解决了这个问题吧。。。

© 著作权归作者所有

共有 人打赏支持
吾爱
粉丝 142
博文 265
码字总数 89754
作品 0
后端工程师
私信 提问
Apache ActiveMQ实战(1)-基本安装配置与消息类型

ActiveMQ简介 ActiveMQ是一种开源的,实现了JMS1.1规范的,面向消息(MOM)的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通信。ActiveMQ使用Apache提供的授权,任何人都...

lifetragedy
2016/07/06
0
0
swoole实现Timer定时器、心跳检测及Task进阶实例:mysql连接池

Table of Contents 1.Timer定时器 2.心跳检测 3.Task进阶:MySQL连接池 环境说明: 系统:Ubuntu14.04 (安装教程包括CentOS6.5) PHP版本:PHP-5.5.10 swoole版本:1.7.7-stable 1.Timer定时...

太阳黑子
2016/10/28
127
0
基于SWOOLE的分布式SOCKET消息服务器架构

消息服务器使用socket,为避免服务器过载,单台只允许500个socket连接,当一台不够的时候,扩充消息服务器是必然,问题来了,如何让链接在不同消息服务器上的用户可以实现消息发送呢? 要实现...

tomener
2016/06/16
339
0
PHP的异步并行扩展Swoole发布1.7版本

Swoole 1.7.0 发布了,该版本主要改进内容包括: reactor线程与writer线程合并 对send优化,加入out_buffer机制 增加AIO异步读写文件的API 增加DNS异步查询函数 swooleclient在php-fpm或apa...

matyhtf
2014/04/17
6K
39
swoole-1.8.0 发布,PHP 的异步并行 C 扩展

Swoole-1.8.0 版本已发布,此版本是一个里程碑式新版本,新增了多项新特性、多项核心功能优化以及问题修复、移除了无效的特性。更新内容如下: 客户端 增加原生异步 MySQL 客户端 增加原生异...

matyhtf
2016/01/27
3K
24

没有更多内容

加载失败,请刷新页面

加载更多

Nginx/Apache/PHP Hidden Version Number

nginx隐藏版本号的方法 在nginx配置文件nginx.conf中,加入以下代码: server_tokens off; apache隐藏版本号的方法 在apache配置文件httpd.conf中,加入以下代码: ServerTokens ProdServer...

Linux就该这么学
10分钟前
1
0
iOS 滚动视图 UIScrollView 代理方法 相关属性 状态栏 滚动条 回弹 弹簧效果

iOS 滚动视图 UIScrollView 代理方法 相关属性 状态栏 滚动条 回弹 弹簧效果 #import "ViewController.h"@interface ViewController () <span style="color:#ff0000;"><UIScrollViewDel......

壹峰
16分钟前
0
0
【转】Hive 工作原理详解

什么是Hive? Hive是建立在 Hadoop 上的数据仓库基础构架。它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储、查询和分析存储在 Hadoop 中的大规模数据的机制。...

hnairdb
16分钟前
1
0
开源 java CMS - FreeCMS2.8 微信管理 公众号设置

项目地址:http://www.freeteam.cn/ 公众号设置 管理员可以在这里设置微信公众号的相关配置,每个站点都可设置自己的微信公众号。 其中接口URL需要配置在微信公众号中,如下图所示 App Key ...

freeteam
18分钟前
1
0
MySQL中 replace 函数应用

将以下字段中的【忻州】替换为【洛阳】 Sql语句如下 UPDATE sys_organization SET org_name = REPLACE(org_name,'忻州','洛阳'); 执行结果如下...

karma123
21分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部