1 初心
大家好,我是勇哥。花了三個月的時間,我手寫了個簡訊平臺服務 platform-sms
,今天開源出來 Beta 版本。
寫這個開源專案的初心其實很簡單:"幫助初中級研發工程師入門架構設計,提升他們的技術認知"。
2018年,作為架構師,我參與一個簡訊平臺的重構。傳送簡訊的場景包括還款業務、CRM、促銷業務等。
不同的技術團隊都是使用客戶端模式傳送簡訊,但並不統一,大概分為四種 :
- 使用阿里雲提供的簡訊 SDK 傳送簡訊 。
- 根據億美提供的樣例直接傳送簡訊 。
- 使用綠城提供的簡訊 SDK 傳送簡訊。
- 架構團隊簡訊 SDK ,類似於
SMS4J
的設計方式,支援億美、綠城簡訊傳送 。
客戶端的模式在多團隊協作場景中,缺點還是很明顯:
-
維護成本
假如運營不再使用某一個簡訊渠道,那麼很多團隊將會收到影響,不得不配合重新修改配置,重新上線,耗費的時間成本很高。
-
無法支援高階功能
客戶端實現某些功能比較麻煩,比如:客戶端因為偶發情況(網路原因)透過三方渠道傳送簡訊超時,此時需要將簡訊傳送到備份渠道,從而確保簡訊傳送的成功率。
因此,多團隊協作的場景中,簡訊服務的模式應該是服務端模式。
我參考了騰訊雲的簡訊服務的設計思路 :
- 模仿騰訊雲的 SDK 設計,提供簡單易用的傳送簡訊方法 (單發,群發,營銷單發,營銷群發,模板單發,模板群發) ;
- 設計簡訊服務 API 端,接收發簡訊請求,傳送簡訊資訊到訊息佇列;
- worker 服務消費訊息,按照負載均衡的演算法,呼叫不同渠道商的簡訊介面;
- 控制檯可以檢視簡訊傳送記錄,配置渠道商資訊、模版資訊等。
簡訊平臺研發完成之後,滿足了當時的業務需求,因為簡訊的管理也歸於統一,提升了業務接入簡訊服務的效率,所以各個技術團隊也比較認可。
隨著經驗的累積,我見過了不少公司的簡訊服務,核心問題不外乎兩點:
-
簡訊服務與業務服務邊界問題。
為了滿足業務服務需求,在簡訊平臺中新增過多的業務功能,導致簡訊服務功能臃腫,也不經意的加入了隱藏的風險 。
-
切換三方渠道非常不方便。
當運營端需要從三方簡訊渠道 A 切換到 B 時,因為程式碼不夠抽象,增加三方渠道程式碼時維護成本較高。
基於這些原因,我想寫一個迷你版的簡訊服務,它應該包含如下的功能:
-
簡單的簡訊 SDK 支援按照模版傳送簡訊 。
業務服務對於簡訊是從哪一個三方簡訊渠道傳送出來的並不在乎,只需要確保傳送簡訊的成功率即可。
因此,SDK 提供的核心介面是:按照模版編號傳送簡訊。
阿里雲、騰訊雲、華為雲提供的都是按照模版傳送簡訊的介面,為了統一管理模版,我們也只提供按照模版傳送簡訊的介面。
簡訊平臺需要提供業務服務的
appKey
和appSecret
, SDK 與服務端之間透過固定協議互動。 -
簡訊平臺支援模版的管理 。
阿里雲、騰訊雲、華為雲都提供簽名、模版管理的介面,因此從產品設計層面,理論上,我們可以透過簡訊平臺管理所有的簽名和模版。
簡訊平臺當前提供了手工繫結的簡訊模版的功能,也就是我們需要先在阿里雲或者騰訊雲先申請簽名和模版,然後繫結到我們在平臺建立的模版。
-
介面卡模式維護三方簡訊渠道。
參考了開源專案
canal
的介面卡模組,將三方簡訊渠道的 API 獨立成模組單獨維護,這樣可以大大提升程式碼的可維護性。
2 架構
專案的設計應該設計得簡單,因為它的目標首先是讓初中級工程師快速入門架構設計。
所以,我將簡訊平臺設計成單體應用的模式,架構圖如下:
簡訊平臺分為兩個部分,這兩部分可以獨立部署,也可以將前端檔案放置在後端中,生成單部署包。
1、前端:admin-ui
控制檯模組是 vue 專案,管理員登入之後可以進行應用管理、渠道管理、簡訊管理、模版管理。
2、後端:admin-web
後端模組按照功能依次分為五個模組:請求控制層、業務服務層、命令處理器、三方渠道介面卡外掛、資料庫訪問層。
3 演示
3.1 環境準備
1、建立資料庫以及相關表
建立資料庫tech_platform
,執行 doc/sql
目錄下的 tech_platform.sql
。
執行後效果如下:
2、修改部署包配置
從 Release 下載 platform-sms-admin.tar.gz
,解壓縮後,進入 conf
目錄 。
編輯 application.yml
檔案:
進入 bin 目錄,啟動服務:
bin/startup.sh
3.2 操作流程
1、登入頁面
服務啟動後,訪問地址:http://localhost:8089
。
使用者名稱和密碼儲存在
conf
目錄的application.yml
,預設使用者名稱密碼分別是:admin/admin1984 。
2、新建應用
應用資訊包含應用名稱、應用 appKey
, 應用秘鑰
,備註
。其中,應用 key 和 金鑰在使用客戶端 SDK 時需要配置 。
3、新建三方簡訊渠道
注意:因為騰訊雲的 SDK 請求 中需要攜帶 APPID ,所以 Beta 版中將 appId 儲存在 附件屬性中。
4、建立模版
在模版管理
模組,點選新建模版
按鈕。
新建模版時,簽名名稱必須和渠道申請的簽名必須一致。
下圖展示了筆者的騰訊雲申請的簽名,筆者建立的模版必須和騰訊雲賬號的簽名保持一致。
建立完模版之後,需要繫結渠道,我們需要在三方渠道先建立簡訊模版,然後提交繫結。
- 三方渠道先建立簡訊模版
如上圖,筆者建立了編號為 1955325 的簡訊模版,因為我們需要在繫結介面繫結該渠道的模版,理論上在簡訊平臺建立的模版可以繫結多個渠道。
- 繫結渠道
繫結完成之後,可以在模版管理頁面檢視模版列表 。
3.3 傳送簡訊
傳送簡訊可以參考 DEMO 模組:
1、新增依賴
<dependency>
<groupId>com.courage</groupId>
<artifactId>platform-sms-client</artifactId>
<version>${parent.version}</version>
</dependency>
2、客戶端配置
首先在 application.yml
中配置如下:
sms:
smsServerUrl: http://localhost:8089
appKey: qQjEiFzn80v8VM4h
appSecret: 9c465ece754bd26a9be77f3d0e2606bd
然後編寫配置類:
@Configuration
public class SmsConfiguration {
@Value("${sms.smsServerUrl}")
private String smsServerUrl;
@Value("${sms.appKey}")
private String appKey;
@Value("${sms.appSecret}")
private String appSecret;
@Bean
public SmsSenderClient createClient() {
SmsConfig smsConfig = new SmsConfig();
smsConfig.setAppKey(appKey);
smsConfig.setSmsServerUrl(smsServerUrl);
smsConfig.setAppSecret(appSecret);
SmsSenderClient smsSenderClient = new SmsSenderClient(smsConfig);
return smsSenderClient;
}
}
3、單發簡訊
@Autowired
private SmsSenderClient smsSenderClient;
@GetMapping("/test")
public String test() {
// 手機號
String mobile = "15011319235";
// 簡訊平臺模版編號
String templateId = "555829270636703745";
// 模版引數
Map<String, String> param = new HashMap<String, String>();
param.put("code", "1234");
param.put("time", "10");
SmsSenderResult senderResult = smsSenderClient.sendSmsByTemplateId(mobile, templateId, param);
System.out.println("senderResult:" + JSON.toJSONString(senderResult));
return "hello , first short message !";
}
呼叫介面之後,使用者就會收到如下的簡訊:
4 開源
程式碼庫地址:
勇哥想把這個專案做為架構入門的教學專案,您可以從中學到 :
- 設計一個精簡的客戶端 SDK 。
- 理解 SPI 機制以及介面卡模式。
- 配置合理的執行緒模型。
如果我的文章對你有所幫助,還請幫忙點贊、在看、轉發一下,你的支援會激勵我輸出更高質量的文章,非常感謝!