java消息推送解决方案
来源:广州软件定制 编辑:广州软件开发公司 日期:2016-04-30
消息分类
目标:信息系统有大量业务事件要及时通知给用户;但是不希望客户端以轮询方式连接服务器来查询最新消息。并要实现以下效果:
无论发出消息时,客户端开机或关机,登陆系统后客户端消息总都可以收到消息
消息可以过滤、有权限的人才能收到相关通知。
在系统里面实现消息框提示。
根据需要,消息被发送和接受的同时,可以保存到数据库中,作为消息发送和阅读的日志和历史依据。
综上所述:所有业务数据仍然存放在数据库中。JMS的消息队列并不存储业务数据,可以运用JMS来实现异步通知机制,避免客户端轮询带来的开销。
1、 实时性信息:用于紧急情况,管理员需要立即传达系统所有正在使用的户用,客户端能第一时间能接受、弹出管理员发送出来的指令,类似QQ会自动弹出腾讯服务器中心发送出来的各种实时性新闻功能,让所有登录上QQ的用户第一时间接受到最新的新闻。
2、 非常实时性信息:用于发送不是紧急情况消息,管理员发送消息后,可以允许接受方一天以内任何时间查看到信息都可以。类似邮件服务器那种,客户需要主动从服务器去获取信息。
实现方案
1、 实时性信息解决方案:产生让服务器“主动”给浏览器客户端发送数据,那就是利用http长连接来实现消息推送系统。消息推送系统又叫服务器推、Comet技术、Push Server、Server Push等等。实现了攻受的颠倒和权力的反转。服务器不用再傻乎乎地等待着客户端的请求才能发送最新的数据,而是占据了主动,当有新数据的时候,服务器可以立即主动地将数据push给相关的客户端
在消息推送系统中,客户端+服务器端一起,使用的是异步非阻塞
HTTP长连接
翻译自http keep-alive connection和http persistent connection,又叫http connection reuse,网上也有反过来翻译成http long connection。
下面这个图来自wikipedia,讲解了http长连接是在一个TCP连接的基础之上,发送多个HTTP请求以及接收多个HTTP响应,这是为了避免每一次请求都去打开一个新的连接。在HTTP 1.1标准中,所有的请求都认为是长连接。
在这里的消息推送系统中,HTTP长连接的作用就是向服务器发送请求,然后一直等待服务器的返回数据。这就相当于客户端在“监听”服务器了,可以随时接收来自服务器的消息
同步与异步
同步:IO操作将导致请求进程阻塞,直到IO操作完成。也就是说客户端在发送请求后,必须得在服务端有回应后才发送下一个请求。
异步:IO操作不导致请求进程阻塞。也就是说客户端在发送请求后,不必等待服务端的回应就可以发送下一个请求。
同步与异步说的是客户端与服务器端之间的一种通信方式。
阻塞与非阻塞
阻塞:服务器端的线程或者进程没有处理完数据的时候,不会返回,线程或者进程回被挂起,不再响应其他请求。
非阻塞:服务器端在没有处理完的时候,会立即返回,不会挂起线程或者进程,可以继续响应其他请求。
a. 客户端发出一个http长连接请求,然后等待服务器的响应。这个请求是异步的,所以客户端可以继续工作,比如发起其他ajax请求等等。这个时候客户端就是一个待推倒的。
b. 服务器接到请求之后,并不立即发送出数据,而是hold住这个connecton。这个处理是非阻塞的,所以服务器可以继续处理其他请求。
c. 在某个时刻,比如服务器有新数据了,服务器再主动把这个消息推送出去,即通过之前建立好的连接将数据推送给客户端。
d. 客户端收到返回。这个时候就可以处理数据,然后再次发起新的长连接。
2、 实时性信息解决方案:管理员将发送的信息提交到服务器端,服务器端会将发送的相关信息保存到数据库表中。当客户端向服务器发出获取数据信息时,服务器会对客户端身份进行校验,提取有关这个对这个客户消息,并发送到该客户端。
3、 使用JMS实现有以下三种方式
a、采用pub/sub机制,系统有1个或者若干个全局的Topic,所有的消息根据业务分类,发送到不同的topic;每个user都对相关的topic进行durableSubscribe,从而避免消息丢失;收到消息后,客户端应用程序再根据业务逻辑过滤掉消息。过滤后再根据需要在系统托盘中提示。当系统添加/删除一个user的时候,就建立相关的durable subscription或者unsubscribe。
特点:对消息进行过滤的程序比较复杂,如果有多个topic,可以根据每个topic分别写过滤程序,从而分解过滤程序;有的消息接受方与业务角色相关,有的消息接受方是由发送者专门指定(比如发送一个开会通知,指定了会议人员/部门)。消息太多,过滤程序总要到数据库中查询业务逻辑,来过滤消息。假设100个消息,100个用户,需要100×100次过滤,增加数据库负荷。所以,该方案适用于过滤比较简单、比较统一、便于用过滤语句来直接写的通知。
b、采用point(sender with logic filter) to point方式,消息发送程序根据业务逻辑,得到所有有权收到消息的用户,与之建立连接,发送消息。
特点:发送程序稍微复杂,但是控制接受方的业务逻辑分散在每个发送程序中,因此不会过分复杂;如果接受方太多(100个用户),发送程序要向100个接受方发送消息,可能会有点慢(事务),响应不够快?当创建或者删除一个用户的时候,就为之建立/删除队列。
c、采用point-point-dispatch with logic filter-point方式
所有的消息发送到全局一个唯一的队列,dispatch程序在后台运行,不断从该全局队列中取出消息,根据业务逻辑进行dispatch到相应的接受者队列中。
特点:dispatch程序比较复杂,实现过滤业务逻辑,找出接受方。如果dispatch的时候找不到合法接受方,则抛弃消息。
消息的过虑
JMS本身提供的消息过虑类似于SQL,太简单,不适合信息系统复杂业务逻辑,需要自己编程来确定哪些用户能够接收/读取消息。
消息的接受与提示:
都采用异步机制,即实现MessageListener即可;采用Observer模式,在托盘中闪动提示。
确认:
JMS系统的确认(acknowledge)是系统内部使用的,与事务和消息处理机制相关,业务上的确认本质上是专门发送一个message,与jms的acknowledge无关。
非实时性信息解决方案:
a. 用户被动获取信息,用户在每次登录系统时,系统会自动获取该用户有关的信息,并显示在消息窗口供用户查收。
b. 用户主动获取信息,系统提供一个获取信息按钮功能,用户在点击“获取信息”按钮时,客户端主动向服务端发送获取信息请求,服务端接受到客户端请求时,对该用户进行判断,读取有该用户信息,并传回给客户端。
c. 客户可以设置事件定触发机制,比如客户端每隔30分钟,或者更长时间主动向服务器端获读取有该用户信息,并传回给客户端。
数据库设计
1. 系统消息表(SYS_MESSAGE)
字段名 |
编码 |
数据类型 |
长度 |
非空约束 |
取值描述 |
系统消息Id |
MESSAGE_ID |
varchar |
32 |
Y |
|
标题 |
SUBJECT |
varchar |
132 |
Y |
|
内容 |
CONTENT |
varchar |
1200 |
Y |
|
接受机构 |
RECIEVER_TYPE |
varchar |
432 |
N |
请看说明部分 |
机构对象 |
RECIEVER_LIST |
varchar |
750 |
N |
只有接受对为个人时,才需要特别指定。 |
发送机构 |
SENDER |
varchar |
32 |
Y |
|
发送日期 |
SEND_DATE |
DATE |
|
|
|
|
|
|
|
|
|
主键 |
MessageId |
|
|
|
|
说明: 消息接受机构可分为以下几种
a. 接受机构为全体对象时:点击机构树,请选择接受机构对象为全体对象,消息将发送给系统中用所有用户,系统所有用户都将可以看到这条消息。
b. 接受机构为指定部分机构时:点击机构树,请选择您将发送的机构对象:比如柜员机构等,可以对机构对象进行多选,在选择”确定”之后,多个对象之间用分号(;)进行分隔,用户在获取消息时会对其所属机构进行判断,会自动判断获该用户机构下面的消息内容。
c. 接受机构为指定机构下面用户时, 点击机构树,请选择您将发送的机构下面成员,可以对机构成员进行多选,成员对象可以跨机构的选择,在选择”确定”之后,多个成员之间用分号(;)进行分隔,用户在获取消息时会对其所属成员身份进行判断,会自动判断获该用户成员下面的消息内容。
2. 接受阅读消息表(RECIEVER_READ)
字段名 |
编码 |
数据类型 |
长度 |
非空约束 |
取值描述 |
系统消息Id |
MESSAGE_ID |
varchar |
32 |
Y |
|
接受机构类型 |
RECIEVER_TYPE |
varchar |
32 |
Y |
|
接受机构 |
RECIEVER |
varchar |
32 |
Y |
|
阅读时间 |
READ_DATE |
DATE |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
主键 |
MESSAGE_ID, RECIEVER |
3. 日志参考配置表(T_Conf_Log)
字段名 |
编码 |
数据类型 |
长度 |
非空约束 |
取值描述 |
配置ID |
CONF_ID |
varchar |
32 |
Y |
|
配置名称 |
CONF_NAME |
varchar |
32 |
Y |
|
日志级别 |
LOG_LEVEL |
varchar |
32 |
Y |
FATAL 0
ERROR 3
WARN 4
INFO 6
DEBUG 7 |
日志输出目的地 |
LOG_OUTPUT |
varchar |
232 |
|
org.apache.log4j.ConsoleAppender(控制台), org.apache.log4j.FileAppender(文件), org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件), org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件), org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
|
日志输出格式 |
LOG_Layout |
varchar |
232 |
|
org.apache.log4j.HTMLLayout(以HTML表格形式布局), org.apache.log4j.PatternLayout(可以灵活地指定布局模式), org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串), org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息) |
是否生效 |
STATUS |
varchar |
2 |
Y |
Y/N |
|
|
|
|
|
|
|
|
|
|
|
|
主键 |
CONF_ID |
|
|
|
|
相关阅读