WebSocket 与Node.js 结合实现公交系统实时位置查询
2019-06-15钱立
钱 立
(四川职业技术学院,四川 遂宁 629000)
1 引言
伴随着智能手机的全面普及,人们在衣食住行各方面依赖手机查询各种有用信息[1]。无车上班族每天出行几乎都依赖城市公交系统,这类人会习惯性查询实时公交信息。公交实时位置查询带来两大好处,一是节省乘客等待时间,基本上可以比较“准时”地赶上车,一定程度上减少各站台乘客拥挤状态,二是社会心理学方面,可缓解乘客等待时的焦虑,增加社会和谐度。
2 公交实时位置功能分析
公交系统实时位置查询功能虽说简单但又有并发响应难度。简单即是说任何一个乘客进入公交系统查询页面,选择将要乘坐的公交路数和往返方向,比如203 路(从育才西路到四川职业技术学院方向),那么在查询结果展示页面上将显示出这个线路上全部站台多个车辆的运行和到站实时情况。查询仅需提供两个参数,一个是公交路数,另一个是往或返的方向。
有难度即是说对于一个中大型城市,公交系统往往有几十路或上百路公交车,每一路公交分往返两个方向,每一路公交的站台一般有十多个,高峰上下班期间假定平均每个站台有15 名乘客,其中有10 名乘客会使用公交实时位置查询。那么这个公交查询系统高峰期间每秒种可能提供的查询请求数万次左右,所以该系统应当有较高的请求并发性,能及时响应。
3 相关技术介绍
乘客查询公交实时位置都会使用Http 方式连接到服务器,以往使用技术Long POLLing 等轮询方式来实现实时,但这种技术浪费大量网络、服务器资源和等待时间,不是最好解决方案。在HTML5 技术不断推陈出新后,使用WebSocket 可提供更加高效的实时数据交互。
WebSocket 是HTML5 提供的一种在单个TCP连接上进行全双工通讯的协议[2]。可以看做是Http 协议的一个升级,使得在服务器和浏览器之间能进行双向交流,只要连接创建后服务器就可以实时推送消息给浏览器,这是一个重要的改变。主要API 有:连接建立时触发open 事件,onopen()进行处理;客户端接收服务端数据时触发message 事件,onmessage()进行处理;使用send()发送数据,close()关闭连接。[3-4]
通过分析知道查询系统需要能及时响应高并发请求,现阶段Node.js 技术用来做高并发是一种很好的选择。Node.js 是一个基于Chrome V8引擎的JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式I/O 的模型,使其轻量又高效。Node.js 适合运用在高并发、I/O 密集、少量业务逻辑的场景。[5]
PC 和手机上的现代浏览器都支持WebSocket技术,Node.js 为了能支持WebSocket 需要第三方软件支持包(这类软件包很多,本文选用ws)。ws 是应用于Node.js 下的实现了Web-Socket 功能的一个软件包,它简单快速,集成了客户端和服务端测试能力。ws 有两个主要类WebSocket.Server 和WebSocket[5]。WebSocket.Server 主要事件是connection 事件,与Html5 的WebSocket API 类似。
4 设计思路及数据格式设计
对于公交系统实时位置查询,本文仅考虑浏览器发出查询请求,服务器查询得到实时位置数据推送给浏览器这两个过程,不考虑各路公交GPS 位置的收集、发送给服务器判断位置及存储等其余过程。
先考虑一路公交车往返两个方向的查询及显示,多路公交同样处理。Node.js 结合Express做页面查询busInfo.htm,并且设计一个Query-Server.js 提供服务端查询服务。QueryServer.js 需引用ws 模块以便Node.js 支持WebSocket。
以站台为基准来设计数据格式,将某路公交线路上的站台依次编号1、2、……、n,各编号有站台名称,来车状态两种(0:表示未到,1:表示到站)。考虑数据精简,选择JSON 格式,实例公交203 路车从育才西路到四川职业技术学院方向数据表示如下:
{"RouteID":203,//公交车路数
"GoBack":0,//0:往方向1:返方向
"stations":[
{"xuhao":1,"status":0, "name":" 育才西路"},
{"xuhao":0,"status":1, "name":" 育才西路出"},
{"xuhao":2,"status":0, "name":" 育才路口"},
……,
{"xuhao":13,"status":1,"name":" 环岛商务中心"},
{"xuhao":0,"status":0,"name":" 环岛商务中心出"},
{"xuhao":14,"status":0,"name":" 四川职业技术学院"}]}
含义描述:RouteID 表示公交路数;GoBack表示往返;stations 表示站台,是一个JSON 数组。数组中每个站台有三个属性,xuhao 表示站台序号(xuhao 为0 表示某两个站台之间),name 表示站台名,status 为1 表示对应站台序号有车,为0 表示无车。现在站台的情况是:在育才西路与育才路口之间的途中有车,在环岛商务中心有车到站。
5 开发实现
5.1 服务器端QueryServer.js
const WebSocket = require(’ws’);
const wss = new WebSocket.Server ({port:8010});
wss.on (’connection’,function connection(ws,req){
// 根据req.url 中车次routeID 和往返方向0 查询
var busRouteInfo=getBusRouteInfo(routeID,0);
ws.on (’message’, function incoming(message){
ws.send(busRouteInfo);
});
var tm = setInterval(function(){
try { busRouteInfo=getBusRouteInfo(routeID,0);
ws.send(busRouteInfo);
}catch(e){
consol e.log("出错,清除定时器"+e);
clear Interval(t m);
}},5000);//每隔5 秒钟发送一次更新});
console.log (’ 服务器运行,绑定在端口8010’);
其中getBusRouteInfo(routeID,0)这个方法(需依据后台数据库单独设计)根据提供的公交路数和往返方向参数从数据库查询到数据后以JS O N 格式返回。服务器端设置了一个定时器,每隔5 秒钟就重新查询更新公交位置信息。
5.2 客户端busInfo.htm
//打开一个WebSocket
var ws = new WebSocket ("ws://192.168.1.1:8010/RouteNo="
+checi.value+"&goback=0");
ws.onopen = function(){
ws.send (" 请查询"+checi.value+" 路公交车");
};
wws.onmessage = function (evt) {
var busRouteInfo = evt.data;
jsonRoute = JSON.parse(busRouteInfo);// 先删除所有子节点
while(myRoute.hasChildNodes()){
myRoute.removeChild (myRoute.firstChild);
}
busStartEnd.innerText = "";
var number = jsonRoute.stations.length;
myLine.style.height = number*40+’px’;
var len = jsonRoute.stations.length;
busStartEnd.innerText = " 公交"
+checi.value+" 路,始发站:
+jsonRoute.stations [0].name+"---〉终点站:"
+jsonRoute.stations[len-1].name;
for(var i in jsonRoute.stations){
var tmpDiv = document.createElement(’div’);
var tmpImg = document.createElement(’img’);
var tmpSpan = document.createElement(’span’);
if (jsonRoute.stations [i].status == 0){
tmpImg.src=’Images/kong.png’;
}else{ tmpImg.src=’Images/bus.png’; }
if (i%2==1){tmpSpan.innerText = "-- 途中";
}else{
tmpSpan.innerText =
jsonRoute.stations[i].xuhao+
" "+jsonRoute.stations[i].name;
}
tmpDiv.append(tmpImg);
tmpDiv.append(tmpSpan);
myRoute.append(tmpDiv);
}//end for
};//end onmessage()
图1 公交203 路实时运行情况
浏览器端使用WebSocket 方式先创建与服务器的链接,当服务器推送消息来时,取出该消息解析为JS O N 格式,然后依次创建相应的页面元素显示,运行效果如上图1。
6 总结
智慧城市为了实现其智慧功能要求城市公交提供更优的服务。城市公交实时位置查询是无车上班族出行的一个重要需求。本文分析了公交实时位置查询系统应具备高并发处理能力,采用Node.js 结合Express 实现Web 页面浏览查询,在Web 页面使用HTML5 的WebSocket 技术,服务器端使用ws 组件提供WebSocket 支持与之结合,实现了服务器端更高效的实时推送位置信息。HTML5 的WebSocket 技术和Node.js 结合使得实现公交系统实时位置查询变得更加简洁高效。