三個月寫了個簡訊平臺,開源出來!

勇哥程式設計遊記發表於2023-11-26

1 初心

大家好,我是勇哥。花了三個月的時間,我手寫了個簡訊平臺服務 platform-sms,今天開源出來 Beta 版本。

寫這個開源專案的初心其實很簡單:"幫助初中級研發工程師入門架構設計,提升他們的技術認知"。

2018年,作為架構師,我參與一個簡訊平臺的重構。傳送簡訊的場景包括還款業務、CRM、促銷業務等。

不同的技術團隊都是使用客戶端模式傳送簡訊,但並不統一,大概分為四種 :

  • 使用阿里雲提供的簡訊 SDK 傳送簡訊 。
  • 根據億美提供的樣例直接傳送簡訊 。
  • 使用綠城提供的簡訊 SDK 傳送簡訊。
  • 架構團隊簡訊 SDK ,類似於 SMS4J的設計方式,支援億美、綠城簡訊傳送 。

客戶端的模式在多團隊協作場景中,缺點還是很明顯:

  • 維護成本

    假如運營不再使用某一個簡訊渠道,那麼很多團隊將會收到影響,不得不配合重新修改配置,重新上線,耗費的時間成本很高。

  • 無法支援高階功能

    客戶端實現某些功能比較麻煩,比如:客戶端因為偶發情況(網路原因)透過三方渠道傳送簡訊超時,此時需要將簡訊傳送到備份渠道,從而確保簡訊傳送的成功率。

因此,多團隊協作的場景中,簡訊服務的模式應該是服務端模式

服務端模式

我參考了騰訊雲的簡訊服務的設計思路 :

  1. 模仿騰訊雲的 SDK 設計,提供簡單易用的傳送簡訊方法 (單發,群發,營銷單發,營銷群發,模板單發,模板群發) ;
  2. 設計簡訊服務 API 端,接收發簡訊請求,傳送簡訊資訊到訊息佇列;
  3. worker 服務消費訊息,按照負載均衡的演算法,呼叫不同渠道商的簡訊介面;
  4. 控制檯可以檢視簡訊傳送記錄,配置渠道商資訊、模版資訊等。

簡訊平臺研發完成之後,滿足了當時的業務需求,因為簡訊的管理也歸於統一,提升了業務接入簡訊服務的效率,所以各個技術團隊也比較認可。

隨著經驗的累積,我見過了不少公司的簡訊服務,核心問題不外乎兩點:

  1. 簡訊服務與業務服務邊界問題。

    為了滿足業務服務需求,在簡訊平臺中新增過多的業務功能,導致簡訊服務功能臃腫,也不經意的加入了隱藏的風險 。

  2. 切換三方渠道非常不方便。

    當運營端需要從三方簡訊渠道 A 切換到 B 時,因為程式碼不夠抽象,增加三方渠道程式碼時維護成本較高。

基於這些原因,我想寫一個迷你版的簡訊服務,它應該包含如下的功能:

  1. 簡單的簡訊 SDK 支援按照模版傳送簡訊 。

    業務服務對於簡訊是從哪一個三方簡訊渠道傳送出來的並不在乎,只需要確保傳送簡訊的成功率即可。

    因此,SDK 提供的核心介面是:按照模版編號傳送簡訊

    阿里雲、騰訊雲、華為雲提供的都是按照模版傳送簡訊的介面,為了統一管理模版,我們也只提供按照模版傳送簡訊的介面。

    簡訊平臺需要提供業務服務的appKeyappSecret , SDK 與服務端之間透過固定協議互動。

  2. 簡訊平臺支援模版的管理 。

    阿里雲、騰訊雲、華為雲都提供簽名、模版管理的介面,因此從產品設計層面,理論上,我們可以透過簡訊平臺管理所有的簽名和模版。

    簡訊平臺當前提供了手工繫結的簡訊模版的功能,也就是我們需要先在阿里雲或者騰訊雲先申請簽名和模版,然後繫結到我們在平臺建立的模版。

  3. 介面卡模式維護三方簡訊渠道。

    參考了開源專案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、建立模版
模版管理模組,點選新建模版按鈕。

新建模版時,簽名名稱必須和渠道申請的簽名必須一致。

下圖展示了筆者的騰訊雲申請的簽名,筆者建立的模版必須和騰訊雲賬號的簽名保持一致。

建立完模版之後,需要繫結渠道,我們需要在三方渠道先建立簡訊模版,然後提交繫結。

  1. 三方渠道先建立簡訊模版

如上圖,筆者建立了編號為 1955325 的簡訊模版,因為我們需要在繫結介面繫結該渠道的模版,理論上在簡訊平臺建立的模版可以繫結多個渠道。

  1. 繫結渠道

繫結完成之後,可以在模版管理頁面檢視模版列表 。

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 開源

程式碼庫地址:

https://github.com/makemyownlife/platform-sms

勇哥想把這個專案做為架構入門的教學專案,您可以從中學到 :

  1. 設計一個精簡的客戶端 SDK 。
  2. 理解 SPI 機制以及介面卡模式。
  3. 配置合理的執行緒模型。

如果我的文章對你有所幫助,還請幫忙點贊、在看、轉發一下,你的支援會激勵我輸出更高質量的文章,非常感謝!