文档章节

Pushlet的那些坑

DDL007
 DDL007
发布于 2016/12/12 22:59
字数 1324
阅读 537
收藏 0
点赞 0
评论 0

1. 服务器端推送组件

CometDPushletDWRAPE(Ajax Push Engine)

2. 软件环境

使用Pushlet完成服务器端的消息推送,实现群组IM。客户端模式为PULL,数据交换格式为XML-STRICT

3. 其中的坑

3.1 中文消息坑 

现象

中文消息丢失后,似乎整个系统都瘫痪了

跟踪调查

结合源代码跟踪调试发现,所有要发送的消息都基于Event对象,Event对象最终被转换为XML格式的字符串发送至客户端。而在toXML过程中,当遇到中文时程序进入异常处理过程,错误消息为“非ISO-8859-1字符”,该消息因为异常不再发送至客户端,消息丢失了。可恶的是,后台日志中并没有明显错误。

补救方法

将待发送的对象作为Event的data属性,将待发送对象转换为JSON格式的字符串,并转码。我在项目中使用的是UTF-8编码。

new String(JSONObject.fromObject(obj).toString().getBytes("UTF-8"),"ISO-8859-1");

虽然在控制台中输出是乱码的,实际测试发现,浏览器端UTF-8编码能够正确接收并显示中文。

3.2 配置文件

根据Pushlet.properties中的注释,个人修改了部分配置,结果消息丢失率很高。考虑到jar包不大,代码相对较少就读了一些关键类,如SessionManager,Session,Controller,Subscriber,Subscription等。总结一下结论如下:

A .SessionManager删除Session

当如下情况发送时

1. 当发送数据时,出现异常

2. 当Session的timetoLive<0。

3. 当Session的两次Refresh请求间隔,超过了配置的refresh.timeout

B. 关于Session是否过期的检查

通过如下手段实现

1.  每次客户端发送refresh请求,就会将Session的timeToLi ve重置为session.timeout.mins

2. 服务器端有1个AgeTask来定时检查Session的timeToLive,周期为1分钟。所以,配置文件中session.timeout的单位为分钟

3.  每次客户端发送refresh请求,等待时间主要受queue.read.timeout.millis影响。如果没有新消息到达,请求是在读取消息队列超时之后返回

C. 基于B的推理

1. pull.session.timeout 不能设置为1,最小值为2。因为设置为1意味着Session的timeToLive为1分钟,考虑到实际线程调度的问题,AgeTask的执行间隔可能会超过1分钟。当AgeTask对每个Session的TimeToLive减去执行间隔delta时,Session纷纷超时。于是,刚刚发送的群组消息,仅有少数几个群组用户可以正确接收。说没法送成功吧,有人接收到了消息。说发送成功吧,莫非程序也检查用户人品。

2. queue.read.timeout+ 必须远小于 pull.refresh.timeout。因为如果有消息到达,则请求会立刻返回,而后发送下一次请求。如果没有消息到达,则要一直等到timeout,结合A.1,如果下一次请求没有如期到达,则该Session将会被stop掉,进而被remove掉。

3. 此外在完成本次请求,开启下一次请求之前的间隔受pull.refresh.wait.min.millis和pull.refresh.wait.max.millis两个参数影响。通过读取代码发现,客户端会生成1个属于[min,max]的随机值作为请求等待时间,也会对refresh是否如期到达造成影响。本人使用中将两个值全部设置为0,实现下次请求的立刻执行。

从推理得出如下内容:

pull.session.timeout>=2

queue.read.timeout + random(pull.refresh.wait.min.millis,pull.refresh.wait.max.millis)+网络传输时间 < pull.refresh.timeout

同时,也证明,曾经发送成功的消息,确实是人品大爆发。按照推理修改了配置文件值如下:

listen.force.pull.all=true

pull.refresh.timeout.millis=10000

queue.read.timeout.millis=5000
queue.write.timeout.millis=300

pull.refresh.wait.min.millis=0
pull.refresh.wait.min.millis=0

3.3 与HttpSession关联

项目中有针对某个人发送消息的需求。所以,我们需要把PushletSession与HttpSession关联起来。这里要注意的是,我是直接关联的PushletSession对象本身。但SessionManager种经常会对Session进行克隆。结果就出现一种现象,关联的PushletSession已过期,但SessionManager中该Session依然active。其实,仅有Session的id是不变的,其对应的Session可能被clone多次,而与HttpSession关联的这一个,早已被SessionManager丢弃了。所以,仅使用与HttpSession关联的PushletSession的id,而不直接使用当前关联的PushletSession。

3.4 断线重连

客户端提供onError回调函数,我们可以在该函数中,进行断线重连。当然,如果是浏览器关闭,就没有必要了。

3.5 消息重发

    当Session被stop时,将Session中Subscriber中的EventQueue暂时恢复到HttpSession中。当新的Session重建OK时,优先发送这些缓存的消息。

    不过由于前后两个Session是没有关联的,在前1个Session stop之后,新的Session start之前,服务器端将无法向该用户推送消息。这个希望与诸位小伙伴讨论,欢迎拍砖!

© 著作权归作者所有

共有 人打赏支持
DDL007
粉丝 0
博文 5
码字总数 5104
作品 0
普陀
程序员
Pushlet定点推送消息

上一篇日志利用推送源周期性地向订阅了某一事件的所有网页端推送信息,但怎么实现向特定的某一个用户推送信息呢,想象一个网络聊天室,怎么向单独的一个好友私聊呢。问题的关键就是那个Sessi...

叶落花开 ⋅ 2012/03/23 ⋅ 9

Pushlet 使用记录

前段工作中需要用到Pushlet这个小工具做数据通信,在使用的时候需要数据定时(每秒)展示到页面中,如下图所示。Pushlet默认数据传输间隔比较大而且不固定。 网上也没有找到有用的资料解决这个...

martin_li ⋅ 2014/01/11 ⋅ 0

关于ExtJs整合pushlet的JsonStore,data参数赋值问题,在线等!

这一段JS代码通过pushlet服务器推送获得数据源event。为单独的文件。名为pushlet-keep,js PL._init();//PL.setDebug(true);PL.joinListen('/zhaoyang/hi');function onData(event) { 这一段代...

JavaOlder ⋅ 2013/04/26 ⋅ 1

开源的Comet框架--Pushlet

Pushlet 是一个开源的 Comet 框架,Pushlet 使用了观察者模型:客户端发送请求,订阅感兴趣的事件;服务器端为每个客户端分配一个会话 ID 作为标记,事件源会把新产生的事件以多播的方式发送到...

匿名 ⋅ 2011/11/01 ⋅ 3

开源框架Pushlet入门

一、comet基本概念 1.comet是一个用于描述客户端和服务器之间交互的术语,即使用长期保持的http连接来在连接保持畅通的情况下支持客户端和服务器间的事件驱动的通信。 2.传统的web系统的工作...

haopeng ⋅ 2013/12/26 ⋅ 0

开源框架Pushlet入门_java_web

开源框架Pushlet入门 一、comet基本概念 1.comet是一个用于描述客户端和服务器之间交互的术语,即使用长期保持的http连接来在连接保持畅通的情况下支持客户端和服务器间的事件驱动的通信。 ...

引鸩怼孑 ⋅ 2015/07/28 ⋅ 0

pushlet+负载均衡

现在pushlet要和某一台服务器保持一直的固定的通信(排除其他bug因素或者人为刷新以及人为发起新的请求),在负载均衡的情况下?有可能或出现pushlet正在维护的长链接被重新分发的情况吗? ...

VmLia ⋅ 2013/01/22 ⋅ 0

网页版即时通讯

web聊天室的实现方法有多种,包括:基于ajax技术的实现,基于Comet(Pushlet)技术的实现,基于XMPP协议的实现,以及基于flash的XmlSocket和远程共享对象的实现。 1)基于ajax技术的实现。 ...

为梦而来 ⋅ 2014/04/25 ⋅ 0

struts2 集成 pushlet ???

最近搞了搞pushlet,略懂略懂~~~可我想在有struts2的环境下使用,怎么才能集成到一起呢?困惑啊,求指导! 是直接互相有整合的接口?或者第三方帮助jar? 还是,用spring之类的去整合它们两个...

VmLia ⋅ 2012/11/06 ⋅ 1

OSC动弹的即时更新是怎么实现的?

@红薯 你好,想跟你请教个问题: OSC动弹的即时更新是怎么实现的? comet? websockt? pushlet? 还是其它什么?

673 ⋅ 2012/07/17 ⋅ 6

没有更多内容

加载失败,请刷新页面

加载更多

下一页

如何优雅的编程——C语言界面的一点小建议

我们鼓励在编程时应有清晰的哲学思维,而不是给予硬性规则。我并不希望你们能认可所有的东西,因为它们只是观点,观点会随着时间的变化而变化。可是,如果不是直到现在把它们写在纸上,长久以...

柳猫 ⋅ 21分钟前 ⋅ 0

从零手写 IOC容器

概述 IOC (Inversion of Control) 控制反转。熟悉Spring的应该都知道。那么具体是怎么实现的呢?下面我们通过一个例子说明。 1. Component注解定义 package cn.com.qunar.annotation;impo...

轨迹_ ⋅ 21分钟前 ⋅ 0

系统健康检查利器-Spring Boot-Actuator

前言 实例由于出现故障、部署或自动缩放的情况,会进行持续启动、重新启动或停止操作。它可能导致它们暂时或永久不可用。为避免问题,您的负载均衡器应该从路由中跳过不健康的实例,因为它们...

harries ⋅ 23分钟前 ⋅ 0

手把手教你搭建vue-cli脚手架-详细步骤图文解析[vue入门]

写在前面: 使用 vue-cli 可以快速创建 vue 项目,vue-cli很好用,但是在最初搭建环境安装vue-cli及相关内容的时候,对一些人来说是很头疼的一件事情,本人在搭建vue-cli的项目环境的时候也是...

韦姣敏 ⋅ 33分钟前 ⋅ 0

12c rman中输入sql命令

12c之前版本,要在rman中执行sql语句,必须使用sql "alter system switch logfile"; 而在12c版本中,可以支持大量的sql语句了: 比如: C:\Users\zhengquan>rman target / 恢复管理器: Release 1...

tututu_jiang ⋅ 47分钟前 ⋅ 0

Nginx的https配置记录以及http强制跳转到https的方法梳理

Nginx的https配置记录以及http强制跳转到https的方法梳理 一、Nginx安装(略) 安装的时候需要注意加上 --with-httpsslmodule,因为httpsslmodule不属于Nginx的基本模块。 Nginx安装方法: ...

Yomut ⋅ 今天 ⋅ 0

SpringCloud Feign 传递复杂参数对象需要注意的地方

1.传递复杂参数对象需要用Post,另外需要注意,Feign不支持使用GetMapping 和PostMapping @RequestMapping(value="user/save",method=RequestMethod.POST) 2.在传递的过程中,复杂对象使用...

@林文龙 ⋅ 今天 ⋅ 0

如何显示 word 左侧目录大纲

打开word说明文档,如下图,我们发现左侧根本就没有目录,给我们带来很大的阅读障碍 2 在word文档的头部菜单栏中,切换到”视图“选项卡 3 然后勾选“导航窗格”选项 4 我们会惊奇的发现左侧...

二营长意大利炮 ⋅ 今天 ⋅ 0

智能合约编程语言Solidity之线上开发工具

工具地址:https://ethereum.github.io/browser-solidity/ 实例实验: 1.创建hello.sol文件 2.调试输出结果

硅谷课堂 ⋅ 今天 ⋅ 0

ffmpeg 视频格式转换

转 Mp4 格式 #> ffmpeg -i input.avi -c:v libx264 output.mp4#> ffmpeg -i input.avi -c:v libx264 -strict -2 output.mp4#> ffmpeg -i input.avi -c:v libx264 -strict -2 -s 1......

Contac ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部