用框架ACI設(shè)計與實踐:從協(xié)議選型到多端接入)
1. 為什么會有 Zorv AI ACI 這個框架跨進程能力調(diào)用的痛點做智能體應(yīng)用開發(fā)的朋友應(yīng)該都有過這種經(jīng)歷辛辛苦苦把 AI 能力做成了一套服務(wù)結(jié)果發(fā)現(xiàn)它只能在當(dāng)前進程里跑。換個應(yīng)用訪問不了換個終端設(shè)備更是不行。能力越做越多調(diào)用入口卻越收越窄最后全憋在一個進程里既沒法擴展也沒法復(fù)用。Zorv AI ACI 框架就是沖著這個問題來的。ACI 的全稱是 Agent Control Interface本質(zhì)上是為智能體提供的一套標(biāo)準(zhǔn)化的能力調(diào)用接口。你可以把它理解成智能體世界的 USB-C 接口不管背后接的是攝像頭、存儲芯片還是充電模塊只要接口標(biāo)準(zhǔn)統(tǒng)一了插上就能用。ACI 做的就是這個統(tǒng)一化的工作它把散落在各個進程里的 AI 能力比如自然語言理解、圖像識別、語音合成、規(guī)則引擎等統(tǒng)一封裝成可跨進程調(diào)用的服務(wù)讓上層應(yīng)用能以一致的方式去調(diào)用這些能力。這個框架解決的實際問題很明確。第一能力共享問題多個應(yīng)用不必各自維護一套 AI 能力實現(xiàn)統(tǒng)一通過 ACI 調(diào)用即可第二進程隔離問題能力提供方崩潰不會拖垮調(diào)用方進程間的故障邊界清晰第三多端一致性問題PC 端、移動端、云端服務(wù)調(diào)用同一套能力時交互協(xié)議完全一致不需要為每個端單獨適配。我把這套框架從架構(gòu)設(shè)計到實際部署完整走了一遍踩了些坑也總結(jié)了不少實測經(jīng)驗這篇就當(dāng)是一份完整的使用記錄希望對你接入時有參考價值。2. 跨進程能力調(diào)用的架構(gòu)核心協(xié)議設(shè)計、尋址機制與調(diào)用鏈路2.1 通信協(xié)議選擇為什么最終選了 JSON-RPC over WebSocketACI 框架的底層通信業(yè)界常見的選擇有這么幾種gRPC、HTTP REST、WebSocket 自定義協(xié)議。我在選型時做過比較核心考量因素有三個跨語言能力、長連接交互、調(diào)試便捷度。先看 gRPC。性能確實好基于 HTTP/2有雙向流式通信protobuf 序列化效率高。但問題是它要求兩端都生成對應(yīng)的 stub 代碼服務(wù)端和客戶端需要維護同一套 .proto 文件。在多端接入場景下PC 端還好說移動端和 Web 端引入 gRPC 依賴構(gòu)建鏈路會變得比較重。而且調(diào)試 http/2 的流式接口工具支持沒有 HTTP/1.1 那么順手。REST 是普適性最強的方案但也因為太靈活容易失控。ACI 的核心訴求是一組結(jié)構(gòu)化的遠程過程調(diào)用而不是一組資源對象的增刪改查。用 REST 表達調(diào)用某個 AI 能力并傳參這樣的語義需要自己定義資源路徑、動作映射、錯誤碼約定搞到最后每個人寫的 REST 接口風(fēng)格都不太一樣。最終選型是 JSON-RPC 2.0 over WebSocket。理由很實際JSON 格式的通用性好任意語言都有現(xiàn)成的實現(xiàn)庫WebSocket 天然支持雙向通信調(diào)用方可以發(fā)起請求服務(wù)方也能主動推送進度或事件JSON-RPC 2.0 協(xié)議本身極簡就 id、method、params、result、error 五個字段學(xué)習(xí)和排查成本極低。實際部署中這套組合非常穩(wěn)。一次典型的跨進程調(diào)用請求體長這樣{ jsonrpc: 2.0, id: req_8f7a3c2e, method: aci.nlp.intent_recognize, params: { query: 幫我訂一張明天上午從上海到北京的高鐵票, context: { session_id: sess_20250321_001 }, timeout_hint: 5000 } }響應(yīng)體則通過 id 字段與請求關(guān)聯(lián)支持并發(fā)亂序返回{ jsonrpc: 2.0, id: req_8f7a3c2e, result: { intent: book_train_ticket, slots: { departure: 上海, destination: 北京, date: 2026-03-22, time_pref: morning }, confidence: 0.94 } }2.2 能力尋址與會話路由從 method 到實例的解析過程ACI 框架里一個核心概念叫能力路由Capability Routing。調(diào)用方傳過來的 method 是一個帶命名空間的字符串格式為aci.{domain}.{subdomain}.{action}。服務(wù)端收到請求后不是簡單查個表就行而是要走一套完整的解析鏈路把邏輯請求映射到具體的處理實例上。這套鏈路分四步命名空間拆解將aci.nlp.intent_recognize拆成 domain“nlp”、action“intent_recognize”用于確認所屬能力域能力注冊表查詢從本地能力注冊表Capability Registry中匹配已注冊的 processor實例池負載選擇如果同一個能力部署了多份實例通過一致性哈?;蜃钚∵B接數(shù)策略選出目標(biāo)實例上下文綁定從 params.context 中提取 session_id綁定對應(yīng)的會話狀態(tài)存儲。最有價值的是第四步。跨進程調(diào)用最容易被忽視的問題就是會話連續(xù)性。智能體應(yīng)用幾乎都是多輪對話形態(tài)請求之間必須共享上下文狀態(tài)。ACI 框架把 session 狀態(tài)從調(diào)用方剝離出來統(tǒng)一放在服務(wù)端的會話存儲中。調(diào)用方只需要在每次請求時帶上 session_id服務(wù)端自動恢復(fù)上下文。還有一類請求不需要會話狀態(tài)比如一次性的圖像分類調(diào)用??蚣苤С衷?method 前加上stateless.前綴路由層會跳過會話加載直接從實例池派發(fā)請求響應(yīng)速度能提升近一倍。這個設(shè)計思路很像 HTTP 的 stateless 與 stateful 請求區(qū)分在容量規(guī)劃和橫向擴展時會非常方便。2.3 調(diào)用超時控制與鏈路追蹤最容易忽略的故障溫床做過分布式調(diào)用的人都知道超時和鏈路追蹤是排障的基本功但很多框架把這兩件事當(dāng)附加功能ACI 則是把它們做進了協(xié)議底層。先說超時。ACI 的每個請求都帶timeout_hint字段這個設(shè)計非常關(guān)鍵。調(diào)用方可以根據(jù)交互場景彈性設(shè)置超時語音交互場景通常設(shè) 3000 毫秒以內(nèi)給人秒回的體驗復(fù)雜推理任務(wù)可以放到 15000 毫秒以上。更重要的機制在下游——每個能力處理器在執(zhí)行過程中框架會檢查剩余可用時間如果發(fā)現(xiàn)剩余時間不足以完成當(dāng)前子步驟就直接中斷執(zhí)行并返回 timeout 錯誤。這就避免了上游已經(jīng)放棄等待下游還在空轉(zhuǎn)消耗算力的情況。鏈路追蹤方面框架在握手建立連接時就給每個會話分配一個全局唯一的 trace_id。之后的每次請求、每個處理步驟的耗時、每個節(jié)點的序列化耗時都會掛在這個 trace_id 下統(tǒng)一上報到追蹤系統(tǒng)。我在定位一次響應(yīng)偶發(fā)延遲的問題時就是靠 trace_id 發(fā)現(xiàn)瓶頸不在推理本身而在跨進程傳輸時的序列化耗時不正常最終定位到是循環(huán)引用的對象導(dǎo)致 JSON.stringify 性能驟降。這種問題如果沒有鏈路追蹤基本無從下手。3. 安全認證體系設(shè)計令牌、簽名、加密三層防線3.1 為什么不能用簡單的 API Key 認證做內(nèi)部框架的時候最容易犯的錯誤就是覺得反正只有我自己用認證搞簡單點就行。ACI 框架的第一個版本確實就這么干的客戶端和服務(wù)端約定一個靜態(tài) API Key請求頭里帶上就放行。上線測試時什么問題都沒有直到有一次把調(diào)試端口暴露到了內(nèi)網(wǎng)同事的腳本誤掃到端口后直接發(fā)的請求居然全被當(dāng)成合法請求處理了。好在那次事件沒有造成實際數(shù)據(jù)損失但教訓(xùn)很深刻ACI 要接入的 AI 能力往往是高價值資產(chǎn)而且跨進程場景下調(diào)用方身份是動態(tài)變化的單靠一個靜態(tài) Key 無法解決兩個核心安全問題——憑據(jù)泄露后的時效控制、以及不同調(diào)用方之間的權(quán)限隔離。于是整體安全體系重構(gòu)成了三層令牌校驗、請求簽名、傳輸加密。3.2 令牌層JWT 短時有效 刷新機制第一層是調(diào)用方身份認證采用標(biāo)準(zhǔn)的 JWTJSON Web Token方案。調(diào)用方啟動時先向認證服務(wù)申請一個 access token有效期為 30 分鐘過期后通過 refresh token 自動續(xù)期。JWT 里除了常規(guī)的 issuer、audience、exp 字段還自定義了兩個關(guān)鍵 claimsscope聲明該調(diào)用方允許訪問的能力域列表比如[nlp, ocr, asr]精確到能力類別capability_level調(diào)用方的訪問級別基礎(chǔ)級只能調(diào)用標(biāo)準(zhǔn)接口高級別可以調(diào)用需要加載大數(shù)據(jù)模型的推理接口。這一層的意義在于即使 token 泄露攻擊者也只能在 30 分鐘的窗口期內(nèi)使用而且只能調(diào)用 scope 限定范圍內(nèi)的能力。實際測試中我故意泄露過 token 做攻防驗證效果確實符合設(shè)計預(yù)期。3.3 簽名層防止請求被篡改的 HMAC 機制JWT 解決的是你是誰的問題但沒解決請求內(nèi)容有沒有被中間人改過的問題。假設(shè)攻擊者截獲了一次合法的意圖識別請求把請求里的action: intent_recognize改成action: delete_user_data如果服務(wù)端只校驗 JWT這個非法請求是會通過的。簽名層就是為這個設(shè)計的??蛻舳藢γ總€請求體做 HMAC-SHA256 簽名計算方式是HMAC_SHA256(secret, timestamp body nonce)其中secret是調(diào)用方密鑰由認證服務(wù)在申請令牌時單獨下發(fā)。服務(wù)端收到請求后用同樣的密鑰重新計算簽名不一致則直接拒絕。這里有個實現(xiàn)細節(jié)值得注意nonce一次性隨機數(shù)的生成不能簡單用時間戳。時間戳有回撥風(fēng)險而且同一個時間戳內(nèi)的兩次重放完全測不出來。我用的是random_bytes(16)生成的隨機數(shù)同時在服務(wù)端維護一個滑動窗口去重集合只保留最近 5 分鐘內(nèi)的 nonce既能防重放也不會讓內(nèi)存無限增長。3.4 傳輸層與端口收斂加密之外更重要的一步第三層是傳輸加密WebSocket 連接統(tǒng)一走 WSSTLS這個不細說了。真正容易被忽略的是端口收斂策略。ACI 框架的典型部署形態(tài)是內(nèi)網(wǎng)服務(wù)很多人覺得內(nèi)網(wǎng)就不需要收斂端口這是大錯特錯的。內(nèi)網(wǎng)橫向滲透是最常見的攻擊路徑開放不必要的端口等于給攻擊者送了通路。我的生產(chǎn)環(huán)境配置堅持三個原則ACI 服務(wù)只監(jiān)聽內(nèi)網(wǎng)網(wǎng)卡的指定端口比如 8890絕不綁定 0.0.0.0防火墻僅放行已知調(diào)用方的來源 IP 段如果調(diào)用方與 ACI 服務(wù)不在同一網(wǎng)段中間必須加一層反向代理做 TLS 終結(jié)和訪問控制。實測這套下來端口掃描階段的攻擊面會大幅減少。4. 多端接入實戰(zhàn)PC 端、移動端、Web 端的差異化適配4.1 連接層適配健康檢查、斷線重連與心跳保活多端接入的第一步是建立 WebSocket 連接。說來簡單但每個端的網(wǎng)絡(luò)環(huán)境差異、生命周期差異、重連策略差異都會在這里體現(xiàn)。我在做 PC 端接入時用的是 Python 客戶端網(wǎng)絡(luò)環(huán)境相對穩(wěn)定重連策略可以激進一點斷線后 1 秒、2 秒、4 秒指數(shù)退避重試最多重試 10 次。移動端則完全不同App 會頻繁進入后臺系統(tǒng)可能隨時掛起網(wǎng)絡(luò)連接重連必須結(jié)合應(yīng)用生命周期控制。iOS 端我監(jiān)聽了UIApplicationDidEnterBackgroundNotification進入后臺時主動斷開連接并暫停重試回到前臺時重新連接Android 端則依賴onResume和onPause做同樣的控制。如果不做這個處理App 在后臺會被系統(tǒng)反復(fù)喚醒重連電量消耗非常明顯。Web 端還有一個額外的挑戰(zhàn)瀏覽器對 WebSocket 的并發(fā)連接數(shù)限制是 6 條。如果頁面里有多個組件各自建立連接很容易觸發(fā)這個限制導(dǎo)致部分連接掛起。正確姿勢是所有的 ACI 調(diào)用共用一條連接內(nèi)部通過請求 id 分發(fā)到對應(yīng)的 Promise 回調(diào)。我這里實現(xiàn)了一個簡單的請求派發(fā)器核心就兩件事發(fā)送時把 id 和 Promise 的 resolve/reject 存入 Map接收時通過 id 把消息分發(fā)給對應(yīng)回調(diào)。心跳保活機制我建議統(tǒng)一服務(wù)端做裁決服務(wù)端每 30 秒檢測一次空閑連接如果 90 秒內(nèi)沒有收到任何請求或心跳包就主動關(guān)閉連接客戶端收到 close 后自動重連。這個策略能自動清理半開連接避免失效連接堆積導(dǎo)致服務(wù)器連接數(shù)打滿。4.2 協(xié)議層適配請求批處理、優(yōu)先級標(biāo)記與響應(yīng)壓縮連接適配完接下來是協(xié)議層的優(yōu)化。不同端的調(diào)用形態(tài)差異很大Web 端往往是頁面初始化時一次性并發(fā)發(fā)起多個能力請求PC 端的自動化任務(wù)有大量順序依賴移動端則頻繁出現(xiàn)短小交互。ACI 框架在協(xié)議層支持三種優(yōu)化機制。第一是請求批處理支持在一個 WebSocket 消息里打包多個 JSON-RPC 請求適合 Web 端和移動端初始化場景實測批量發(fā)送 20 個輕量請求比逐個發(fā)送節(jié)省了約 45% 的握手和路由開銷。第二是優(yōu)先級標(biāo)記這是一個自定義的 params 擴展字段priority: high | normal | low服務(wù)端的調(diào)度器會優(yōu)先處理高優(yōu)先級請求。我在語音交互場景里使用比較頻繁因為交互時人類對延遲的感知非常敏感后臺日志分析之類的低優(yōu)先級任務(wù)可以適當(dāng)排隊。第三是響應(yīng)壓縮對超過 4KB 的 JSON 響應(yīng)體服務(wù)端會使用壓縮算法處理后再返回Android 端和 Web 端實測能節(jié)省 70% 以上的傳輸體積。4.3 能力層適配不同終端的 AI 能力裁剪策略接入到最后你一定會碰到這個問題PC 端的能力特別全移動端想擺一套精簡版Web 端又是另一套。如果每端都調(diào)全部能力且不說浪費流量某些重模型在低配手機上根本跑不出理想延遲。ACI 框架的能力裁剪不是在客戶端做的而是由服務(wù)端根據(jù)調(diào)用方的 scope claim 自動決定可調(diào)用的能力集合。接入方在申請令牌時會明確一個能力清單。如果某端確實需要臨時調(diào)用某個未授權(quán)的能力可以走動態(tài)授權(quán)流程在認證層增加該能力到 scope 后重新下發(fā)令牌。這樣做的好處是各端的能力差異完全由服務(wù)端統(tǒng)一下發(fā)客戶端不需要維護一份哪些能力我有權(quán)限的清單也不怕漏掉或?qū)戝e。5. 真實接入案例復(fù)盤一次語音交互能力的完整接入鏈路理論講了這么多用一個真實案例把鏈路串起來可能更直觀。下面是我在一個類似于智能助手場景里接入語音能力的一整條鏈路從客戶端發(fā)起到服務(wù)端返回完整走一遍。第一步客戶端iOS App啟動時向認證服務(wù)申請令牌。認證服務(wù)校驗 App 的 bundle id、簽名以及預(yù)下發(fā)的 app_key 后返回 JWT 和 refresh token。這一步的耗時通常在 100ms 以內(nèi)可以放在 App 啟動的異步流程里。第二步App 將令牌緩存起來建立 WSS 連接。這一步我會在請求頭里帶一個X-ACI-Token字段方便連接層做快速鑒權(quán)而不是把令牌放到每次業(yè)務(wù)請求的 body 里——避免 JWT 在日志中泄漏。連接建立后服務(wù)端返回連接級配置包括當(dāng)前服務(wù)端的協(xié)議版本號、心跳周期等。第三步用戶說話觸發(fā)語音識別請求。App 將語音數(shù)據(jù)按 20ms 一幀持續(xù)推送到 ACI方法名是aci.asr.stream_recognize這是一個多消息構(gòu)成的流式調(diào)用。第一幀帶上 JWT、采樣率、編碼格式參數(shù)之后每幀只帶音頻數(shù)據(jù)。服務(wù)端邊收邊識別每識別出中間結(jié)果就通過同一個 WebSocket 通道反向推送。第四步語音識別完成后客戶端根據(jù)中間結(jié)果拼接完整的 query調(diào)用aci.nlp.intent_recognize做意圖識別和槽位提取。第五步不同的意圖由各自的能力處理器執(zhí)行。比如識別到query_weather意圖框架路由到天氣查詢處理器處理器調(diào)用第三方天氣 API把結(jié)果格式化成自然語言后返回給客戶端。完整鏈路實測數(shù)據(jù)如下環(huán)節(jié)平均耗時備注令牌申請80ms含一次網(wǎng)絡(luò)往返WSS 握手150ms首次連接含 TLS 協(xié)商語音流式識別3 秒音頻1200ms服務(wù)端算力正常時意圖識別90ms輕量模型無會話狀態(tài)執(zhí)行 返回350ms依賴第三方 API 響應(yīng)端到端總耗時約 1.9s不含網(wǎng)絡(luò)抖動這套鏈路在接入過程中踩過一個大坑語音識別的并發(fā)連接數(shù)沒有做限制測試時 5 臺設(shè)備同時發(fā)起流式識別直接把 NVRAM 打滿部分請求超時。后來在 ACI 服務(wù)端加上了連接級并發(fā)配額按調(diào)用方維度限制最大并發(fā)流數(shù)超出的請求直接返回 429Too Many Requests客戶端配合做隊列重試問題才解決。關(guān)于重試還有一個經(jīng)驗語音流式調(diào)用不要做 ABA 式重試。識別過程中如果只重傳最后幾幀服務(wù)端的解碼器會因為缺失上文數(shù)據(jù)產(chǎn)生突變甚至亂碼。正確做法是流式中斷后整段重新發(fā)起服務(wù)端通過 session_id 自動清理未完成的識別狀態(tài)。6. 框架部署與運維要點從單機到多實例的擴展實踐6.1 目錄結(jié)構(gòu)與配置管理部署 ACI 框架看似就是起一個服務(wù)進程但配置管理的規(guī)范性直接影響后期運維效率。我的建議是采用一個主配置目錄加外部覆蓋文件的方式/etc/aci/ ├── aci.yaml # 主配置 ├── capabilities/ # 能力插件配置 │ ├── nlp.yaml │ ├── asr.yaml │ └── ocr.yaml └── certs/ # TLS 證書與私鑰主配置文件里最需要注意的幾個關(guān)鍵參數(shù)listen.addr監(jiān)聽地址建議內(nèi)網(wǎng) IP不要用默認 0.0.0.0除了前面說的安全考慮還能避免和其他服務(wù)搶端口session.timeout會話狀態(tài)過期時間。默認 30 分鐘無訪問自動清理。這個值要根據(jù)業(yè)務(wù)來調(diào)如果做的是長時間推理任務(wù)可以適當(dāng)增長到 1 小時如果是語音助手這類短交互15 分鐘就夠太長了白白占用內(nèi)存concurrency.limit全局并發(fā)請求上限這里需要根據(jù)服務(wù)端 NVRAM 和 GPU 顯存規(guī)劃我這邊設(shè)的 256auth.modestrict模式下強制校驗全部三層安全機制local-dev模式僅供本機聯(lián)調(diào)用禁止在生產(chǎn)開啟。6.2 多實例部署與狀態(tài)一致性當(dāng)單個實例不足以支撐流量時ACI 服務(wù)會橫向擴展成多實例部署。這里有個關(guān)鍵問題session 狀態(tài)存儲放在哪里。第一種方案是實例本地內(nèi)存存儲。實現(xiàn)最簡單響應(yīng)速度最快但問題是用戶請求被路由到實例 AA 保存了 session下一次請求負載均衡到了實例 BB 沒有這個 session多輪對話就斷了。解決辦法是負載均衡層做會話粘滯session affinity將同一 session_id 的請求固定路由到同一實例。問題在于某個實例宕機時會話狀態(tài)會全部丟失。第二種方案是外部共享存儲比如 Redis。會話狀態(tài)統(tǒng)一存 Redis任何實例都能讀取實例伸縮無狀態(tài)化。代價是多了一層額外的存取延遲但實測也就 1ms 以內(nèi)遠低于推理耗時完全可接受。我的生產(chǎn)方案就是用 Redis同時配合一致的 session 過期策略自動清理失效會話。值得注意的是能力本身的模型實例并不支持簡單水平擴展。比如語音識別模型如果加載了多個副本每個副本都需要分配模型顯存。我遇到過一種情況兩個實例分別加載了同一套 ASR 模型流量被均勻分發(fā)結(jié)果因為模型切換從推理模式切換到微調(diào)模式導(dǎo)致兩個實例上的模型狀態(tài)不一致識別結(jié)果各不相同。這個問題的根因在于管理面操作和數(shù)據(jù)面操作混在了一起。解決辦法是在管理面增加了一個模型版本公告機制所有模型變更先在集群內(nèi)廣播各實例確認切換完成后再對新調(diào)用放行。6.3 可觀測性建設(shè)指標(biāo)、日志與告警基線的設(shè)定部署運維至少要覆蓋三個維度的可觀測性指標(biāo)、日志、鏈路追蹤。指標(biāo)方面最核心的幾個自定義指標(biāo)建議重點盯aci_request_total總請求量按能力域、調(diào)用方維度做 label 拆解用于流量評估aci_request_duration_seconds請求耗時直方圖關(guān)注 P95 和 P99 分位數(shù)比平均值更能反映極端情況aci_wss_connection_active當(dāng)前活躍連接數(shù)觀察連接曲線的波峰波谷評估容量水位aci_error_total錯誤數(shù)按錯誤類型拆分特別注意token_expired和capability_not_found這兩個類別。前者多了說明客戶端令牌刷新邏輯有問題后者說明調(diào)用方申請的能力清單與自身使用不一致。日志統(tǒng)一走 JSON 格式輸出方便收集到日志平臺后進行結(jié)構(gòu)化檢索。每次請求的日志至少要包含 trace_id、caller_id、method、duration_ms、status_code 這五個字段。告警我建議分兩級。一級告警對應(yīng)的條件包括P99 耗時連續(xù) 5 分鐘超過 2000ms、內(nèi)存使用率持續(xù) 5 分鐘超過 80%、WSS 連接數(shù)超過實例上限的 80%。二級告警包括錯誤率超過 1%、令牌校驗失敗次數(shù)突增。一級告警要電話通知二級告警走群消息即可。這些閾值剛上線時可以先放寬跑一段時間觀察正常波動的范圍再逐步收緊。7. 從實踐中總結(jié)的幾條關(guān)鍵經(jīng)驗框架本身的能力邊界和運維細節(jié)已經(jīng)寫了非常多最后把幾輪實戰(zhàn)下來最有價值的幾條心得放在這里未必每一條都能立刻用上但遇到對應(yīng)場景時你會想起來。第一跨進程調(diào)用框架第一步要定義的是進程邊界不是接口邊界。先搞清楚哪些能力必須跨進程、哪些能力留在本地進程里就夠了。ACI 框架的定位是連接器而不是萬能容器盲目把所有能力都塞進 ACI 服務(wù)端只會讓框架變成一個新的單體應(yīng)用。第二安全認證不是寫在接口層就行而是需要貫穿連接層、請求層、會話層。我在這篇文章里寫的三層安全體系每一層解決一類問題少了任何一層都有對應(yīng)的攻擊路徑可以穿透。哪怕是內(nèi)網(wǎng)服務(wù)也建議至少做到 JWT HMAC 兩層。第三多端接入的核心不是能連上而是斷了能自動恢復(fù)且不影響狀態(tài)。無論你用 WebSocket 還是其他長連接協(xié)議重連機制、會話恢復(fù)、冪等處理這三件事必須在一開始就設(shè)計好否則后面每增加一個接入端都要回來給連接層打補丁。第四可觀測性不是上線以后才補而是要從第一行代碼開始埋點。后來排查過的疑難雜癥幾乎全部依賴鏈路追蹤日志定位的。所以如果框架本身沒有現(xiàn)成的可觀測性能力早早在自己的代碼里把結(jié)構(gòu)化日志打好后面能省非常多的時間。我曾經(jīng)在一個生產(chǎn)接線群里見證過一次差點釀成事故的部署有人把 ACI 服務(wù)端配置里的認證模式切成了 local-dev好在大版本上線前走了一遍全鏈路安全檢查及時發(fā)現(xiàn)并改回來了。這類問題靠人盯是不現(xiàn)實的最好是加一道配置文件校驗的 CI 檢查把生產(chǎn)環(huán)境禁用的配置項直接做成編譯期攔截。配置安全同樣如此始終有敏感配置校驗的 CI 檢查永遠比相信隊友手動配置不會出錯可靠。