.net core实践系列之短信服务-架构设计
前言
上篇《.net core實踐系列之短信服務(wù)-為什么選擇.net core(開篇)》簡單的介紹了(水了一篇).net core。這次針對短信服務(wù)的架構(gòu)設(shè)計和技術(shù)棧的簡析。
源碼地址:https://github.com/SkyChenSky/Sikiro.SMS
為什么需要架構(gòu)設(shè)計
有人會問短信服務(wù)也要架構(gòu)設(shè)計?不就寫個service封裝個send方法就得了嗎?干嘛還要大動干戈。
如果在單塊應(yīng)用的情況下,以上面的做法是無可厚非的。
然而架構(gòu)設(shè)計解決的是應(yīng)用復(fù)雜度,架構(gòu)設(shè)計的大還是小取決于業(yè)務(wù)規(guī)模,技術(shù)的使用是要落實到應(yīng)用場景。
場景假設(shè)
以我們公司作為例子:
- 已擁有多套系統(tǒng),運營后臺、資金平臺、賬單平臺、APP API等; 
- 需接入多個短信運營商,避免某個出異常后隨時切換; 
- 及時發(fā)送、定時發(fā)送; 
從上面場景分析出,要由多系統(tǒng)、多平臺接入需要單獨抽離出來進行服務(wù)化,而且隨著接入的系統(tǒng)越多,性能將成為瓶頸,因此需要良好的橫向拓展能力。定時發(fā)送需要調(diào)度任務(wù)系統(tǒng)進行解決。
因此下面為我設(shè)計的架構(gòu)圖
架構(gòu)圖
架構(gòu)簡析
SmsApi服務(wù)
以HTTP協(xié)議RESTful風(fēng)格JSON格式提供給其他系統(tǒng)(服務(wù))接入,以swagger作為服務(wù)描述提供對外查看。
接口主要功能有:
- 發(fā)送短信 
- 查詢短信列表 
發(fā)送短信支持批量,接口接受到請求后將數(shù)據(jù)先持久化到MongoDB。
如果及時發(fā)送則立刻發(fā)送RabbitMQ,再由Sikiro.SMS.Bus訂閱隊列進行統(tǒng)一發(fā)送;
如果定時發(fā)送則等待Sikiro.SMS.Job進行輪循MongoDB,輪詢到時的消息則發(fā)送到RabbitMQ,再由Sikiro.SMS.Bus訂閱隊列進行統(tǒng)一發(fā)送。
Sikiro.SMS.Job調(diào)度任務(wù)服務(wù)
此服務(wù)以Quartz.NET框架為基礎(chǔ),通過設(shè)計可以隨意增加Trigger或者服務(wù),使其多線程或多個進程同時運行,避免數(shù)據(jù)量大了后成為發(fā)送瓶頸。
此服務(wù)不直接做短信發(fā)送,只是觸發(fā)器的存在,通過RabbitMQ進行解耦,避免執(zhí)行過程過長如果停止服務(wù)時則中斷。
Sikiro.SMS.Bus隊列消費服務(wù)
無論定時、及時短信都由該服務(wù)進行發(fā)送,如果接入了新的短信運營商,只需要停止該服務(wù)進行更新即可。停止了服務(wù)消息不會丟失,將暫存在RabbitMQ,因需對RabbitMQ的消息做持久化。
可以在不同的服務(wù)器上部署服務(wù),因為訂閱同一個隊列,良好的橫向擴展保證了高可用、高性能
可伸縮性
可伸縮性指在不改變系統(tǒng)軟硬件設(shè)計,僅僅通過新增服務(wù)器的情況下,就能提升系統(tǒng)的處理能力。
HTTP API的無狀態(tài),在調(diào)度任務(wù)里的MongoDB原子操作FindOneAndUpdate的使用,多消費者的訂閱都是為了可伸縮性。同時通過部署多臺服務(wù)器也可以提高高性能與高可用。
MongoDB的選擇
我選擇MongoDB主要原因是聚合一致性、無模式。
雖說不需要ACID但不代表沒有一致性,而MongoDB體現(xiàn)的聚合一致性,以聚合做操作。
聚合
一組具有內(nèi)聚關(guān)系的相關(guān)對象的稱為集合
關(guān)系型數(shù)據(jù)庫
則以下面兩表通過SmsId關(guān)聯(lián)讀取,寫入則兩表作為一個事務(wù)
MongoDB
則以下面聚合方式表示,以聚合取,以聚合寫
無模式
MongoDB一大特點則是無模式,意思是無需預(yù)先定義集合結(jié)構(gòu)與字段類型,這體現(xiàn)了良好的拓展性。這是優(yōu)點也是缺點,假如別的服務(wù)對該集合進行操作,在他不知情的情況下隨意寫入不同類型的值,則會影響已運行的服務(wù)。
因此需要將此作為應(yīng)用服務(wù)數(shù)據(jù)庫,也就是服務(wù)化,把對集合的操作(讀與寫)以服務(wù)形式提供接口給其他服務(wù)使用。
服務(wù)粒度
有些人會問為什么不把三個運營商Service也拆出來作為獨立的API服務(wù)?
回顧下現(xiàn)在執(zhí)行流程,一次短信發(fā)送最長的調(diào)用鏈為:請求SmsApi,Sikiro.SMS.Job輪詢數(shù)據(jù),Sikiro.SMS.Bus消費隊列消息并請求短信運營商服務(wù)。
架構(gòu)上的擴展性的本質(zhì)的確是拆,但是拆得過細將出現(xiàn)三個問題:
- 調(diào)用鏈過長影響性能 
- 調(diào)用鏈過長難以定位問題 
- 增加開發(fā)、維護成本 
假如哪天短信沒發(fā)送成功,首先看看API日志看看是不是調(diào)用成功了,如果沒問題那可能JOB出問題了。如果JOB正常跑,難道是隊列問題?假如再加多一層,那就定位更加的復(fù)雜了。
就如開始所說的如果添加一個短信運營商只需要添加一個Service利用工廠模式,就可以良好的拓展了。而添加一個服務(wù)的開發(fā)、部署、維護成本無疑是比在組件內(nèi)擴展的成本高。
結(jié)尾
該篇描述我的架構(gòu)設(shè)計,下篇會正式對各個服務(wù)的實現(xiàn)進行講解。如果您有更好的建議可以在下方評論反饋給我。
相關(guān)文章:
- .net core實踐系列之短信服務(wù)-為什么選擇.net core(開篇) 
原文地址:?https://www.cnblogs.com/skychen1218/p/9547543.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com 
總結(jié)
以上是生活随笔為你收集整理的.net core实践系列之短信服务-架构设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 浅谈surging服务引擎中的rabbi
- 下一篇: CAP 2.3版本发布,支持 Mongo
