FlyFish2.0版本後端源碼學習筆記

語言: CN / TW / HK

本文是用户Mark Wu近期在學習使用FlyFish源碼的學習筆記,雲智慧AIOps社區徵得原作者同意後授權發佈,本文使用的是FlyFish版本2.0,目前最新版本已更新到2.1

FlyFish代碼結構

以下是代碼的基本結構,使用的是基於MVC的thinkJS框架,但是通篇看下來,你是不是注意到,只看到了M(Model)和C(Controller),唯獨缺少View,所以View在哪?所以就帶着這個問題繼續學習下去。
├── code-server #在線編輯器
│ ├── linux
│ └── macos
├── config #初始化數據庫配置文件
│ ├── database.${dev}.json
│ ├── node.development.js #入口文件
├── download #大屏模塊文件
├── log #日誌
├── migrations_init #數據庫初始化
├── runtime #運行時配置存儲
├── src #後端項目核心代碼
│ ├── common #通用業務配置
│ │ ├── bootstrap #
│ │ ├── config #通用配置
│ │ │ ├── adapter #適配器配置
│ │ │ ├── config #通用配置
│ │ │ ├── extend #拓展配置
│ │ │ ├── middleware #中間件配置
│ │ │ ├── validator #自定義複雜校驗規則,在logic中使用
│ │ ├── constants #枚舉
│ │ ├── middleware #中間件
│ │ ├── model #Model層---M
│ │ │ ├── baseModel.js #定義了基本的CURD,其它所有的model都繼承自它
│ │ ├── service #通用邏輯方法
│ └── web #定製化業務-----實現具體業務邏輯
│ ├── config #業務配置
│ ├── controller #控制器層---C
│ ├── logic #前置後置操作---如字段校驗、權限控制,其它通用邏輯
│ ├── model #數據庫操作
│ ├── service #業務邏輯---數據處理、格式轉換等業務邏輯操作
├── scripts #項目部署腳本
├── storage #
├── template #大屏、組件模板
├── view #html模板
├── www #靜態資源
│ ├── solution-platform-web
│ └── static
│ └── upload
├── Dockerfile #dockerFile
├── options.json
├── options.json
├── pm2.json
├── README.md
├── startup.sh #啟動項目腳本

thinkJS框架

  • Config:通用配置,如上config所示,可配置項目各種配置,最後會根據運行環境合到一起;
  • Context:上下文,用户請求、回覆數據存儲對象以及狀態透傳;
  • Middleware:中間件,在配置與使用上類似於webpack的plugins,可使用各項函數(內置或引入)實現各項功能,所有的用户請求處理都是由middleware完成;
  • Logic:邏輯,其中的action與controller的action一一對應,可定義執行action的前置後置操作;
  • Controller:控制器,和.net的控制器的使用非常相似,其內會按照路由執行對應的action;
  • View:視圖(這裏就是答案了),需要使用拓展來實現視圖;
  • Router:路由,可自定義路由規則;
  • Adapter:適配器,解決一類功能的多種實現,配合extend,如view、數據庫,view可以選擇多種模板引擎,數據庫可配置多種數據庫,通過 think-helper模塊中的 parseAdapterConfig解析;
  • Extend:拓展,支持的擴展類型為:think、application、context、request、response、controller、logic 和 service,框架內置的很多功能也是擴展來實現的,如:Session、Cache。

view是如何生成的

adapter.js裏面配置view模板的目錄為view裏面的html模板,模板引擎為nunjucks,配合extend裏面引入的think-view使用。
/**
view adapter config
@type {Object}
*/
exports.view = {
type: 'nunjucks', // 這裏指定默認的模板引擎是 nunjucks
common: {
viewPath: path.join(think.ROOT_PATH, 'view'),//模板文件的根目錄
sep: '_',//Controller 與 Action 之間的連接符
extname: '.html'
},
nunjucks: {
handle: nunjucks
}
};

 

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
...
<title>{{title}}</title>
<link rel="icon" href="{{prefix}}/static/solution_platform_web/favicon.ico">
...
<link href="{{prefix}}/static/solution_platform_web/platform/vendor.css" rel="stylesheet">
</head>

<body>
<div id="wrapper"></div>
<script src="{{prefix}}/static/solution_platform_web/config/ENV.production.js"></script>
<script src="{{prefix}}/static/solution_platform_web/platform/runtime.js"></script>
<script src="{{prefix}}/static/solution_platform_web/platform/vendor.js"></script>
<script src="{{prefix}}/static/solution_platform_web/platform/app.js"></script>
</body>

</html>

 

可以看到模板裏面有兩個 prefix、title變量,會引入加載頁面所需靜態資源。extend裏面引入了think-view,通過 view 擴展,框架就支持渲染模板的功能,Controller 類上就有了 assign、display 等方法,引入model(think.app) 支持模型功能,會添加方法 think.Model、think.model、ctx.model、controller.model、service.model。
 
// extend.js
const view = require('think-view');
const model = require('think-model');
const session = require('think-session');
const cache = require('think-cache');

module.exports = [
session,
cache,
view, // make application support view
model(think.app),
];

 

router裏面配置路由規則,以/pw/開頭的get請求會指向web模塊的view控制器下index的一個叫platform的action;
// router.js
module.exports = [
// 代理平台的靜態頁面
[/^\/pw\/(.*)/i, '/web/view/index/platform', 'get'],
[/^\/proxyDataHub\/(.*)/i, 'web/proxy', 'rest'],
];

// web/controller/view/index.js
module.exports = class extends think.Controller {
platformAction() {
this.assign('prefix', this.config('platformPrefix', undefined, 'web').replace(/\/$/, ''));
this.assign('title', this.config('indexTitle', undefined, 'web').replace(/\/$/, ''));
return this.display();
}
};
platformAction會根據配置以及模塊改變prefix、title變量的值,這樣view模板就能正確加載靜態資源。同時middleware也配置默認模塊為web,默認控制器action為platformAction
...
//路由操作
{
handle: 'router',
enable: true, //是否開啟該中間件
options: {
defaultModule:'web', // 默認模塊
defaultController: 'view/index', // 默認控制器
defaultAction: 'platform', // 默認action
}
},
...

 

數據流

API請求數據流如下圖所示
服務端建議:可以適當增加Workers數量,以增加服務端穩定性,一個Worker出現問題後,Master會停止它,然後fork一個新的Worker出來。

部署問題

在使用飛魚2.0的過程中,遇到了很多部署方面的問題,這裏我挑幾個典型的記錄一下
 
Q:服務器上部署docker容器,本地訪問飛魚平台,發現登錄地址請求是127.0.0.1的地址;
A:按照部署流程仔細檢查了一下,發現配置文件www/static/solution_platform_web/config/ENV.production.js沒有正確配置。
 
Q:docker容器部署起來,做添加大屏操作的時候報錯ER_NO_SUCH_TABLE: Table 'flyfish.visual_screen_tag_view' doesn't exist, SQL: SHOW COLUMNS FROM visual_screen_tag_view
A:檢查發現數據庫沒有啟動。
 
Q:code-server 下面 ,grpc安裝失敗,一起沒有成功;
A:切換成cnpm源後成功,其實也可以試試使用yarn進行安裝;
 

寫在最後

FlyFish發佈2.1版本後,已經支持安裝包一件部署方式,極大縮減了部署流程,具體如下所示
# CentOS 7.5/7.6 x86-64
# 須使用root賬户
mkdir -p /data/app/
cd /data/app/

git clone -b main https://github.com/CloudWise-OpenSource/FlyFish.git FlyFish
or
git clone -b main https://gitee.com/CloudWise/fly-fish.git FlyFish

cd /data/app/FlyFish
bash flyfish.sh install

# 一鍵卸載
bash flyfish.sh uninstall

# 一鍵更新
# FlyFish-2.1.1 升級至 FlyFish-2.1.2
git checkout main
git pull origin main

bash flyfish.sh update

作者簡介

Mark Wu( 吳銀波 )雲智慧前端工程師,精通javascript、css、React、Vue、Webpack、ThreeJS等前端技術棧,致力於雲智慧大屏產品及飛魚開源社區服務,擁有豐富的前端性能優化和開源項目經驗。

關於FlyFish

部分大屏案例:
 
微信掃描識別下方二維碼,備註【飛魚】加入AIOps社區飛魚開發者交流羣,與 FlyFish 項目 PMC 面對面交流~