童 敏,张文盛,钱立三
基于Node.js的高性能站群系统设计与实现
童 敏,张文盛,钱立三
(安徽广播电视大学 信息技术与网络管理中心,安徽 合肥 230022)
站群系统是统一数据、标准和管理的建站模式,可以轻松建立多个站点,并在各站点间共享信息,从而显著减少信息孤岛现象。Node.js是javascript语言在服务器端的实现,采用V8高性能引擎,结合语言本身独特的异步特性,可以构建高性能网站。提出一种基于Node.js的网站架构,采用MVC、Widgets和SOA进行解耦,增加并行性,提高系统性能。在此架构上,设计和实现一套高性能站群系统,该系统结构清晰简单,可扩展性好,稳定性高,性能优越,适合高校使用。
Node.js;站群系统;MVC;Widgets;SOA
随着信息技术的不断发展,技术驱动和需求驱动让我们在许多领域开发软件,随之软件之间的关联又成为新的问题,形成信息孤岛。信息孤岛是指信息系统之间相互不关联,信息不能共享,数据不能交换,以及信息与业务流程和应用相互脱节。信息孤岛是信息化进程中的必然产物。人们尝试着从数据库、集成总线的方向努力把各个信息系统进行关联,但是总是不能如愿,孤岛依然普遍存在。具体到高校,由于每个部门和院系普遍都有网站,各个网站之间互相独立,自成一体,因此高校网站信息孤岛现象最为典型。网站信息孤岛有如下特点:技术架构千差万别,界面风格各显神通,安全防护形同虚设,稳定性无法保证,性能参差不齐,管理随意分散。
针对网站信息孤岛问题,目前通用的解决方案是采用站群系统。站群系统是指在统一规划、统一标准和统一技术构架基础之上,实现分级管理、分级维护、耦合程度高和基于特定权限共享呈送信息的网站集合[1]。站群系统中的所有站点遵从相对一致的网站运行和服务规范,能够互联互通,实行集群化管理。站群系统并不是多个网站的简单堆砌,站群系统的特点是统一建设、分级管理、信息共享和单点登录,此外站群系统还具有界面风格一致,安全防护可控,运行稳定,性能卓越,轻松建站,建设成本低等诸多优点[2]。
站群系统已经有很多成熟产品面世,功能丰富,可以定制。各高校正在不遗余力进采购和建设站群系统,逐步将分散的网站迁移到站群系统中。站群系统采用的技术架构主要有PHP,ASP.net和JSP,相比较而言,Node.js算后起之秀[3]。Node.js是javascript语言在服务器端的实现,解决了javascript只能应用在客户端的缺点。Node.js采用Chrome V8高性能引擎,能够将脚本直接编译成机器码运行,性能优异。Node.js 使用了一个事件驱动、非阻塞式I/O的模型,使其轻量又高效[4]。javascript是异步编程语言,单进程就可以承载大负荷处理任务。因此Node.js可以构建高性能网站,新的应用层出不穷[5]。本文采用Node.js构建高性能网站群系统,探讨设计和实现问题。
本架构采用MVC设计。MVC的全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计规范[6]。它是用一种业务逻辑、数据与界面显示分离的方法来组织代码,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑,达到减少编码的时间[7]。
本架构还采用SOA(Service-Oriented Architecture,面向服务架构)技术。SOA是一种使用松耦合的黑盒子服务构建业务应用的体系架构,这些服务可以通过编排连接在一起以实现特定的功能。SOA具有更易维护、更高的可用性和更好的伸缩性等优点。
本架构包括两层:前端和后端。前端和客户端直接交互,提供业务逻辑处理和html静态资源访问,采用Node.js实现。后端向前端提供数据存储和检索服务,采用ASP.net+SQL server 2005实现。系统结构如图1所示。
图1中,服务器端使用两台服务器,一台负责前端功能,一台负责后端功能。前端服务器安装Linux CentOS 7.2操作系统,运行Node.js。后端服务器安装Winows 2008 R2操作系统,运行II7(ASP.net)和SQL server 2005。客户端使用浏览器访问Node.js。Node.js接受用户请求,执行路由,定位视图模版,向后端请求数据,处理数据,渲染模版,返回最终结果给客户端。ASP.net提供Web接口管理数据,数据存储在SQL server 2005数据库中。Node.js访问Web接口获取数据,Web接口使用JSON(JavaScript Object Notation)返回操作结果。本架构中,前端负责View和Controller,后端负责Model。
图1 Node.js网站系统结构
Node.js采用Express框架提供前端服务。Express 是一个简洁而灵活的Node.js Web应用框架, 提供了一系列强大特性帮助创建各种Web应用和丰富的HTTP工具。使用 Express可以快速地搭建一个完整功能的网站。Express框架核心特性有:可以设置中间件来响应HTTP请求,定义路由表用于执行不同的HTTP请求动作,可以通过向模板传递参数来动态渲染HTML页面。
本架构设计小部件(Widgets)技术,使用中间件方式处理Widgets。Widgets是在视图中使用的可重用单元,使用面向对象方式创建复杂和可配置用户界面单元。传统的MVC和基于Widgets的MVC工作原理比较如图2所示。
传统MVC中一个页面对应一个Controller和一个View文件,Controller从多个Model获取数据,然后渲染View文件,并输出最终结果。基于Widgets的MVC,一个页面可以对应多个皮肤(Skin)文件。不同的Skin有不同的布局和风格,可以根据用户喜好选择,使网站表现丰富多彩[8]。Skin将不同的功能区域封装成不同的Widget。Widget只有一个Controller和一个View,通常只调用一个Model,功能单一,方便重用。
图2 传统MVC和基于Widgets的MVC比较
一个Skin通常有多个Widget占位符,一个Widget占位符代表一个Widget。Widgets中间件采用并行方法进行处理,同时处理所有Widget,等到所有Widget处理完成,再将Skin中的Widget占位符全部替换成对应结果,形成最终页面。
后端负责业务逻辑和数据存储,以Web接口对方式对外提供服务,采用JSON标准交换数据。JSON是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。本架构定义的JSON格式如下:
{
code=1,//成功代码
msg=’错误消息’,//出错消息,可选
data1=’’,//数据部分
data2=’’,//更多的数据
}
其中code指示操作是否成功,1表示成功,0表示失败。msg指出错误信息,code为1时可选,code为0时必须有。根据具体业务的不同,后面附上相应的业务数据。
现代网站通常采用cookie+session的方式执行状态控制,包括记录用户登录状态和对用户操作进行权限检查[9]。本架构中,状态控制主要由后端处理,包括session的生成、存储和检索,并使用cookie跟踪session ID。前端负责在客户端和后端之前传递cookie。当调用后端服务返回cookie信息时,前端将cookie再传给浏览器。当浏览器的请求中包含cookie时,前端就将cookie传给后端服务。
基于node.js的站群系统结构如图3所示。
图3 站群系统结构
图3中,站群系统由一个主站、多个子站和一个管理后台站点组成。在结构上各个站点是平行关系。在逻辑上,主站是所有子站和管理后台的入口,子站可以推送信息到主站,管理后台执行账户管理,配置主站和子站,发布和推送信息。
站群系统通常只配置一个域名,需要为各个站点规划URL。本系统中,在站点名称和URL之间建立直接映射。例如主站命名为portal,则访问http://域名/portal/就是访问主站。管理后台命名为manger。根据规则,主站URL是http://域名/portal,而不是 http://域名/。因此当访问http://域名/时,需要重定向到主站URL。
每个站点都需要创建一个路由文件,建立站点下所有页面到各自Skin的映射规则。例如访问http://域名/portal/search,实际上访问的皮肤文件是/var/wwwroot/themes/portal/skins/search.html。路由文件以站点名称命名,例如portal.js。
本系统中,为了减少表的数量,将所有的展示类信息归一化存储到单个表中,命名为文章表,可以存储多条信息如新闻和公告,也可以存储单条信息如学校简介、办公电话和校历等。除此之外还有站点表,栏目表,用户表和权限表。ER图如图4所示。
图4 ER图
图4中,站点表存储站点信息,一个站点表示为一条记录。一个站点可有拥有多个栏目。一个栏目可以拥有多个文章。一个用户有权维护多个栏目,一个栏目也可以有多个用户维护,是多对多关系。
站群系统维护多个站点,更容易遭受攻击,因此安全设计更要仔细[10]。本系统主要防范注入攻击,跨站脚本攻击,跨站请求伪造和枚举攻击,此外还进行数据库安全加固。
针对目前比较流行的脚本注入攻击,最有效方法是采用参数化查询,先编译SQL语句,将执行计划固定,再传参,确保最终执行逻辑没有偏差。微软推出LINQ语言,不但是ORM(Object Relational Mapping,对象关系映射)框架,而且也是参数化查询技术,只要使用得当,不存在注入漏洞。本系统后端采用ASP.net,使用LINQ操纵数据库。
跨站脚本攻击是一种极难防范的攻击[11]。针对跨站脚本攻击,通常对用户的输入执行严格检查,转义非法字符。文章表是防范重点,主要是内容字段。为了方便排版允许内容字段带有html代码,因此内容字段处理比较复杂。考虑到本系统中可以发表文章的地方只有后台站点,且只有授权用户才有权发表,合法用户执行跨站攻击的可能性很小。即使执行了跨站脚本攻击,如果将最后一道防线session保护好,就可以阻止权限窃取。本系统采用最小化保护策略,将包含session ID的cookie设置http only和path=/manager属性。
针对跨站请求伪造,为关键操作设置验证码,例如删除文章时,弹出验证码窗口,提示正在删除文章,要求输入验证码,验证码正确才允许删除。
枚举攻击是指当文章的ID采用自增整数时,如果显示文章页面URL是show?id=x,通过不断自增id的值,即可将所有文章枚举出来。本系统中文章ID采用随机生成的字符串,不可预测,没有枚举的可能。
数据库安全加固包括使用普通账户和执行逻辑删除。使用普通账户而不是超级用户连接数据库,该普通账户只能操作站群数据库,且只能select,create和update。采用逻辑删除策略,当删除数据时将deleted字段从0改成1。
重点给出widget的实现代码。以portal的默认文档index.html为例,其路由规则如下:
router.get('/', function (req, res, next) {// 对/ GET的路由规则
res.context = {};
res.context._r_widget = true;//有widget
res.context._r_widget_skin = 'index.html';//皮肤文件
next();
});
index.html前两行如下:
定义了两个widget:header和banner。
处理widget的中间件代码如下:
const reg = new RegExp(/
function widget(req, res, next) {
var skin = path.join(req.site.paths.skins, res. context ._r_widget_skin); //取skin路径
fs.readFile(skin, 'utf8', (err, data) => { /读skin文件
var widgets = [],temp = {},runs = [],widget_ids = [];
while ((temp = reg.exec(data)) !== null) {//解析出所有的widget
widgets.push({holder: temp[0],id: temp[1]});
widget_ids.push(temp[1]);}
//执行widget的data.js脚本从后端获取数据,用数据渲染模版
widgets.forEach(function (e) {//对于每个widget
runs.push(function (callback) {//定义渲染过程,后面同时发射
var _w_path = path.join(req.site.paths. widget, e.id),
_w_js = path.join(_w_path, 'data.js'), //data.js
_w_html = path.join(_w_path, 'view'); //view.html
//准备结果对象
var result = {site: req.site, _widget_name: _w_real.name, _widget_path: util.format('widgets/%s', _w_real.name) };
fs.accessSync(_w_js, fs.R_OK); //data.js存在
//执行data.js
require(_w_js)(req, res, utils). then(function (r) {
r.site = req.site;
r._widget_name = result._widget_name;
r._widget_path = result._widget_path;
//用数据渲染模版
var content = template.renderFile (_w_html, r);
callback(null, {js: _w_js, holder: e.holder, content: content}); //渲染结果传递给回调函数,替换占位符
});
});
}, this);
//并发执行前面的渲染过程,传入回调函数。全部执行完成,才回调。
async.parallel(runs, function (err, result) {
result.forEach(function (e) {//用渲染结果替换占位符
data = data.replace(e.holder, e.content);});
res.send(data);
next();
});
});
}
子站可以将新闻推送到主站,实现信息共享。根据ER图,一条新闻只能对应一个站点[12]。因此新闻推送将创建两条文章记录,一条是子站点所有,一条是主站点所有。两条记录通过PID(party ID,对方ID)字段指向对方,即主站新闻的PID字段设置为子站新闻ID,主站新闻的PID字段设置为子站新闻ID。主站新闻重要性高于子站。当主站新闻未通过审核时,修改子站新闻将同步到主站新闻。当主站新闻通过审核后(审核标志为1),修改子站新闻将无法同步到主站新闻。反过来,主站新闻修改总是同步到子站新闻。
站群系统建设不但是解决信息孤岛现象的重要手段,也是推进高校信息化向前发展的一个抓手。本文通过Node.js构建高性能站群系统,采用了诸多热门技术,包括MVC,Widget和SOA等,结构轻量,稳定可靠,给出站群系统建设的新模式。实际部署表明系统支持高并发请求,用户体验良好,完全满足需求。
[1] 陈洁, 雷萌. 基于脉冲耦合神经网络的乳鼠心肌细胞图像增强[J]. 软件, 2018, 39(02): 41-43.
[2] 李军. 高并发Web系统的设计与优化[D]. 北京交通大学, 2009.
[3] 郭家宝. Node. js开发指南[M]. 人民邮电出版社, 2012.
[4] 闫晓甜, 李玉斌. 微信平台支持下的高校微课程设计与应用研究[J]. 中国远程教育, 2015(07): 52-57+80.
[5] 冼学辉. 基于Web的实时信息推送技术的研究[D]. 华北电力大学, 2013.
[6] 刘欣. 基于MVC模式的Web软件系统开发框架设计与实现[D]. 山东大学, 2013.
[7] 宋婷婷, 徐世许. 基于全采样和L1范数降采样的卷积神经网络图像分类方法[J]. 软件, 2018, 39(02): 75-80.
[8] 付向东, 孙宁, 何长鹏. 高等院校站群系统建设与实践[J]. 中国教育信息化, 2014(05): 82-84.
[9] 贺盈. 重庆文理学院站群系统开发研究与实现[D]. 电子科技大学, 2012.
[10] 杨盾, 王小鹏. 应对DDoS攻击的SDN网络安全特性研究[J]. 软件, 2018, 39(03): 175-180.
[11] 罗淑元. Android系统中Widget的设计与实现[D]. 北京交通大学, 2012.
[12] 陈培君. 基于SOA的数字校园综合信息服务平台的研究与设计[D]. 电子科技大学, 2013.
Design and Implementation of High Performance Station Cluster System Based on Node.js
TONG Min, ZHANG Wen-sheng, QIAN Li-san
(Anhui Radio and TV University Information Technology and Network Management Center, Hefei, Anhui, 230022)
Station cluster system is station model with unified data, standard and management, which can establish a number of sites easily and share information between sites, and reduce information island phenomenon significantly. Node.js is implementation of JavaScript language on server side, with V8 high performance engine, combined with unique asynchronous features of language, it can build high performance web site. The article proposes a website architecture based on Node.js, to decouple with MVC, Widgets and SOA, increase parallelism and improve system performance. Under the framework, the article discusses design and implemention of a set of high performance station cluster system, which has advantages of clear and simple structure, good scalability, high stability and superior performance, and is suitable for colleges and universities.
Node.js; Station cluster system; MVC; Widgets; SOA
TN711
A
10.3969/j.issn.1003-6970.2018.08.003
安徽广播电视大学软件开发项目“电大移动服务平台”(编号RJ17-01)
童敏(1992-),女,助理工程师,硕士,研究方向:计算机网络应用;张文盛(1980-),男,高级工程师,本科,研究方向:计算机网络应用;钱立三(1970-),男,高级工程师,本科,研究方向:计算机网络应用。
本文著录格式:童敏,张文盛,钱立三. 基于Node.js的高性能站群系统设计与实现[J]. 软件,2018,39(8):09-13