服務網關
在微服務架構中,網關的作用是什麼
在微服務架構中,網關(Gateway)具有以下作用:
- 統一入口:網關為所有的微服務提供一個唯一的入口點,從而簡化了客户端與服務的交互,同時保障了後台服務的安全性。
- 鑑權校驗:網關能夠識別每個進來的請求,並根據其權限進行校驗,阻止不符合要求的請求通過。
- 動態路由:根據需要,網關可以動態地將請求路由到不同的後端集羣中,實現服務的靈活調度。
- 降低耦合度:通過在網關層做映射,可以將客户端與服務解耦,使服務可以獨立發展,減少兩者之間的依賴。
- 提供附加功能:網關不僅可以保護微服務,還可以為服務提供和沉澱更多附加功能,如熔斷、限流等。
什麼是API網關?
API網關(API Gateway)是一種中間層服務器,用於集中管理、保護和路由對後端服務的訪問。它充當了客户端與後端服務之間的入口點,提供了一組統一的接口來管理和控制API的訪問。
API網關的主要功能包括:
- 路由轉發:API網關根據請求的URL路徑或其他標識,將請求路由到相應的後端服務。通過配置路由規則,可以靈活地將請求分發給不同的後端服務。
- 負載均衡:API網關可以在後端服務之間實現負載均衡,將請求平均分發到多個實例上,提高系統的吞吐量和可擴展性。
- 安全認證與授權:API網關可以集中處理身份驗證和授權,確保只有經過身份驗證的客户端才能訪問後端服務。它可以與身份提供者(如OAuth、OpenID Connect)集成,進行用户認證和授權操作。
- 緩存:API網關可以緩存後端服務的響應,減少對後端服務的請求次數,提高系統性能和響應速度。
- 監控與日誌:API網關可以收集和記錄請求的指標和日誌,提供實時監控和分析,幫助開發人員和運維人員進行故障排查和性能優化。
- 數據轉換與協議轉換:API網關可以在客户端和後端服務之間進行數據格式轉換和協議轉換,如將請求從HTTP轉換為WebSocket,或將請求的參數進行格式轉換,以滿足後端服務的需求。
- API版本管理:API網關可以管理不同版本的API,允許同時存在多個API版本,並通過路由規則將請求正確地路由到相應的API版本上。
……
通過使用API網關,可以簡化前端與後端服務的交互,提供統一的接口和安全性保障,同時也方便了服務治理和監控。它是構建微服務架構和實現API管理的重要組件之一。
SpringCloud可以選擇哪些API網關?
使用SpringCloud開發,可以採用以下的API網關選型:
- Netflix Zuul(已停止更新):Netflix Zuul是Spring Cloud早期版本中提供的默認API網關。它基於Servlet技術棧,可以進行路由、過濾、負載均衡等功能。然而,自2020年12月起,Netflix宣佈停止對Zuul 1的維護,轉而支持新的API網關項目。
- Spring Cloud Gateway:Spring Cloud Gateway是Spring Cloud官方推薦的API網關,取代了Netflix Zuul。它基於非阻塞的WebFlux框架,充分利用了響應式編程的優勢,並提供了路由、過濾、斷路器、限流等特性。Spring Cloud Gateway還支持與Spring Cloud的其他組件集成,如服務發現、負載均衡等。
- Kong:Kong是一個獨立的、雲原生的API網關和服務管理平台,可以與Spring Cloud集成。Kong基於Nginx,提供了強大的路由、認證、授權、監控和擴展能力。它支持多種插件和擴展,可滿足不同的API管理需求。
- APISIX:APISIX基於Nginx和Lua開發,它具有強大的路由、流量控制、插件擴展等功能。APISIX支持靈活的配置方式,可以根據需求進行動態路由、負載均衡和限流等操作。
説説你對Spring Cloud Gateway的理解
Spring Cloud Gateway是Spring Cloud官方推出的第二代網關框架,取代Zuul 1.0網關。網關作為流量的,在微服務系統中有着非常作用,網關常見的功能有路由轉發、權限校驗、限流控制等作用。
使用了一個RouteLocatorBuilder的bean去創建路由,除了創建路由RouteLocatorBuilder可以讓你添加各種predicates和filters,predicates斷言的意思,顧名思義就是根據具體的請求的規則,由具體的route去處理,filters是各種過濾器,用來對請求做各種判斷和修改。
Spring Cloud Gateway核心概念?
在Spring Cloud Gateway裏,有三個關鍵組件:
- Route(路由):路由是Spring Cloud Gateway的基本構建塊,它定義了請求的匹配規則和轉發目標。通過配置路由,可以將請求映射到後端的服務實例或URL上。路由規則可以根據請求的路徑、方法、請求頭等條件進行匹配,並指定轉發的目標URI。
- Predicate(斷言):斷言用於匹配請求的條件,如果請求滿足斷言的條件,則會應用所配置的過濾器。Spring Cloud Gateway提供了多種內置的斷言,如Path(路徑匹配)、Method(請求方法匹配)、Header(請求頭匹配)等,同時也支持自定義斷言。
- Filter(過濾器):過濾器用於對請求進行處理和轉換,可以修改請求、響應以及執行其他自定義邏輯。Spring Cloud Gateway提供了多個內置的過濾器,如請求轉發、請求重試、請求限流等。同時也支持自定義過濾器,可以根據需求編寫自己的過濾器邏輯。
我們再來看下Spring Cloud Gateway的具體工作流程:
兩個比較重要的概念:
- Gateway Handler(網關處理器):網關處理器是Spring Cloud Gateway的核心組件,負責將請求轉發到匹配的路由上。它根據路由配置和斷言條件進行路由匹配,選擇合適的路由進行請求轉發。網關處理器還會依次應用配置的過濾器鏈,對請求進行處理和轉換。
- Gateway Filter Chain(網關過濾器鏈):網關過濾器鏈由一系列過濾器組成,按照配置的順序依次執行。每個過濾器可以在請求前、請求後或請求發生錯誤時進行處理。過濾器鏈的執行過程可以修改請求、響應以及執行其他自定義邏輯。
什麼是限流算法,網關如何實現限流
限流算法是指用於限制單位時間內服務的請求數量的算法,目的是防止服務被過高的請求壓力所擊垮。常見的限流算法包括計數器算法、滑動窗口算法、漏桶算法、令牌桶算法。
網關如何實現限流:
- 利用限流算法插件/模塊:網關可以集成限流算法插件/模塊,通過配置相關參數(如令牌桶大小、令牌生成速率等)來實現限流。例如,Spring Cloud Gateway可以使用Redis的RateLimiter限流算法插件來實現限流。
- 自定義限流邏輯:網關可以通過編程方式自定義實現限流邏輯。例如,在微服務架構中,可以在每個服務的網關層(如Nacos、Eureka等)實現限流邏輯,或者使用限流SDK(如Sentinel)對請求進行限流。
- 利用雲平台提供的限流功能:一些雲平台提供了自動化的限流功能,例如AWS CloudWatch、Azure Application Insights等,網關可以利用這些雲平台的功能來實現限流。
你項目裏為什麼選擇 Gateway 作為網關?
選擇 Spring Cloud Gateway 的原因主要有兩個:
- 以前用得比較多的是 Spring Cloud 官方開源的Zuul,其用得比較多的還是1.0 的版本,不過1.0版本 Netflix很早就宣佈進入維護狀態了,雖然Zuul已經出了2.0版本,但是 Spring Cloud 官方團隊好像沒有整合的計劃,並且 Netflix 很多相關的組件,如 Eureka、Hystrix 都已經進入維護期了,所以不知道前景如間,然後 Sping doud 官方自己研發了Spring Cloud Gateway,並且大力支持和推薦,所以相比與Zuul, Gateway是一個更好的選擇。
- Spring Cloud Gateway 有很多的特性:
- 基於 Spring5和 Spring Boot 2 進行構建,與 Spring 生態兼容較好
- 動態路由:可以根據配置條件,如 URL、請求方法等實現動態配置
- 可以對路由指定斷言(Predicate)和過濾器(Filter)
- 集成 Hystrix 斷路器功能,可以實現服務熔斷
- 集成 Spring Cloud 相關組件,如 Eureka、Nacos、Consule 等實現服務的註冊與發現
- 內置了限流模塊,可以根據配置實現服務限流
Dubbo和 Spring Cloud Gateway 有什麼區別?
Dubbo 是一個RPC(遠程過程調用)框架,主要用於服務之間的通信。它提供高性能的 RPC 調用、負載均衡、服務發現、服務註冊、服務治理等功能。適用於需要高性能 RPC 調用的分佈式系統,常用於內部服務通信。
Spring Cloud Gateway是一個API 網關,用於處理外部客户端請求並將其路由到後端服務。它提供請求路由、負載均衡、協議轉換、安全管理、流量控制、日誌和監控等功能。適用於微服務架構中的統一入口管理,常用於外部請求的入口層。
所以説它們不是一個層級的東西。
鏈路追蹤
為什麼要用微服務鏈路追蹤?
在微服務中,有的上下游可能有十幾個服務,如果某一環出了問題,排查起來非常困難,所以,就需要進行鏈路追蹤,來幫助排查問題。
通過鏈路追蹤,可以可視化地追蹤請求從一個微服務到另一個微服務的調用情況。除了排查問題,鏈路追蹤黑還可以幫助優化性能,可視化依賴關係、服務監控和告警。
SpringCloud可以選擇哪些微服務鏈路追蹤方案?
Spring Cloud提供了多種選擇的微服務鏈路追蹤方案。以下是一些常用的方案:
- Zipkin:Zipkin 是一個開源的分佈式實時追蹤系統,由 Twitter 開發並貢獻給開源社區。Spring Cloud Sleuth 提供了與 Zipkin 的集成,可以通過在微服務中添加相應的依賴和配置,將追蹤信息發送到 Zipkin 服務器,並通過 Zipkin UI 進行可視化展示和查詢。
- Jaeger:Jaeger 是 Uber 開源的分佈式追蹤系統,也被納入了 CNCF(雲原生計算基金會)的維護。通過使用 Spring Cloud Sleuth 和 Jaeger 客户端庫,可以將追蹤信息發送到 Jaeger 並進行可視化展示和查詢。
- SkyWalking:Apache SkyWalking 是一款開源的應用性能監控與分析系統,提供了對 Java、.NET 和 Node.js 等語言的支持。它可以與 Spring Cloud Sleuth 集成,將追蹤數據發送到 SkyWalking 服務器進行可視化展示和分析。
- Pinpoint:Pinpoint 是 Naver 開源的分佈式應用性能監控系統,支持 Java 和 .NET。它提供了與 Spring Cloud Sleuth 的集成,可以將追蹤數據發送到 Pinpoint 服務器,並通過其 UI 進行分析和監控。
這些方案都可以與 Spring Cloud Sleuth 進行集成,Spring Cloud Sleuth 是 Spring Cloud 中的一個組件,提供了在微服務調用時生成追蹤信息的能力。
分佈式事務
什麼情況下需要用到分佈式事務?有哪些方案?
分佈式事務是指在多個網絡節點或服務之間進行數據一致性處理的情況。以下是一些可能需要使用分佈式事務的場景:
- 微服務之間通過遠程調用完成事務操作:當不同的微服務之間需要進行數據一致性保證時,就需要使用分佈式事務。例如,一個電商微服務中的訂單服務和庫存服務需要通過遠程調用進行事務操作,保證庫存數量和訂單信息的同步更新,避免出現超賣或缺貨的情況。
- 單體系統訪問多個數據庫實例:當一個系統需要訪問多個數據庫實例時,例如用户信息和訂單信息分別存儲在兩個不同的數據庫實例中,需要通過分佈式事務保證數據一致性,避免出現數據不一致的情況。
- 多服務訪問同一個數據庫實例:當多個服務訪問同一個數據庫實例時,例如訂單微服務和庫存微服務都需要訪問同一個數據庫,也可能需要使用分佈式事務。因為跨JVM進程的多個服務同時持有不同的數據庫連接進行數據庫操作,可能會出現數據不一致的情況。
在這些場景下,我們需要使用分佈式事務來保證數據的一致性。常用的分佈式事務方案包括兩階段提交(2PC)、三階段提交(3PC)、TCC、Saga、本地消息表等。其中,兩階段提交和三階段提交都是基於鎖機制實現的,而TCC、Saga和本地消息表則是基於業務邏輯實現的。選擇哪種方案取決於業務需求、系統複雜性和性能等多個因素。
詳情可以看這篇文章:深度解析分佈式事務的七大核心方案
什麼是分佈式事務的防懸掛,空回滾?
防懸掛是指在分佈式事務的第一階段,防止在沒有對應的 Try 操作的情況下出現 Confirm 或 Cancel 操作。這是為了保證事務的正確性和一致性。
分佈式事務中最常見的模型是 TCC(Try-Confirm-Cancel)模型。在 TCC 模型中,事務分為三個步驟:
- Try:資源的預留操作。
- Confirm:確認操作,完成業務邏輯
- Cancel:取消操作,回滾預留資源。
防懸掛機制的作用是確保在分佈式事務中,Confirm 和 Cancel 操作只會在 Try 操作成功執行後才會觸發。
防懸掛的場景通常是以下情況:
- Confirm 操作懸掛:如果 Confirm 操作在沒有執行過 Try 操作的情況下被調用,可能會導致數據不一致。
- Cancel 操作懸掛:類似地,如果 Cancel 操作在沒有 Try 操作的情況下被調用,也會破壞數據的一致性。
為了防止這種情況,需要通過某些機制來檢測和防止懸掛。例如:
- 冪等性檢查:Confirm 和 Cancel 操作應該具備冪等性,避免多次調用引發問題。
- 狀態校驗:在執行 Confirm 或 Cancel之前,可以先檢査是否有對應的 Try 操作成功過,如果沒有,則拒絕執行 Confirm 或 Cancel 操作
空回滾是指在沒有執行成功的Try操作時,Cancel 操作仍然被調用了。Cancel 操作實際上就是 Try操作的回滾操作,如果 Try 操作根本沒有成功,則Cancel 操作實際不會對任問資源產生影響,這就是空回滾
空回滾一般發生在分佈式系統中的異常情況下,比如:
- 網絡超時:Try 操作還沒執行成功,網絡就超時了,分佈式事務協調器可能誤認為 Try 操作失敗,因此會調用 Cancel。
- 網絡分區或中斷:Try 操作請求未到達相應的服務端,客户端誤認為 Try 操作已經失敗併發起 Cancel。
在這些情況下,Cancel 操作會被執行,但因為 Try 操作並沒有成功,所以 Cancel 實際上什麼都不需要做。這就是空迴流,。為了支持空回滾,Cancel操作必須具備以下能力:
- 冪等性:即使 Cancel 操作被多次調用,它的效果也只能是執行一次,不會對系統產生額外影響。
- 空回滾兼容性:Cancel 操作在發現沒有Try 操作執行成功時,不做任何修改,直接返回成功狀態
什麼是Seata?談談你對Seata的理解
Seata是一款開源的分佈式事務解決方案,它主要用於解決在分佈式系統中全局事務的一致性問題。
在分佈式系統中,由於一次業務操作需要跨多個數據源或進行遠程調用,往往會產生分佈式事務問題。例如,在一個電商微服務系統中,訂單服務和庫存服務需要協同工作,如果訂單服務已經創建成功,但庫存服務因為某些原因失敗了,就會導致數據不一致的問題。Seata就是為解決這個問題而產生的。
Seata的主要特點是無侵入以及高性能。它對業務無侵入,可以減少技術架構上的微服務化所帶來的分佈式事務問題對業務的侵入,同時高性能則是減少分佈式事務解決方案所帶來的性能消耗。
在Seata的事務處理中主要有三個重要的角色:事務的協調者(TC)、事務的管理者(TM)和事務的作業管理器(RM)。
- 事務協調者(TC)主要負責管理全局的分支事務的狀態,用於全局性事務的提交和回滾。它會對所有的分支事務進行註冊,然後根據各個分支事務的狀態來決定是否提交或者回滾全局事務。
- 事務管理者(TM)用於開啓、提交或回滾事務。它會根據業務邏輯來決定何時開啓一個新的事務,並在適當的時候提交或回滾該事務。
- 資源管理器(RM)用於分支事務上的資源管理,向TC註冊分支事務,上報分支事務的狀態,接收TC的命令來提交或者回滾分支事務。
Seata支持哪些模式的分佈式事務?
Seata以下幾種模式的分佈式事務:
- AT(Atomikos)模式:AT模式是Seata默認支持的模式,也是最常用的模式之一。在AT模式下,Seata通過在業務代碼中嵌入事務上下文,實現對分佈式事務的管理。Seata會攔截並解析業務代碼中的SQL語句,通過對數據庫連接進行攔截和代理,實現事務的管理和協調。
- TCC(Try-Confirm-Cancel)模式:TCC模式是一種基於補償機制的分佈式事務模式。在TCC模式中,業務邏輯需要實現Try、Confirm和Cancel三個階段的操作。Seata通過調用業務代碼中的Try、Confirm和Cancel方法,並在每個階段記錄相關的操作日誌,來實現分佈式事務的一致性。
- SAGA模式:SAGA模式是一種基於事件驅動的分佈式事務模式。在SAGA模式中,每個服務都可以發佈和訂閲事件,通過事件的傳遞和處理來實現分佈式事務的一致性。Seata提供了與SAGA模式兼容的Saga框架,用於管理和協調分佈式事務的各個階段。
- XA模式:XA模式是一種基於兩階段提交(Two-Phase Commit)協議的分佈式事務模式。在XA模式中,Seata通過與數據庫的XA事務協議進行交互,實現對分佈式事務的管理和協調。XA模式需要數據庫本身支持XA事務,並且需要在應用程序中配置相應的XA數據源。
瞭解Seata的實現原理嗎?
Seata的實現原理主要包括三個核心組件:事務協調器(Transaction Coordinator)、事務管理器(Transaction Manager)和資源管理器(Resource Manager)。
- 事務協調器(Transaction Coordinator):事務協調器負責協調和管理分佈式事務的整個過程。它接收事務的開始和結束請求,並根據事務的狀態進行協調和處理。事務協調器還負責記錄和管理事務的全局事務 ID(Global Transaction ID)和分支事務 ID(Branch Transaction ID)。
- 事務管理器(Transaction Manager):事務管理器負責全局事務的管理和控制。它協調各個分支事務的提交或回滾,並保證分佈式事務的一致性和隔離性。事務管理器還負責與事務協調器進行通信,並將事務的狀態變更進行持久化。
- 資源管理器(Resource Manager):資源管理器負責管理和控制各個參與者(Participant)的事務操作。它與事務管理器進行通信,並根據事務管理器的指令執行相應的事務操作,包括提交和回滾。
Seata的實現原理基於兩階段提交(Two-Phase Commit)協議,具體的機制如下:
- 一階段:在事務提交的過程中,首先進行預提交階段。事務協調器向各個資源管理器發送預提交請求,資源管理器執行相應的事務操作並返回執行結果。在此階段,業務數據和回滾日誌記錄在同一個本地事務中提交,並釋放本地鎖和連接資源。
- 二階段:在預提交階段成功後,進入真正的提交階段。此階段主要包括提交異步化和回滾反向補償兩個步驟:
- 提交異步化:事務協調器發出真正的提交請求,各個資源管理器執行最終的提交操作。這個階段的操作是非常快速的,以確保事務的提交效率。
- 回滾反向補償:如果在預提交階段中有任何一個資源管理器返回失敗結果,事務協調器發出回滾請求,各個資源管理器執行回滾操作,利用一階段的回滾日誌進行反向補償。
Seata的事務執行流程是什麼樣的?
Seata事務的執行流程可以簡要概括為以下幾個步驟:
- 事務發起方(Transaction Starter)發起全局事務:事務發起方是指發起分佈式事務的應用程序或服務。它向Seata的事務協調器發送全局事務的開始請求,生成全局事務ID(Global Transaction ID)。
- 事務協調器創建全局事務記錄:事務協調器接收到全局事務的開始請求後,會為該事務創建相應的全局事務記錄,並生成分支事務ID(Branch Transaction ID)。
- 分支事務註冊:事務發起方將全局事務ID和分支事務ID發送給各個參與者(Participant),即資源管理器。參與者將分支事務ID註冊到本地事務管理器,並將事務的執行結果反饋給事務協調器。
- 執行業務邏輯:在分佈式事務的上下文中,各個參與者執行各自的本地事務,即執行業務邏輯和數據庫操作。
- 預提交階段:事務發起方向事務協調器發送預提交請求,事務協調器將預提交請求發送給各個參與者。
- 執行本地事務確認:參與者接收到預提交請求後,執行本地事務的確認操作,並將本地事務的執行結果反饋給事務協調器。
- 全局事務提交或回滾:事務協調器根據參與者反饋的結果進行判斷,如果所有參與者的本地事務都執行成功,事務協調器發送真正的提交請求給參與者,參與者執行最終的提交操作;如果有任何一個參與者的本地事務執行失敗,事務協調器發送回滾請求給參與者,參與者執行回滾操作。
- 完成全局事務:事務協調器接收到參與者的提交或回滾結果後,根據結果更新全局事務的狀態,並通知事務發起方全局事務的最終結果。
全局事務ID和分支事務ID是怎麼傳遞的?
全局事務ID和分支事務ID在分佈式事務中通過上下文傳遞的方式進行傳遞。常見的傳遞方式包括參數傳遞、線程上下文傳遞和消息中間件傳遞。具體的傳遞方式可以根據業務場景和技術選型進行選擇和調整。
Seata的事務回滾是怎麼實現的?
Seata的事務回滾是通過回滾日誌實現的。每個參與者在執行本地事務期間生成回滾日誌,記錄了對數據的修改操作。
當需要回滾事務時,事務協調器向參與者發送回滾請求,參與者根據回滾日誌中的信息執行撤銷操作,將數據恢復到事務開始前的狀態。
回滾日誌的管理和存儲是Seata的核心機制,可以選擇將日誌存儲在不同的介質中。通過回滾日誌的持久化和恢復,Seata確保了事務的一致性和恢復性。
Sentinel 與Hystrix的區別是什麼
Hystrix和Sentinel都是微服務架構中實現熔斷和限流的工具,它們有以下區別和特點:
Hystrix是Netflix開源的熔斷器實現,主要用於保護分佈式系統中的服務調用。它的主要特點包括線程隔離、資源保護和降級處理。Hystrix通過將每個服務調用放入獨立的線程池中來實現線程隔離,防止一個服務的延遲或故障影響其他服務。它通過監控服務調用的成功率、延遲等指標來保護後端資源,並在失敗的請求或響應超時達到一定閾值時自動打開熔斷器,避免連鎖故障。此外,Hystrix還提供了降級處理功能,可以在服務不可用或響應過慢時返回預定義的降級響應,保證系統的可用性。
Sentinel是阿里巴巴開源的流量控制和系統保護工具,主要用於實現微服務架構中的流量控制、熔斷、降級和系統負載保護等。它的主要特點包括實時監控和動態規則配置、豐富的流量控制策略、細粒度的服務保護以及支持多種編程語言。Sentinel可以實時監控服務的請求流量和各項指標,並提供實時的儀表盤和可視化的監控界面。它還支持通過API動態配置流量控制和熔斷規則,可以根據實際情況進行動態調整。Sentinel提供了多種流量控制策略,包括基於QPS、線程數、併發連接數等多種指標進行的流量控制。此外,Sentinel還支持對每個具體的服務接口進行熔斷、降級和限流等操作,以實現精確的服務保護策略。同時,Sentinel不僅支持Java,還支持Go、Python等多種編程語言,使其適用於跨語言的微服務架構。
總的來説,Hystrix注重線程隔離和資源保護,適用於保護單個服務調用。而Sentinel注重流量控制和動態規則配置,適用於對整個系統的流量進行監控和保護。根據實際需求和技術棧,可以選擇適合的工具來實現微服務架構中的熔斷和限流功能。
如果 Sentinel 的異常處理規則不滿足需求,應該怎麼辦?
如果 Sentinel 的默認異常處理機制無法滿足需求,可以選擇自定義異常處理規則。
Sentinel 允許通過自定義實現 BlockedExceptionHandler 接口,然後將自定義的異常處理器對象交給 Spring 容器進行管理。 可以根據實際業務需求,定製化異常處理策略,例如全局兜底處理、日誌打印、空指針檢查等。 同時,還可以在處理器中加入自定義的業務邏輯,例如對異常進行分類、統計和反饋等。 這樣,可以根據具體的應用場景和業務需求,靈活地擴展 Sentinel 的異常處理能力。
什麼是分佈式事務的防懸掛,空回滾
在分佈式事務中,防懸掛和空回滾是兩個重要的概念,它們通常在實現分佈式事務時涉及的鎖定機制、隔離性、錯誤處理等方面。下面對這兩個概念進行詳細解釋
- 防懸掛
防懸掛是指在分佈式事務的第一階段,防止在沒有對應的 Try 操作的情況下出現 Confirm 或 Cancel操作。這是為了保證事務的正確性和一致性。
分佈式事務中最常見的模型是 TCC(Try-Confirm-Cancel)模型。在 TCC 模型中,事務通常分為三個步驟:
- Try:資源的預留操作。
- Confirm:確認操作,完成業務邏輯
- Cancel:取消操作,回滾預留資源。
防懸掛機制的作用是確保在分佈式事務中,Confirm 和 Cancel 操作只會在 Try 操作成功執行後才會觸發。防懸掛的場景通常是以下情況:
- Confirm 操作懸掛:如果 Confirm 操作在沒有執行過 Try 操作的情況下被調用,可能會導致數據不一致
- Cancel 操作懸掛:類似地,如果 Cancel 操作在沒有 Try 操作的情況下被調用,也會破壞數據的一致性。
為了防止這種情況,通常需要通過某些機制來檢測和防止懸掛。例如:
- 冪等性檢查:Confirm 和 Cancel 操作應該具備冪等性,避免多次調用引發問題。
- 狀態校驗:在執行 Confirm 或 Cancel 之前,可以先檢查是否有對應的 Try 操作成功過,如果沒有,則拒絕執行 Confirm 或 Cancel 操作
- 空回滾
空回滾是指在沒有執行成功的Try操作時,Cancel操作仍然被調用了。Cancel操作實際上就是 Try操作的回滾操作,如果 Try 操作很本沒有成功,則 Cancel 操作實際不會對任何資源產生影響,這種情況下稱為空回滾
空回滾通常發生在分佈式系統中的異常情況下,比如:
- 網絡超時:Try 操作還沒執行成功,網絡就超時了,分佈式事務協調器可能誤認為 Try 操作失敗,因此會調用 Cancel。
- 網絡分區或中斷:Try 操作請求未到達相應的服務端,客户端誤認為 Try 操作已經失敗併發起 Cancel。
在這些情況下,Cancel 操作會被執行,但因為 Try 操作並沒有成功,所以 Cancel 實際上什麼都不需要做。這就是空回滾。
為了支持空回滾,Cancel 操作必須具備以下能力:
- 冪等性:即使 Cancel 操作被多次調用,它的效果也只能是執行一次,不會對系統產生額外影響。
- 空回滾兼容性:Cancel操作在發現沒有 Try 操作執行成功時,不做任何修改,直接返回成功狀態
當前有個本地操作 A,遠程操作 B,我需要保證 A和 B事務的一致性,你會如何實現?
這個題目經常有人會直接踩坑,然後就被面試官繞進去出不來了
要保證本地操作A和遠程操作B的事務一致性,這是一個分佈式事務問題。不能在本地事務中直接嵌入遠程 RPC調用(這就是坑),而是通過異步解耦+補償機制實現最終一致性。
常見方案是本地消息表:本地事務A執行時,先記錄一條“待執行遠程操作B”的日誌(與A在同一事務中),本地事務提交後,通過異步線程或消息隊列觸發遠程調用B、若B失敗,通過定時任務重試(因為有日誌,可以掃描日誌重試),直到成功或人工介入。
為什麼不能在本地事務中直接調用遠程 RPC?
begin transaction
update A 本地數據庫
調用遠程服務B(RPC)
commit
舉個例子:本地操作A是“扣庫存”(數據庫事務),遠程操作B是“調用支付接口扣款”。如果在本地事務中直接調用B,若 B超時 則本地事務回滾,但B實際執行了,導致庫存與支付狀態不一致。
除此之外,還有長事務問題,畢竟外部系統不可控(即使是公司其他部分的接口),若B執行時間過長,會導致 A 操作本地事務鎖持有時間延長,引發數據庫連接耗盡或死鎖問題。
所以,不建議將 RPC調用嵌入本地事務中。同理,像發MQ、更新外部系統(如緩存)等操作,都不建議放在事務內。
現在需要你設計一個將已登錄的用户踢下線的功能,如何實現?
可以通過標記用户 token 為失效或者直接移除其 session來實現踢下線功能
簡單來説,就是讓後續請求中帶的登錄憑證不再被系統接受。標記失效和直接刪除都行,這樣用户下次請求就會被攔截或要求重新登錄
分佈式系統
把單體項目進行了多機部署,多台服務器是如何共享用户登錄信息的?
目前主流有兩個方案:
- 將 Session 放置第三方共享存儲中,例如 Redis、Memcached 等分佈式緩存 或數據庫中,所有的服務器統一訪問第三方。
- JWT,即服務器不存儲會話,用户登錄後返回簽名令牌(含用户信息),每次請求攜帶令牌驗證即可。不過現在很多項目會把 JWT 存在 Redis 中
因為單機時候會話(Session)會存儲在本地,比如 Tomcat 的 HttpSession 默認存在當前服務器內存中。多機部署後,同一個用户多次請求可能會被負載均衡到其他服務器,新服務器無法讀取原會話數據,這時候登錄態就丟了有些人會採用 粘性會話,比如利用 Nginx 根據用户 IP 或 Cookie 哈希固定轉發到同一台服務器。這個方式有侷限性,如果服務器宕機了會話就丟失(登錄態就掉了),且擴容縮容時會導致負載不均,無法實現真正的彈性伸縮。所以普遍會採用第三方共享存儲 Session,比如用 Redis 存放 Session,這樣一來所有的服務都可以共享訪問到同一個 Session。
舉個例子
- 用户登錄後,服務端生成 SessionID,並將用户數據(如用户ID、權限)寫入Redis(Key=SessionID,Value=序列化數據)。
- 響應中設置 Cookie(如SESSION=abc123)或 Header 返回 Token。
- 用户下次請求攜帶 Session ID,任意服務器從 Redis 讀取數據,還原用户上下文
服務監控
你們的服務怎麼做監控和告警?
我們使用Prometheus和Grafana來實現整個微服務集羣的監控和告警:
- Prometheus:Prometheus 是一個開源的監控系統,具有靈活的數據模型和強大的查詢語言,能夠收集和存儲時間序列數據。它可以通過HTTP協議定期拉取微服務的指標數據,並提供可擴展的存儲和查詢功能。
- Grafana:Grafana 是一個開源的可視化儀表板工具,可以與 Prometheus 結合使用,創建實時和歷史數據的儀表板。Grafana 提供了豐富的圖表和可視化選項,可以幫助用户更好地理解和分析微服務的性能和狀態。
你們的服務怎麼做日誌收集?
日誌收集有很多種方案,我們用的是ELK:
- Elasticsearch:Elasticsearch是一個分佈式搜索和分析引擎,用於存儲和索引大量的日誌數據。它提供了快速的搜索和聚合功能,可以高效地處理大規模的日誌數據。
- Logstash:Logstash是一個用於收集、過濾和轉發日誌數據的工具。它可以從各種來源(如文件、網絡、消息隊列等)收集日誌數據,並對數據進行處理和轉換,然後將其發送到Elasticsearch進行存儲和索引。
- Kibana:Kibana是一個用於日誌數據可視化和分析的工具。它提供了豐富的圖表、儀表盤和搜索功能,可以幫助用户實時監控和分析日誌數據,發現潛在的問題和趨勢。
簡單説,這三者裏Elasticsearch提供數據存儲和檢索能力,Logstash負責將日誌收集到ES,Kibana負責日誌數據的可視化分析。
使用ELK進行微服務日誌收集的一般流程如下:
- 在每個微服務中配置日誌輸出:將微服務的日誌輸出到標準輸出(stdout)或日誌文件。
- 使用Logstash收集日誌:配置Logstash收集器,通過配置輸入插件(如文件輸入、網絡輸入等)監聽微服務的日誌輸出,並進行過濾和處理。
- 將日誌數據發送到Elasticsearch:配置Logstash的輸出插件,將經過處理的日誌數據發送到Elasticsearch進行存儲和索引。
- 使用Kibana進行可視化和分析:通過Kibana連接到Elasticsearch,創建儀表盤、圖表和搜索查詢,實時監控和分析微服務的日誌數據。
除了應用最廣泛的ELK,還有一些其它的方案比如Fluentd、Graylog、Loki、Filebeat,一些雲廠商也提供了付費方案,比如阿里雲的sls。
其它
説一下你對於 DDD 的瞭解?
DDD全名叫做 Domain-driven design,即領域驅動設計,它是一種軟件開發方法,其主要目的就是讓開發人員和領域專家可以更好地協作,從而開發出滿足業務需求的系統
DDD 的關鍵概念包括領域模型和限界上下文。
- 領域模型描述了業務領域的規則和邏輯,讓開發人員能夠更好地理解業務需求。
- 限界上下文則定義了一個特定的業務領域內的模型和代碼,使得其可以獨立於其他上下文進行開發和維護。
除此之外,DDD還強調分層架構和事件溯源的重要性,分層架構將系統劃分為不同層次的結構,每個層次的職責和角色各有不同,從而方便業務代碼的開發和維護。事件溯源則是一種存儲和處理業務事件的技術,支持審計、合規和業務分析等需求。
總得來説,DOD是一種設計和開發複雜軟件系統的方法,一般情況下 MVC 已經能夠完成許多軟件業務的開發了,如果項目本身比較簡單,引入 DDD的話不僅不能降低開發成本,還會增加開發的複雜程度,所以 DDD 在使用之前需要一定的思考。
什麼是灰度發佈、金絲雀部署以及藍綠部署?
灰度發佈、金絲雀部署和藍綠部署是三種常見的軟件發佈策略,它們用於在系統升級時降低風險,確保在新版本上線過程中服務的穩定性和可控性
- 灰度發佈
灰度發佈是一種新進式的發佈方式,它通過將新版本逐步推送給部分用户進行試用,逐步擴大使用範圍,直到新版本完全替換舊版本,其目的是通過小範圍的用户測試,驗證新版本的穩定性,降低發佈新版本的風驗
實現方式:通常通過流量控制的方式,將一部分用户請求引導到新版本實例上。如果新版本表現正常,可以逐步增加新版本的用户羣體,直到全量用户使用新版本。
適用場景:適合在業務邏輯變動較大的場景中使用,通過灰度發佈可以發現新版本中的潛在問題,並在影響範圍較小的情況下進行回滾。
- 金絲雀部署
金絲雀部署(Ccanary Deployment)是一種特殊的灰度發佈策略,通常是指將新版本部署到少量的實例上,並僅將部分流量引導至這些實例,以驗證新版本在實際生產環境中的表現。
和灰度發佈的區別:金絲雀部署更強調在生產環境中逐步驗證新版本的表現,類似於讓“金絲雀”先進入礦井檢測安全性,一旦檢測到問題,可以快速回滾。
實現方式:可以通過負載均衡器或服務網格,將一定比例的流量引導到運行新版本的實例上。若新版本穩定,再逐步增加其流量佔比。
適用場景:適用於需要在生產環境中驗證新功能或配置變更的場景。通過金絲雀部署,可以提前發現新版本在生產環境中的潛在問題,降低對全量用户的影響,
- 藍綠部署
藍綠部署(Blue-Green Deployment)是一種無縫切換的部署策略,在這種模式下,生產環境中始終存在兩個版本:藍色版本(當前的生產版本)和綠色版本(新版本)。當綠色版本準備就緒時,通過負載均衡或路由切換,將所有流量從藍色版本切換到綠色版本。
特點:在藍綠部署中,舊版本(藍色版本)始終保持可用,可以在新版本(綠色版本)出現問題時,快速切換回舊版本,實現快速回滾。
實現方式:通常通過負載均衡器、DNS 切換或 API網關,來切換藍色版本和綠色版本之間的流量指向。
適用場景:適用於需要快速切換和回滾的場景,特別是在對系統穩定性要求較高的應用中,通過藍綠部署,可以實現無停機升級。