Node.js Server之二:業務框架
此文是自己正在使用的Node.js Server分享系列中的第二篇,繼上一次的Node.js Server之一:概述後,本文講述自己對業務框架的理解和自己的實踐總結。
業務框架是什麼
想不到一個更好的標準名詞來總結自己與大家分享的這部分內容,綜合考慮內容的核心是業務與框架,因而稱之爲業務框架。
上篇文章提到Express、Koa、Egg,我稱之爲基礎技術框架,它們偏向於提供基礎的API與技術概念供大家使用,而使用它們提供的API結合具體業務所組成的中間層框架我稱之爲業務框架。在Express、Koa、Egg這三個框架中,Egg相對特別,我認爲它不是一個技術框架,而更偏向於是一個業務框架,正如其官方口號“爲企業級框架和應用而生”,這是最好的例證。
在一個具體的項目中,指導實現某個功能所需要的通常步驟以及如何完成這些步驟的約束,再加上對實現該功能所能提供的幫助,這三者共同構成一個業務框架的基礎。簡而言之,業務框架是不同公司,不同技術組,實現不同業務需求的一種經驗體現,由於公司不同,技術人員不同,業務需求不同,業務框架在細微處可能千差萬別,但業務需求通常存在共性,這就是Egg的價值。
爲什麼需要業務框架
解釋過業務框架是什麼之後,再聊聊爲什麼需要業務框架。
我們都知道有編碼規範,命名規範等,業務框架可藉此作類比,它是你實現業務功能方式的約束與規範,通過約束和規範,業務框架能給業務實現提供指導,同時儘可能的減少重複工作。
業務框架的難點在於不同公司的業務差異,同一個業務框架,A公司覺得非常好用,到了B公司變成另外一個評價,這是有極有可能的。也正是因爲不同公司之間的差異導致公司與業務框架匹配度不盡相同,我們才需要自己的業務框架,並結合業務進行持續優化。
實踐
在實現自己的業務框架時,一個好的開始是至關重要的,我們不是從零實現一個HTTP Server,只是爲了更好的與業務結合,可選擇基於Express或Koa。
因爲做的事情與Egg類似,不建議使用它作爲業務框架的基礎,但可以學習Egg的原理,然後應用到自己的業務框架上
核心要素:
- 配置
用配置描述行爲,用程序解釋配置,主要包含基礎配置與單個App配置
- App
業務邊界的體現,小的話像一個模塊,大的話更像一個應用,統一稱爲App
- AppManage
管理App,如初始化App,提供App間通信
- bootstrap
實例化AppManage並啓動
以上四個點是自己業務框架的主心骨,下面描述每個要素的核心內容。
配置
配置描述行爲,程序解釋配置,業務框架便是這個程序,基礎配置文件主要包含以下信息:
- 應用基礎信息,如:name、host、port等
- app路徑、middleware路徑、靜態資源路徑等
- 需要啓動的app列表
- 全局中間件申明
- 應用所需其他配置
所有業務框架需需要知道的信息都可以通過配置指定,然後業務框架會根據host、port啓動server、根據app路徑查找要啓動的app列表項配置,根據中間件申明掛載相應中間件…
通過定義配置加載規則和其背後的行爲,你幾乎可以實現自己的所有想法,但也有可能搞的一團糟,這也是樂趣的來源。
分享一個配置大家感受下:
// alpha.json
{
"name": "alpha",
"env": "prod",
"host": "127.0.0.1",
"port": "8001",
"path": "/Users/shasha/private/isl",
"appPath": "/Users/shasha/private/isl/app",
"fwPath": "/Users/shasha/private/server",
"modules": [
"common",
"wechat",
"view",
"alpha"
],
"component": {
"converters": [
"entity",
"cookie",
"session",
"clientIp"
],
"redirectors": [],
"interceptors": [{
"mode": "dev",
"name": "asset.file",
"options": {
"dir": "asset"
}
}],
"interferes": [],
"finishers": ["log.access"]
},
"lib": {
"mysql": {
"database": "alpha"
},
"redis": {}
},
"oss": {},
"session": {
"redis": {}
}
}
大部分內容大家都能理解,但對於component中的內容可能一下看不明白,其實也就是中間件,只不過是用自己定義的規則和加載方式體現罷了。
App
在概述那篇文章中,我提到過分層和分模塊的順序問題,我覺得先分模塊再分層更合理,這裏App的概念便是模塊,對應基礎配置中modules
的每一項。
App表示一個應用/模塊,其主要內容包括:
- 根據模塊配置進行實例化
- 對外提供init、start、restart、reload、stop等生命週期方法
- 在start中根據配置進行路由註冊、中間件註冊
- 按配置對外暴露必要接口,用於模塊間通信
App可通過Class定義,實例化時傳入模塊配置,服務運行階段該實例可一直被AppManage持有用於控制某些模塊行爲。
AppManage
AppManage作用相對簡單,就是集中管理App,主要在應用啓動階段讀取App配置、實例化App,在服務運行階段對外提供App間通信接口。
bootstrap
有了配置、App以及AppMange之後,我們需要啓動整個server,主要使用命令:node server/index.js -c xxx.json
,下面描述一下命令背後的主要過程:
- 解析配置文件
xxx.json
解析命令行參數,按路徑讀取配置文件並做必要轉換與解析,比如將同一配置內容的不同表達方式轉換爲統一形式
- 通過Express或Koa實例化一個HTTP Server
爲中間件申明、路由註冊、端口監聽作準備
- 設置Server全局行爲
主要是一些全局中間件,如Cookie、Session、Body-Parse、AccessLog等,這部分行爲儘量也按照配置文件內容進行設置
- 實例化AppMange
根據配置文件的內容實例化AppManage,在AppManage內部會實例化所指定的App,並持有引用
- 調用AppManage的init方法
順序或併發調用所持有App的init方法,這個階段主要是讓每個App內部做一些準備工作,比如建表,註冊定時任務等
- 調用AppManage的start方法
調用持有App的start方法,App-start需要作的事情主要是依照模塊配置註冊路由與中間件,這中間的具體規則與實現都是靈活的,可簡單可複雜
- 代理AppMange的部分方法
部分App內也許會用到一些框架層面的功能,而server不希望對外暴露AppManage,那麼AppManage提供的的模塊間調用功能就可以通過server進行代理,達到隱藏內部細節的目的
- 通過前面的Express或Koa實例化的HTTP Server監聽host與port
以上所有的步驟完成後,通過所持有的HTTP Server完成監聽,整個服務即完整啓動了,同時server可以監聽部分進程信號,結合AppManage實現reload等功能
總結
這片文章本打算細緻的講解自己server中的所實現的業務框架,但寫完後發現還是非常概念化,感覺很多細節都沒能展開,計劃在下一篇用實戰的方式實現一個簡單的業務框架。