【js学习】js连接RabbitMQ达到实时消息推送

摘要:
js连接RabbitMQ达到实时消息推送最近在自己捯饬一个网站,有一个功能是需要后端处理完数据把数据发布到MQ中,前端再从MQ中接收数据。参考基于RabbitMQ的实时消息推送rabbitMQ官网实现服务器端推送的几种方式Web应用都是基于HTTP协议的请求/响应模式,无法像TCP协议那样保持长连接,因此Web应用就很难像手机那样实现实时的消息推送。前端通过websocket连接RabbitMQRabbitMQ有很多第三方插件,可以在AMQP协议基础上做出许多扩展的应用。

js连接RabbitMQ达到实时消息推送

最近在自己捯饬一个网站,有一个功能是需要后端处理完数据把数据发布到MQ中,前端再从MQ中接收数据。但是前端连接MQ又成了一个问题,在网上搜了下资料,点进去一篇IBM DW后发现竟然是超哥写的,真是巧哈~因为超哥写的很好所以很多我就直接摘抄过来了,他应该不会介意的(逃。

参考

实现服务器端推送的几种方式

Web 应用都是基于 HTTP 协议的请求/响应模式,无法像 TCP 协议那样保持长连接,因此 Web 应用就很难像手机那样实现实时的消息推送。就目前来看,Web 应用的消息推送方式主要有以下几种:

1.Ajax 短轮询
Ajax 轮询主要通过页面端的 JS 定时异步刷新任务来实现数据的加载,但这种方式实时效果较差,而且对服务端的压力也较大。

2.长轮询
长轮询主要也是通过 Ajax 机制,但区别于传统的 Ajax 应用,长轮询的服务器端会在没有数据时阻塞请求直到有新的数据产生或者请求超时才返回,之后客户端再重新建立连接获取数据。但长轮询服务端会长时间地占用资源,如果消息频繁发送的话会给服务端带来较大的压力。

3.WebSocket 双向通信
WebSocket 是 HTML5 中一种新的通信协议,能够实现浏览器与服务器之间全双工通信。如果浏览器和服务端都支持 WebSocket 协议的话,该方式实现的消息推送无疑是最高效、简洁的。并且最新版本的 IE、Firefox、Chrome 等浏览器都已经支持 WebSocket 协议,Apache Tomcat 7.0.27 以后的版本也开始支持 WebSocket。

安装RabbitMQ

在macOS上安装rabbitmq(提前已经安装了brew):

brew install rabbitmq

启动stomp有关的一系列插件

rabbitmq-plugins enable rabbitmq_management rabbitmq_web_stomp rabbitmq_stomp rabbitmq_web_stomp_examples

可以通过下面这条命令查看已启动了哪些RabbitMQ插件:

rabbitmq-plugins list

重启rabbitmq:

brew services restart rabbitmq

我们可以在15670端口访问web-stomp-examples,

http://localhost:15670/

其中RabbitMQ运行在15672端口,stomp服务运行在15674端口

前端通过websocket连接RabbitMQ

RabbitMQ 有很多第三方插件,可以在 AMQP 协议基础上做出许多扩展的应用。Web STOMP 插件就是基于 AMQP 之上的 STOMP 文本协议插件,利用 WebSocket 能够轻松实现浏览器和服务器之间的实时消息传递,具体实现方式如下图所示:

w

RabbitMQ Web STOMP 插件可以理解为 HTML5 WebSocket 与 STOMP 协议间的桥接,目的也是为了让浏览器能够使用 RabbitMQ。当 RabbitMQ 消息服务器开启了 STOMP 和 Web STOMP 插件后,浏览器端就可以轻松地使用 WebSocket 或者 SockerJS 客户端实现与 RabbitMQ 服务器进行通信。

前端通过stomp连接RabbitMQ的代码如下:

// 初始化 ws 对象
if (location.search == '?ws') {
    var ws = new WebSocket('ws://localhost:15674/ws');
} else {
    var ws = new SockJS('http://localhost:15674/stomp');
}

// 获得Stomp client对象
var client = Stomp.over(ws);

// SockJS does not support heart-beat: disable heart-beats
client.heartbeat.outgoing = 0;
client.heartbeat.incoming = 0;
client.debug = pipe('#second');

// 定义连接成功回调函数
var on_connect = function(x) {
    //data.body是接收到的数据
    client.subscribe("/queue/default", function(data) {
        var msg = data.body;
        alert("收到数据:" + msg);
    });
};

// 定义错误时回调函数
var on_error =  function() {
    console.log('error');
};

// 连接RabbitMQ
client.connect('guest', 'guest', on_connect, on_error, '/');
console.log(">>>连接上http://localhost:15674");

我们可以看到代码主要包括以下几个部分:

  • 初始化websocket对象
  • 构造stomp client
  • 定义连接成功的回调函数
  • 定义连接错误时的回调函数
  • 连接RabbitMQ

因此我们要做的主要是定义这个连接成功的回调函数,其中:

client.subscribe("/queue/default", function(data) {
    var msg = data.body;
    alert("收到数据:" + msg);
});

这个函数的功能是订阅了一个名为"default"的queue,当有生产者向该队列发送数据时,该函数会作为消费者接收到数据,并触发回调函数。我们可以在回调函数中对接收到的数据进行展示,更新到界面上,从而可以达到和轮询一样的效果。

当我们把这段js放进html中run起来后,通过Chrome F12工具也可以看到这样的提示:

Opening Web Socket...
stomp.js:114 Web Socket Opened...
stomp.js:114 >>> CONNECT
accept-version:1.1,1.0
heart-beat:0,0
host:/
login:guest
passcode:guest

stomp.js:114 <<< CONNECTED
server:RabbitMQ/3.6.6
session:***
heart-beat:0,0
version:1.1

stomp.js:114 connected to server RabbitMQ/3.6.6
stomp.js:114 >>> SUBSCRIBE
id:sub-0
destination:/queue/default

当我们向/queue/default发送一条测试数据“aaa”,前端js就会接收到数据,再看F12工具中的显示:

<<< MESSAGE
subscription:sub-0
destination:/queue/default
message-id:***
redelivered:false
persistent:1
content-length:3

aaa

可以看到已经收到了"aaa"这条消息,并且可以注意到Stomp协议是以文本格式进行数据传输的,而RabbitMQ是以二进制传输的。通过data.body就可以获取到Stomp中的消息的主体了。

思考

关于websocket连接MQ进行实时消息推送,固然是实现消息推送的一个很好的方式,但是不得不思考在大量并发情况下,MQ端是否能承受的了数量庞大的websocket连接。MQ将前后端进行了解耦和异步化,但是也可能成为系统的性能瓶颈。对于这种实现方式,目前只能说是且学且用,性能方面还尚待考究。

免责声明:文章转载自《【js学习】js连接RabbitMQ达到实时消息推送》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Ubuntu 及Ubuntu server版如何启用root用户登录腾讯QQ头像/QQ网名等相关获取API接口下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

打开自定义链接新窗口(safari JS prompt的坑!)2016.03.08

很简单的一个小练习,但做的过程中发现safari的一个坑,使用prompt()方法的时候,点击取消和不输入一样,会返回空字符' ',而不是null! 要求:制作新按钮,“新窗口打开网站” ,点击打开新窗口。 任务: 新窗口打开时弹出确认框,是否打开 提示: 使用 if 判断确认框是否点击了确定,如点击弹出输入对话框,否则没有任何操作。 通过输入对话框,确...

移动端css、Js优处理

CSS 篇 0.5px细线 移动端 H5 项目越来越多,设计师对于 UI 的要求也越来越高,比如 1px 的边框。在高清屏下,移动端的 1px 会很粗。 那么为什么会产生这个问题呢?主要是跟一个东西有关,DPR(devicePixelRatio) 设备像素比,它是默认缩放为 100%的情况下,设备像素和 CSS 像素的比值。目前主流的屏幕 DPR=2(...

js格式化input输入框内容(每几位分一组,并使用特定字符分隔)

<html> <head> <title></title> </head> <body> <input id="inputDom" /> <script type="text/javascript"> var input...

HTML5触屏版多线程渲染模板技术分享

  前言: 了解js编译原理的屌丝们都知道,js是单线程的,想当年各路神仙为了实现js的多线程,为了解决innerHTML输出大段HTML卡页面的顽疾,纷纷设计了诸如假冒的“多线程“实现,我自己也在写开源框架KitJs时候,写过类似的组件http://www.cnblogs.com/xueduanyang/archive/2012/05/30/252642...

debian 安装 plymouth 美化开机动画

Plymouth 目录 Plymouth 参考 简介 简单步骤,无脑按照wiki走 下载,请注意wiki里kde桌面的提醒 修改grub配置,建议修改前保存一下旧有配置 应用修改 查看一下默认主题 设置主题 看看效果 不试验了,花里胡哨,没啥用…… 如何显示原始的内核消息 参考 debian wiki B站视频 简介 debian默认的开机...

js之split()和join()的用法

说明 这几天写了一个简单的vue项目,需要截取字符串,一时间想到了正则表达式,还折腾了还一会儿,最后上网查了一下,使用split()再简单不过了,也顺便回忆一下join()。可见我有多菜,哈哈,学了这么久,竟然对它们这么陌生。 split(separator,howmany) 说明:可以把某个字符串str按某个字符(separator)分割成多个字符串...