1. 程式人生 > >簡單聊聊SOA和微服務

簡單聊聊SOA和微服務

利用 java res content 視野 分布式數據庫 而不是 frame 分庫分表

轉自:https://juejin.im/post/592f87feb123db0064e5ef7c (2017-06)

簡單聊聊SOA和微服務

技術分享圖片架構設計中的樸素主義

前兩天和一個朋友聊天,他向我咨詢如何從零開始構建一個健壯、強大的軟件系統,聊著聊著他忽然問我,「聽大家都在說微服務(下文中有的地方會使用MSA),還有人會提到SOA,那麽他們的區別到底在哪裏?」。我想了想,一時也列不出來一個詳細的列表,只能跟他講說其實他們在概念上是相似的。

關於軟件系統的架構設計,是一個太多人喜歡討論的問題,尤其是對軟件開發不了解的人士來說,總是被各種各樣的概念繞來繞去。從更高的層次,更大的視野研究架構設計的一些專家(如Martin Fowler、Chris Richardson)能夠很清晰的列出這些眾多概念的區別,而身在開發一線的我們更多的是對這些概念有一些感性的、樸素的認識。將之內化到自己的工作中去,才能更好的發揮架構的優勢。

本文將簡單談談SOA和MSA的概念,並簡單列舉一下如果使用Java來構建一個微服務系統時所會遇到的一些概念。本文只是「Yet Another」敘述微服務的文章,而且觀點並沒有很嚴謹,希望能讓讀者對微服務和SOA留下一個感性的認識,如果有什麽不對的地方,還請輕拍。

微服務和SOA的區別

所以,到底SOA和微服務有什麽區別?

短答案:微服務是SOA發展出來的產物,它是一種比較現代化的細粒度的SOA實現方式。

微服務就是這樣的一個「概念」,說白了,它不過就是近些年火起來的有一個名詞而已,一時間仿佛整個行業都在討論它,仿佛終於找到了銀彈。這個時候SOA看待微服務大概就如同當年的Friendster和Myspace看待Facebook一樣——大家都忘了社交網絡這個東西並不是Facebook發明的。你再談如何使用SOA去構建一個系統,就像是在談一個過氣的明星,人們會認為你已經落伍了。但真的是這樣的嗎?

MSA is a SOA

較早實踐微服務的公司Netflix就曾經稱他們構建的架構是「細粒度的SOA」

討論「微服務和SOA的差別」的意義遠不如討論「微服務和單體系統的差別」更大,因為他們的區別實在有點微妙。此外,互聯網近些年的發展,越來越朝去中心化的方向前進了,就像今天的IT工程師不需要像律師、教師那樣,需要得到某些機構的認可才能更好的開展工作,這一方面意味著門檻的降低,另一方面也意味著更多的概念沒有一個權威的聲音來對它進行定義,使得每個人可以根據自己的需求做出不同的調整。

微服務和SOA都是這樣背景下的產物,並沒有一個權威的定義,來說明它們各自包含了什麽東西,使用什麽的方法進行系統的構建。但是,還是可以從最大的範圍來對比它們的不同,當我們今天說出這兩個概念時,其區別往往沒有那麽大,但SOA是有一定的歷史了,在歷史上的SOA往往意味著更多的東西,而這些是現在很多人在做架構設計時不會采用的。

MSA vs SOA

1. 最多被人談起的,應該算是ESB了

技術分享圖片萬能的ESB(圖片來自Wikipedia)

ESB(enterprise service bus)曾經著實跟隨著SOA火了一陣子,第一次知道它是一個朋友在一家物流公司工作,說他們用了一個很高級的玩意兒,叫企業服務總線,接著給我灌輸了一堆ESB的理念。當時感覺這玩意兒太牛了,設計理念也很厲害。

從名稱就能知道,它的概念借鑒了計算機組成原理中的通信模型——總線,所有需要和外部系統通信的系統,統統接入ESB,豈不是完美地兼容了現有的互相隔離的異構系統,可以利用現有的系統構建一個全新的松耦合的異構的分布式系統。

但,實際使用中,它還是會有很多的缺點,首先就是ESB的本身就很復雜,大大增加了系統的復雜性和可維護性。其次就是由於ESB想要做到所有服務都通過一個通路通信,直接降低了通信速度。

而在現代的微服務中,往往是一個「富終端、瘦通信」(Smart endpoints and dumb pipes),使用輕量級的通信機制,而每個終端(服務)有自己的處理邏輯,它知道它要找的服務在哪裏,不需要在通信的鏈路上做什麽事情。

然而,ESB是一個歷史產物,用今天的眼光看待它,並且將之當做SOA的一個標簽是不合理不公平的。

2. 服務化的概念和服務的尺寸

如前所述,SOA的出現其實是為了解決歷史問題:企業在信息化的過程中會有各種各樣互相隔離的系統,需要有一種機制將他們整合起來,所以才會有上邊所述的ESB的出現。同樣的,也造成了SOA初期的服務是很大的概念,通常指定的一個可以獨立運作的系統(這樣看,好像服務間天然的松耦合)。這種做法相當於是「把子系統服務化」。

而微服務沒有歷史包袱,輕裝上陣,服務的尺寸通常不會太大,關於服務的尺寸,在實際情況中往往是一個服務應該能夠代表「實際業務場景中的一塊不可分割或不易分割的業務實體」。將服務的尺寸控制在一個較小的體量可以帶來很多的好處:

  1. 更易於實現低耦合、高內聚
  2. 更易於維護
  3. 更易於擴展
  4. 更易於關註實際業務場景
3. 通信協議(好吧,我實在編不下去了)

如今越來越多的工程開始使用RESTful來作為API的設計的基礎,但僅僅幾年前還有大把的API使用SOAP、WSDL等基於XML的重量級協議的Web Service。

這點和上文說到的2點其實大同小異,仔細想想,它們都是由於歷史原因造成的,同樣的,通信協議經過這些年的發展,現在主流的基本上了兩種:

  1. 文本協議
    使用最廣泛的多是基於HTTP的RESTful規範
  2. 輕量級二進制協議
    Thrift、Protobuf,或者任何自定義的輕量級協議

要解決的問題

大家都在討論微服務,造成了當有人要構建一個系統,往往會第一時間想到使用它,較少有人會去想為什麽要用微服務,是不是有更好的選擇。

沒有銀彈

軟件工程是一個處處有坑的事情,但MSA不是銀彈,並不是所有的軟件系統都適合。它有自己適應的場景和不足之處,下面根據自己的理解列出一些系統的需求,如果你的系統有這方面的需求,那麽可以考慮使用微服務來構建你的系統。

復雜性

顧名思義,微服務首先強調的是服務粒度比較小,這就帶來了一個直接好處:實現簡單。

如果你判斷你的系統需要有很多截然不同的功能模塊,復雜的業務邏輯,業務目標多種多樣,那麽你可以開始考慮使用MSA將你的系統分解成概念上獨立的服務,這樣一來開發工作的難度可以直接的降低了。當然,與此同時你要面對的是另外一種復雜性挑戰——從概念上分解和管理這些服務本身就是一件十分復雜的工作。好在現在開源社區有很多較完善的服務治理的框架和解決方案,正可以用來解決這方面的復雜性問題。

相反,假如你要做一個論壇系統,或者一個簡單的電商網站,並沒有進行大面積推廣的計劃,預計用戶規模在可預見的範圍內不會超過10萬。那麽你需要的不是微服務,而是可以快速開發並上線的架構,這種情況單體應用最合適,也有很多的開源解決方案可以用來開發MVP。

可維護性

微服務的細粒度服務和分布式部署的特點,帶來的一個好處是:可獨立維護。

如果你的系統需要持續的改進,以配合業務的不斷發展,那麽可以考慮使用MSA來做系統的架構。例如,你們正在做一個電商網站,經常要做各種各樣的活動,優惠條件、優惠力度、甚至優惠的計算方式都經常在變,這所有的變化不可能在系統設計的時候完全考慮到,當需要開發介入時,MSA的優點就體現出來了。

服務的分離所遵循的很多原則(如SRP、開閉原則)正是為這種改變所提出的,根據這些原則,你的系統裏可能有一個服務叫「訂單服務」,所有的改動都只需要在這個服務內進行,或者更進一步,你有一個專門處理活動的服務,只需要很少的開發和測試的工作量就可以實現。

C10K、C100K。。。

高並發這個概念快變得爛大街了,不同的高並發場景需要的解決方案千差萬別,同時它也是一個系統工程,而不是通過某一個方面就能解決的。如對於一個做內容的網站,高並發帶來的直接挑戰是大量數據(圖片、文本)的獲取,而對於寫的需求相對而言並不會很高,所以CDN、緩存、網頁靜態化等都是可以采用的軟硬件解決方案;而對於電商類的交易系統,更重要的是保證系統的快速響應、持續可用、最終一致、和水平擴展,所以NIO、分庫分表、緩存、API升降級、負載均衡都是可以采用的方案。

當然,本文的重點是MSA,所以這裏只從架構的角度講一下MSA對於解決高並發問題的優勢。由於MSA通常是分布式部署,通過服務註冊中心實現服務的發現,服務具體部署的機器對於服務的調用方來說是透明的,然後通過客戶端或者服務端的軟負載均衡,可以在某個服務的壓力大的時候直接添加機器實現水平擴展,對於性能的提示在某個範圍內可以認為是線性的。從架構的角度,微服務是解決某一類高並發的較好的解決方案。

同時,高層的架構設計只能從大局上解決這個問題,比如你設計了一個很完善的分布式系統,但好多的服務經常出現內存泄漏,動不動機器就當掉,那多好的架構都於事無補。

框架選擇的玄學

雖然Java的框架還沒有多到JS那麽離譜,但相同或相似的功能通常都會有兩個或兩個以上的選擇,有的需要多選其一,有的可能要組合使用。如何在這些名目繁多的框架中選擇出來適合自己的框架十分困難,每個人心中都有自己的一套的價值觀,快變成了玄學了。

技術分享圖片在github搜索「framework」的結果

有一派的存在主義哲學認為,人是自由的,這體現在人有選擇的自由,一個人做的每一個選擇都成為他未來的自己的一個組成部分。放在架構設計上也適用,你在做各種各樣的選擇時,也一步步地成就了你要構建的那個系統的樣子。

Java中的微服務

雖然MSA其本身不排斥多語言的異構系統,實際場景中也會有多語言開發的例子,但多數情況下,很多人還是習慣於系統中大多數的服務都是用相同的語言進行開發。在Java的生態中,已經有很多十分成熟的,可以拿來實現MSA的中間件,比較出名的有:Spring全家桶(基於Netflix)、Dubbo(國內十分流行)、Thrift(需要自己實現一些基礎的東西)。
通常,MSA的實現通常要滿足下面幾個條件:

  1. 服務足夠的小,需要根據自己的實際需求決定服務的大小。
  2. 服務可以獨立開發、部署、測試。
  3. 使用輕量級通信方式。
  4. 數據分離

實際場景中的選擇

在實際的MSA的實踐中,會遇到各種各樣的選擇,To be or not to be,被這個問句困擾著的不止哈姆雷特,還有很多開發者。實際場景中會遇到的選擇包括但不限於以下幾點,可以拿來作為一個checklist。
這並不是一個完整的列表。

  • 具體細節的實現方式
    從代碼級的角度看,主要是具體細節的實現方案,代碼的好與壞很難用一個定量的標準去衡量,但GOF的設計模式是一個很好的開始,「重構」那本書中也講到了很多「代碼中的壞味道」。多數情況下,這裏講到的壞代碼並不是指的性能,而是指其可讀性與可擴展性。

  • 基礎設施
    任何軟件系統都是要部署到具體的基礎設施上去的,關於基礎設施的部署也有很多的選擇,如:PC vs Docker、Apache vs Nginx、Tomcat vs Jetty。

  • 微服務框架

    1. Spring全家桶
      用起來很舒服,只有你想不到,沒有它做不到。
    2. Dubbox
      很多國內的企業還在用,可以支持RESTful風格的API,但更多的還是會使用Dubbox的默認的基於RPC的API,調用遠程API像調用本地API一樣。這樣做無疑帶來了很多優勢,但同時其基於接口的方式增加了服務間的耦合,怎麽說呢,各有利弊。
    3. Thrift
      如果你比較高冷,完全可以基於Thrift自己搞一套抽象的自定義框架。
  • 同步vs異步
    在跨服務的業務邏輯的實現上,使用基於消息的異步調用,還是使用保證結果的同步方案。

  • 數據服務
    內存數據庫 vs 持久化數據庫(Redis vs MySQL)
    關系型數據庫 vs 非關系型數據庫(MySQL vs Mongo)
    傳統數據庫 vs 分布式數據庫(MySQL vs F1)
    非關系型數據庫又有如KV數據庫,文檔數據庫,圖數據庫等。
    由於MSA提倡服務間的數據隔離,往往不同的服務使用不同的數據源,這就會直接導致數據聚合查詢比較困難的問題。進行數據聚合又有幾種不同的方案(如CQRS)。

  • 日誌分析
    日誌分析也是有很多的成熟解決方案(如ELK)。

簡單聊聊SOA和微服務