日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

RPC框架的可靠性设计

發(fā)布時間:2024/4/17 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RPC框架的可靠性设计 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 背景

1.1 分布式調用引入的故障

在傳統(tǒng)的單體架構中,業(yè)務服務調用都是本地方法調用,不會涉及到網絡通信、協議棧、消息序列化和反序列化等,當使用RPC框架將業(yè)務由單體架構改造成分布式系統(tǒng)之后,本地方法調用將演變成跨進程的遠程調用,會引入一些新的故障點,如下所示:

圖1 RPC調用引入的潛在故障點

新引入的潛在故障點包括:

1.消息的序列化和反序列化故障,例如,不支持的數據類型。

2.路由故障:包括服務的訂閱、發(fā)布故障,服務實例故障之后沒有及時刷新路由表,導致RPC調用仍然路由到故障節(jié)點。

3.網絡通信故障,包括網絡閃斷、網絡單通、丟包、客戶端浪涌接入等。

1.2 第三方服務依賴

RPC服務通常會依賴第三方服務,包括數據庫服務、文件存儲服務、緩存服務、消息隊列服務等,這種第三方依賴同時也引入了潛在的故障:

1.網絡通信類故障,如果采用BIO調用第三方服務,很有可能被阻塞。

2.“雪崩效用”導致的級聯故障,例如服務端處理慢導致客戶端線程被阻塞。

3.第三方不可用導致RPC調用失敗。

典型的第三方依賴示例如下:

圖2 RPC服務端的第三方依賴

2. 通信層的可靠性設計

2.1 鏈路有效性檢測

當網絡發(fā)生單通、連接被防火墻Hang住、長時間GC或者通信線程發(fā)生非預期異常時,會導致鏈路不可用且不易被及時發(fā)現。特別是異常發(fā)生在凌晨業(yè)務低谷期間,當早晨業(yè)務高峰期到來時,由于鏈路不可用會導致瞬間的大批量業(yè)務失敗或者超時,這將對系統(tǒng)的可靠性產生重大的威脅。

從技術層面看,要解決鏈路的可靠性問題,必須周期性的對鏈路進行有效性檢測。目前最流行和通用的做法就是心跳檢測。

心跳檢測機制分為三個層面:

1.TCP層面的心跳檢測,即TCP的Keep-Alive機制,它的作用域是整個TCP協議棧。

2.協議層的心跳檢測,主要存在于長連接協議中。例如MQTT協議。

3.應用層的心跳檢測,它主要由各業(yè)務產品通過約定方式定時給對方發(fā)送心跳消息實現。

心跳檢測的目的就是確認當前鏈路可用,對方活著并且能夠正常接收和發(fā)送消息。做為高可靠的NIO框架,Netty也提供了心跳檢測機制,下面我們一起熟悉下心跳的檢測原理。

心跳檢測的原理示意圖如下:

圖3 鏈路心跳檢測

不同的協議,心跳檢測機制也存在差異,歸納起來主要分為兩類:

1.Ping-Pong型心跳:由通信一方定時發(fā)送Ping消息,對方接收到Ping消息之后,立即返回Pong應答消息給對方,屬于請求-響應型心跳。

2.Ping-Ping型心跳:不區(qū)分心跳請求和應答,由通信雙方按照約定定時向對方發(fā)送心跳Ping消息,它屬于雙向心跳。

心跳檢測策略如下:

1.連續(xù)N次心跳檢測都沒有收到對方的Pong應答消息或者Ping請求消息,則認為鏈路已經發(fā)生邏輯失效,這被稱作心跳超時。

2.讀取和發(fā)送心跳消息的時候如何直接發(fā)生了IO異常,說明鏈路已經失效,這被稱為心跳失敗。

無論發(fā)生心跳超時還是心跳失敗,都需要關閉鏈路,由客戶端發(fā)起重連操作,保證鏈路能夠恢復正常。

Netty的心跳檢測實際上是利用了鏈路空閑檢測機制實現的,它的空閑檢測機制分為三種:

1.讀空閑,鏈路持續(xù)時間t沒有讀取到任何消息。

2.寫空閑,鏈路持續(xù)時間t沒有發(fā)送任何消息。

3.讀寫空閑,鏈路持續(xù)時間t沒有接收或者發(fā)送任何消息。

Netty的默認讀寫空閑機制是發(fā)生超時異常,關閉連接,但是,我們可以定制它的超時實現機制,以便支持不同的用戶場景,鏈路空閑接口定義如下:

protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception { ctx.fireUserEventTriggered(evt); }

鏈路空閑的時候并沒有關閉鏈路,而是觸發(fā)IdleStateEvent事件,用戶訂閱IdleStateEvent事件,用于自定義邏輯處理,例如關閉鏈路、客戶端發(fā)起重新連接、告警和打印日志等。利用Netty提供的鏈路空閑檢測機制,可以非常靈活的實現鏈路空閑時的有效性檢測。

2.2 客戶端斷連重連

當發(fā)生如下異常時,客戶端需要釋放資源,重新發(fā)起連接:

1.服務端因為某種原因,主動關閉連接,客戶端檢測到鏈路被正常關閉。

2.服務端因為宕機等故障,強制關閉連接,客戶端檢測到鏈路被Rest掉。

3.心跳檢測超時,客戶端主動關閉連接。

4.客戶端因為其它原因(例如解碼失敗),強制關閉連接。

5.網絡類故障,例如網絡丟包、超時、單通等,導致鏈路中斷。

客戶端檢測到鏈路中斷后,等待INTERVAL時間,由客戶端發(fā)起重連操作,如果重連失敗,間隔周期INTERVAL后再次發(fā)起重連,直到重連成功。

為了保證服務端能夠有充足的時間釋放句柄資源,在首次斷連時客戶端需要等待INTERVAL時間之后再發(fā)起重連,而不是失敗后就立即重連。

為了保證句柄資源能夠及時釋放,無論什么場景下的重連失敗,客戶端都必須保證自身的資源被及時釋放,包括但不限于SocketChannel、Socket等。重連失敗后,需要打印異常堆棧信息,方便后續(xù)的問題定位。

利用Netty Channel提供的CloseFuture,可以非常方便的檢測鏈路狀態(tài),一旦鏈路關閉,相關事件即被觸發(fā),可以重新發(fā)起連接操作,代碼示例如下:

future.channel().closeFuture().sync(); } finally { // 所有資源釋放完成之后,清空資源,再次發(fā)起重連操作 executor.execute(new Runnable() { public void run() { try { TimeUnit.SECONDS.sleep(3);//3秒之后發(fā)起重連,等待句柄釋放 try { // 發(fā)起重連操作 connect(NettyConstant.PORT, NettyConstant.REMOTEIP); } catch (Exception e) { ......異常處理相關代碼省略 } });

2.3 緩存重發(fā)

當我們調用消息發(fā)送接口的時候,消息并沒有真正被寫入到Socket中,而是先放入NIO通信框架的消息發(fā)送隊列中,由Reactor線程掃描待發(fā)送的消息隊列,異步的發(fā)送給通信對端。假如很不幸,消息隊列中積壓了部分消息,此時鏈路中斷,這會導致部分消息并沒有真正發(fā)送給通信對端,示例如下:

圖4 鏈路中斷導致積壓消息沒有發(fā)送

發(fā)生此故障時,我們希望NIO框架能夠自動實現消息緩存和重新發(fā)送,遺憾的是作為基礎的NIO通信框架,無論是Mina還是Netty,都沒有提供該功能,需要通信框架自己封裝實現,基于Netty的實現策略如下:

1.調用Netty ChannelHandlerContext的write方法時,返回ChannelFuture對象,我們在ChannelFuture中注冊發(fā)送結果監(jiān)聽Listener。

2.在Listener的operationComplete方法中判斷操作結果,如果操作不成功,將之前發(fā)送的消息對象添加到重發(fā)隊列中。

3.鏈路重連成功之后,根據策略,將緩存隊列中的消息重新發(fā)送給通信對端。

需要指出的是,并非所有場景都需要通信框架做重發(fā),例如服務框架的客戶端,如果某個服務提供者不可用,會自動切換到下一個可用的服務提供者之上。假定是鏈路中斷導致的服務提供者不可用,即便鏈路重新恢復,也沒有必要將之前積壓的消息重新發(fā)送,因為消息已經通過FailOver機制切換到另一個服務提供者處理。所以,消息緩存重發(fā)只是一種策略,通信框架應該支持鏈路級重發(fā)策略。

2.4 客戶端超時保護

在傳統(tǒng)的同步阻塞編程模式下,客戶端Socket發(fā)起網絡連接,往往需要指定連接超時時間,這樣做的目的主要有兩個:

1.在同步阻塞I/O模型中,連接操作是同步阻塞的,如果不設置超時時間,客戶端I/O線程可能會被長時間阻塞,這會導致系統(tǒng)可用I/O線程數的減少。

2.業(yè)務層需要:大多數系統(tǒng)都會對業(yè)務流程執(zhí)行時間有限制,例如WEB交互類的響應時間要小于3S。客戶端設置連接超時時間是為了實現業(yè)務層的超時。

對于NIO的SocketChannel,在非阻塞模式下,它會直接返回連接結果,如果沒有連接成功,也沒有發(fā)生I/O異常,則需要將SocketChannel注冊到Selector上監(jiān)聽連接結果。所以,異步連接的超時無法在API層面直接設置,而是需要通過用戶自定義定時器來主動監(jiān)測。

Netty在創(chuàng)建NIO客戶端時,支持設置連接超時參數。Netty的客戶端連接超時參數與其它常用的TCP參數一起配置,使用起來非常方便,上層用戶不用關心底層的超時實現機制。這既滿足了用戶的個性化需求,又實現了故障的分層隔離。

2.5 針對客戶端的并發(fā)連接數流控

以Netty的HTTPS服務端為例,針對客戶端的并發(fā)連接數流控原理如下所示:

圖5 服務端HTTS連接數流控

基于Netty的Pipeline機制,可以對SSL握手成功、SSL連接關閉做切面攔截(類似于Spring的AOP機制,但是沒采用反射機制,性能更高),通過流控切面接口,對HTTPS連接做計數,根據計數器做流控,服務端的流控算法如下:

1.獲取流控閾值。

2.從全局上下文中獲取當前的并發(fā)連接數,與流控閾值對比,如果小于流控閾值,則對當前的計數器做原子自增,允許客戶端連接接入。

3.如果等于或者大于流控閾值,則拋出流控異常給客戶端。

4.SSL連接關閉時,獲取上下文中的并發(fā)連接數,做原子自減。

在實現服務端流控時,需要注意如下幾點:

1.流控的ChannelHandler聲明為@ChannelHandler.Sharable,這樣全局創(chuàng)建一個流控實例,就可以在所有的SSL連接中共享。

2.通過userEventTriggered方法攔截SslHandshakeCompletionEvent和SslCloseCompletionEvent事件,在SSL握手成功和SSL連接關閉時更新流控計數器。

3.流控并不是單針對ESTABLISHED狀態(tài)的HTTP連接,而是針對所有狀態(tài)的連接,因為客戶端關閉連接,并不意味著服務端也同時關閉了連接,只有SslCloseCompletionEvent事件觸發(fā)時,服務端才真正的關閉了NioSocketChannel,GC才會回收連接關聯的內存。

4.流控ChannelHandler會被多個NioEventLoop線程調用,因此對于相關的計數器更新等操作,要保證并發(fā)安全性,避免使用全局鎖,可以通過原子類等提升性能。

2.6 內存保護

NIO通信的內存保護主要集中在如下幾點:

1.鏈路總數的控制:每條鏈路都包含接收和發(fā)送緩沖區(qū),鏈路個數太多容易導致內存溢出。

2.單個緩沖區(qū)的上限控制:防止非法長度或者消息過大導致內存溢出。

3.緩沖區(qū)內存釋放:防止因為緩沖區(qū)使用不當導致的內存泄露。

4.NIO消息發(fā)送隊列的長度上限控制。

當我們對消息進行解碼的時候,需要創(chuàng)建緩沖區(qū)。緩沖區(qū)的創(chuàng)建方式通常有兩種:

1.容量預分配,在實際讀寫過程中如果不夠再擴展。

2.根據協議消息長度創(chuàng)建緩沖區(qū)。

在實際的商用環(huán)境中,如果遇到畸形碼流攻擊、協議消息編碼異常、消息丟包等問題時,可能會解析到一個超長的長度字段。筆者曾經遇到過類似問題,報文長度字段值竟然是2G多,由于代碼的一個分支沒有對長度上限做有效保護,結果導致內存溢出。系統(tǒng)重啟后幾秒內再次內存溢出,幸好及時定位出問題根因,險些釀成嚴重的事故。

Netty提供了編解碼框架,因此對于解碼緩沖區(qū)的上限保護就顯得非常重要。下面,我們看下Netty是如何對緩沖區(qū)進行上限保護的:

首先,在內存分配的時候指定緩沖區(qū)長度上限:

/** * Allocate a {@link ByteBuf} with the given initial capacity and the given * maximal capacity. If it is a direct or heap buffer depends on the actual * implementation. */ ByteBuf buffer(int initialCapacity, int maxCapacity);

其次,在對緩沖區(qū)進行寫入操作的時候,如果緩沖區(qū)容量不足需要擴展,首先對最大容量進行判斷,如果擴展后的容量超過上限,則拒絕擴展:

@Override public ByteBuf capacity(int newCapacity) { ensureAccessible(); if (newCapacity \u0026lt; 0 || newCapacity \u0026gt; maxCapacity()) { throw new IllegalArgumentException(\u0026quot;newCapacity: \u0026quot; + newCapacity); }

在消息解碼的時候,對消息長度進行判斷,如果超過最大容量上限,則拋出解碼異常,拒絕分配內存,以LengthFieldBasedFrameDecoder的decode方法為例進行說明:

if (frameLength \u0026gt; maxFrameLength) { long discard = frameLength - in.readableBytes(); tooLongFrameLength = frameLength; if (discard \u0026lt; 0) { in.skipBytes((int) frameLength); } else { discardingTooLongFrame = true; bytesToDiscard = discard; in.skipBytes(in.readableBytes()); } failIfNecessary(true); return null; }

3. RPC調用層的可靠性設計

3.1 RPC調用異常場景

RPC調用過程中除了通信層的異常,通常也會遇到如下幾種故障:

  • 服務路由失敗。

  • 服務端超時。

  • 服務端調用失敗。

RPC框架需要能夠針對上述常見的異常做容錯處理,以提升業(yè)務調用的可靠性。

3.1.1 服務路由失敗

RPC客戶端通常會基于訂閱/發(fā)布的機制獲取服務端的地址列表,并將其緩存到本地,RPC調用時,根據負載均衡策略從本地緩存的路由表中獲取到一個唯一的服務端節(jié)點發(fā)起調用,原理如下所示:

圖6 基于訂閱發(fā)布機制的RPC調用

通過緩存的機制能夠提升RPC調用的性能,RPC客戶端不需要每次調用都向注冊中心查詢目標服務的地址信息,但是也可能會發(fā)生如下兩類潛在故障:

1.某個RPC服務端發(fā)生故障,或者下線,客戶端沒有及時刷新本地緩存的服務地址列表,就會導致RPC調用失敗。

2.RPC客戶端和服務端都工作正常,但是RPC客戶端和服務端的連接或者網絡發(fā)生了故障,如果沒有鏈路的可靠性檢測機制,就會導致RPC調用失敗。

3.1.2 服務端超時

當服務端無法在指定的時間內返回應答給客戶端,就會發(fā)生超時,導致超時的原因主要有:

1.服務端的I/O線程沒有及時從網絡中讀取客戶端請求消息,導致該問題的原因通常是I/O線程被意外阻塞或者執(zhí)行長周期操作。

2.服務端業(yè)務處理緩慢,或者被長時間阻塞,例如查詢數據庫,由于沒有索引導致全表查詢,耗時較長。

3.服務端發(fā)生長時間Full GC,導致所有業(yè)務線程暫停運行,無法及時返回應答給客戶端。

3.1.3 服務端調用失敗

有時會發(fā)生服務端調用失敗,導致服務端調用失敗的原因主要有如下幾種:

1.服務端解碼失敗,會返回消息解碼失敗異常。

2.服務端發(fā)生動態(tài)流控,返回流控異常。

3.服務端消息隊列積壓率超過最大閾值,返回系統(tǒng)擁塞異常。

4.訪問權限校驗失敗,返回權限相關異常。

5.違反SLA策略,返回SLA控制相關異常。

6.其他系統(tǒng)異常。

需要指出的是,服務調用異常不包括業(yè)務層面的處理異常,例如數據庫操作異常、用戶記錄不存在異常等。

3.2 RPC調用可靠性方案

3.2.1注冊中心與鏈路檢測雙保險機制

因為注冊中心有集群內所有RPC客戶端和服務端的實例信息,因此通過注冊中心向每個服務端和客戶端發(fā)送心跳消息,檢測對方是否在線,如果連續(xù)N次心跳超時,或者心跳發(fā)送失敗,則判斷對方已經發(fā)生故障或者下線(下線可以通過優(yōu)雅停機的方式主動告知注冊中心,實時性會更好)。注冊中心將故障節(jié)點的服務實例信息通過心跳消息發(fā)送給客戶端,由客戶端將故障的服務實例信息從本地緩存的路由表中刪除,后續(xù)消息調用不再路由到該節(jié)點。

在一些特殊場景下,盡管注冊中心與服務端、客戶端的連接都沒有問題,但是服務端和客戶端之間的鏈路發(fā)生了異常,由于發(fā)生鏈路異常的服務端仍然在緩存表中,因此消息還會繼續(xù)調度到故障節(jié)點上,所以,利用RPC客戶端和服務端之間的雙向心跳檢測,可以及時發(fā)現雙方之間的鏈路問題,利用重連等機制可以快速的恢復連接,如果重連N次都失敗,則服務路由時不再將消息發(fā)送到連接故障的服務節(jié)點上。

利用注冊中心對服務端的心跳檢測和通知機制、以及服務端和客戶端針對鏈路層的雙向心跳檢測機制,可以有效檢測出故障節(jié)點,提升RPC調用的可靠性,它的原理如下所示:

圖7 注冊中心與鏈路雙向心跳檢測機制原理

3.2.2 集群容錯策略

常用的集群容錯策略包括:

1.失敗自動切換(Failover)。

2.失敗通知(Failback)。

3.失敗緩存(Failcache)。

4.快速失敗(Failfast)。

失敗自動切換策略:服務調用失敗自動切換策略指的是當發(fā)生RPC調用異常時,重新選路,查找下一個可用的服務提供者。

服務發(fā)布的時候,可以指定服務的集群容錯策略。消費者可以覆蓋服務提供者的通用配置,實現個性化的容錯策略。

Failover策略的設計思路如下:消費者路由操作完成之后,獲得目標地址,調用通信框架的消息發(fā)送接口發(fā)送請求,監(jiān)聽服務端應答。如果返回的結果是RPC調用異常(超時、流控、解碼失敗等系統(tǒng)異常),根據消費者集群容錯的策略進行容錯路由,如果是Failover,則重新返回到路由Handler的入口,從路由節(jié)點繼續(xù)執(zhí)行。選路完成之后,對目標地址進行比對,防止重新路由到故障服務節(jié)點,過濾掉上次的故障服務提供者之后,調用通信框架的消息發(fā)送接口發(fā)送請求消息。

RPC框架提供Failover容錯策略,但是用戶在使用時需要自己保證用對地方,下面對Failover策略的應用場景進行總結:

1.讀操作,因為通常它是冪等的。

2.冪等性服務,保證調用1次與N次效果相同。

需要特別指出的是,失敗重試會增加服務調用時延,因此框架必須對失敗重試的最大次數做限制,通常默認為3,防止無限制重試導致服務調用時延不可控。

失敗通知(Failback):在很多業(yè)務場景中,客戶端需要能夠獲取到服務調用失敗的具體信息,通過對失敗錯誤碼等異常信息的判斷,決定后續(xù)的執(zhí)行策略,例如非冪等性的服務調用。

Failback的設計方案如下:RPC框架獲取到服務提供者返回的RPC異常響應之后,根據策略進行容錯。如果是Failback模式,則不再重試其它服務提供者,而是將RPC異常通知給客戶端,由客戶端捕獲異常進行后續(xù)處理。

失敗緩存(Failcache):Failcache策略是失敗自動恢復的一種,在實際項目中它的應用場景如下:

1.服務有狀態(tài)路由,必須定點發(fā)送到指定的服務提供者。當發(fā)生鏈路中斷、流控等服務暫時不可用時,RPC框架將消息臨時緩存起來,等待周期T,重新發(fā)送,直到服務提供者能夠正常處理該消息。

2.對時延要求不敏感的服務。系統(tǒng)服務調用失敗,通常是鏈路暫時不可用、服務流控、GC掛住服務提供者進程等,這種失敗不是永久性的失敗,它的恢復是可預期的。如果客戶端對服務調用時延不敏感,可以考慮采用自動恢復模式,即先緩存,再等待,最后重試。

3.通知類服務。例如通知粉絲積分增長、記錄接口日志等,對服務調用的實時性要求不高,可以容忍自動恢復帶來的時延增加。

為了保證可靠性,Failcache策略在設計的時候需要考慮如下幾個要素:

1.緩存時間、緩存對象上限數等需要做出限制,防止內存溢出。

2.緩存淘汰算法的選擇,是否支持用戶配置。

3.定時重試的周期T、重試的最大次數等需要做出限制并支持用戶指定。

4.重試達到最大上限仍失敗,需要丟棄消息,記錄異常日志。

快速失敗(Failfast):在業(yè)務高峰期,對于一些非核心的服務,希望只調用一次,失敗也不再重試,為重要的核心服務節(jié)約寶貴的運行資源。此時,快速失敗是個不錯的選擇。快速失敗策略的設計比較簡單,獲取到服務調用異常之后,直接忽略異常,記錄異常日志。

4. 第三方服務依賴故障隔離

4.1 總體策略

盡管很多第三方服務會提供SLA,但是RPC服務本身并不能完全依賴第三方服務自身的可靠性來保障自己的高可靠,第三方服務依賴隔離的總體策略如下:

1.第三方依賴隔離可以采用線程池 + 響應式編程(例如RxJava)的方式實現。

2.對第三方依賴進行分類,每種依賴對應一個獨立的線程/線程池。

3.服務不直接調用第三方依賴的API,而是使用異步封裝之后的API接口。

4.異步調用第三方依賴API之后,獲取Future對象。利用響應式編程框架,

可以訂閱后續(xù)的事件,接收響應,針對響應進行編程。

4.2 異步化

如果第三方服務提供的是標準的HTTP/Restful服務,則利用異步HTTP客戶端,例如Netty、Vert.x、異步RestTemplate等發(fā)起異步服務調用,這樣無論是服務端自身處理慢還是網絡慢,都不會導致調用方被阻塞。

如果對方是私有或者定制化的協議,SDK沒有提供異步接口,則需要采用線程池或者利用一些開源框架實現故障隔離。

異步化示例圖如下所示:

圖8 異步化原理示意圖

異步化的幾個關鍵技術點:

1.異步具有依賴和傳遞性,如果想在某個業(yè)務流程的某個過程中做異步化,則入口處就需要做異步。例如如果想把Redis服務調用改造成異步,則調用Redis服務之前的流程也需要同時做異步化,否則意義不大(除非調用方不需要返回值)。

2.通常而言,全棧異步對于業(yè)務性能和可靠性提升的意義更大,全棧異步會涉及到內部服務調用、第三方服務調用、數據庫、緩存等平臺中間件服務的調用,異步化改造成本比較高,但是收益也比較明顯。

3.不同框架、服務的異步編程模型盡量保持一致,例如統(tǒng)一采取RxJava風格的接口、或者JDK8的CompletableFuture。如果不同服務SDK的異步API接口風格差異過大,會增加業(yè)務的開發(fā)成本,也不利用線程模型的歸并和整合。

4.3.基于Hystrix的第三方依賴故障隔離

集成Netflix開源的Hystrix框架,可以非常方便的實現第三方服務依賴故障隔離,它提供的主要功能包括:

1.依賴隔離。

2.熔斷器。

3.優(yōu)雅降級。

4.Reactive編程。

5.信號量隔離。

建議的集成策略如下:

1.第三方依賴隔離:使用HystrixCommand做一層異步封裝,實現業(yè)務的RPC服務調用線程和第三方依賴的線程隔離。

2.依賴分類管理:對第三方依賴進行分類、分組管理,根據依賴的特點設置熔斷策略、優(yōu)雅降級策略、超時策略等,以實現差異化的處理。

總體集成視圖如下所示:

圖9 基于Hystrix的第三方故障隔離框架

基于Hystrix可以非常方便的實現第三方依賴服務的熔斷降級,它的工作原理如下:

1.熔斷判斷:服務調用時,對熔斷開關狀態(tài)進行判斷,當熔斷器開關關閉時, 請求被允許通過熔斷器。

2.熔斷執(zhí)行:當熔斷器開關打開時,服務調用請求被禁止通過,執(zhí)行失敗回調接口。

3.自動恢復:熔斷之后,周期T之后允許一條消息通過,如果成功,則取消熔斷狀態(tài),否則繼續(xù)處于熔斷狀態(tài)。

流程如下所示:

圖10 基于Hystrix的熔斷降級

5. 作者簡介

李林鋒,10年Java NIO、平臺中間件設計和開發(fā)經驗,精通Netty、Mina、分布式服務框架、API Gateway、PaaS等,《Netty進階之路》、《分布式服務框架原理與實踐》作者。目前在華為終端應用市場負責業(yè)務微服務化、云化、全球化等相關設計和開發(fā)工作。

聯系方式:新浪微博 Nettying 微信:Nettying

Email:neu_lilinfeng@sina.com

總結

以上是生活随笔為你收集整理的RPC框架的可靠性设计的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。