王仡捷
目前,互聯(lián)網(wǎng)技術(shù)被廣泛應(yīng)用到科研教育、物流倉(cāng)儲(chǔ)、金融證券、電子商務(wù)、電子政務(wù)等領(lǐng)域,使人類社會(huì)的自動(dòng)化與信息化水平不斷提高.在這一過(guò)程中,網(wǎng)站的訪問(wèn)流量越來(lái)越大,并發(fā)程度越來(lái)越高,特別是大數(shù)據(jù)和人工智能時(shí)代的來(lái)臨,這種情況更為突出.因此,如何使Web服務(wù)器適應(yīng)高并發(fā)訪問(wèn)已成為現(xiàn)代軟件設(shè)計(jì)的重點(diǎn).相關(guān)學(xué)者提出了Mapreduce與云計(jì)算解決的方案.對(duì)于基于這種方案建立的網(wǎng)站,每天有數(shù)以億計(jì)的用戶在使用,維護(hù)比較困難,并且建設(shè)周期長(zhǎng),費(fèi)用比較高[1].后來(lái),計(jì)算機(jī)學(xué)者提出了Node.JS 的分布式服務(wù)器集群方案,更好地解決了訪問(wèn)用戶多和服務(wù)器并發(fā)操作頻次高的問(wèn)題,使互聯(lián)網(wǎng)普適性與人類社會(huì)共享化水平得到進(jìn)一步的提高.
Node.JS 為JavaScript 運(yùn)行環(huán)境,封裝Chrome V8引擎.Node.JS對(duì)特殊用例進(jìn)行優(yōu)化,并且提供替代的API,使Chrome V8 引擎能夠在非瀏覽器環(huán)境中運(yùn)行.其主要目的就是使服務(wù)器端執(zhí)行并且運(yùn)行JavaScript 代碼.一直以來(lái),JavaScript 都是以瀏覽器作為基礎(chǔ)的客戶端腳本語(yǔ)言,有了Node.JS 技術(shù)之后,JavaScript 不再只依賴于瀏覽器解析,還能使其代碼在服務(wù)器端運(yùn)行,使其成為服務(wù)器端語(yǔ)言.因?yàn)镹ode.JS 具有異步非阻塞特點(diǎn),其能夠在高并發(fā)、長(zhǎng)連接的環(huán)境中具有明顯優(yōu)勢(shì).所以,本文以Node.JS作為基礎(chǔ)設(shè)計(jì)高并發(fā)網(wǎng)絡(luò)應(yīng)用架構(gòu).
使用Node.JS 技術(shù)設(shè)計(jì)高并發(fā)網(wǎng)絡(luò)應(yīng)用架構(gòu),可以快捷、簡(jiǎn)單地創(chuàng)建互聯(lián)網(wǎng)應(yīng)用和輕量級(jí)服務(wù)平臺(tái).高并發(fā)網(wǎng)絡(luò)應(yīng)用架構(gòu)由數(shù)據(jù)存儲(chǔ)層、負(fù)載均衡層和核心處理層構(gòu)成,各層有自己獨(dú)立的功能,又相互協(xié)作無(wú)法分離.在進(jìn)行設(shè)計(jì)的過(guò)程中,利用合適的負(fù)載均衡算法對(duì)用戶情況進(jìn)行分配,可有效緩解負(fù)載壓力,降低用戶的響應(yīng)時(shí)間.利用核心處理層實(shí)現(xiàn)網(wǎng)絡(luò)應(yīng)用前后端業(yè)務(wù)流程與內(nèi)部邏輯,核心處理層為架構(gòu)基礎(chǔ),也是網(wǎng)絡(luò)應(yīng)用中央控制模塊,能夠?qū)I(yè)務(wù)邏輯進(jìn)行處理,實(shí)現(xiàn)交互模塊和內(nèi)部模塊通信的管理.數(shù)據(jù)存儲(chǔ)層能夠存儲(chǔ)數(shù)據(jù),通過(guò)分布式存儲(chǔ)使數(shù)據(jù)存儲(chǔ)性能瓶頸和功率問(wèn)題得到解決.整體網(wǎng)絡(luò)應(yīng)用將事件驅(qū)動(dòng)機(jī)制、負(fù)載均衡技術(shù)與Node.JS 平臺(tái)作為基礎(chǔ),用戶通過(guò)單線程的方式處理請(qǐng)求,使服務(wù)器資源開(kāi)銷(xiāo)得到縮小,通過(guò)異步非阻塞I/O模型使CPU 資源使用率增加[2].圖1 為高并發(fā)網(wǎng)絡(luò)應(yīng)用架構(gòu).
圖1 高并發(fā)網(wǎng)絡(luò)應(yīng)用架構(gòu)
在該架構(gòu)中,Node.JS技術(shù)是基礎(chǔ),用于快速地搭建響應(yīng)速度快、易于擴(kuò)展的網(wǎng)絡(luò)應(yīng)用.然而對(duì)于GZIP編碼、靜態(tài)文件、HTTP緩存、SSL處理、負(fù)載平衡和反向代理等,都可以通過(guò)Nginx 來(lái)完成,從而減小Node.JS 的負(fù)載,并通過(guò)Nginx 強(qiáng)大的緩存來(lái)節(jié)省網(wǎng)站的流量從而提高網(wǎng)站的加載速度.Nginx技術(shù)能夠承受高負(fù)載的考驗(yàn),根據(jù)官方數(shù)據(jù)顯示,最高能夠支持50 000個(gè)并發(fā)連接線路.Nginx的穩(wěn)定性比較高,使用分階段資源分配技術(shù),使其CPU與內(nèi)存占用率低,避免活動(dòng)連接,此特點(diǎn)能夠使Nginx從容地應(yīng)對(duì)高并發(fā)訪問(wèn)等問(wèn)題對(duì)網(wǎng)絡(luò)穩(wěn)定的影響.Nginx 還具備高部署的功能,基于正常服務(wù)改變負(fù)載均衡算法.核心處理模塊能夠?qū)I(yè)務(wù)邏輯進(jìn)行處理,從而展現(xiàn)視圖,主要由控制層、內(nèi)存緩存服務(wù)、數(shù)據(jù)訪問(wèn)層與視圖層等部分構(gòu)成.各部分相互連接,使網(wǎng)絡(luò)應(yīng)用構(gòu)架松耦合性與強(qiáng)可擴(kuò)展性得到保證.圖2 為核心處理層四部分基本交互時(shí)序,通過(guò)圖2可以清楚地看到不同部分的交互時(shí)序流程[3].
圖2 核心處理層四部分基本交互時(shí)序
視圖層的UI展現(xiàn)層為EJS,其為基于Node.JS的高并發(fā)模塊引擎,使用過(guò)程方便,具有強(qiáng)大的功能,在前后端數(shù)據(jù)交互過(guò)程中性能良好.將EJS作為視圖層核心技術(shù),能夠使應(yīng)用開(kāi)發(fā)的效率得到提高.
在數(shù)據(jù)存取抽象操作過(guò)程中,數(shù)據(jù)訪問(wèn)層為主要操作接口,是具備操作一致性的數(shù)據(jù)訪問(wèn)接口,方便業(yè)務(wù)邏輯的統(tǒng)一調(diào)用.將MongoDB 數(shù)據(jù)庫(kù)作為網(wǎng)絡(luò)架構(gòu),利用Mongoose 使MongoDB 的數(shù)據(jù)操作得到實(shí)現(xiàn).數(shù)據(jù)訪問(wèn)層的操作效率和網(wǎng)絡(luò)應(yīng)用架構(gòu)整體性能具有密切關(guān)系,良好數(shù)據(jù)庫(kù)和驅(qū)動(dòng)程序能夠進(jìn)一步增強(qiáng)網(wǎng)絡(luò)應(yīng)用的高并發(fā)能力.
在網(wǎng)絡(luò)應(yīng)用控制層中使用Express 框架,目的是將Node.JS 作為基礎(chǔ)的高并發(fā)網(wǎng)絡(luò)架構(gòu),進(jìn)一步地增強(qiáng)架構(gòu)整體可擴(kuò)展性與靈活性,方便在未來(lái)使用過(guò)程中的維護(hù)和升級(jí).在實(shí)際使用的過(guò)程中,通過(guò)需求使業(yè)務(wù)邏輯設(shè)計(jì)得到實(shí)現(xiàn).在業(yè)務(wù)邏輯升級(jí)、增強(qiáng)與更換的過(guò)程中,通過(guò)此框架很容易將全新功能融入進(jìn)來(lái)[4].
內(nèi)存緩存服務(wù)層指的是應(yīng)用架構(gòu)輔助層.增加內(nèi)存緩存服務(wù)層,使得到數(shù)據(jù)時(shí)間與處理時(shí)間得以改善,有效實(shí)現(xiàn)網(wǎng)絡(luò)應(yīng)用高并發(fā)的性能.Redis為實(shí)際工程中最佳選擇,讀寫(xiě)性能良好.Redis的查詢速度較快,主要是因?yàn)槠淠軌蛲ㄟ^(guò)TCP對(duì)數(shù)據(jù)直接訪問(wèn),還能夠并發(fā)海量高速讀寫(xiě)需求.將高并發(fā)用戶訪問(wèn)環(huán)境作為基礎(chǔ),在用戶使用和體驗(yàn)過(guò)程中以響應(yīng)速度為重點(diǎn),實(shí)現(xiàn)用戶對(duì)數(shù)據(jù)頻繁地訪問(wèn),在Redis 中實(shí)現(xiàn)用戶頻繁訪問(wèn)數(shù)據(jù)的存儲(chǔ),降低數(shù)據(jù)庫(kù)的訪問(wèn)頻率,利用Redis高效化讀寫(xiě)性能降低應(yīng)用的響應(yīng)速度,使用戶體驗(yàn)得到提高.
數(shù)據(jù)存儲(chǔ)層為架構(gòu)基礎(chǔ)數(shù)據(jù)層,能夠?qū)崿F(xiàn)對(duì)業(yè)務(wù)數(shù)據(jù)持久化地存儲(chǔ).為了適應(yīng)高并發(fā)網(wǎng)絡(luò)應(yīng)用架構(gòu)的需求,一般都使用MongoDB,其海量數(shù)據(jù)分布式計(jì)算與存儲(chǔ)具有一定的優(yōu)勢(shì),并且具備可擴(kuò)展性、可用性、靈活性與安全性.MongoDB對(duì)大數(shù)據(jù)存儲(chǔ)效率與性能還能夠?qū)崿F(xiàn)完整索引、分布式存儲(chǔ)與自動(dòng)分片等功能[5].
上述設(shè)計(jì)的高并發(fā)網(wǎng)絡(luò)應(yīng)用架構(gòu),基于Node.JS技術(shù),使技術(shù)社區(qū)網(wǎng)絡(luò)得到實(shí)現(xiàn).通過(guò)Java編程語(yǔ)言對(duì)后臺(tái)框架與邏輯進(jìn)行設(shè)計(jì).由于架構(gòu)中央控制層為核心處理層,使業(yè)務(wù)邏輯主體與第三方組件交互得到實(shí)現(xiàn),包括緩存組件、數(shù)據(jù)庫(kù)等.圖3為技術(shù)社區(qū)網(wǎng)絡(luò)應(yīng)用功能的結(jié)構(gòu).
圖3 技術(shù)社區(qū)網(wǎng)絡(luò)應(yīng)用功能的結(jié)構(gòu)
基于Node.JS 準(zhǔn)則規(guī)范實(shí)現(xiàn)新型框架設(shè)計(jì),提高Web應(yīng)用開(kāi)發(fā)效率,和傳統(tǒng)框架對(duì)比有效性有所提高.此架構(gòu)模式較為普通,通過(guò)分層思想實(shí)現(xiàn)分區(qū)分開(kāi)地展示,模型表示為服務(wù)器端數(shù)據(jù)結(jié)構(gòu),前端表現(xiàn)層為視圖,控制器能夠?qū)I(yè)務(wù)邏輯進(jìn)行實(shí)現(xiàn).
業(yè)務(wù)控制層主要目的就是承上啟下,并且兼顧邏輯層.接收前端傳輸用戶輸入,對(duì)其進(jìn)行格式化,在業(yè)務(wù)邏輯接口中實(shí)現(xiàn)數(shù)據(jù)的傳遞,并且對(duì)數(shù)據(jù)開(kāi)展深加工處理.前后相互銜接過(guò)程主要包括以下內(nèi)容:
(1)利用Node.JS內(nèi)置對(duì)象,能夠使前端和后端數(shù)據(jù)交互實(shí)現(xiàn),利用Request 對(duì)象得到前臺(tái)輸入數(shù)據(jù)信息,Response對(duì)象能夠使業(yè)務(wù)數(shù)據(jù)和結(jié)果通過(guò)后臺(tái)處理,之后發(fā)送到前端,并且利用相應(yīng)方式展現(xiàn)在頁(yè)面中.
(2)整合數(shù)據(jù)訪問(wèn)層和業(yè)務(wù)控制層,將數(shù)據(jù)訪問(wèn)層耦合到相應(yīng)模塊的業(yè)務(wù)控制層中,也就是業(yè)務(wù)控制層對(duì)數(shù)據(jù)加工處理之后,再通過(guò)數(shù)據(jù)訪問(wèn)層實(shí)現(xiàn)數(shù)據(jù)持久化操作.
此應(yīng)用系統(tǒng)是關(guān)于技術(shù)社區(qū)的,所以應(yīng)用包括回復(fù)、郵件、標(biāo)簽、話題、用戶、上傳和聚合信息等控制器.上述控制器能夠?qū)崿F(xiàn)模塊業(yè)務(wù)邏輯,利用數(shù)據(jù)訪問(wèn)層與松耦合的方式交互,保證整體結(jié)構(gòu)的良好性和易擴(kuò)展性[6].圖4 為數(shù)據(jù)存儲(chǔ)的流程.
圖4 數(shù)據(jù)存儲(chǔ)的流程
EJS 框架屬于系統(tǒng)架構(gòu)和技術(shù)社區(qū)中視圖引擎展示層核心前端的展示框架,EJS為實(shí)際使用過(guò)程中的前端展示組件.一般都是和視圖模塊、EJS框架、錯(cuò)誤處理組件、視圖工具組件相互結(jié)合,其中,DJS 框架和錯(cuò)誤處理組件是主要部分.模板的創(chuàng)建為頁(yè)面展示與業(yè)務(wù)邏輯的分離,也就是動(dòng)靜分離,利用CSS 層與Html 層疊樣式將靜態(tài)內(nèi)容展現(xiàn)出來(lái),通過(guò)Java代碼得到后端傳輸數(shù)據(jù)動(dòng)態(tài)創(chuàng)建業(yè)務(wù)模型.
頁(yè)面展示部分為Html 結(jié)合CSS 靜態(tài)代碼片斷,由于要展示在瀏覽器中,所以滿足W3C標(biāo)準(zhǔn).應(yīng)用業(yè)務(wù)邏輯利用Java代碼實(shí)現(xiàn),接收Response對(duì)前端數(shù)據(jù)發(fā)送,實(shí)現(xiàn)數(shù)據(jù)格式化處理,更方便實(shí)現(xiàn)對(duì)用戶的展現(xiàn).
正確使用日志在程序設(shè)計(jì)人員編寫(xiě)程序的過(guò)程中尤為重要,調(diào)試信息也是記錄在日志中的.日志模塊基于Seelog 實(shí)現(xiàn)開(kāi)發(fā),根據(jù)Level 的不同值控制不同類型日志的輸出,從而簡(jiǎn)化開(kāi)發(fā)程序與部署程序過(guò)程,提高實(shí)用性.一般地,在程序開(kāi)發(fā)過(guò)程中設(shè)置Level 值,在程序部署過(guò)程中提高Level值,對(duì)開(kāi)發(fā)過(guò)程中調(diào)試信息屏蔽.日志模塊在記錄日志時(shí)融入了Seelog部署中的思想,根據(jù)不同Level 值記錄日志.但Webgo 日志系統(tǒng)是輕量級(jí)的,僅利用系統(tǒng)自帶的接口傳輸信息,用戶通過(guò)此接口實(shí)現(xiàn)輸出和自定義設(shè)置[7].
在幾年的時(shí)間里,Node.JS 逐漸發(fā)展成為一個(gè)成熟的開(kāi)發(fā)平臺(tái),吸引了許多開(kāi)發(fā)者.有許多大型高流量網(wǎng)站都采用Node.JS進(jìn)行開(kāi)發(fā),此外,開(kāi)發(fā)人員還可以使用他開(kāi)發(fā)一些快速移動(dòng)Web框架.
利用Node.JS技術(shù)解決異步并發(fā)網(wǎng)絡(luò)應(yīng)用架構(gòu)問(wèn)題,和不同組件技術(shù)相互結(jié)合,保證了架構(gòu)性能,提高了擴(kuò)展性.在實(shí)踐過(guò)程中,利用業(yè)務(wù)需求改變各個(gè)維度具體實(shí)現(xiàn)方案,通過(guò)最前端負(fù)載均衡到最后底層分布式數(shù)據(jù)存儲(chǔ)都能夠使用不同實(shí)現(xiàn)方式創(chuàng)建系統(tǒng),對(duì)高層服務(wù)接口與平臺(tái)一致性進(jìn)行保證,使中小型網(wǎng)絡(luò)對(duì)中等規(guī)模高并發(fā)的性能需求得到滿足.