SOA架構,微服務,技術實踐彙總
service-oriented architecture,SOA SOA架構,是一種粗粒度、開放式、鬆耦合的服務結構,要求軟體產品在開發過程中,按照相關的標準或協議,進行分層開發。 通過這種分層設計或架構體系可以使軟體產品變得更加彈性和靈活,且儘可能的與第三方軟體產品互補相容,以達到快速擴充套件,滿足或響應市場或客戶需求的多樣化、多變性。
SOA是面向服務的架構,每個廠商都有自己的定義和解釋。有人說是一種架構,有人說是一種方法論。
SOA體系架構帶來的主要觀點是業務驅動IT,即業務驅動和業務更加緊密地聯絡在一起。以粗粒度的業務服務作為基礎來對公司業務進行建模, 這樣就可以產生簡潔的業務和系統檢視;以業務服務為基礎來實現的IT系統更靈活、更易於重用、也更快地應對企業業務需求的變化;以業務服務為基礎, 通過顯式地方式來定義、描述、實現和管理業務層次的粗粒度服務(包括業務流程),提供了業務服務模型和相關IT業務之間提供了更好的"可追溯性"
SOA的目標在於讓IT變得更有彈性,以更快地響應業務單位的需求,實現實時企業。 ESB全稱為Enterprise Service Bus,即企業服務匯流排。 它是傳統中介軟體技術與XML、Web服務等技術結合的產物。ESB提供了網路中最基本的連線中樞,是構築企業神經系統的必要元素。
微服務(Microservice)架構
作者:何明璐 連結:https://www.zhihu.com/question/37808426/answer/93335393
微服務是指開發一個單個 小型的但有業務功能的服務,每個服務都有自己的處理和輕量通訊機制,可以部署在單個或多個伺服器上。
微服務也指一種種鬆耦合的、有一定的有界上下文的面向服務架構。也就是說,如果每個服務都要同時修改,那麼它們就不是微服務,
因為它們緊耦合在一起;如果你需要掌握一個服務太多的上下文場景使用條件,那麼它就是一個有上下文邊界的服務,這個定義來自DDD領域驅動設計。
3.微服務優點是什麼?
每個微服務都很小,這樣能聚焦一個指定的業務功能或業務需求。
微服務能夠被小團隊單獨開發,這個小團隊是2到5人的開發人員組成。
微服務是鬆耦合的,是有功能意義的服務,無論是在開發階段或部署階段都是獨立的。
微服務能使用不同的語言開發。
微服務允許容易且靈活的方式整合自動部署,通過持續整合工具,如Jenkins, Hudson, bamboo 。
一個團隊的新成員能夠更快投入生產。
微服務易於被一個開發人員理解,修改和維護,這樣小團隊能夠更關注自己的工作成果。無需通過合作才能體現價值。
微服務允許你利用融合最新技術。
微服務只是業務邏輯的程式碼,不會和HTML,CSS 或其他介面元件混合。
微服務能夠即時被要求擴充套件。
微服務能部署中低端配置的伺服器上。
易於和第三方整合。
每個微服務都有自己的儲存能力,可以有自己的資料庫。也可以有統一資料庫。
4. 微服務架構的缺點是什麼?
微服務架構可能帶來過多的操作。
需要DevOps技巧 (http://en.wikipedia.org/wiki/DevOps).
可能雙倍的努力。
分散式系統可能複雜難以管理。
因為分佈部署跟蹤問題難。
當服務數量增加,管理複雜性增加。
5. 微服務適合哪種情況?
當你需要支援桌面 web 移動 智慧電視 可穿戴時都是可以的,甚至將來你可能不知道但需要支援的某種環境。
API閘道器封裝內部系統的架構,並且提供 API給各個客戶端。它還可能還具備授權、監控、負載均衡、快取、請求分片和管理、靜態響應處理等功能。
API閘道器的優點和缺點
對於API閘道器的優點,其實是類似傳統ESB企業服務匯流排的優點,即實現服務透明,同時對於服務執行過程中的日誌,
安全,路由,快取等問題進行統一配置和處理,而不需要每個微服務API實現時都去考慮。如開源的Dubbo服務匯流排即可以看作是一個API閘道器的實現。
API閘道器和ESB的一些重要區別點在於API閘道器更加輕量和高效能,它不需要去考慮太多遺留系統和諸多協議的適配,其次也不需要考慮服務整合過程中的大量資料轉換和對映。
同時為了提升服務閘道器的效能,一般API閘道器在實現過程中不會去記錄詳細的資料傳輸日誌,或者類似Dubbo架構資料傳輸根本就不會通過API閘道器。
使用 API 閘道器的最大優點是,它封裝了應用程式的內部結構。客戶端只需要同閘道器互動,而不必呼叫特定的服務。API閘道器也有一些不足。
它增加了一個我們必須開發、部署和維護的高可用元件。還有一個風險是,API 閘道器變成了開發瓶頸。
簡單來說,在我們期望的去中心化和全分散式架構中,閘道器又成了一箇中心點或瓶頸點,正是由於這個原因我們在閘道器設計的時候必須考慮即使APIGateway宕機也不要影響到服務的呼叫和執行。
作者:何明璐
連結:https://www.zhihu.com/question/37808426/answer/93335393
來源:知乎
著作權歸作者所有,轉載請聯絡作者獲得授權。
第四篇 服務發現的可行方案以及實踐案例
首先還是先說場景,看似簡單的服務註冊和服務目錄庫管理為何會變複雜,其主要的原因還是在結合了雲端PaaS和Docker容器部署後,對於微服務模組部署完成後提供出來的IP地址是動態在變化的,包括模組在進行動態叢集擴充套件的時候也需要動態接入新的服務提供IP地址。正是由於這個原因引入了服務發現和管理的困難度。
在文章中提到了兩種服務發現模式,即客戶端發現模式和服務端發現模式,分開描述如下:
服務客戶端發現模式
使用客戶端發現模式時,客戶端決定相應服務例項的網路位置,並且對請求實現負載均衡。客戶端查詢服務登錄檔,後者是一個可用服務例項的資料庫;然後使用負載均衡演算法從中選擇一個例項,併發出請求。客戶端從服務註冊服務中查詢,其中是所有可用服務例項的庫。客戶端使用負載均衡演算法從多個服務例項中選擇出一個,然後發出請求。
注:這是類似Dubbo實現機制一樣的兩階段模式,即任何一個服務的消費都需要分兩個步驟進行,第一步首先是訪問服務註冊庫(更多是APIGateWay提供的一個能力)返回一個已經動態均衡後的服務可用地址,第二步即客戶端和該地址直接建立連線進行服務消費和訪問。
在這種模式的實現中有兩個重點,其一是動態負載均衡演算法,其二是服務閘道器需要能夠對原始服務提供點進行實時的心跳檢測以確定服務提供的可用性。
Netflix OSS 是客戶端發現模式的絕佳範例。Netflix Eureka是一個服務登錄檔,為服務例項註冊管理和查詢可用例項提供了 REST API 介面。Netflix Ribbon 是 IPC 客戶端,與Eureka 一起實現對請求的負載均衡。
缺點:底層的IP雖然動態提供出去了,但是最終仍然暴露給了服務消費方,再需要進一步做安全和防火牆隔離的場景下顯然是不能滿足要求的。
服務端發現模式
客戶端通過負載均衡器向某個服務提出請求,負載均衡器查詢服務登錄檔,並將請求轉發到可用的服務例項。如同客戶端發現,服務例項在服務登錄檔中註冊或登出。在原文中有圖示,基本看圖就清楚了,即在服務註冊庫前新增加了一個LoadBalancer節點。注:這兩個節點感覺是可以合併到API GateWay的能力中去的。
服務端發現模式兼具優缺點。它最大的優點是客戶端無需關注發現的細節,只需要簡單地向負載均衡器傳送請求,這減少了程式語言框架需要完成的發現邏輯。並且如上文所述,某些部署環境免費提供這一功能。這種模式也有缺點。除非負載均衡器由部署環境提供,否則會成為一個需要配置和管理的高可用系統元件。
服務登錄檔
服務登錄檔需要高可用而且隨時更新。客戶端能夠快取從服務登錄檔中獲取的網路地址,然而,這些資訊最終會過時,客戶端也就無法發現服務例項。因此,服務登錄檔會包含若干服務端,使用複製協議保持一致性。
首先可以看到服務登錄檔本身不能是單點,否則存在單點故障,當服務登錄檔有多臺伺服器的時候同時需要考慮服務註冊庫資訊在多臺機器上的實時同步和一致。我們操作和配置服務註冊資訊的時候往往只會在一個統一的服務管控端完成。
其次如果服務註冊伺服器宕機是否一定影響到服務本身的消費和呼叫,如果考慮更高的整體架構可用性,還可以設計對於服務註冊庫資訊在客戶端本地進行快取,當服務登錄檔無法訪問的時候可以臨時讀取本地快取的服務註冊庫資訊併發起服務訪問請求。
對於服務登錄檔,文章提供了三種選擇,感覺最常用的實現仍然是基於ZooKeeper進行的。
Etcd – 高可用、分散式、一致性的鍵值儲存,用於共享配置和服務發現。
Consul – 發現和配置的服務,提供 API 實現客戶端註冊和發現服務。
Apache ZooKeeper – 被分散式應用廣泛使用的高效能協調服務。
如前所述,服務例項必須在登錄檔中註冊和登出。註冊和登出有兩種不同的方法。方法一是服務例項自己註冊,也叫自注冊模式(self-registrationpattern);另一種是採用管理服務例項註冊的其它系統元件,即第三方註冊模式。(原文有詳細機制描述,不再累述)
雖然方法一把服務例項和服務登錄檔耦合,必須在每個程式語言和框架內實現註冊程式碼。但是在自己實現完整微服務架構中,考慮到PaaS平臺下微服務模組的動態部署和擴充套件,採用方法1相當來說更加容易實現。但是方法1仍然不能代替服務註冊庫本身應該具備的服務節點的心跳檢測能力。
Dubbo
官網連結:http://dubbo.ioDubbo是Alibaba開源的分散式服務框架,它最大的特點是按照分層的方式來架構,使用這種方式可以使各個層之間解耦合(或者最大限度地鬆耦合)。從服務模型的角度來看,Dubbo採用的是一種非常簡單的模型,要麼是提供方提供服務,要麼是消費方消費服務,所以基於這一點可以抽象出服務提供方(Provider)和服務消費方(Consumer)兩個角色。關於註冊中心、協議支援、服務監控等內容
需求
(#)
在大規模服務化之前,應用可能只是通過RMI或Hessian等工具,簡單的暴露和引用遠端服務,通過配置服務的URL地址進行呼叫,通過F5等硬體進行負載均衡。
(1) 當服務越來越多時,服務URL配置管理變得非常困難,F5硬體負載均衡器的單點壓力也越來越大。
此時需要一個服務註冊中心,動態的註冊和發現服務,使服務的位置透明。
並通過在消費方獲取服務提供方地址列表,實現軟負載均衡和Failover,降低對F5硬體負載均衡器的依賴,也能減少部分成本。
(2) 當進一步發展,服務間依賴關係變得錯蹤複雜,甚至分不清哪個應用要在哪個應用之前啟動,架構師都不能完整的描述應用的架構關係。
這時,需要自動畫出應用間的依賴關係圖,以幫助架構師理清理關係。
(3) 接著,服務的呼叫量越來越大,服務的容量問題就暴露出來,這個服務需要多少機器支撐?什麼時候該加機器?
為了解決這些問題,第一步,要將服務現在每天的呼叫量,響應時間,都統計出來,作為容量規劃的參考指標。
其次,要可以動態調整權重,在線上,將某臺機器的權重一直加大,並在加大的過程中記錄響應時間的變化,直到響應時間到達閥值,記錄此時的訪問量,再以此訪問量乘以機器數反推總容量。
成熟度
功能成熟度
(#)
Feature | Maturity | Strength | Problem | Advise | User |
---|---|---|---|---|---|
併發控制 | Tested | 併發控制 | 試用 | ||
連線控制 | Tested | 連線數控制 | 試用 | ||
直連提供者 | Tested | 點對點直連服務提供方,用於測試 | 測試環境使用 | Alibaba | |
分組聚合 | Tested | 分組聚合返回值,用於選單聚合等服務 | 特殊場景使用 | 可用於生產環境 | |
引數驗證 | Tested | 引數驗證,JSR303驗證框架整合 | 對效能有影響 | 試用 | LaiWang |
結果快取 | Tested | 結果快取,用於加速請求 | 試用 | ||
泛化引用 | Stable | 泛化呼叫,無需業務介面類進行遠端呼叫,用於測試平臺,開放閘道器橋接等 | 可用於生產環境 | Alibaba | |
泛化實現 | Stable | 泛化實現,無需業務介面類實現任意介面,用於Mock平臺 | 可用於生產環境 | Alibaba | |
回聲測試 | Tested | 回聲測試 | 試用 | ||
隱式傳參 | Stable | 附加引數 | 可用於生產環境 | ||
非同步呼叫 | Tested | 不可靠非同步呼叫 | 試用 | ||
本地呼叫 | Tested | 本地呼叫 | 試用 | ||
引數回撥 | Tested | 引數回撥 | 特殊場景使用 | 試用 | Registry |
事件通知 | Tested | 事件通知,在遠端呼叫執行前後觸發 | 試用 | ||
本地存根 | Stable | 在客戶端執行部分邏輯 | 可用於生產環境 | Alibaba | |
本地偽裝 | Stable | 偽造返回結果,可在失敗時執行,或直接執行,用於服務降級 | 需註冊中心支援 | 可用於生產環境 | Alibaba |
延遲暴露 | Stable | 延遲暴露服務,用於等待應用載入warmup資料,或等待spring載入完成 | 可用於生產環境 | Alibaba | |
延遲連線 | Tested | 延遲建立連線,呼叫時建立 | 試用 | Registry | |
粘滯連線 | Tested | 粘滯連線,總是向同一個提供方發起請求,除非此提供方掛掉,再切換到另一臺 | 試用 | Registry | |
令牌驗證 | Tested | 令牌驗證,用於服務授權 | 需註冊中心支援 | 試用 | |
路由規則 | Tested | 動態決定呼叫關係 | 需註冊中心支援 | 試用 | |
配置規則 | Tested | 動態下發配置,實現功能的開關 | 需註冊中心支援 | 試用 | |
訪問日誌 | Tested | 訪問日誌,用於記錄呼叫資訊 | 本地儲存,影響效能,受磁碟大小限制 | 試用 | |
分散式事務 | Research | JTA/XA三階段提交事務 | 不穩定 | 不可用 |
策略成熟度
(#)
Feature | Maturity | Strength | Problem | Advise | User |
---|---|---|---|---|---|
Stable | 支援基於網路的叢集方式,有廣泛周邊開源產品,建議使用dubbo-2.3.3以上版本(推薦使用) | 依賴於Zookeeper的穩定性 | 可用於生產環境 | ||
Stable | 支援基於客戶端雙寫的叢集方式,效能高 | 要求伺服器時間同步,用於檢查心跳過期髒資料 | 可用於生產環境 | ||
Tested | 去中心化,不需要安裝註冊中心 | 依賴於網路拓普和路由,跨機房有風險 | 小規模應用或開發測試環境 | ||
Tested | Dogfooding,註冊中心本身也是一個標準的RPC服務 | 沒有叢集支援,可能單點故障 | 試用 | ||
Feature | Maturity | Strength | Problem | Advise | User |
Stable | 支援JFreeChart統計報表 | 沒有叢集支援,可能單點故障,但故障後不影響RPC執行 | 可用於生產環境 | ||
Feature | Maturity | Strength | Problem | Advise | User |
Stable | 採用NIO複用單一長連線,並使用執行緒池併發處理請求,減少握手和加大併發效率,效能較好(推薦使用) | 在大檔案傳輸時,單一連線會成為瓶頸 | 可用於生產環境 | Alibaba | |
Rmi協議 | Stable | 可與原生RMI互操作,基於TCP協議 | 偶爾會連線失敗,需重建Stub | 可用於生產環境 | Alibaba |
Stable | 可與原生Hessian互操作,基於HTTP協議 | 需hessian.jar支援,http短連線的開銷大 | 可用於生產環境 | ||
Feature | Maturity | Strength | Problem | Advise | User |
Netty Transporter | Stable | JBoss的NIO框架,效能較好(推薦使用) | 一次請求派發兩種事件,需遮蔽無用事件 | 可用於生產環境 | Alibaba |
Mina Transporter | Stable | 老牌NIO框架,穩定 | 待發送訊息佇列派發不及時,大壓力下,會出現FullGC | 可用於生產環境 | Alibaba |
Grizzly Transporter | Tested | Sun的NIO框架,應用於GlassFish伺服器中 | 執行緒池不可擴充套件,Filter不能攔截下一Filter | 試用 | |
Feature | Maturity | Strength | Problem | Advise | User |
Hessian Serialization | Stable | 效能較好,多語言支援(推薦使用) | Hessian的各版本相容性不好,可能和應用使用的Hessian衝突,Dubbo內嵌了hessian3.2.1的原始碼 | 可用於生產環境 | Alibaba |
Dubbo Serialization | Tested | 通過不傳送POJO的類元資訊,在大量POJO傳輸時,效能較好 | 當引數物件增加欄位時,需外部檔案宣告 | 試用 | |
Json Serialization | Tested | 純文字,可跨語言解析,預設採用FastJson解析 | 效能較差 | 試用 | |
Java Serialization | Stable | Java原生支援 | 效能較差 | 可用於生產環境 | |
Feature | Maturity | Strength | Problem | Advise | User |
Javassist ProxyFactory | Stable | 通過位元組碼生成代替反射,效能比較好(推薦使用) | 依賴於javassist.jar包,佔用JVM的Perm記憶體,Perm可能要設大一些:java -XX:PermSize=128m | 可用於生產環境 | Alibaba |
Jdk ProxyFactory | Stable | JDK原生支援 | 效能較差 | 可用於生產環境 | |
Feature | Maturity | Strength | Problem | Advise | User |
Stable | 失敗自動切換,當出現失敗,重試其它伺服器,通常用於讀操作(推薦使用) | 重試會帶來更長延遲 | 可用於生產環境 | Alibaba | |
Stable | 快速失敗,只發起一次呼叫,失敗立即報錯,通常用於非冪等性的寫操作 | 如果有機器正在重啟,可能會出現呼叫失敗 | 可用於生產環境 | Alibaba | |
Stable | 失敗安全,出現異常時,直接忽略,通常用於寫入審計日誌等操作 | 呼叫資訊丟失 | 可用於生產環境 | Monitor | |
Tested | 失敗自動恢復,後臺記錄失敗請求,定時重發,通常用於訊息通知操作 | 不可靠,重啟丟失 | 可用於生產環境 | Registry | |
Tested | 並行呼叫多個伺服器,只要一個成功即返回,通常用於實時性要求較高的讀操作 | 需要浪費更多服務資源 | 可用於生產環境 | ||
Tested | 廣播呼叫所有提供者,逐個呼叫,任意一臺報錯則報錯,通常用於更新提供方本地狀態 | 速度慢,任意一臺報錯則報錯 | 可用於生產環境 | ||
Feature | Maturity | Strength | Problem | Advise | User |
Stable | 隨機,按權重設定隨機概率(推薦使用) | 在一個截面上碰撞的概率高,重試時,可能出現瞬間壓力不均 | 可用於生產環境 | Alibaba | |
Stable | 輪循,按公約後的權重設定輪循比率 | 存在慢的機器累積請求問題,極端情況可能產生雪崩 | 可用於生產環境 | ||
Stable | 最少活躍呼叫數,相同活躍數的隨機,活躍數指呼叫前後計數差,使慢的機器收到更少請求 | 不支援權重,在容量規劃時,不能通過權重把壓力導向一臺機器壓測容量 | 可用於生產環境 | ||
Stable | 一致性Hash,相同引數的請求總是發到同一提供者,當某一臺提供者掛時,原本發往該提供者的請求,基於虛擬節點,平攤到其它提供者,不會引起劇烈變動 | 壓力分攤不均 | 可用於生產環境 | ||
Feature | Maturity | Strength | Problem | Advise | User |
Stable | 基於條件表示式的路由規則,功能簡單易用 | 有些複雜多分支條件情況,規則很難描述 | 可用於生產環境 | Alibaba | |
Tested | 基於指令碼引擎的路由規則,功能強大 | 沒有執行沙箱,指令碼能力過於強大,可能成為後門 | 試用 | ||
Feature | Maturity | Strength | Problem | Advise | User |
Stable | 自動載入META-INF/spring目錄下的所有Spring配置 | 可用於生產環境 | Alibaba | ||
Stable | 啟動一個內嵌Jetty,用於彙報狀態 | 大量訪問頁面時,會影響伺服器的執行緒和記憶體 | 可用於生產環境 | Alibaba | |
Stable | 自動配置log4j的配置,在多程序啟動時,自動給日誌檔案按程序分目錄 | 使用者不能控制log4j的配置,不靈活 | 可用於生產環境 | Alibaba |
協議支援
Dubbo支援多種協議,如下所示:
- Dubbo協議
- Hessian協議
- HTTP協議
- RMI協議
- WebService協議
- Thrift協議
- Memcached協議
- Redis協議
如何做服務降級
一般需要針對業務進行服務分級
比如分為一級服務,二級服務,三級服務
比如在緊急情況下面,務必保證一級服務的穩定性,然後可以犧牲二級三級服務,這個就是服務降級 — 黑夜路人
分享下我們的方案
原理很簡單 利用nginx lua 和快取
lua裡做個監控,對一定時間內的伺服器500或者其他錯誤做技術,如果超過一定的頻率就直接從快取中取出資料丟給使用者
這樣在瞬時流量過來的時候能夠保證段時間內恢復服務
如果再做的友好點,就在lua中加個白名單,保證直接丟快取內容也不會有大影響,一些有狀態的不能快取可以直接過
還有就是梳理關鍵路徑
在可預測的大流量是,把非關鍵路徑的服務關了