作者 | 寒斜(阿里云云原生中間件前端負責人)?
如何使用 Serverless 架構實作全雙工通信的應用,Serverless 架構中資料庫是如何使用的,本篇文章將為您揭開答案,
?
Serverless 的理念是即時彈性,用完即走,服務并非長時間運行,這也就意味著像 websocket 這種長鏈接的請求模式看起來并不適合 Serverless,
是否有其它的辦法即可以滿足長連接模式請求,又能夠利用 Serverless 本身特性呢?
答案是肯定的,上一篇文章我們談及了網關的關鍵作用,所以這次也是通過網關來解決全雙工通信的問題,本次將以彈幕場景為例,為大家展開我們是怎么使用 Serverless 架構來實作這個場景的,

應用效果預覽
?
彈幕應用的實用場景比較多,比如運營推廣,年會活動等,但是通常實作一套帶管控的流程,且部署發布的話,一般會花費比較長的時間,本篇實戰則可以讓你在 2 分鐘之內就部署好自己的彈幕應用,同時做到支持炫彩和彈幕內容管控,你可以用它來豐富公司年會的形式,文末也會貼上原始碼,可以供大家參考和二次定制,
?
架構一覽
?
整體架構依然采用 dns 決議 -> 網關 -> oss | fc ,不一樣的是分了 3 個靜態資源的工程,函式部分則采用事件驅動和 http 相結合,并且 api 部分采用 tablestore 進行資料的持久化,
流程說明
?
彈幕應用總工由大螢屏, 個人用戶,管理員三個客戶端,以及一個注冊設備的服務 & api 服務組成,客戶端跟服務端的長鏈接由網關來承載,每次客戶端連接到網關的時候,網關都會存盤設備編號,并且觸發一次注冊函式,設備編號存盤到 tablestore,
當用戶發起彈幕的時候經網關到 api 服務,api 服務會做一次查詢先判斷彈幕是否被管制,如果無管制則直接查找當前的大螢屏設備 id,并且進行網關的下行呼叫,網關在發到前端頁面,顯示資料,如果被管制,則查詢在線的管理員設備,將彈幕下行通知到網關,網關發送給管理員前端頁面,
資料表設計
?
- equipment(設備)
| 欄位 | 型別
| 說明 | |
|---|---|
| id |
| string
| 設備表主鍵
|
| deviceld
| string | 設備id |
| docld
| string | 備用欄位
|
| type
| string | 設備型別(screen | admin)
|
barrage(彈幕)
| 欄位 | 型別 | 說明 |
| --- | --- | --- |
| gid | string | 磁區鍵 |
| id | integer | 主鍵自增 |
| fromId | string | 彈幕作者id |
| fromName | string | 來源作者名稱 |
| color | string | 彈幕顏色 |
| fontSize | string | 彈幕字體大小 |
| checkStatus | integer | 彈幕狀態0(未處理)1(審批通過)2(審批未過) |
| sendTime | string | 彈幕發送時間 |
| checkTime | string | 彈幕更新時間 |
| message | string | 彈幕內容 |interceptor (過濾器)
| 欄位 | 型別 | 說明 |
| --- | --- | --- |
| id | integer | 主鍵/磁區鍵 |
| status | integer | 攔截狀態0不攔截 1攔截 2攔截加過濾 |
| filterWords | string | 過濾欄位 |
1、準備作業
同前篇《人人都是 Serverless 架構師 | 現代化 Web 應用開發實戰》文章一樣需要提前準備好域名,并安裝好 Serverless Devs 開發者工具,以及下面的產品:
- 云決議 DNS
- API 網關
- 函式計算
- 物件存盤 OSS
- Tablestore
這次我們引入了 tablestore 的資料庫記性資料的持久化功能,同樣需要創建好資料庫實體備用,
2、操作步驟
為了更好的展示效果,本次演示使用 ServerlessDesktop 來給大家演示一下如何 2 分鐘部署一個復雜的彈幕應用,你可以根據自身需要選擇 Serverless Devs Cli 或者 Serverless Desktop 對彈幕應用進行初始化和部署構建,
1)秘鑰配置
可參考密鑰獲取檔案:
_http://www.serverless-devs.com/zh-cn/docs/provider-config/alibabacloud.html_
2)初始化

本次初始化除了需要將應用模板下載到本地之外,還會幫忙初始化 tablestore 的表和資料,因此需要預配置幾個引數:?
?
- 秘鑰別名 - 對應你的阿里云賬號
- 域名 - 自定義域名
- bucketName - oss 的 bucket 名稱
- endpoint - 對應 tablestore 實體的公網訪問地址
- instance - 對應 tablestore 的實體名
預配置引數寫好后點擊 “確定”,接下來的作業就叫給 Serverless Devs,它會幫我們初始化彈幕應用的表,
3)構建部署
初始化之后,我們重新進入配置頁面,對專案進行部署,配置資訊 -> 全量操作 -> deploy 點擊后其他的就交給 Serverless Devs了,它會幫助我們完成:
- 大螢屏,管理后臺和玩家的前端部署;
- 注冊函式以及 api 函式的部署
- 以及網關的路由設定和網關的域名系結
?
4) 部署效果查看
- 網關
- 函式計算
- Oss
- DNS
此時訪問_ barragego.serverless-developer.com _發現訪問不同,檢查發現原因是 apigateway 的域名和 oss 域名都未系結成功,我們手動處理一下:
?
接下來再訪問 barragego.serverless-developer.com 即可看到效果:
2、資料庫明細
資料庫方面想拿出來說一下,主要本次用的資料庫確實比較新,也就是 tablestore,
1)資料庫配置傳遞
可以看到,我們在初始化應用的時候是填寫了資料庫的公網訪問地址和實體名稱資訊的,初始化的時候會把用戶的輸入配置寫入到 s.yaml 中,這里如果是比較敏感的資訊建議從 s.yaml 提取出來放到 .env 環境中,并且 ignore 掉這個檔案,減少資料庫資訊被泄露到代碼倉庫的風險,
最終 Devs 會把這兩個基本資訊放到函式計算的環境變數中然后各運行時可以通過環境變數取到這些值,比如這里是 nodejs 的運行環境,則通過 process.env.instance 獲取,
除了實體名稱和公網訪問地址外資料庫的初始化還需要 用戶的秘鑰資訊,鑒于秘鑰資訊的敏感性比較高,不建議直接把秘鑰資訊配置到 s.yaml 里,而是通過給函式服務授權 tablestore 角色權限,讓函式內置臨時秘鑰資訊,
- 函式服務授權配置如下:
- 函式內獲取秘鑰資訊如下:
2)資料庫初始化
為了減少資料庫初始化次數,我們可以在函式的 initializer 方法中初始化,當函式未被釋放的時候可以直接使用資料庫的實體而不必重新連接,這樣可以降低請求回應時間,單實體多并發的情況下比較實用,
exports.initializer = (context, callback) => {
try {
const ak = context.credentials.accessKeyId;
const sk = context.credentials.accessKeySecret;
const stsToken = context.credentials.securityToken;
SAT.init(endpoint, instance, ak, sk, stsToken);
internal = { tableClient: SAT, TableStore };
callback();
} catch (err) {
callback(err.message);
}
}
資料庫實體初始化之后,我們通過賦值給全域變數來從其他的方法中取得實體,進行后續的操作,
3)CRUD
tablestore 原生的 api 去做 CRUD 操作用戶體驗不夠友好,tablestore 社區提供了一個很好的封裝 SAT,我們用它來做基礎的增刪改查會非常的方便,代碼看起來也非常整潔,
// 單主鍵查詢
const getInterceptor = async (ctx) => {
const { tableClient } = ctx.req.requestContext.internal;
const res = await tableClient.table('interceptor').get(1, cols = []);
return res;
}
// 查詢全部
const getAllEquipment = async (tableClient,TableStore) => {
const res = await tableClient.table('equipment').getRange(TableStore.INF_MIN, TableStore.INF_MAX, cols = [])
return Object.keys(res).map((key)=> res[key]);
}
// 雙主鍵(一個磁區鍵,一個自增鍵)的插入
const addBarrage = async (ctx) => {
const { tableClient, TableStore } = ctx.req.requestContext.internal;
const { fromId, fromName, color, fontSize = '28px', checkStatus = 0, message } = ctx.request.body;
const currentTime = Date.now().toString();
const newData = https://www.cnblogs.com/Serverless/archive/2022/02/07/Object.assign({}, { fromId, fromName, color, fontSize, checkStatus: parseInt(checkStatus), message }, { sendTime: currentTime, checkTime: currentTime });
const res = await tableClient.table('barrage', ['gid', 'id']).put([1, TableStore.PK_AUTO_INCR], newData, c = 'I');
return res;
}
// 更新
const updateBarrage = async (ctx) => {
const { tableClient } = ctx.req.requestContext.internal;
const { checkStatus } = ctx.request.body;
const { id } = ctx.request.params;
const currentTime = Date.now().toString();
const res = await tableClient.table('barrage', ['gid', 'id']).update([1, parseInt(id)], { checkStatus: parseInt(checkStatus), checkTime: currentTime }, c = 'I')
return res;
}
// 條件查詢
const getBarrageByCondition = async (ctx) => {
const { tableClient, TableStore } = ctx.req.requestContext.internal;
const res = await tableClient.table('barrage').search('index', ['checkStatus', 0])
return res;
}
當然如果你想做更高級的查詢,就需要自己去查閱官網檔案了
總結
這個專案本身是對 Serverless 如何使用 websocket 的一個展示示例,你可以把它變成任意相近形態的應用,比如聊天室,多人協作平臺等,
應用本身也還有很多改進空間,比如增加點贊效果,管控部分可以加上管理員的登錄注冊等,總之你可以根據自身需求定制更高級的功能,相關的原始碼已經提供出來供大家參考,下個篇章我會繼續跟大家聊一聊 Serverless 和低代碼的場景,并分享一個我們最近做的實踐,
文中涉及網址匯總:
Serverless Devs:https://github.com/Serverless-Devs
云決議DNS:https://wanwang.aliyun.com/domain/dns
API網關:https://www.aliyun.com/product/apigateway
函式計算:https://www.aliyun.com/product/fc
物件存盤OSS:https://www.aliyun.com/product/oss
ServerlessDesktop:http://www.serverless-devs.com/zh-cn/desktop/index.html
Serverless Devs Cli:http://www.serverless-devs.com/zh-cn/cli/index.html
Serverless Hub:https://serverlesshub.resume.net.cn/#/hubs/specialview
Tablestore表格存盤:https://www.aliyun.com/product/ots
官網檔案:https://help.aliyun.com/document_detail/27304.html?spm=5176.54465.J_7985555940.4.15942e0c3qkHbU
原始碼:https://github.com/devsapp/start-barrage
更多內容關注 Serverless 微信公眾號(ID:serverlessdevs),匯集 Serverless 技術最全內容,定期舉辦 Serverless 活動、直播,用戶最佳實踐,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/423468.html
標籤:其他
上一篇:PyTorch 介紹 | BUILD THE NEURAL NETWORK
下一篇:Git常用命令(超實用)
