? ? 雖然我沒有實踐過集成平臺,但是技術(shù)的原理都是一樣的,什么是SOA、ESB、消息隊列等等知識都是從網(wǎng)上獲取到。我們都知道,學(xué)習(xí)一門技術(shù),只要把原理搞懂了,就“一通百通”。我之前寫過《如何成為寫SQL高手》文章,里面提到的幫小伙伴分析的sql問題,我也不知道他們用的是什么his系統(tǒng),都是從原理岀發(fā)來解決。
一、信息系統(tǒng)問題的大小
? ? ? 我們經(jīng)常聽到有人說,有很多問題,大問題、小問題、難問題、簡單問題。首先從計算機專業(yè)人士,如何定義一個信息系統(tǒng)問題大小。從很宏觀的角度,我個人建議用“數(shù)據(jù)量”來衡量一個問題的大小。我舉個例子,對數(shù)據(jù)進(jìn)行排序這個問題,當(dāng)數(shù)據(jù)量很小的時候,基本調(diào)用一下編程語言提供的sort函數(shù)就可以了;當(dāng)數(shù)據(jù)量有幾十個GB,甚至幾個TB,你還能調(diào)用一下sort處理嗎?顯然不行,數(shù)據(jù)量越大,處理的難度越大。
? ? ? 數(shù)據(jù)量大小如果沒有超過“內(nèi)存”稱為“內(nèi)存級”問題;數(shù)據(jù)大小超過“內(nèi)存”,但是沒有超過硬盤稱為“硬盤級”問題;數(shù)據(jù)量大小超過“硬盤”稱為“大數(shù)據(jù)級”數(shù)據(jù),也就就是分布式要解決的問題??此仆粋€問題,從“內(nèi)存級”到“硬盤級”再到“大數(shù)據(jù)級”,難度只會越來越越大。
? ? 舉個例子,實時統(tǒng)計醫(yī)院消耗前10的藥品,大部分醫(yī)院解決方案就是一條sql語句就能搞定,沒必要搞的太復(fù)雜,否則“殺雞用牛刀”,得不償失。某大型電商,實時統(tǒng)計前10銷售的商品,通常是“大數(shù)據(jù)級”的問題,就沒這么簡單了。
? ? 我再舉個曾經(jīng)開過我“腦洞”的例子,英文句子倒置,比如把“Welcome to HIT meeting”變成“meeting HIT to Welcome”,我用java編寫的示例代碼如下:


? ? 特別說明 , 以上代碼沒有在實際環(huán)境中運行過,我最重要的是把套路說明白。第一種方法,98%的人都可以想到,學(xué)了幾十年的英文,英文句子不就是由單個單詞組成,先把拆分句子得到單詞,再組裝起來。第二種方法,打破慣性認(rèn)識,在計算機里面“Welcome to HIT meeting”就不要當(dāng)成英文句子來看待,而是一個String,先將這個String反轉(zhuǎn)過來變成“gniteem TIH ot emocleW”,再進(jìn)行相應(yīng)處理。
? ? 或許你會問,2種代碼用哪種都無所謂,如果你在“內(nèi)存級”層面,當(dāng)然無所謂;如果你在“大數(shù)據(jù)級”層面,第二種明顯優(yōu)于第一種,少了一個數(shù)組開銷,意外著每次在內(nèi)存中可以多加載一些“數(shù)據(jù)”,提高效率。據(jù)說這是某大廠的面試題,當(dāng)時知道這種處理方式,真是開“腦洞”,很多時候我們處理問題的確是受這種慣性思維的影響。
? ? 集成平臺主要用作數(shù)據(jù)實時交換,大部分醫(yī)院除去影像圖片,當(dāng)日HIS數(shù)據(jù)量不會超過幾個GB,大部分醫(yī)院集成平臺問題屬于“內(nèi)存級”的。
二、同步與異步
? ? ? 不理解同步與異步,就很難理解在集成平臺下開發(fā)HIT“難”在哪里。據(jù)小伙伴反應(yīng),大量廠商接入集平臺使用同步調(diào)用,這可能造成集成平臺崩潰的“元兇”,我個人沒有實踐過,所以沒有發(fā)言權(quán)。同步與異步是一個非常重要的概念,值得好好普及一下。從專業(yè)視角來看待這個問題,一般稱之為,同步阻塞,異步非阻塞。它們之間有什么區(qū)別,我用掛號偽代碼,舉例說明,如下圖所示。

? 以上面代碼為例 ,同步,“寫數(shù)據(jù)庫”就不能同時“發(fā)送消息”,這樣形成阻塞。異步,“寫數(shù)據(jù)庫”與“發(fā)送消息”同時執(zhí)行,就是非阻塞。同步調(diào)用,簡單粗暴,我不做過多討論。重點來討論異步,異步的好處高并發(fā),缺點也十分明顯,對系統(tǒng)失去控制,而且異步要比同步實現(xiàn)起來要復(fù)雜許多,優(yōu)先使用同步調(diào)用是最保險的方案。
? ? 在異步模式,為什么會失去控制?假設(shè)“寫數(shù)據(jù)庫”失敗了,“發(fā)送消息”成功了,或者是數(shù)據(jù)庫”成功了,“發(fā)送消息”失敗了,這就是失控;又比如“寫數(shù)據(jù)庫”與“發(fā)送消息”同時執(zhí)行,究竟是什么時候執(zhí)行完成的,這也是失控。第一個問題,業(yè)務(wù)邏輯中盡可能規(guī)避了“寫失敗”的風(fēng)險,萬一寫失敗了,要有日志記錄,并通知管理員,或者是業(yè)務(wù)重試。第二個問題,一般會注冊一個回調(diào)函數(shù)來反饋給主程序。
? ? 集成平臺,最核心的功能服務(wù)通過“消息隊列”來訂閱/發(fā)布(Subscribe/Publish),對應(yīng)軟件設(shè)計模式是觀察者模式,典型異步調(diào)用,在下面中詳細(xì)分析如何解決“失控性”問題。
三、基于“集成平臺"開發(fā)基本問題模型
? ? ? 假設(shè)某醫(yī)院,存在以下的最基本的業(yè)務(wù)模型,患者掛號成功以后,將"掛號消息"推送至”微信“和”醫(yī)生就診“。

? ? ? 掛號業(yè)務(wù)成功以后,向消息隊列發(fā)一個消息,這個消息我們采用一個專用的術(shù)語叫”主題(Topic)“。假設(shè)”醫(yī)生就診服務(wù)“,成功獲取到”掛號“并處理成功,或者明確失敗,返回給調(diào)用方,這2個問題都好處理。
? ? 但是有一個問題比較難處理,”醫(yī)生就診服務(wù)“超時,不知道是成功,還是失敗?難點就在這里,一旦發(fā)生超時,一般會選擇重發(fā)”消息“,解決這種問題,有一個專業(yè)的術(shù)語叫”冪等“。 什么是冪等(Idempotency)?簡單來說,一個操作如果多次任意執(zhí)行所產(chǎn)生的影響,均與一次執(zhí)行的影響相同,我們就稱其為冪等。舉例說明,查詢賬戶余額,查詢一次和多次區(qū)別都一樣,這就是一個”冪等“操作。假設(shè)往賬戶上面增加100元,操作一次和多次,區(qū)別就很大,這個就不是冪等操作了,怎么實現(xiàn)冪等,可以從業(yè)務(wù)邏輯代碼入手,先查詢賬戶余額,再判斷要不要加100元。如果發(fā)生超時了,先判斷前后兩次賬戶余額是否一致,如果不一致,說明之前操作沒成功,一致說明之前的操作是成功的。
? ? ? 怎樣保證冪等,一般來說有3種方法,第一種方法,可以數(shù)據(jù)庫表增加鍵約束;第二種方法,業(yè)務(wù)代碼實現(xiàn)冪等,有時非常難;第三種方法,實現(xiàn)一個通用冪等框架,賦予每個業(yè)務(wù)操作一個全局唯一的”冪等號“,根據(jù)冪等號判斷是否執(zhí)行成功,非常難。
? ? 如果發(fā)生業(yè)務(wù)超時,不是每個服務(wù)自動做”冪等“處理,有時候會直接拋給用戶決定是否重試。
? ? 最后小結(jié),傳統(tǒng)這種C/S架構(gòu),這種業(yè)務(wù)并發(fā)通常由”數(shù)據(jù)庫“來保證的,開發(fā)相對比較容易。而基于”集成平臺“環(huán)境的HIT軟件,經(jīng)過我前面的描述,其實是有難度的,難點如何實現(xiàn)“冪等”。但是”集成平臺“問題也沒有大到阿里的“雙11”、京東“618”可能同時在線用戶超過1個億,基本屬于“內(nèi)存級”的。如果面對有難度的開發(fā),his還是保持“粗、糙、猛、快”習(xí)慣,把開發(fā)生產(chǎn)當(dāng)流水線,最后結(jié)果是用戶不滿意,工程師罵街,領(lǐng)導(dǎo)發(fā)飚,最后只能選擇”分手“。HIT市場會越來越理性,不像過去那樣,把搞定領(lǐng)導(dǎo)做為突破口,越來越不靠譜。