在剛結束的全球網際網路技術大會(GITC)裡面,我在前端專場給大家分享了「微信小程式雲端解決方案探索之路」,介紹到了我們之前對小程式雲端解決方案的探索過程。
小程式剛推出的時候,很多人都覺得它就是 H5,因為開發小程式的三大語言和 HTML、CSS、JS 是一脈相承的,即使改變了擴充名也改不了其實質。
那麼小程式的實質到底是不是 H5 呢?經過我們的論證分析,我們認為小程式并不是 H5 應用。主要原因如下:
在小程式裡面無法使用 DOM 接口,是以 HTML5 生态中一切基于 DOM 的庫都無法使用(如 jQuery)
小程式并非使用 URL 通路,是以沒有域名的概念。這個特性有兩個影響
不存在跨域問題,是以通路控制是直接在微信 MP 上配置域名白名單
不支援 Cookie 存儲,這将導緻後面我們重點研究了會話管理的實作
從上面兩個角度來考慮,我們認為小程式更偏向于傳統的 CS 架構。
那麼,小程式和傳統 CS 架構的差別在哪兒?主要包括下面兩點:
網絡和續航
小程式在移動端運作,網絡環境會比較複雜,頻繁的網絡連接配接可能會過度消耗資源導緻續航下降,是以小程式對網絡和資源的優化都提出了要求。
伸縮能力
小程式寄托在微信平台上運作,作為一個十億級的社交平台,業務可能會面臨爆炸式的增長。如果在爆點小程式不能快速伸縮應對,那麼将失去這樣一個重要的機會。是以小程式對其背景架構的伸縮能力提出了比較高的要求。
在上面一些結論下,我們進行了一些嘗試,包括上傳下載下傳、會話管理、WebSocket、視訊點播等等。這次重點來分享會話管理和 WebSocket,因為我們面臨的挑戰主要集中在這兩個案例上。
我們最早開發了一個一筆到底的案例來實作會話管理,案例需要根據使用者儲存使用者的作品,每次使用者登入,都可以看到使用者自己的繪畫。
但是,因為小程式不支援 Cookie 傳輸,是以會話服務需要自行實作。
我們會話管理的實作目标是:
完成微信要求的鑒權流程,生成使用者會話
利用會話确定每個請求對應哪個微信使用者
安全性和擴充性滿足要求
我們案例按照這個流程進行會話建立:

會話建立流程
其中在小程式和伺服器我們分别提供 JS 和 Node SDK 來提供會話支援。這個案例完成了會話服務的功能性目标,可以提供會話建立和驗證的能力。但是弊端在于,該能力隻能被 Node 開發者使用,其他語言的開發者無法使用。同時,因為小程式的 <code>appId</code> 和 <code>appSecret</code> 存放在外網可以通路的伺服器上,也有一定安全性問題。會話服務和我們的業務耦合在一起,也給後續的橫向擴充帶來了麻煩。
于是,我們提出了改進的手段:
會話管理伺服器獨立提供
提供多語言的 SDK
appId 和 appSecret 存放到資料庫中
其中多語言的 SDK 正式因為會話管理伺服器的獨立而可以快速開發到。
優化後,會話的建立流程如下圖所示:
而會話的驗證流程如下圖所示:
會話檢查流程
我們的會話服務改進取得的效果還是很明顯的:
流程和安全性上完全符合了微信的鑒權要求
獨立會話伺服器,可以友善進行獨立的更新和擴充,也為多語言 SDK 的開發打開了友善的大門
我們面臨的另外一個挑戰就是 WebSocket。在進行案例分析之前,先跟大家分析一下微信支援 WebSocket 的原因。
傳統的 HTTPS 連接配接請求,每個請求都需要建立一次連接配接,耗費比較多的資源。同時微信有最大連接配接數的限制(5個),是以實時通信的需求不好做,長連接配接的方案也隻能串行傳輸,這種方案耗電高體驗差。
當我們把目光轉向 WebSocket 之後,會發現 WebSocket 通信全程隻需要建立一次連接配接,就可以實作雙向的實時通信,更省電的情況下獲得更好的體驗。
這就是小程式支援 WebSocket 的一個重要原因,可以提高業務的體驗并增加續航。
鑒于很多同學可能對 WebSocket 還不了解,這裡簡單介紹一下。
WebSocket 示意圖
我們的 HTTP 連接配接是在 TCP 的基礎上建立的,當伺服器支援 WebSocket 的時候,可以相應一個頭部,告知用戶端進行協定更新。更新協定後,會複用之前的 TCP 連接配接,在上面實作 WebSocket 協定實作雙向通信。更加詳細的資料可以參考 MDN 上的說明。
回到我們的案例上來,我們當時使用小程式提供的 WebSocket 做了一個實時的剪刀石頭布遊戲。
遊戲截圖
我們使用 Socket.IO 實作其後端後,發現在小程式無法使用 Socket.IO 的用戶端代碼支援。我們隻能自己去啃了一下 Socket.IO 的上層協定,實作了一個簡版的用戶端,進而實作剪刀石頭布這個遊戲邏輯。
這個案例驗證了在小程式上面 WebSocket 的可行性,但是由于用戶端的實作是自行實作,和 Socket.IO 的後端配合可能會出現不可控的情況。同時,我們發現 WebSocket 的後端實作門檻比較高,并且進行橫向擴充的話會更加困難。
作為雲服務廠商,我們首先想到的方案是使用 PaaS 提供服務來支援 WebSocket 連接配接。這是怎麼一個思路呢?
PaaS 服務支援 WebSocket
上圖很好地解釋了 PaaS 形式和傳統 WebSocket 形式的不同之處,PaaS 實際上是要實作一個三方通信。
我們看一下使用 PaaS 服務來建立 WebSocket 連接配接的過程:
建立 WS 連接配接
建立連接配接後,小程式和業務伺服器之間可以通過下面的形式進行通信:
WS 通信
經過 PaaS 的改造,我們得到了一個新的 WebSocket 方案。該方案的優劣在哪裡?
首先,優勢比較明顯,由平台來提供的服務,由平台自己完成擴充能力的支援以及穩定性和性能的保障,業務無需擔心。同時,業務也無需關心 WebSocket 協定的實作,因為業務伺服器和信道服務之前的通信都是傳統的 HTTP,這樣也可以節約業務伺服器的長連接配接資源。
但是這種方案也有它的局限之處。業務伺服器和信道伺服器之間采取公網通信,處于對資訊安全的考慮,最好還是走 HTTPS 通信,這個過程的通信延遲比較客觀。其次,三方通信的調試便利性也不如傳統的連接配接方式。
對于上面兩個問題,其實我們也有對應方案。如果業務伺服器在騰訊雲機房運作,那麼可以讓業務伺服器和信道伺服器之間通過内網 HTTP 傳輸,延遲大大降低。信道服務後續也會提供調試日志供大家分析發現問題。
總體來說,PaaS 方案會幫助更多開發者解決掉了門檻較高的部分。
我們上面對于會話服務和信道服務都進行了一個有益的實踐,那麼這兩個服務是否可以整合,信道服務裡面是否可以支援會話識别?
事實上我們可以做這個事情。下面的表格描述了會話服務和信道服務與服務子產品之間的關系。
服務與子產品關系
我們可以把用戶端的部分整合為用戶端 SDK,把業務伺服器的部分整合為伺服器 SDK,并且提供會話伺服器的源碼開源。
那麼上面三個部分加起來,就是目前騰訊雲的開源項目 - Wafer。
Wafer 包含了會話服務和信道服務的支援,從全棧子產品來提供開源的資源,并且提供了豐富的文檔。有興趣的開發者可以使用上面的連接配接來檢視 Wafer 項目。
Wafer 定位
Wafer 幫開發者解決了小程式開發過程中信道服務和會話服務的門檻問題,但是作為小程式開發者,還要關心背景架構、資源采供、資源部署、擴充能力、安全性、域名申請等等與業務開發無關的部分。這部分,我們提出了一個一站式部署的方案。
一站式部署
這個方案,會幫你配置設定好資源并自動部署下面的架構,讓開發者可以專注于業務開發。
整體架構
自動部署的過程其實挺複雜的,有興趣的同學可以參考下圖了解。
自動部署
上面就是 Wafer 的産品化實踐 - 騰訊雲小程式一站式解決方案。也可以掃碼了解更多資訊:
QR Code
從 16 年 9 月份開始,團隊開始接觸微信小程式,對它的一個特性進行了思考和驗證。在後面案例開發的過程中,碰到了會話服務和信道服務的兩個門檻,不斷優化,最終整合成了開源項目 Wafer 及其産品化方案,希望這些方案可以對小程式開發者提供幫助。
GITC 主題演講的幻燈片可以在這裡下載下傳。