郭政健,楊 軍
(北京郵電大學自動化學院,北京 100876)
企業(yè)的生產管理信息化建設主要通過建立企業(yè)資源計劃(ERP)、制造執(zhí)行系統(MES)、過程控制系統(PCS)等,來實現計劃層、執(zhí)行層及設備層的有機結合。其中的ERP 實現對企業(yè)內部資源和生產計劃的有效管理,PCS 完成對生產過程和車間設備的及時管控;而位于執(zhí)行層的MES 系統則擔當協調和傳遞企業(yè)計劃與實際生產信息橋梁的角色,在制造業(yè)信息化過程中起著越來越重要的作用[1]。
隨著隨著企業(yè)員工對移動辦公和遠程工作的需求不斷上升,信息管理系統移動化是企業(yè)提升管理能力和產品質量、降低生產運作成本、應對市場競爭的客觀需要。
Web 應用具有天然的跨平臺優(yōu)勢,采用傳統開發(fā)模式開發(fā)MES 應用,在開發(fā)桌面應用的同時,根據需求往往需要相應開發(fā)Android 和IOS 兩大平臺的APP,不僅造成了成本上升和開發(fā)周期延長,也會加重小型企業(yè)的經營負擔。
近些年來,利用Web 技術開發(fā)MES 系統的實踐與論文設計越來越多。但經過調研發(fā)現,這些Web系統或者只使用落后技術如JSP 進行開發(fā),或是沒有有效利用Web 技術的新特性,因而造成應用性能不足、體驗較差、開發(fā)部署成本較大等問題。隨著Web 前后端技術的不斷發(fā)展,Chrome 瀏覽器V8 內核性能的提升,Web 應用已經從最初用于單純展示信息使用的靜態(tài)頁面發(fā)展成了具有成熟開發(fā)架構,可以處理復雜業(yè)務需求的應用。本文將從Web 前端SPA 技術與微服務化、Web 后端技術選型及設計、WebSocket 及WebWoker 的應用,結合MES 系統的具體功能場景進行討論實現,在一定程度上提升了MES 系統利用Web 技術跨平臺的性能和體驗。
SPA(Single Page Application)技術,即為單頁應用技術。它將所有的活動局限在一個Web 頁面中,所有業(yè)務功能都是其子模塊,這些子模塊通過特定的方式掛接到頁面中[2]。單頁Web 應用只加載單個HTML 頁面,在用戶與應用程序交互時動態(tài)更新該頁面的Web 應用程序,通常使用JSON 數據格式進行數據交換。其具有以下顯著優(yōu)點:
(1)更好的用戶體驗,因為不需要再切換頁面時發(fā)起二次HTTP 請求獲取新的HTML。
(2)減輕服務器壓力,因為頁面所需的資源(HTML CSS JS 等),在一次請求中就加載完成,也不需刷新地動態(tài)加載。
(3)經典MVC 開發(fā)模式,前后端各負其責,程序耦合度低利于維護。
SPA 技術在帶來性能及體驗優(yōu)化的同時,同樣存在著一些問題:由于應用只有一個HTML 頁面,它不利于搜索引擎優(yōu)化(SEO),同時靜態(tài)資源的一次性獲取會造成應用首屏加載相對緩慢。不過對于MES 系統的應用場景,這些缺點將變得無關緊要。而其可以提供快速流暢的用戶體驗和交互特性,非常適合于制造執(zhí)行系統即時通信,快速反應的需求。
SPA 應用技術的核心是前端路由攔截,可以通過HTML5 提供的History API 進行實現,核心代碼如下:
class Route {
constructor (routeMap) {
this.routeMap = routeMap;
this._bindPopState();
}
init (path) {
path = Route.correctPath(path);
history.replaceState({path: path}, '', path);
this.routeMap[path] && this.routeMap[path]();
}
go (path) {
path = Route.correctPath(path);
history.pushState({path: path}, '', path);
this.routeMap[path] && this.routeMap[path]();
}
_bindPopState () {
window.addEventListener('popstate', (e) => {
const path = e.state && e.state.path;
this.routeMap[path] && this.routeMap[path]();
});
}
static correctPath (path) {
if (path !== '/' && path.slice(-1) === '/') {
path = path.match(/(.+)/$/)[1];
}
return path;
}
}
通常我們不需要自己編寫一套完整的SPA 邏輯實現,可以采用社區(qū)中成熟的SPA 模式框架進行系統的開發(fā),如React.js。
前端微服務技術將微服務的理念應用于瀏覽器端,即將Web 應用由單一的單體應用轉變?yōu)槎鄠€小型前端應用聚合為一的應用。各個前端應用還可以獨立運行、獨立開發(fā)、獨立部署。這里的前端應用特指基于前述討論的SPA 技術開發(fā)出的應用。
單體前端應用的路由是由框架進行分發(fā),將路由指定到對應的組件或者內部服務中。前端微服務將應用內的組件調用變成了更細粒度的應用間組件調用,即從將路由分發(fā)到應用的組件執(zhí)行,變?yōu)楦鶕酚蓙碚业綄膽?,再由應用分發(fā)到對應的組件上。
當Web 應用復雜到一定規(guī)模時,通常會面臨程序代碼管理困難、開發(fā)人員配合困難等問題,使用微服務思想構建系統是一個可行有效的方法。前端微服務化的架構圖如圖1 所示:
圖1 前端微服務架構圖 Fig.1 Front-end Microservice architecture
圖2 MES 系統主要模塊圖 Fig.2 Main module of Manufacturing Execution System
國際制造執(zhí)行系統協會MESA 對制造執(zhí)行系統定義11 個功能模塊,包括工序詳細調度、資源分配和狀態(tài)管理、生產單元分配、過程管理、人力資源管理、維護管理、質量管理、文檔控制、產品跟蹤和產品清單管理、性能分析和數據采集[3]。MES 系統主要包含的模塊如圖2 所示:
可以看出,MES 系統設計的功能模塊很多,且每一個模塊的縱向和橫向擴展也可以很大。雖然多數情況下并不需要所有的功能模塊,一旦面臨這種特別復雜的系統實現時。前端微服務技術可以提供很大的幫助,有利于模塊間的解耦和不同開發(fā)人員的協同配合,并提高應用程序的加載體驗。實現前端微服務化的方式并不唯一,下面闡述一種實現方式:
(1)Web 應用具有一個主工程,主工程在運行時去服務器獲取最新的應用配置。
(2)主工程在獲取到配置后,將一一創(chuàng)建應用,并為應用綁定生命周期。
(3)當主工程監(jiān)測到路由變化的時候,將尋找是否有對應的路由匹配到應用。
(4)當匹配對應應用時,加載相應的應用。 其架構圖如圖3 所示。
圖3 前端微服務設計圖 Fig.3 Front-end microservice design
Node.js 是一個基于Chrome V8 引擎的JavaScript 運行環(huán)境,它使JavaScript 代碼既可以在瀏覽器運行,也可以在服務器端運行,同時可實現文件處理、網絡通信等功能[4]。Node.js 使用了一個事件驅動、非阻塞式I/O 的模型,使其輕量又高效。開發(fā)者可以在不使用線程的情況下開發(fā)出一個能夠承載高并發(fā)的服務器。其他服務器端語言難以開發(fā)高并發(fā)應用,而且即使開發(fā)出來,性能也不盡人意。Node.js 正是在這個前提下被創(chuàng)造出來。Node.js 把JavaScript 的易學易用和Unix 網絡編程的強大結合到了一起。它專注于網絡功能,在HTTP、DNS、TCP 等方面更加成熟。
如上文所述,Node.js 可以認為是數據密集型分布式部署環(huán)境下的實時應用系統的出色解決方案。相對其他方案而言,它不適合CPU 使用率較重、IO 使用率較輕的應用——如視頻編碼、人工智能等。但對于MES 系統面對的并發(fā)量較高,網絡請求頻繁而計算負擔并不嚴重的場景性能更高,是一種優(yōu)秀的選擇。
在系統設計實踐中,可以配合Node.js 框架Koa 協同開發(fā)。Koa 框架是Express 框架作者提出的另一種Node.js 平臺Web 框架[5],致力于成為Web 應用和API 開發(fā)領域中的一個更小、更富有表現力、更健壯的基石。它通過利用async 函數,Koa 丟棄了傳統的回調函數,并有力地增強錯誤處理,同時具有更好的性能。
MongoDB 是一個基于分布式文件存儲的數據庫,屬于非關系數據庫,用C++語言編寫而成,旨在為Web 應用程序提供可擴展的高性能數據存儲解決方案[6]。它在許多場景下用于替代傳統的關系型數據庫或鍵值對存儲方式。它主要具有以下幾點特性:
(1)實用性
MongoDB 是一個面向文檔的數據庫,它并不是關系型數據庫,直接存取BSON,這意味著MongoDB更加靈活,因為可以在文檔中直接插入數組之類的復雜數據類型,設計數據庫將變得非常方便,可以大大地提升開發(fā)進度。
(2)可用性和負載均衡
MongoDB 在高可用和讀負載均衡上的實現非常簡潔和友好,自帶副本集的概念,通過設計適合自己業(yè)務的副本集和驅動程序,可以非常有效和方便地實現高可用,讀負載均衡。而在其他數據庫產品中想實現以上功能,往往需要額外安裝復雜的中間件,大大提升了系統復雜度,故障排查難度和運維成本。
(3)擴展性
在擴展性上,MongoDB 有非常有效的,現成的解決方案。通過自帶的Mongos 集群,只需要在適當的時候繼續(xù)添加Mongo 分片,就可以實現程序段自動水平擴展和路由,一方面緩解單個節(jié)點的讀寫壓力,另外一方面可有效地均衡磁盤容量的使用情況。整個mongos 集群對應用層完全透明,并可完美地做到各個Mongos 集群組件的高可用性。
MongoDB 的劣勢是不適合數據量小,數據間交叉引用關系復雜,查詢模式豐富的系統。而MES系統在多數場景下,如生產數據管理、文檔設備人員管理、庫存管理等并不需要過于復雜的查詢邏輯,因此不會受到明顯的影響。同時MES 系統的并發(fā)量較高,數據量較大同時面臨數據庫擴容的問題,很符合MongoDB 數據庫的應用場景。因此選取MongoDB 作為數據庫開發(fā)系統是一種可行有效的方案。
在實際系統開發(fā)中,需要為Node.js 提供操作MongoDB的插件,比較優(yōu)秀的一種方案是使用Mongoose。Mongoose是在NodeJS 異步情況下對MongoDB 進行方便快捷操縱行為的目標模型工具庫[7]。它封裝了對MongoDB 對文檔操作的常用處理方法,使得Node.js 操作MongoDB 數據庫變得更加容易。Web 后端的簡易架構圖如圖4 所示:
圖4 后端簡易架構圖 Fig.4 Back-end simple architecture
WebSocket 協議是基于TCP 的一種新的網絡協議。WebSocket 本質上是建立在TCP 協議上的Socket連接,在應用層對Socket 連接進行了封裝,簡化了接口及調用方法[8]。它實現了瀏覽器與服務器全雙工(full-duplex)通信——允許服務器主動發(fā)送信息給客戶端。
WebSocket 協議為實現即時服務帶來了兩大好處:
(1)互相溝通的Header 是很小的-大概只有2 Bytes。
(2)服務器的推送,服務器不再被動的接收到瀏覽器的請求之后才返回數據,而是在有新數據時就主動推送給瀏覽器。
傳統Web 應用中的即時通信采用ajax 輪詢的機制,這樣既耗費了服務器的資源,又會帶來通信不及時,通信中斷等問題。
生產監(jiān)控是MES 系統的核心模塊,在生產實際中往往需要實時的獲取機器設備的狀態(tài)參數如溫度、濕度等,以及獲取機器的加工狀態(tài)數據如正在加工的工件數據、加工時間和進展等。利用WebSocket技術可以解決傳統Web 應用的性能弊端,是一種有效的解決方案。
在實際開發(fā)中,通常利用Socket.IO 進行輔助開發(fā),Socket.IO 是一個WebSocket 庫,包括了客戶端的JavaScript 和服務器端的Node.js,它的目標是構建可以在不同瀏覽器和移動設備上使用的實時應用。開發(fā)生產監(jiān)控實際應用的核心代碼如下,為了演示方便假設機器加工數據會被推送到某個文件中:
const server = require('http').Server(app.callback());
const io = require('socket.io')(server);
io.on('connection', function (socket) {
socket.on('monitor', () => {
socket.join('monitor', () => {
let cacheData;
fs.readFile('../static/processData.txt', (err, data) => {
cacheData = data.toString(); // 緩存數據
io.to('monitor').emit('status', cacheData);
fs.watch('../static/processData.txt', (eventType, filename) => {
fs.readFile('../static/processData.txt', (err, data) => {
if (data.toString() !== cacheData) {
io.to('monitor').emit('status', data.toString());
}
});
});
});
});
})
});
瀏覽器端的WebSocket 實現方式與上述服務端類似,限于篇幅不再列出核心代碼。
JavaScript 語言采用的是單線程模型,所有任務只能在一個線程上完成。隨著計算機計算能力的增強,尤其是多核CPU 的出現,單線程帶來很大的不便,無法充分發(fā)揮計算機的計算能力。
H5 的出現為我們帶來了WebWorker,WebWorker 允許我們通過瀏覽器主線程來創(chuàng)建工作線程[9]。WebWorker 為Web 內容在后臺線程中運行腳本提供了一種簡單的方法。線程可以執(zhí)行任務而不干擾用戶界面。等到工作線程完成計算任務,再把結果返回給主線程。這樣一些計算密集型或高延遲的任務可以交付被工作線程解決,主線程(通常負責UI 交互)不會被阻塞或拖慢。
計劃排產模塊是MES 系統的又一個核心模塊,它的主要作用是解決柔性作業(yè)調用問題(FJSSP)。柔性作業(yè)車間調度問題(FJSSP)是組合優(yōu)化和生產管理領域很重要的研究課題,它是經典的作業(yè)車間調度問題(JSSP)的延伸且被認為是強NP-hard 問題[10]。在FJSSP 中,同一個工序的加工機器可能有多臺。FJSSP 由兩個子問題組成,第一個子問題是將一系列可選的機器分配給指定的工序,第二個子問題是計算分配給指定機器的工序序列的完工時間。目前業(yè)界流行的FJSSP 問題解決方案是以遺傳算法為基礎,結合其他算法進行深度優(yōu)化。
在一般的MES 系統的開發(fā)中,算法程序可以內置在Web 后端的Java 程序中,或是在Web 后端和Python 算法模塊進行數據交換得到排產數據返回Web 前端。隨著Chrome 瀏覽器V8 內核性能的提升,瀏覽器端的計算速度得到了較大提升。同時由于HTML5 中WebWorker 技術的出現,Web 前端的純算法計算可以不造成JavaScript 主線程的阻塞從而影響用戶的使用。
在Web 前端部署一些算法的好處是可以避免發(fā)送相關的網絡請求,以及在斷網異常情況下仍然可以完成模塊的功能。盡管在WebWorker 中運行算法的速度仍然和傳統的后端運行環(huán)境有一定的差距,但對于一些小型企業(yè),排產需求相對不復雜,這種方案的運算速度將足以勝任生產需求,并可以發(fā)揮前述列舉的優(yōu)勢。WebWorker 在項目中的實踐核心代碼如下:
// 主線程
let worker = new Worker('work.js');// 引入文件
worker.postMessage({plans: [], mechines: []}); // 傳入工序配置和加工機器
worker.onmessage = function (event) {
getDataSuccess(event.data); // 獲取排產數據
}
function getDataSuccess () {
// 執(zhí)行后續(xù)任務
worker.postMessage('Work done!');
…
}
// Worker 線程
self.addEventListener('message', function (e) {
let data = doJob();
self.postMessage('result ' + data); // 將排產結果返回給主線程
}, false);
function doJob (){
// 這里進行相關算法(如遺傳算法)的運算
….
}
本文給出了結合現代Web 技術開發(fā)MES 系統的有效方案,分別從Web 前端架構設計、Web 后端設計及技術選型、WebSocket 在MES 系統生產監(jiān)控中的應用以及WebWorker 在MES 系統排產中的應用方案等方面進行探討。這些方案在Web 應用的體驗及性能優(yōu)化、減輕服務器負載、降低開發(fā)成本及提高開發(fā)效率等方面起到了很好的幫助作用??梢詾镸ES 系統的開發(fā)人員提供有效可行的參考,在工程實踐上具有很大的意義。