服务器向浏览器实时消息推送

迷途小羔羊678 2017-12-14 01:37:18
各位好,我现在有一个消息推送的问题。
场景:
当有 用户在app上发送一个消息,消息请求到达app后台服务器,这个时候 需要将消息发送到后台管理系统(web)的部分用户(多个),要求实时的(精确到秒级)。
环境:后台是spring boot+mybatis beb前台是使用ng-js前后台分离的系统。
项目已使用 rabit mq。

请问各位 怎么实现 越详细越好
...全文
756 41 打赏 收藏 转发到动态 举报
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
迷途小羔羊678 2017-12-21
  • 打赏
  • 举报
回复
引用 40 楼 weixin_37626416 的回复:
msg就是后台推送过来的信息体
你这是后台发来消息 的处理,问题是后台什么时候会发?我看过的都是,一个客户端发送消息到后台,然后后台在把这些消息发给别的客户端,并不能在没有任何客户端发起的时候,主动往客户端发消息。
柠檬拌饭 2017-12-21
  • 打赏
  • 举报
回复
msg就是后台推送过来的信息体
柠檬拌饭 2017-12-21
  • 打赏
  • 举报
回复
socket.onmessage = function(msg) { // 收到消息回调 message(msg); }; 比如这样
柠檬拌饭 2017-12-21
  • 打赏
  • 举报
回复
引用 37 楼 zhangdehua678 的回复:
[quote=引用 36 楼 weixin_37626416 的回复:] [quote=引用 33 楼 zhangdehua678 的回复:] [quote=引用 31 楼 maradona1984 的回复:] [quote=引用 29 楼 zhangdehua678 的回复:] [quote=引用 28 楼 hjgzj 的回复:] 轮询的是时候不要直接查库,把推送的消息放进缓存中去查。
现在是这么用的,想优化[/quote] 优化其实很简单,有消息的时候修改状态(可以数据库保存,也可以redis之类的缓存,这样压力不会集中到消息表),前端发现有消息之后再尝试拉取消息,也不需要对代码进行大规模修改[/quote]那问题是 前端怎么发现有消息。。。。。。问题点就在这啊,要后台告诉前端有消息呀[/quote] ...websocket有个socket.onmessage 事件,当后台有信息推送这个方法可以接受并且处理的。[/quote] 这个是被动触发的呀,一旦后台有信息推送到前端,就会触发这个事件,然后你在这个事件中添加你前台的处理方法就可。
引用 36 楼 weixin_37626416 的回复:
[quote=引用 33 楼 zhangdehua678 的回复:] [quote=引用 31 楼 maradona1984 的回复:] [quote=引用 29 楼 zhangdehua678 的回复:] [quote=引用 28 楼 hjgzj 的回复:] 轮询的是时候不要直接查库,把推送的消息放进缓存中去查。
现在是这么用的,想优化[/quote] 优化其实很简单,有消息的时候修改状态(可以数据库保存,也可以redis之类的缓存,这样压力不会集中到消息表),前端发现有消息之后再尝试拉取消息,也不需要对代码进行大规模修改[/quote]那问题是 前端怎么发现有消息。。。。。。问题点就在这啊,要后台告诉前端有消息呀[/quote] ...websocket有个socket.onmessage 事件,当后台有信息推送这个方法可以接受并且处理的。[/quote]我看过一些例子,这个方法是带了注解的,可以主动调用?有样例
迷途小羔羊678 2017-12-21
  • 打赏
  • 举报
回复
引用 36 楼 weixin_37626416 的回复:
[quote=引用 33 楼 zhangdehua678 的回复:] [quote=引用 31 楼 maradona1984 的回复:] [quote=引用 29 楼 zhangdehua678 的回复:] [quote=引用 28 楼 hjgzj 的回复:] 轮询的是时候不要直接查库,把推送的消息放进缓存中去查。
现在是这么用的,想优化[/quote] 优化其实很简单,有消息的时候修改状态(可以数据库保存,也可以redis之类的缓存,这样压力不会集中到消息表),前端发现有消息之后再尝试拉取消息,也不需要对代码进行大规模修改[/quote]那问题是 前端怎么发现有消息。。。。。。问题点就在这啊,要后台告诉前端有消息呀[/quote] ...websocket有个socket.onmessage 事件,当后台有信息推送这个方法可以接受并且处理的。[/quote]
引用 36 楼 weixin_37626416 的回复:
[quote=引用 33 楼 zhangdehua678 的回复:] [quote=引用 31 楼 maradona1984 的回复:] [quote=引用 29 楼 zhangdehua678 的回复:] [quote=引用 28 楼 hjgzj 的回复:] 轮询的是时候不要直接查库,把推送的消息放进缓存中去查。
现在是这么用的,想优化[/quote] 优化其实很简单,有消息的时候修改状态(可以数据库保存,也可以redis之类的缓存,这样压力不会集中到消息表),前端发现有消息之后再尝试拉取消息,也不需要对代码进行大规模修改[/quote]那问题是 前端怎么发现有消息。。。。。。问题点就在这啊,要后台告诉前端有消息呀[/quote] ...websocket有个socket.onmessage 事件,当后台有信息推送这个方法可以接受并且处理的。[/quote]我看过一些例子,这个方法是带了注解的,可以主动调用?有样例吗,谢谢
柠檬拌饭 2017-12-21
  • 打赏
  • 举报
回复
引用 33 楼 zhangdehua678 的回复:
[quote=引用 31 楼 maradona1984 的回复:] [quote=引用 29 楼 zhangdehua678 的回复:] [quote=引用 28 楼 hjgzj 的回复:] 轮询的是时候不要直接查库,把推送的消息放进缓存中去查。
现在是这么用的,想优化[/quote] 优化其实很简单,有消息的时候修改状态(可以数据库保存,也可以redis之类的缓存,这样压力不会集中到消息表),前端发现有消息之后再尝试拉取消息,也不需要对代码进行大规模修改[/quote]那问题是 前端怎么发现有消息。。。。。。问题点就在这啊,要后台告诉前端有消息呀[/quote] ...websocket有个socket.onmessage 事件,当后台有信息推送这个方法可以接受并且处理的。
迷途小羔羊678 2017-12-21
  • 打赏
  • 举报
回复
引用 30 楼 qq_15824553 的回复:
socket.io.js
我了解下
迷途小羔羊678 2017-12-21
  • 打赏
  • 举报
回复
引用 32 楼 weixin_37626416 的回复:
可以使用 atomsphere+websocket,实现前后台互推,这个框架比较小众,你可以了解下。
好的
迷途小羔羊678 2017-12-21
  • 打赏
  • 举报
回复
引用 31 楼 maradona1984 的回复:
[quote=引用 29 楼 zhangdehua678 的回复:] [quote=引用 28 楼 hjgzj 的回复:] 轮询的是时候不要直接查库,把推送的消息放进缓存中去查。
现在是这么用的,想优化[/quote] 优化其实很简单,有消息的时候修改状态(可以数据库保存,也可以redis之类的缓存,这样压力不会集中到消息表),前端发现有消息之后再尝试拉取消息,也不需要对代码进行大规模修改[/quote]那问题是 前端怎么发现有消息。。。。。。问题点就在这啊,要后台告诉前端有消息呀
柠檬拌饭 2017-12-21
  • 打赏
  • 举报
回复
可以使用 atomsphere+websocket,实现前后台互推,这个框架比较小众,你可以了解下。
maradona1984 2017-12-21
  • 打赏
  • 举报
回复
引用 29 楼 zhangdehua678 的回复:
[quote=引用 28 楼 hjgzj 的回复:] 轮询的是时候不要直接查库,把推送的消息放进缓存中去查。
现在是这么用的,想优化[/quote] 优化其实很简单,有消息的时候修改状态(可以数据库保存,也可以redis之类的缓存,这样压力不会集中到消息表),前端发现有消息之后再尝试拉取消息,也不需要对代码进行大规模修改
RockeyCui 2017-12-21
  • 打赏
  • 举报
回复
socket.io.js
迷途小羔羊678 2017-12-20
  • 打赏
  • 举报
回复
引用 28 楼 hjgzj 的回复:
轮询的是时候不要直接查库,把推送的消息放进缓存中去查。
现在是这么用的,想优化
yannsPeng 2017-12-19
  • 打赏
  • 举报
回复
引用 20 楼 zhangdehua678 的回复:
引用 19 楼 baidu_27893705 的回复:
webSocket完美解决。
webSocket怎么实现后台感知主动推送啊?我可以用mq监听感知,需要主动推送到页面
/**
	 * 定时发送
	 */
	this.timedExecution = function()
	{
		setInterval(function(){
		    websocketInit();
		},10000);
	}
	
	/**
	 * websocket初始化
	 */
	function websocketInit()
	{
		var ws = new WebSocket('ws:	//localhost:8888/websocket');
		ws.onopen = function()
		{  
			var geekHomeUser = $.parseJSON($.cookie('geek_home_user'));
		  	ws.send(geekHomeUser.userName);
		};
		ws.onmessage = function(evt)
		{
		  	var geekHomeUser = $.parseJSON($.cookie('geek_home_user'));
		  	geekHomeUser.signUpState = evt.data;
		  	$.cookie('geek_home_user',JSON.stringify(geekHomeUser), {expires: 7});
		  	if(evt.data == 0){
//		  		console.log($.parseJSON($.cookie('geek_home_user')));
		  		$("#m_Iframe").contents().find("#signOrNot").text("签到");
		  	}
		  	
		};
		ws.onclose = function(evt)
		{
		  	console.log("WebSocketClosed!");
		};
		ws.onerror = function(evt)
		{
		  	console.log("WebSocketError!");
		};
	}
前台。
package com.geekhome.config;

import java.io.IOException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;
import com.geekhome.common.utils.SpringContextUtils;
import com.geekhome.entity.Integral;
import com.geekhome.entity.service.IntegralService;

@Component
@ServerEndpoint(value = "/websocket")
public class WebSocket  
{
    @OnOpen  
    public void onOpen(){  
        System.out.println("连接已完成");  
    }
    
    @OnMessage    
    public void say(String message, Session session){  
        try { 
            IntegralService integralService = (IntegralService)SpringContextUtils.getBeanByClass(IntegralService.class);
            Integral integral = integralService.findIntegralByUserName(message);
            session.getBasicRemote().sendText(String.valueOf(integral.getState()));  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    } 
    
    @OnError  
    public void onError(Throwable t){//参数必须加上,不然不能启动  
        System.out.println("error");  
    }  
      
    @OnClose  
    public void onClose(){  
        System.out.println("close");  
    }  
    
}
后台
shayebuhui0 2017-12-19
  • 打赏
  • 举报
回复
应该是用websocket .最近正在做
迷途小羔羊678 2017-12-19
  • 打赏
  • 举报
回复
引用 15 楼 maradona1984 的回复:
[quote=引用 13 楼 qq_29548659 的回复:] [quote=引用 11 楼 zhangdehua678 的回复:] [quote=引用 9 楼 qq_29548659 的回复:] 客户端发出一个http长连接请求,然后等待服务器的响应。这个请求是异步的,所以客户端可以继续工作,比如发起其他ajax请求等等。这个时候客户端就是一个待推倒的小萝莉了。 服务器接到请求之后,并不立即发送出数据,而是hold住这个connecton。这个处理是非阻塞的,所以服务器可以继续处理其他请求。 在某个时刻,比如服务器有新数据了,服务器再主动把这个消息推送出去,即通过之前建立好的连接将数据推送给客户端。 客户端收到返回。这个时候就可以处理数据,然后再次发起新的长连接。
判断有新数据,肯定是轮询咯。轮询有时间间隔,现在是在优化,希望实时,其次是性能[/quote] 轮询对服务器压力太大了[/quote] 一天几百个请求的系统,能有多大用户量,轮询无所谓了,人家web微信都是轮询的[/quote]我们这个功能是请求不多,不过很重要,但是web要实时感知,轮询终归不好,整个系统还是不小的
迷途小羔羊678 2017-12-19
  • 打赏
  • 举报
回复
引用 19 楼 baidu_27893705 的回复:
webSocket完美解决。
webSocket怎么实现后台感知主动推送啊?我可以用mq监听感知,需要主动推送到页面
yeyuanzhi2016 2017-12-19
  • 打赏
  • 举报
回复
路过,学习!!!
yannsPeng 2017-12-19
  • 打赏
  • 举报
回复
webSocket完美解决。
maradona1984 2017-12-19
  • 打赏
  • 举报
回复
引用 16 楼 qq_29548659 的回复:
[quote=引用 15 楼 maradona1984 的回复:] [quote=引用 13 楼 qq_29548659 的回复:] [quote=引用 11 楼 zhangdehua678 的回复:] [quote=引用 9 楼 qq_29548659 的回复:] 客户端发出一个http长连接请求,然后等待服务器的响应。这个请求是异步的,所以客户端可以继续工作,比如发起其他ajax请求等等。这个时候客户端就是一个待推倒的小萝莉了。 服务器接到请求之后,并不立即发送出数据,而是hold住这个connecton。这个处理是非阻塞的,所以服务器可以继续处理其他请求。 在某个时刻,比如服务器有新数据了,服务器再主动把这个消息推送出去,即通过之前建立好的连接将数据推送给客户端。 客户端收到返回。这个时候就可以处理数据,然后再次发起新的长连接。
判断有新数据,肯定是轮询咯。轮询有时间间隔,现在是在优化,希望实时,其次是性能[/quote] 轮询对服务器压力太大了[/quote] 一天几百个请求的系统,能有多大用户量,轮询无所谓了,人家web微信都是轮询的[/quote] 现在是可以满足需求, 但是不要为了满足需求而实现功能 后期的可维护性和可扩展性很重要的[/quote] 轮询消息就是一个普通的请求,并不存在维护性和扩展性的问题,相反websocket之类也存在相应的问题,而且更不好解决
加载更多回复(20)
WebSocket客户端和服务端实例源码 WebSocket ws实例 HTML5 用java实现的服务端 Websocket与服务器的正常通信 众所周知,Web 应用的交互过程通常是客户端通过浏览器发出一个请求,服务器端接收请求后进行处理并返回结果给客户端,客户端浏览器将信息呈现,这种机制对于信息变化不是特别频繁的应用尚可,但对于实时要求高、海量并发的应用来说显得捉襟见肘,尤其在当前业界移动互联网蓬勃发展的趋势下,高并发与用户实时响应是 Web 应用经常面临的问题,比如金融证券的实时信息,Web 导航应用中的地理位置获取,社交网络的实时消息推送等。 传统的请求-响应模式的 Web 开发在处理此类业务场景时,通常采用实时通讯方案,常见的是: 轮询,原理简单易懂,就是客户端通过一定的时间间隔以频繁请求的方式向服务器发送请求,来保持客户端和服务器端的数据同步。问题很明显,当客户端以固定频率向服务器端发送请求时,服务器端的数据可能并没有更新,带来很多无谓请求,浪费带宽,效率低下。 基于 Flash,AdobeFlash 通过自己的 Socket 实现完成数据交换,再利用 Flash 暴露出相应的接口为 JavaScript 调用,从而达到实时传输目的。此方式比轮询要高效,且因为 Flash 安装率高,应用场景比较广泛,但在移动互联网终端上 Flash 的支持并不好。IOS 系统中没有 Flash 的存在,在 Android 中虽然有 Flash 的支持,但实际的使用效果差强人意,且对移动设备的硬件配置要求较高。2012 年 Adobe 官方宣布不再支持 Android4.1+系统,宣告了 Flash 在移动终端上的死亡。 从上文可以看出,传统 Web 模式在处理高并发及实时性需求的时候,会遇到难以逾越的瓶颈,我们需要一种高效节能的双向通信机制来保证数据的实时传输。在此背景下,基于 HTML5 规范的、有 Web TCP 之称的 WebSocket 应运而生。 早期 HTML5 并没有形成业界统一的规范,各个浏览器和应用服务器厂商有着各异的类似实现,如 IBM 的 MQTT,Comet 开源框架等,直到 2014 年,HTML5 在 IBM、微软、Google 等巨头的推动和协作下终于尘埃落地,正式从草案落实为实际标准规范,各个应用服务器浏览器厂商逐步开始统一,在 JavaEE7 中也实现了 WebSocket 协议,从而无论是客户端还是服务端的 WebSocket 都已完备,读者可以查阅HTML5 规范,熟悉新的 HTML 协议规范及 WebSocket 支持。

81,092

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧