嗶哩嗶哩淘寶小程序盲盒抽獎實踐

目錄

背景

名詞解釋

整體業務流程

技術實現

調用鏈路

雲開發( Serverless )

雲開發的限制

編寫雲函數

怎麼拿到授權查詢輕店鋪用戶訂單

輕店鋪雲網關

數字簽名網關

網關技術選型

Vert.x介紹

同步和異步

阻塞和非阻塞

I/O 多路複用

Netty

網關實現

反應式和非阻塞編程

總結



背景

爲嗶哩嗶哩天貓旗艦店添加類似泡泡瑪特盲盒抽獎的淘寶小程序,也叫淘寶輕店鋪。

由於淘寶不允許直接在輕店鋪中發起對第三方服務的請求,只能通過雲函數轉發,詳見:淘寶輕店鋪官方說明

輕店鋪客戶端調用嗶哩嗶哩服務要經過的鏈路:輕店鋪雲函數->輕店鋪雲服務->奇門→SLB→ECS→OpenApi嗶哩嗶哩後端服務。輕店鋪雲服務必須使用輕店鋪奇門,奇門必須使用阿里SLB,阿里SLB只支持阿里ECS。所以我們的方案必須使用到阿里雲配套方案。

名詞解釋

輕店鋪:淘寶APP小程序。輕店鋪控制檯: https://miniapp.open.taobao.com/#/

盲盒:盒子上沒有標註,只有打開纔會知道自己抽到了什麼。

抽盒機:進行抽獎、發貨、訂單展示的應用。

奇門:淘寶小程序網關,輕店鋪請求bilibili服務先通過奇門,https://open.taobao.com/doc.htm?docId=106847&docType=1 (對於非標準化的場景對接,提供網關基礎能力,支持服務商做自己的服務開放). 奇門控制檯:https://qimen.taobao.com

SLB:阿里的負載均衡。 輕店鋪對應的奇門接口必須使用SLBSLB只支持阿里雲(ECS) 。輕店鋪只支持內網SLB,配置阿里SLB的時候要選擇免費的私網實例。雲控制檯:https://console.cloud.tmall.com/#/index

ECS:雲主機,部署自定義服務,關聯到SLB。 雲控制檯:https://console.cloud.tmall.com/#/index

RDS: 阿里雲數據庫,阿里雲增值服務,裏面聚合了嗶哩嗶哩淘寶店鋪的所有訂單。

雲函數:輕店鋪客戶端通過雲函數調用嗶哩嗶哩提供的第三方服務。 雲函數控制檯: https://console-snipcode.taobao.com/miniapp/index

Serverless 雲開發:小程序前後端服務。

雲服務: Serverless雲函數服務端。

整體業務流程

輕店鋪共有兩種訂單:抽獎次數訂單、郵費訂單。

由於淘寶不允許上架虛擬貨幣,抽獎次數通過抽盒次數訂單購買轉換,抽獎之後,根據抽盒次數訂單地址,購買運費訂單實現發貨。

如圖是抽盒機若干頁面,通過購買抽獎次數訂單轉換爲抽盒機會,消費抽盒機會實現盲盒抽獎,抽獎看到商品,選擇商品後發貨。淘寶抽獎次數訂單轉換爲抽盒機抽獎次數採用了前端異步刷新,後端Job輪詢方式。前端把抽獎用戶Id傳遞給後端,後端根據用戶Id實時拉取用戶訂單,轉換爲對應的次數,同時後臺Job輪詢訂單實現兜底。

整體業務序列圖

技術實現

調用鏈路

如下是購買抽獎訂單轉換爲抽獎次數的一個請求鏈路,可以看到很長。

雲開發( Serverless

小程序基於淘寶小程序SDK,後臺基於雲Serverless。

雲開發(Serverless) 提供以下三種功能:

數據存儲服務是基於 MongoDB 託管在雲端的數據庫,數據以 JSON 格式存儲。數據庫中的每條記錄都是一個 JSON 格式的對象。一個數據庫可以有多個集合(相當於關係型數據中的表)。

文件存儲服務支持文本、圖片和其他由用戶生成的內容存儲到雲端。開發者可以在小程序端和控制檯使用雲存儲功能。圖片上傳成功後,系統會自動生成一個資源鏈接。開發者可以在小程序中使用該圖片地址。

雲函數服務支持使用Node.js進行開發。作爲開發者,您可以可將代碼提交到雲端運行,在客戶端使用小程序提供的 API 進行調用。您還可以在雲函數中直接通過 API 調用數據存儲和文件存儲的服務資源。

雲開發(Serverless) 具有以下優勢:

無運維開發者只需專注業務開發,無需理解後端服務的運維配置。

低成本按實際使用的資源和調用情況計費,有效降低了運維成本和研發成本。

高可用底層能力由阿里雲存儲、數據庫團隊提供支持,支持彈性擴容,同時提供可用性保障。

一雲多端適配多種平臺的小程序端框架,一套代碼多端使用

詳情參考官方文檔:https://miniapp.open.taobao.com/docV3.htm?docId=118541&docType=1&source=search

雲開發的限制

每個雲函數有最大併發限制。現有業務遠達不到雲函數最大併發度,但以防萬一,目前按業務劃分創建了多個雲函數+雲應用。並且諮詢了淘寶技術人員,給出的答覆是併發的瓶頸只會在自己購買的阿里雲主機上面,雲函數會彈性擴容。

如下按業務對雲函數進行劃分。

編寫雲函數

下載小程序IDE,安裝開發環境,基於Node.js

使用淘寶開發賬號關聯IDE,基於官方示例編寫自定義雲函數服務端,然後上傳到雲函數容器。

上傳後基於雲函數Client端實現調用服務端

 

客戶端調用自定義雲服務例子,獲取發貨券列表:
import cloud from '@tbmp/mp-cloud-sdk';  // 導入雲函數sdk
cloud.init({
  env: 'test'  // 設置測試環境
});
try {   
  console.log('begin----------------------------- ');
  cloud.function.invoke(‘test’, {  // 輸入json
    "serviceName": "mall.test.coupon",
    "content": {
      "openId": "AAxxxxxxxxxxxxxx",
      "pageNum": 1,
      "pageSize": 10
    }
  }, 'main')
    .then(res => {
      console.log(res);  // 返回結果
    })
} catch (e) {
  console.log(e);
}

 調用成功返回數據

 

 

 

除了自定義雲函數,也有一些官方雲函數可以在客戶端直接調用輕店鋪雲網

客戶端調用官方雲服務例子,獲取用戶授權:
 my.authorize({
      scopes: ‘scope.userInfo’,   // 淘寶官方雲服務名
      success: (res) => {
        my.setClipboard({
          text: res.accessToken    // 獲取授權token
        });
        my.alert({
          content: res.accessToken
        })
      },
    });
};

 

怎麼拿到授權查詢輕店鋪用戶訂單

由於後臺通過淘寶增值接口查詢輕店鋪用戶訂單需要獲取Token授權。這個問題研究了很久,最終根據淘寶文檔解決。

參考:https://miniapp.open.taobao.com/doc.htm?spm=a219a.7386797.0.0.3af3669aWi4rBz&source=search&docId=118179&docType=1

 

用商家端身份登錄小程序IDE,使用如下代碼獲取商家端授權Token。

由於Token一個月過期,還可以生成二維碼,使用商家端千牛App掃描二維碼授權、續期。

my.authorize({
      scopes: ‘scope.userInfo’,   // 淘寶官方雲服務名
      success: (res) => {
        my.setClipboard({
          text: res.accessToken    // 獲取授權token
        });
        my.alert({
          content: res.accessToken
        })
      },
    });
};

輕店鋪雲網關

商家應用(淘寶小程序)到聚石塔容器服務(指後臺阿里雲主機)的請求需要通過平臺的雲網關進行轉發,調用鏈路入下所示

首先到雲網關控制檯配置一下生產環境阿里雲服務器,與測試環境服務器

輕店鋪奇門雲網關要關聯阿里雲內網SLB

輕店鋪雲網關除配置生產阿里雲SLB外還可以關聯自己的測試環境。

 

雲網關要用到阿里雲SLB,我們需要給自己購買的阿里雲主機加上阿里雲SLB負載網關。

打開阿里雲聚石塔控制檯,添加SLB。由於輕店鋪雲網關只支持阿里雲SLB內網形式,注意SLB不要配置成公網。

數字簽名網關

配置了輕店鋪雲網關、阿里雲SLB後,請求就可以從小程序轉發到自己購買的阿里雲服務器了。我們要對輕店鋪的請求做數字簽名驗證,加簽名,首先需要在阿里雲上面自定義實現一套網關驗證簽名、加簽名。

阿里雲主機配置:兩臺雙核心、4G內存雲主機,通過SLB實行負載平衡。

網關技術選型

自定義網關基於vert.x實現。

除用戶外,前端也會自動刷新,產生不小的網絡連接
阿里雲主機性能有限,價格貴,擴容靠財務
框架要輕量級,開箱即用
Vert.x做網關更專業

Vert.x介紹

Vert.x項目起始於2011年,是一個仿照Node.jsJava開發的,基於EventLoop的異步非阻塞編程框架。

Vert.x的底層IO基於 Netty4 實現,核心模塊 Vertx Core,支持非阻塞 文件IOTCPUDPDNSHTTPHTTPSHTTP2(包括h2h2c)。比較基礎的模塊 Vert.x-Web ,提供了包括 URL 路由,模板引擎在內的開發web server所需的APIVert.x Web Client,提供一個非阻塞Http Client實現。

對於JDBCMongoDBRedisKafakaJava MailApache Shiro等都提供了封裝集成,還提供了服務發現,斷路器,配置中心等微服務所需要的設施,以及基於Hazelcast/Apache Ignite/Zookeeper Cluster功能。

接着普及一下異步,非阻塞,I/O多路複用、Netty的概念。

同步和異步

同步和異步的概念描述的是用戶線程與內核的交互方式:同步是指用戶線程發起IO請求後需要等待或者輪詢內核IO操作完成後才能繼續執行;而異步是指用戶線程發起IO請求後仍繼續執行,當內核IO操作完成後會通知用戶線程,或者調用用戶線程註冊的回調函數。同步、異步的討論對象是被調用者——內核。

阻塞和非阻塞

阻塞和非阻塞的概念描述的是用戶線程調用內核IO操作的方式:阻塞是指IO操作需要徹底完成後才返回到用戶空間;而非阻塞是指IO操作被調用後立即返回給用戶一個狀態值,無需等到IO操作徹底完成。阻塞、非阻塞的討論對象是調用者——用戶線程。

I/O 多路複用

I/O 多路複用,I/O 就是指的我們網絡 I/O,多路指多個 TCP 連接(或多個 Channel),複用指複用一個或少量線程。串起來理解就是很多個網絡 I/O 複用一個或少量的線程來處理這些連接。

I/O 多路複用的實現有多種方式:selectpollepoll

java.nio.channels.Selector Java的非阻塞I/O實現的關鍵。 它使用了 事件通知API以確定在一組非阻塞套接字中有哪些已經就緒能夠進行I/O相關的操作。 因爲 可以在任何的時間檢查任意的讀操作或者寫操作的完成狀態, 所以如圖所示, 一個單 一 的線程便可以處理多個併發的連接。

詳見: https://blog.csdn.net/chinabhlt/article/details/51983622

Jdk在不同操作系統各有不同的實現,如下WindowslinuxSelector實現,poll0epollWait均爲native方法。

Netty

Netty基於Selector對象實現I/O多路複用,通過 Selector, 一個線程可以監聽多個連接的Channel事件, 當向一個Selector中註冊Channel 後,Selector 內部的機制就可以自動不斷地查詢(select) 這些註冊的Channel是否有已就緒的I/O事件(例如可讀, 可寫, 網絡連接完成等),這樣程序就可以很簡單地使用一個線程高效地管理多個 Channel。詳見: https://juejin.im/post/5bea1d2e51882523d3163657

Netty中所有的IO操作都是異步的,不能立刻得知消息是否被正確處理,但是可以過一會等它執行完成或者直接註冊一個監聽,具體的實現就是通過FutureChannelFutures,他們可以註冊一個監聽,當操作執行成功或失敗時監聽會自動觸發註冊的監聽事件。Netty框架將網絡編程邏輯與業務邏輯處理分離開來, 其內部會自動處理好網絡與異 步處理邏輯, 讓我們專心寫自己的業務處理邏輯。 同時, Netty的異步非阻塞能力與 CompletableFuture結合可以讓我們輕鬆實現網絡請求的異步調用。 DubboRocketMqZuul 2.0服務網 關、 Spring WebFlux底層網絡通信等都是基於Netty來實現的。

網關實現

Vert.x基於Netty封裝了線程模型,簡化了業務處理。Event Loop 線程,會不斷地輪詢獲取事件,並將獲取到的事件分發到對應的事件處理器中進行處理。

 

Vert.x簡化了Netty的使用,讓我們更加關注業務。

如下是網關路由核心代碼,僅僅幾行代碼就實現了異步處理請求,配置線程池,與基於請求路徑的路由。

反應式和非阻塞編程

用了異步框架不一定提高性能。

反應式和非阻塞編程通常不會使應用程序運行得更快, 雖然在某些情況下它們可以 (例如使用WebClient並行執行遠程調用) 做到更快。 相反以非阻塞的方式來執行, 需要 做更多的額外工作, 並且可能會增加處理所需的時間。

反應式和非阻塞的關鍵好處是能夠使用少量固定數量的線程和更少的內存實現系統可伸縮性。 這使得應用程序在負載下更具彈性, 因爲它們以更可預測的方式擴展。 但是爲了 得到這些好處, 需要付出一些代價(比如不可預測的網絡IO) 。

當連接數 < 1000,併發程度不高或者局域網環境下 NIO 並沒有顯著的性能優勢。如果放到線上環境,網絡情況在有時候並不穩定的情況下,這種基於 I/O 複用技術的 NIO 的優勢就是傳統 BIO 不可同比的了。

可以看一下Vert.xSpring性能簡單對比,如下在硬件、網絡資源充足情況下,Vert.x並沒有性能優勢

Jvm 啓動參數:-Xmx1024M -Xmn1024M

Spring 參數,起始線程池600:
server.tomcat.max-connections=20000
server.tomcat.max-threads=10000
server.tomcat.min-spare-threads=600
server.tomcat.accept-count=10000
server.port=8080

Vert.x 參數:

限定工作線程600,按CPU核數分配實例。

基於Gatling性能測試框架,先充分預熱,然後模擬500用戶併發,持續時間30秒。上爲spring ,下位vert.x。佔用jvm內存、cpu幾乎無區別。

平均響應時間幾乎無區別

上爲Spring,下位vert.x

總結

以上是基於淘寶小程序從前端到後端的實踐。實戰過程中也發現一些問題。

由於調用鏈路過長,偶爾出現超時問題,這個需要通過Job輪詢進行補償兜底。

阿里雲控制檯可以配置健康檢查策略、報警監控,這個對服務可用性尤爲重要。

在開發實施過程中尤其要鑽研阿里官方文檔,文檔模棱兩可之處還需要提工單等客服回答。

本地調用大量的淘寶增值接口產生了不小的費用,可以把增值接口的調用放到阿里雲主機裏面,本地再調用阿里雲主機,因爲阿里雲裏面調用增值接口費用比較低。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章