【系統(tǒng)設(shè)計】我們是如何一個半月從無到有打造一個互聯(lián)網(wǎng)回收平臺的

我們接到一個需求,開發(fā)一個互聯(lián)網(wǎng)廢舊垃圾回收平臺。需求方只是一個想法,技術(shù)團隊如何落地,不僅僅涉及到系統(tǒng)設(shè)計,更重要的是先梳理清業(yè)務(wù)鏈路。


業(yè)務(wù)分析

廢舊品處理廠期望直面普通用戶進行廢物回收,這是一個串行的長鏈路業(yè)務(wù),所以我們以業(yè)務(wù)參與人員的角度切入分析:

用戶Customer

  • 用戶可以通過微信公眾號,手機App,官網(wǎng)進行回收呼叫,另外考慮到部分老年用戶不太會用手機,需要同時支持400熱線電話

客服CustomerSupportor

  • 客服人員一方面對于用戶發(fā)起的呼叫進行審查,因為回收業(yè)務(wù)是強依賴地址的,需要確保相應(yīng)訂單盡可能準確,否則直接派送回收人員會造成一些問題。
  • 另外一方面,對于直接通過熱線電話發(fā)起的回收呼叫,我們需要客服人員進行會員注冊,訂單創(chuàng)建等操作。
  • 此外,對于用戶投訴,車輛故障等突發(fā)問題,需要客服協(xié)調(diào)解決。

調(diào)度員Dispatcher

  • 對于回收訂單分配,考慮到項目上線時間和初期規(guī)模,不會有特別智能的訂單分配策略方案(路線規(guī)劃,訂單分派,車輛負載檢查等),所以通過調(diào)度人員進行訂單分派補償,才能保證業(yè)務(wù)平穩(wěn)運行。
  • 另外考慮回收后,需要給用戶付錢,回收人員需要統(tǒng)一攜帶現(xiàn)金,并每日進行核對,也需要調(diào)度員這樣一個和回收員緊密聯(lián)系的角色進行資金匯總分發(fā)等操作。

調(diào)度管理員GeneralDispatcher

  • 主要是能看到基于地圖的全局數(shù)據(jù)大盤和綜合業(yè)務(wù)數(shù)據(jù)匯總(例如總車輛,總回收單數(shù),總服務(wù)用戶等)。

回收員Recycler

  • 支持接單,接收審核后調(diào)度分派的訂單,然后找到用戶,審核廢舊品,并貼上全局唯一的條碼,實現(xiàn)全鏈路追溯,錄入系統(tǒng)相應(yīng)訂單和回收物品,完成2C的付款。
  • 支持現(xiàn)場幫用戶下單,考慮有些用戶看到工作人員后可能會現(xiàn)場回收。
  • 支持對訂單做一些操作,例如拒絕接收改單,完成該訂單,停止接單,匯報車輛負載等。

倉儲:需求是打通上下游,那么廢舊品集中回收后,需要運送到專門的倉庫進行分揀歸類,然后統(tǒng)一配送給末端處理企業(yè),這就要求有相應(yīng)倉儲工作人員接入。

倉儲_原料入庫下貨員

  • 回收車輛進入倉庫后,由下貨員進行廢舊品卸貨,掃描回收品上的全局唯一條碼,核對物品類型是否與回收員現(xiàn)場錄入的物品類型一致,核對整車物品數(shù)目是否和系統(tǒng)一致。之后將物品放入循環(huán)傳送帶上,交由下一個環(huán)節(jié)處理。

倉儲_原料分揀員

  • 分揀員按照廢舊品類型分組,例如電視機線,冰箱線,電腦線,手機線,紡織品線等。具體操作可以從主傳送帶上拿取自己負責的物品類型,進行掃碼裝框(每個框子是國家標準制作的大鐵籠),這樣我們就知道一個在客戶A回收的類型為電視機20寸的物品1001,最終被分揀線工人識別為類型電視機20寸,并裝入了31框。當然回收員因為自己的專業(yè)知識可能會對物品規(guī)格識別錯誤,這里有可能出現(xiàn)倉庫分揀的物品類型與回收員錄入的物品類型不一致的情況,我們需要識別分析進行報告。
  • 分揀完成后,當一個框子滿框,分揀員觸發(fā)入庫操作,會自動打印入庫單,并通知叉車員將整框同類型物品送往稱重臺稱重,稱重之后放置于指定存儲區(qū)域,叉車員通過入庫單進行搬送業(yè)務(wù),并不直接在系統(tǒng)中參與到業(yè)務(wù)鏈路中,可以通過人工喊話進行溝通。

倉儲_成品入庫稱重員

  • 通過電子秤,直接獲取框以及滿框物品的總重量,減去框標準重量,就得到了物品總重,稱重員掃描框碼,確認重量,打印標準入庫單,表明框號,批次號,類型,數(shù)量,重量并錄入系統(tǒng)中,之后由叉車員放入成品存放區(qū)。

倉儲_成品出庫員

  • 當運營人員發(fā)現(xiàn)某類型廢舊品分揀成品達到一定數(shù)量,聯(lián)系相應(yīng)終端處理企業(yè)出庫,此時會有一輛大貨車,在出庫員處錄入企業(yè)信息,車輛信息,司機信息,生成預出庫單,憑借預出庫單,前往大電子秤處稱空車重量,然后返回倉庫出庫口,進行出庫品裝載,每個框出庫時進行掃碼,這樣系統(tǒng)就知道哪些物品,多重的物品,被哪個企業(yè)接收走了。

倉儲_成品出庫稱重員

  • 對出庫車輛進行空載稱重
  • 對出庫車輛進行滿載稱重

倉儲_管理員

  • 看到所有物品的倉儲情況
  • 看到所有倉儲人員的處理數(shù)據(jù)
  • 特殊權(quán)限針對物品做強制出入庫,報廢,訂正等操作

財務(wù)

財務(wù)人員

  • 全量訂單數(shù)據(jù)
  • 全量支付數(shù)據(jù)
  • 全量倉儲數(shù)據(jù),包括庫存,入庫,出庫,各種進銷存
  • 定制化報稅單
  • 全量人員數(shù)據(jù)

至此整個業(yè)務(wù)鏈路基本處理完畢,對于終端處理企業(yè),由于數(shù)目眾多類型眾多,我們無法再進行更深一步的打通。


核心業(yè)務(wù)模型抽取

賬戶Account

  • 用戶,客服,調(diào)度,倉儲人員需要統(tǒng)一的核身邏輯,所以我們要打造規(guī)范的賬戶體系。賬戶的核心抽象實際上就是登陸憑證,我們通過Account模型,內(nèi)含登錄名,登錄密碼,賬戶類型等關(guān)鍵字段,就可以完成統(tǒng)一核身和權(quán)限管控。另外對于不同的業(yè)務(wù)參與者Customer,CustomerSupportor等,其描述字段很不相同,例如用戶有用戶昵稱,但是對于Supportor沒有,但是Supportor卻有坐席編號(方便呼叫系統(tǒng)進行熱線轉(zhuǎn)接),所以參與者具體模型Customer等與Account以一一對應(yīng)的關(guān)系設(shè)立。這樣微信公眾號中的OAuth驗證,我們就會創(chuàng)建WechatUser模型,將其與Customer進行一一關(guān)聯(lián)綁定。這樣實現(xiàn)了全站統(tǒng)一的賬戶體系,Account成為核身領(lǐng)域模型。

回收單RecycleOrder

  • 對于用戶來說會進行呼叫回收操作,其包含呼叫人,呼叫時間,回收內(nèi)容等相關(guān)成員。

客服工單SupportorWorkOrder

  • 為了對客服工作進行審計,以及客服通話記錄的管理,我們需要客服工單模型,為什么這部分沒有并入訂單原因也很簡單,一個訂單可能有多次咨詢,會產(chǎn)生多個客服工單;另外一些咨詢投訴,可能并不強關(guān)聯(lián)任何一筆回收單,所以客服工單從產(chǎn)生角度,關(guān)聯(lián)關(guān)系,成員數(shù)據(jù)來看,都應(yīng)該是獨立模型。

回收工單RecyclerWorkOrder

  • 用戶產(chǎn)生回收單后,實際是需要回收人員上門處理的,訂單分配由調(diào)度員產(chǎn)生,所以在回收單基礎(chǔ)上我們設(shè)立了回收工單,其主要屬性包括:回收單承擔人,回收單創(chuàng)建時間,派送時間,考慮到以后可能會賦予回收員更多的業(yè)務(wù)處理能力,例如搬家,商品配送,我們希望工單模型相對獨立,是對回收單,以后可能產(chǎn)生的搬家服務(wù)單,商品配送單的接口模型。

業(yè)務(wù)端回收物品Item

  • 全局唯一可追溯的回收物品模型,包含物品類型,規(guī)格,關(guān)聯(lián)訂單,處理人等信息

倉儲段回收物品Item

  • 考慮到面向用戶的物品分類和面向倉儲末端處理企業(yè)的物品分類不盡相同,我們在倉儲端需要另一種回收物品模型。

倉儲入庫單WarehouseInOrder

倉儲出庫單WarehouseOutOrder

除了上述核心模型外,其它模型例如用戶地址Address,車輛Car,車輛位置CarLocation,回收品類Category,SubCategory,規(guī)格Spec,城市City,全局唯一框Backet,分揀員等模型其實本質(zhì)都是對于上述核心模型的描述和補充。


系統(tǒng)劃分

我們在進行系統(tǒng)劃分時遵循的幾個基本原則:

  • 方便高效開發(fā)。最少的代碼,最少的重復工作,最快的產(chǎn)生結(jié)果。
  • 功能職責單一,高擴展,避免耦合。
  • 系統(tǒng)單元與業(yè)務(wù)單元盡可能保持一致。
  • 由復雜到簡單,由深到淺。不能只按最簡單的來,最簡單就是一個web應(yīng)用 + 一個mysql全部搞定,我們應(yīng)該按照能想到的最細粒度的方式入手,然后根據(jù)實際情況和需求往上層走。
  • 梳理整個系統(tǒng)功能邊界,哪些功能要自己實現(xiàn),哪些功能是要調(diào)用第三方,這些服務(wù)是面向局部的還是面向全局的。
  • 迭代。花必要的時間進行多種方案的頭腦風暴和不斷推演。
  • 梳理技術(shù)難點。難點有兩個角度,一是公認的技術(shù)難點,例如分布式環(huán)境中保證強一致性;一是團隊不熟悉的技術(shù),例如java開發(fā)團隊面臨前端開發(fā)任務(wù)或者去開發(fā)一個windows桌面應(yīng)用。
  • 時刻牢記項目投資規(guī)模,初期性能要求以及上線時間,避免過度設(shè)計和開發(fā)。
  • 保持強的領(lǐng)域意識。就是說當我們劃分出一個系統(tǒng)后,我們要站在這個系統(tǒng)的內(nèi)部,作為系統(tǒng)owner思考該系統(tǒng)的邊界,那些事情作為系統(tǒng)owner愿意做,哪些事情作為系統(tǒng)owner不愿意做。
  • 主導者應(yīng)預先思考一個設(shè)計方案,否則在團隊頭腦風暴時會容易發(fā)生討論發(fā)散,主線不清,結(jié)果不明。
  • 提取領(lǐng)域模型。通過參與人角度非常有利于分析業(yè)務(wù)鏈路和梳理前端入口,但是對于后端系統(tǒng)劃分不夠深入,所以需要提取領(lǐng)域模型,基于領(lǐng)域模型做后端系統(tǒng)劃分更加合適

劃分實踐

我們的劃分過程經(jīng)歷多輪頭腦風暴和迭代,具體過程就不詳細展開了,直接看看最終的方案
互聯(lián)網(wǎng)回收系統(tǒng)
  • 系統(tǒng)模塊
    • 呼叫回收模塊
    • 客服模塊
    • 調(diào)度模塊
    • 前端:客戶app
    • 前端:客戶微信公眾號
    • 前端:客戶官網(wǎng)
    • 前端:回收員app
    • 前端:客服Web頁
    • 前端:調(diào)度Web頁
  • 劃分原因
    • 基于用戶Customer,客服CustomerSupptor,調(diào)度人員Dispatcher的行為進行領(lǐng)域模型抽象,回收單RecycleOrder,客服工單CustomerSupportorOrder,回收工單RecycleWorkOrder相互持有,且有很多共同屬性例如都是基于Account模型。所以將這三個模塊并入一個系統(tǒng)開發(fā),有利于實現(xiàn)代碼復用,減少工作量。
    • 如果將三者劃分成三個獨立系統(tǒng),代價是必須要實現(xiàn)單點登錄,即增加一個獨立的核身系統(tǒng)AccountSystem,另外三個模塊緊密耦合,劃分會帶來大量的跨系統(tǒng)調(diào)用,進而需要引入分布式框架保證一致性和代碼解耦,結(jié)合項目上線時間,投資規(guī)模,和實際使用量來看,不適合劃分過細。
  • 技術(shù)選型
    • 因為沒有足夠的技術(shù)資源和專業(yè)的運維人員,選擇Spring Boot這種輕量級的開發(fā)部署框架
    • 選擇Spring MVC,一方面是有相關(guān)開發(fā)經(jīng)驗,另一方面阿里系基于Spring框架做到這樣一個體量,相關(guān)文檔和解決方案很多,系統(tǒng)擴展?jié)摿容^大。
    • 此外使用了Spring Security做安全架構(gòu)LogBack做日志框架,Spring Test做接口測試。
    • 因為業(yè)務(wù)模型梳理較為細致,且考慮了擴展性,例如客服工單獨立,回收員工單模型獨立,足以支持以后上線的搬家服務(wù),商城服務(wù)。我們有足夠的信心不會大范圍發(fā)生領(lǐng)域模型變化,所以采用Hibernate以及Spring JPA來實現(xiàn)持久化層的代碼。
    • 考慮一期的預期調(diào)用量,MySQL足以應(yīng)對,底層數(shù)據(jù)存儲使用阿里云MySQL雙機版。
    • 考慮靜態(tài)資源訪問可能消耗珍貴接口帶寬,靜態(tài)資源統(tǒng)一采用CDN存儲
    • 考慮業(yè)務(wù)穩(wěn)定性,災(zāi)備,以及線上無感知發(fā)布更新,系統(tǒng)采取3機部署,通過前掛LBS實現(xiàn)負載均衡,LBS可以采取nginx或者阿里云現(xiàn)成服務(wù)。
  • 問題
    • 多模塊耦合導致系統(tǒng)代碼復雜,影響水平擴展,長久來看還是要做更細一步的拆分的
支付系統(tǒng)
  • 系統(tǒng)結(jié)構(gòu)
    • 對外調(diào)用支付寶接口,微信支付接口進行企業(yè)=》用戶的付款,付款查詢等操作
    • 對回收系統(tǒng)提供調(diào)用接口,回收系統(tǒng)不需要識別支付細節(jié),只需要告知支付系統(tǒng)支付對象,支付金額,支付原因,支付渠道即可
  • 劃分原因
    • 支付系統(tǒng)不同于常見的電商支付系統(tǒng)是用戶向企業(yè)付款,有問題可以走退款鏈路。而是由企業(yè)賬戶打款到用戶賬戶,因為回收業(yè)務(wù)是要給用戶付錢?;舅兄Ц稒C構(gòu)都是不可逆操作。而且該接口都是直連企業(yè)第三方支付的企業(yè)賬號,對賬號內(nèi)資金具有全部操作權(quán)限,所以該系統(tǒng)的安全要求和門面系統(tǒng)不可同日而語。單獨劃分系統(tǒng)后,可以通過防火墻,ip白名單等等策略,限制入口調(diào)用和出口調(diào)用,關(guān)閉無關(guān)端口,走單獨的運維策略,在初期項目技術(shù)資源有限的條件下,保證其安全性。
    • 回收系統(tǒng)不應(yīng)當耦合不同支付渠道的實現(xiàn)細節(jié),不應(yīng)當識別不同支付機構(gòu)的接口代碼,因為其本身承擔了三個模塊的代碼,再耦合支付系統(tǒng)復雜性和維護性就不在一個可以接受的水平上了。
  • 技術(shù)選型
    • Apache Tomcat
    • Spring MVC(對業(yè)務(wù)系統(tǒng)提供基于Http的REST調(diào)用接口,并有相應(yīng)的回調(diào)邏輯)
    • MyBatis(主要了是為了擴寬技術(shù)棧,所以沒有用Hibernate)
    • MySQL
  • 問題
    • 基于傳統(tǒng)的同步調(diào)用異步回調(diào)實現(xiàn),代碼不夠簡潔,還耦合回收系統(tǒng)業(yè)務(wù)代碼(訂單查詢保證冪等),應(yīng)該采用消息機制實現(xiàn)更合理的系統(tǒng)調(diào)用。
    • 數(shù)據(jù)庫獨立,在后期數(shù)據(jù)匯總時,例如一個數(shù)據(jù)報表需要從回收系統(tǒng)數(shù)據(jù)庫和支付系統(tǒng)數(shù)據(jù)庫同時出,帶來了一些復雜性。
倉儲系統(tǒng)
  • 系統(tǒng)結(jié)構(gòu)
    • 倉儲操作端:用C#寫的運行在windows上的GUI應(yīng)用,通過DLL對接打印機,通過串口對接電子秤,通過USB對接掃碼槍
    • 倉儲服務(wù)端:提供基于Http RESTFul的接口,提供物品入庫,分揀,稱重,出庫等等請求。
  • 劃分原因
    • 從業(yè)務(wù)邏輯上和領(lǐng)域模型上看,倉儲系統(tǒng)相對很獨立,唯一與主系統(tǒng)耦合的點在,物品入庫時請求主系統(tǒng)獲取該物品類型規(guī)格回收人員等。
    • 該系統(tǒng)涉及到對接其它設(shè)備較多,這些技術(shù)點與回收系統(tǒng),支付系統(tǒng),不相關(guān)。
    • 倉儲系統(tǒng)有特殊的穩(wěn)定性和私有化部署要求,即使回收系統(tǒng)故障,也不應(yīng)該影響倉儲系統(tǒng)運作,例如回收系統(tǒng)故障,但是倉儲系統(tǒng)應(yīng)該能夠正常出入庫。
  • 技術(shù)選型
    • Apache Tomcat
    • Spring MVC,Shiro,Log4j
    • MyBatis
    • MySQL
    • C#
  • 問題
    • 客戶端采用C#導致擴展升級不變,倉庫里投放了多臺壁掛式一體機,成本較大,如果采用手機App作為操作員端,會更加合理(類比快遞員的手持設(shè)備)。我們之所以采用C#一方面是考慮開發(fā)成本,C#有拖拽式界面IDE,另外傳統(tǒng)的磅秤,打印機對windows有良好的調(diào)用支持,如果采用App的話,需要自研中間服務(wù),實現(xiàn)操作端對打印機,電子秤的交互,考慮我們時間資源有限,沒有采用,準備在第二個分揀倉庫建設(shè)時進行重構(gòu)。
    • 因為回收系統(tǒng)Account沒有開放出來,導致倉儲系統(tǒng)無法實現(xiàn)單點登錄,只能自己也存儲了倉儲人員信息,也重復了一些身份驗證代碼,但是后期實踐時發(fā)現(xiàn)倉儲的身份核驗和回收系統(tǒng)不太一樣,管理要求也不一致,所以整體來看,不是特別大的問題。
      數(shù)據(jù)庫獨立,在后期數(shù)據(jù)匯總時,例如一個數(shù)據(jù)報表需要從回收系統(tǒng)數(shù)據(jù)庫和倉儲系統(tǒng)數(shù)據(jù)庫同時出,帶來了一些復雜性。
    • 倉儲系統(tǒng)業(yè)務(wù)模型相對穩(wěn)定,并發(fā)要求不高,應(yīng)該采用Hibernate進行持久層而不應(yīng)該采用MyBatis
400呼叫系統(tǒng)
  • 劃分原因
    • 400呼叫系統(tǒng)主要職責是將用戶打進的電話分配到7個坐席人員的電腦上,坐席人員通過耳麥和網(wǎng)絡(luò)與用戶溝通完成服務(wù)。職責功能非常單一,就是實現(xiàn)電話呼入功能。
  • 技術(shù)選型
    • 目前的坐席呼叫系統(tǒng)本質(zhì)都是把用戶通過手機也好,固話也好,電信會將用戶呼入通過專線投遞給呼叫設(shè)備,呼叫設(shè)備下掛語音IP卡,將語音數(shù)據(jù)轉(zhuǎn)化為可以基于網(wǎng)絡(luò)傳輸?shù)臄?shù)字語音數(shù)據(jù),然后定向發(fā)給與呼叫設(shè)備相連的電腦端,這樣達成坐席通過電腦耳麥和網(wǎng)絡(luò)與用戶進行對話。
    • 另外一種方案是云坐席方案,顧客本地不需要購買呼叫設(shè)備,所有客服人員打開網(wǎng)頁,通過flash建立和云中心的鏈接,云中心部署了呼叫設(shè)備完成與電信的信號對接。但是這種云坐席要價比較高,另外穩(wěn)定性難以保證,與自有系統(tǒng)不好對接,所以我們采用了第一種。
  • 挑戰(zhàn)
    • 呼叫系統(tǒng)接收一個來電,分配好坐席后,我們需要相應(yīng)的坐席人員能夠根據(jù)來電號碼查找是否注冊用戶,查找其關(guān)聯(lián)訂單,關(guān)聯(lián)客服工單等信息。最終解決方案是,呼叫系統(tǒng)定制化開發(fā),坐席接通后post相關(guān)來電信息(來電號碼,坐席編號)到回收系統(tǒng)客服模塊,回收系統(tǒng)后端與客服前端通過WebSocket保持鏈接,一單后端接收到來電就發(fā)送信息給前端頁面,前端頁面通過js進行用戶信息查詢,訂單查詢等操作并刷新頁面。
    • 呼叫系統(tǒng)初期只是通過簡單的路由設(shè)備和坐席人員聯(lián)通,穩(wěn)定性很差,因為局域網(wǎng)不同部門公用,經(jīng)常波動。后來接入另一個地點的外包客服,根本不在內(nèi)網(wǎng),帶來了更大挑戰(zhàn)。這之中,學習了組網(wǎng)知識,購買了企業(yè)級路由器,建立了呼叫設(shè)備與本地坐席和遠程坐席的VPN鏈路,穩(wěn)定性安全性得以保證。這中間經(jīng)歷了不知道多少坑,和華為技術(shù)支持,電信技術(shù)支持,外包坐席網(wǎng)絡(luò)工程師接連對接了N次,付出很多也學到很多。
  • 問題
    • 呼叫系統(tǒng)是一個.NetFramework + SQL Server的本地服務(wù)器模式,定制化開發(fā)比較難,和業(yè)務(wù)系統(tǒng)對接不容易,例如我們想實時獲取一段通話錄音,很難從SQL Server的庫里導出,制作音頻文件,這一步目前往往都是人工實現(xiàn)。另外呼叫系統(tǒng)自帶評分機制,這個數(shù)據(jù)也是需要人工同步。
數(shù)據(jù)報表系統(tǒng)
  • 劃分原因
    • 我們在分析財務(wù)人員和倉儲管理員需求時發(fā)現(xiàn),他們的核心訴求是各種維度,各種組合的數(shù)據(jù)匯總,這些數(shù)據(jù)匯總沒有固定的業(yè)務(wù)模型對應(yīng),另外他們的訴求往往需要我們進行跨數(shù)據(jù)庫的查詢,而跨庫數(shù)據(jù)交換在前面幾個業(yè)務(wù)系統(tǒng)中往往通過接口調(diào)用實現(xiàn)。
    • 基于實際的需求,數(shù)據(jù)報表在代碼邏輯上非常薄,數(shù)據(jù)層實現(xiàn)多數(shù)據(jù)源抓取,上面封裝一些數(shù)據(jù)整合,緩存,分頁等功能,以標準的json或者map設(shè)置就可以直接返回給前端了,前端基于ECharts或者D3或者JQWidget就可以做渲染了,這和其它系統(tǒng)處理鏈路是很不相同的。
    • 另外還有一個原因,我們團隊有位同學是前支付寶平臺數(shù)據(jù)部的數(shù)倉工程師,SQL能力很強,所以大部分的數(shù)據(jù)報表,我們能夠很快得寫出高效的查詢語句。
  • 技術(shù)選型
    • Apache Tomcat
    • Spring MVC,Shiro,Log4j
    • MyBatis
    • 多個MySQL數(shù)據(jù)庫
  • 問題
    • 系統(tǒng)涉及多數(shù)據(jù)源,涉及到跨庫join,如果我們的數(shù)據(jù)庫考慮其穩(wěn)定性放置在不同的MySQL實例中,是無法直接通過SQL實現(xiàn)一些合并操作的。一期我們通過代碼,講兩個庫查詢到的數(shù)據(jù)分別緩存起來,然后按照呈現(xiàn)邏輯進行整合,代價是增加了系統(tǒng)復雜性,消耗了報表系統(tǒng)的性能
    • 二期,我們做了妥協(xié),將多個系統(tǒng)的獨立數(shù)據(jù)庫合并到了一個MySQL實例中,大部分數(shù)據(jù)集合的操作通過SQL實現(xiàn)。結(jié)果是,上層業(yè)務(wù)系統(tǒng)獨立,數(shù)據(jù)庫獨立,但是數(shù)據(jù)服務(wù)器不獨立。從運維管控和擴展性來講,都不是很合理。
    • 三期,未完成,最終梳理的解決方案是,將數(shù)據(jù)報表需求分為兩部分,一部分是實時數(shù)據(jù)展示,一部分是非實時數(shù)據(jù)展示。
      • 實時數(shù)據(jù)展示涉及到跨庫join的場景很少,復雜性低,可以通過接口調(diào)用緩存本地,然后用代碼處理數(shù)據(jù)合并,和一期保持一致;
      • 非實時數(shù)據(jù),可以通過數(shù)據(jù)倉庫,每天定時將分布在多個數(shù)據(jù)庫的數(shù)據(jù)進行抓取清洗,然后存放起來,需要查詢時可以直接訪問數(shù)倉,或者由數(shù)倉回寫到指定數(shù)據(jù)庫,訪問相應(yīng)的數(shù)據(jù)庫。這樣的好處是,數(shù)倉借用阿里云彩云間也即ODPS,是不用耦合業(yè)務(wù)代碼的,其所有操作通過類SQL操作即可實現(xiàn),從而將數(shù)據(jù)join,清洗的工作與代碼解耦。大家稍微看下數(shù)倉的理念或者了解下阿里采云間就會明白。
B2B電子訂單系統(tǒng)
  • 這是一個后期補充需求,業(yè)務(wù)模型相對獨立,主要是為了方便終端處理廠可以電子化的和倉儲運營人員進行貨物買賣。舉個例子,末終端處理廠,需要2000個觸屏手機,或者1噸廢舊襯衫,都可以在該系統(tǒng)中下采購單;同時,他也能通過該系統(tǒng),獲得倉儲中物品規(guī)格數(shù)量的大致信息,根據(jù)現(xiàn)有數(shù)量和物品下采購訂單。這樣就將廢舊品出庫采銷整體打通并實現(xiàn)電子化
  • 技術(shù)選型
    • 前段采用基于MVVM的angularjs,是缺少專業(yè)前端人員團隊進行前端開發(fā)的利器
    • Spring Boot
    • Spring MVC, Spring Security, LogBack
    • Hibernate
    • MySQL

至此,回收平臺系統(tǒng)已經(jīng)設(shè)計完畢,技術(shù)選型也初步確定。項目成功上線,除了因為某些小bug造成的單點故障,在設(shè)計規(guī)模下,沒有發(fā)生因系統(tǒng)設(shè)計不合理引發(fā)的問題,系統(tǒng)擴展性也比較強,對于新增業(yè)務(wù)基本能夠很好得支持。


其它小結(jié)

代碼倉庫:我們的全部代碼初期存放于gitoschina上,后來一段時間經(jīng)常服務(wù)異常,無法commit,所以轉(zhuǎn)移到了aliyuncode,非常穩(wěn)定,速度很快。

持續(xù)集成:我們基于jenkins做了全部系統(tǒng)的持續(xù)集成,支線代碼提交就會部署開發(fā)環(huán)境,主干代碼更新就會部署測試環(huán)境,生產(chǎn)環(huán)境部署也是一鍵達成。其中很多小點還是值得分享的,具體我會在其它博文里介紹。

代碼工程:我們打造了非常規(guī)范,并經(jīng)過實戰(zhàn)優(yōu)化的Spring Boot多Module工程目錄,晚些也會在專題博文里分享介紹。

依賴管理:一般項目用的Maven,一般項目用的Gradle,對比來說,更喜歡Gradle,配置靈活功能強大。

埋點實現(xiàn):

  • 業(yè)務(wù)埋點通過打印日志,然后使用阿里云日志分析服務(wù)實現(xiàn)
  • 訪問埋點通過友盟,功能強大穩(wěn)定,好像已經(jīng)被阿里收購了
  • App埋點通過騰訊bugly,非常好用,追蹤安裝量,打開量,異常很方便,還有在線模擬器可以用,強烈安利!

靜態(tài)資源通過阿里云CDN服務(wù)支持訪問,資費很低,節(jié)約了系統(tǒng)服務(wù)器的寶貴帶寬

車輛定位使用了G7貨運人,還是比較穩(wěn)定的,中間出過一次問題,及時找到對方技術(shù)接口人并解決,此外定制開發(fā)也能找到接口人,效率也挺高。

WebSocket使用了leancloud,但是穩(wěn)定性有段時間不好,后來基于開源自建了一個Socket服務(wù)器。

短信服務(wù)初期使用leancloud,送達率略低,后期切入阿里大于,自費和送達率都符合業(yè)務(wù)要求。

微信開發(fā),因為有微信公眾號,所以對接了微信的各種接口,也填了微信瀏覽器的各種坑,具體細節(jié)會在其它文章分享

支付開發(fā),對接微信支付,支付寶支付,相關(guān)分享會在其它專題文章里講述。

前端框架,使用了angularjs,不得不說是后端MVC人員轉(zhuǎn)型前端開發(fā)利器啊。

前端框架,報表使用了JQWidgets,非常好用

MVC異常處理,我們把所有前端請求分為兩類,page類和api類,page類主要是返回html,api類返回json數(shù)據(jù),所有的返回即使在異常情況下(大部分異常)也是標準的{"result": "","data": "","success": "","message": ""},前端通過angularjs的攔截器功能,實現(xiàn)了全站的異常封裝和交互,節(jié)約了很多代碼

因為我們的遵循了從繁入簡的設(shè)計思想,所以雖然因為實際情況妥協(xié)將回收模塊,客服模塊,調(diào)度模塊進行了耦合,但大家都清楚系統(tǒng)未來演進,業(yè)務(wù)繼續(xù)生長是一定會進行拆分的,所以我們在代碼迭代中會刻意保持不同模塊的獨立性,領(lǐng)域模型不要過度耦合,跨模塊調(diào)用統(tǒng)一采用基于bean的服務(wù)實現(xiàn),關(guān)鍵編號保留分庫分表位。這樣后期如果必須進行拆分時,也會很高效。

...還有很多,一些細節(jié)想起來再加吧,這個項目已經(jīng)交付好久了。


至此基本羅列完了我們對該項目的需求整理,分析以及系統(tǒng)設(shè)計的大致過程。
大家如果對其中的部分細節(jié)感興趣,或者有異議,非常歡迎留言談?wù)撆u指正,我會及時勘正補缺。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容