Node.js实现数据推送

场景:后端更新数据推送到客户端(Java部分使用Tomcat服务器)。

后端推送数据的解决方案有很多,比如轮询、Comet、WebSocket。

1. 轮询对于后端来说开发成本最低,就是按照传统的方式处理Ajax请求并返回数据,在学校的时候实验室的项目一直都采用轮询,因为它最保险也最容易实现。但轮询带来的通信资源的浪费是无法忽视的,无论数据是否改变,都照常发送请求并响应,而且每次HTTP请求都带有很长的头部信息。

2. Comet的概念是长连接,客户端发送请求后,后端将连接保持下来,直到连接超时或后端返回数据时再重新建立连接,有效的将通信资源转移到了服务器上,实际消耗的是服务器资源。

3. WebSocket是HTML5提供的一种全双工通信技术,通过“握手”实现客户端与服务器之间的通信,实时性好,携带的头部也较小,目前支持的浏览器如下:

理想的情况是采取WebSocket与Comet结合的方式,对IE8等浏览器采取Comet方式,做降级处理。但是这样一来,后端需要实现两种处理请求的逻辑,即WebSocket与Comet。所以,本文加入Node.js,之所以这样做,是将处理WebSocket(或Comet)的逻辑转移到Node.js部分,不给后端“添麻烦”,因为在实际情况下,前端开发人员推动后端开发人员并不容易。Node.js作为浏览器与Java业务逻辑层通信的中间层,连接客户端与Tomcat,通过Socket与Tomcat进行通信(是Socket,不是WebSocket,后端需要实现Socket接口。

在客户端,WebSocket与Comet通过Socket.io实现,Socket.io会针对不同的浏览器版本或者不同客户端选择合适的实现方式(WebSocket, long pull..),Socket.io的引入让处理WebSocket(或长连接)变的很容易。Socket.io

客户端引入socket.io:

<script src="static/js/socket.io.js"></script>
客户端JavaScript代码:

 var socket = io.connect('127.0.0.1:8181');
 // 发送数据至服务器
socket.emit('fromWebClient', jsonData);
// 从服务器接收数据
 socket.on('pushToWebClient', function (data) {
  // do sth.
 });

Node.js服务器代码:

 var http = require('http'),
   app = http.createServer().listen('8181'),
   io = require('socket.io').listen(app);
 io.sockets.on('connection', function (socketIO) {
   // 从客户端接收数据
   socketIO.on('fromWebClient', function (webClientData) {
     // do sth.
   });
   // 客户端断开连接
   socketIO.on('disconnect', function () {
     console.log('DISCONNECTED FROM CLIENT');
   });
   // 向客户端发送数据
   socketIO.emit('pushToWebClient', jsonData);
 });

建立好客户端同Node.js服务器的连接只是第一步,下面还需要建立Node.js服务器与Java业务逻辑层的联系。这时,Node.js服务器则作为客户端,向Tomcat发送TCP连接请求。连接成功后,Node.js服务器和Tomcat建立了一条全双工的通道,而且是唯一的一条,不论有多少个客户端请求,都从Node.js服务器转发至Tomcat;同样,Tomcat推送过来的数据,也经由Node.js服务器分发至各个客户端。

这里存在一个问题,就是在WebSocket连接与Socket连接都建立好之后,两次连接彼此之间是屏蔽的。Tomcat不知道是哪次WebSocket连接发送过来的数据,也不知道是哪个客户端发来的数据。当然,Node.js可以利用session id发送至Tomcat来标识是哪一个客户端,但本文采用的是另外一种办法。

客户端同Node.js建立WebSocket连接时,每个连接都会包含一个实例,这里称它为socketIO。每个socketIO都有一个id属性用来唯一标识这个连接,这里称它为socket_id。利用socket_id,在Node.js服务器建立一个映射表,存储每一个socketIO与socket_id的映射关系。Node.js服务器发送数据给Tomcat时带上这个socket_id,再由Java部分进行一系列处理以后封装好每个客户端需要的不同数据一并返回,返回的数据里要有与socket_id的对应关系。这样,Node.js服务器收到Tomcat发来的数据时,通过前面提到的映射表由不同的socketIO分发至不同的客户端。

Node.js服务器代码:

 var http = require('http'),
   net = require('net'),
   app = http.createServer().listen('8181'),
   io = require('socket.io').listen(app),
   nodeServer = new net.Socket();
 // 连接到Tomcat
 nodeServer.connect(8007, '127.0.0.1', function() {
   console.log('CONNECTED');
 });
// 存储客户端的WebSocket连接实例
 var aSocket = {};
 // 同客户端建立连接
 io.sockets.on('connection', function (socketIO) {
  // 从客户端接收数据,然后发送至Tomcat
   socketIO.on('fromWebClient', function (webClientData) {
    // 存储至映射表
     aSocket[socketIO.id] = socketIO;
    // 发送至Tomcat的数据中添加socket_id
    webClientData['sid'] = socketIO.id;
    // 发送String类型的数据至Tomcat
    nodeServer.write(JSON.stringify(webClientData));
   });
   // 客户端断开连接
   socketIO.on('disconnect', function () {
    console.log('DISCONNECTED FROM CLIENT');
   });
});
 // 从Tomcat接收数据
 nodeServer.on('data', function (data) {
   var jsonData = JSON.parse(data.toString());
   // 分发数据至客户端
   for (var i in jsonData.list) {
     aSocket[jsonData.list[i]['sid']].emit('pushToWebClient', jsonData.list[i].data);
  }
 });

上面的代码省略了一些逻辑,比如Node.js服务器从Tomcat接收的数据分为两种,一种是推送过来的数据,另外一种是响应请求的数据,这里统一处理推送过来的数据。

在处理通信时,Node.js发送至Tomcat的数据是String格式,而从Tomcat接收的数据为Buffer对象(8进制),需要转化为String之后再转化为json发送至客户端。

本文只是给出一个这样两次连接的简单例子,具体的业务中需要加入许多东西。既然在项目中引入了Node.js,就需要前端承担更多的事情,比如对数据的处理、缓存、甚至加入很多业务逻辑。

(0)

相关推荐

  • ASP.NET SignaiR 实现消息的即时推送,并使用Push.js实现通知的示例代码

    一.使用背景 1. SignalR是什么? ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务器代码可以立即向其推送内容,而不是让服务器等待客户端请求新的数据. 2.Push.js是什么?[需要浏览器支持H5Notifications] Notifications翻译过来即是通知.那么Push.js的通知又是什么样的,见下图:大多数在屏幕的右下角出

  • vue使用stompjs实现mqtt消息推送通知

    最近在研究vue+webAPI进行前后端分离,在一些如前端定时循环请求后台接口判断状态等应用场景用使用mqtt进行主动的消息推送能够很大程度的减小服务端接口的压力,提高系统的效率,而且可以利用mqtt消息通知建立一个独立于业务服务系统的消息通知服务,这个服务还可以与开发的语言无关,客户端既可以是安卓也可以是ios,也可以是java或者c#,python等.闲话不多扯,这里只是实现了在vue中使用mqtt的js客户端,后台用.net WEB API用的是c#的mqtt客户端 第一步:安装依赖 np

  • 使用 Javascript 实现浏览器推送提醒功能的示例

    本篇文章内容简单,速读只需两三分钟,通过这两三分钟的时间你就可以给自己的网站实现推送提醒的功能 Notification 类 简单明了,这个类就是负责推送消息的,只要用户当前没有关闭页面,及时是在使用其他程序,浏览器也能够将消息推送给用户 请求权限 我们在手机上都收到过消息推送,在接收推送之前我们会先将消息推送权限开放给应用.在浏览器中也一样,在使用浏览器推送之前,需要先获取权限 Notification.requestPermission().then(permission => { cons

  • JavaScript数据推送Comet技术详解

    JavaScript数据推送主要致力于webapp的在线推送服务,不用我们每次都像服务器去发送Ajax请求而主动从Server端推送数据到本地. 数据推送进化史: 1. HTTP协议简易轮询,保持着一个链接不放,或者通过前端不停的向后端发送请求 2. H5更新后有了WebSocket大大改善了双向和单向推送数据的便利性 3. SSE(Server-Send Event):服务器推送数据的新方式 Comet:基于 HTTP 长连接的服务器推送技术 本课时介绍Comet:基于 HTTP 长连接的服务

  • Node.js学习教程之HTTP/2服务器推送【译】

    前言 最近Node.js v8.4+版本发布带来了体验版的HTTP/2,你可以自己通过设置参数--expose-http2启动. 这篇文章,我将介绍HTTP/2最重要的一方面服务器推送并且创建一个小的Node.js程序案例来使用它.下面话不多说了,来一起看看详细的介绍吧. 关于HTTP/2 HTTP/2 的目的是通过支持完整的请求与响应复用来减少延迟,通过有效压缩 HTTP 标头字段将协议开销降至最低,同时增加对请求优先级和服务器推送的支持. 更多关于HTTP/2内容,请查看文章HTTP/2.

  • Node.js实现数据推送

    场景:后端更新数据推送到客户端(Java部分使用Tomcat服务器). 后端推送数据的解决方案有很多,比如轮询.Comet.WebSocket. 1. 轮询对于后端来说开发成本最低,就是按照传统的方式处理Ajax请求并返回数据,在学校的时候实验室的项目一直都采用轮询,因为它最保险也最容易实现.但轮询带来的通信资源的浪费是无法忽视的,无论数据是否改变,都照常发送请求并响应,而且每次HTTP请求都带有很长的头部信息. 2. Comet的概念是长连接,客户端发送请求后,后端将连接保持下来,直到连接超时

  • python 监听salt job状态,并任务数据推送到redis中的方法

    salt分发后,主动将已完成的任务数据推送到redis中,使用redis的生产者模式,进行消息传送 #coding=utf-8 import fnmatch,json,logging import salt.config import salt.utils.event from salt.utils.redis import RedisPool import sys,os,datetime,random import multiprocessing,threading from joi.util

  • SpringBoot使用异步线程池实现生产环境批量数据推送

    目录 前言 编写线程池配置类 编写异步服务 异步批量上报数据 总结 前言 SpringBoot使用异步线程池: 1.编写线程池配置类,自定义一个线程池: 2.定义一个异步服务: 3.使用@Async注解指向定义的线程池: 这里以我工作中使用过的一个案例来做描述,我所在公司是医疗行业,敏感数据需要上报到某监管平台,所以有一个定时任务在流量较小时(一般是凌晨后)执行上报行为.但特殊时期会存在一定要在工作时间大批量上报数据的情况,且要求短时间内就要完成,此时就考虑写一个专门的异步上报接口手动执行,利用

  • 浅谈如何通过node.js对数据进行MD5加密

    md5介绍:MD5是一种常用的哈希算法,主要用于对一些重要数据进行"签名",当然这些数据可以是任意的.最终得到的"签名"通常都是一个16或32位的十六进制的字符串. 实际工作开发中,是不会有人直接将密码明文直接放到数据库当中的.因为这种做法是非常不安全的,一般都要对其进行MD5加密!比如某用户的密码是"123456"(当然这样的密码也没有安全性可言),经过MD5处理后即为: "e10adc3949ba59abbe56e057f20f88

  • node.js微信小程序配置消息推送的实现

    在开发微信小程序时,有一个消息推送,它的解释是这样的. 消息推送具体的内容是下面的这个网址   https://developers.weixin.qq.com/miniprogram/dev/framework/server-ability/message-push.html,他介绍的也还可以,就是我这里换成了node代码. 消息推送 启用并设置消息推送配置后,用户发给小程序的消息以及开发者需要的事件推送,都将被微信转发至该服务器地址中. 在微信小程序的首页开发里面,开发设置中,微信的官网中,

  • 深入浅出了解Node.js Streams

    什么是流(steams) 流(stream)是 Node.js 中处理流式数据的抽象接口. Streams 不是 Node.js 独有的概念.它们是几十年前在 Unix 操作系统中引入的. 它们能够以一种有效的方式来处理文件的读.写,网络通信或任何类型的端到端信息交换. 例如,当你编写了一段程序用来读取文件时,传统的方法是将文件从头到尾读入内存,然后再进行处理.而使用流的话,你就可以逐块读取它,处理其内容而不将其全部保存在内存中. 以如下代码为例 const fs = require('fs')

  • node.js中stream流中可读流和可写流的实现与使用方法实例分析

    本文实例讲述了node.js中stream流中可读流和可写流的实现与使用方法.分享给大家供大家参考,具体如下: node.js中的流 stream 是处理流式数据的抽象接口.node.js 提供了很多流对象,像http中的request和response,和 process.stdout 都是流的实例. 流可以是 可读的,可写的,或是可读可写的.所有流都是 events 的实例. 一.流的类型 node.js中有四种基本流类型: 1.Writable 可写流 (例:fs.createWriteS

  • 浅析Node.js的Stream模块中的Readable对象

    我一直都很不愿意扯 nodejs 的流,因为从第一次看到它我就觉得它的设计实在是太恶心了.但是没办法,Stream 规范尚未普及,而且确实有很多东西都依赖了 nodejs 的流来实现的,所以我也只能捏着鼻子硬着头皮来扯一扯这又臭又硬的 nodejs 流对象了. nodejs 自带了一个叫 stream 的模块,引入它便可以得到一组流对象构造器.现在我只说最简单的 stream.Readable. 其实用过 nodejs 的几乎都接触过 Readable 的实例,只是平时没太在意而已.一个非常典型

  • 我的Node.js学习之路(三)--node.js作用、回调、同步和异步代码 以及事件循环

    一,node.js的作用, I/O的意义,(I/O是输入/输出的简写,如:键盘敲入文本,输入,屏幕上看到文本显示输出.鼠标移动,在屏幕上看到鼠标的移动.终端的输入,和看到的输出.等等)   node.js想解决的问题,(处理输入,输入,高并发 .如 在线游戏中可能会有上百万个游戏者,则有上百万的输入等等)(node.js适合的范畴:当应用程序需要在网络上发送和接收数据时Node.js最为适合.这可能是第三方的API,联网设备或者浏览器与服务器之间的实时通信)   并发的意义,(并发这个术语描述的

随机推荐