公司一般使用的分布式RPC框架及其原理面試
引言
以前在做一個規(guī)模不大的系統(tǒng)的時候,用的是單體架構(gòu),一臺服務器部署上一個應用和數(shù)據(jù)庫也就夠了。
但是現(xiàn)代化互聯(lián)網(wǎng)公司業(yè)務逐漸擴大,服務逐漸細分,很多服務之間需要通過遠程分布式接口調(diào)用通訊,即不同的服務不是部署在同一個服務器上,比如訂單服務在 A 服務上,付款服務在另一個服務上,有同步調(diào)用、也有異步調(diào)用,這個時候我們就需要遠程調(diào)用不同的服務,使用的時候調(diào)用遠程服務就像調(diào)用本地服務一樣,引入一個 jar 包,就能通過 this.xxx( ) 一樣調(diào)用遠程服務,這背后的機制就是通過 RPC 技術(shù)。
重點:RPC 技術(shù)一定是今后工作必備基礎,熟練掌握其中一種,知道原理,閱讀源碼,甚至自己手寫一個。
1、面試官:
公司使用什么 RPC 框架?,可以介紹一下 RPC 的工作原理嗎?
問題分析: 面試官想了解基礎設施是否和我們項目用的一樣,一樣最好了,能直接上手,不一樣了解其它一個別的應該也問題不大,畢竟原理技術(shù)都大同小異,說你最熟悉的一個。
答:RPC 是一個分布式計算的 CS 模式,總是由 Client 向 Server 發(fā)出一個執(zhí)行若干過程請求,Server 接受請求,使用者客戶端提供的參數(shù),計算完成之后將結(jié)果返回給客戶端。
使用最廣泛的 Spring Cloud,基于 Spring Boot 特性整合了開源行業(yè)中優(yōu)秀的組件,整體對外提供了一套在微服務架構(gòu)中服務治理的解決方案。
國內(nèi)開源的框架中,使用比較廣泛的有阿里的 Dubbo,后來捐獻給了 Apache。還有騰訊的 Tars 框架,還有 Thrift 框架,也有基于 Thrift 二次開發(fā)的 RPC 框架,比如美團的 Mtthrift。
這些 RPC 大致原理基本都是一樣的。(這個時候,跟面試官要紙和筆,畫圖解釋 RPC 原理)
這個圖既不顯得太過復雜給自己挖坑,也不會顯得簡單潦草。
1-5 逐行解釋:
- 服務集成 RPC 后,服務(這里的服務就是圖中的 Provider,服務提供者)啟動后會通過 Register(注冊)模塊,把服務的唯一 ID 和 IP 地址,端口信息等注冊到 RPC 框架注冊中心(圖中的 Registry 部分)。
- 當調(diào)用者(Consumer)想要調(diào)用服務的時候,通過 Provider 注冊時的的服務唯一 ID 去注冊中心查找在線可供調(diào)用的服務,返回一個 IP 列表(3.notify 部分)。
- 第三步 Consumer 根據(jù)一定的策略,比如隨機 or 輪訓從 Registry 返回的可用 IP 列表真正調(diào)用服務(4.invoke)。
- 最后是統(tǒng)計功能,RPC 框架都提供監(jiān)控功能,監(jiān)控服務健康狀況,控制服務線上擴展和上下線(5.count)
有清晰的流程圖,有每一步的解釋,面試官表示很滿意,繼續(xù)追加提問。
2、面試官:
服務啟動的時候服務基本信息被注冊到注冊中心,如果服務提供者掛了,注冊中心如何知道服務不可用了呢?
答:服務掉線分為主動下線和心跳檢測
比如服務由于發(fā)版時,在重啟之前先主動通知注冊中心:我要重啟了,有流量進來先不要分給我,讓別的機器服務,等我重啟成功后在放流量進來,或者是在管理后臺手動直接摘掉機器,這個是主動下線。
心跳檢測是處理服務非正常下線(如斷電斷網(wǎng))的情況,這個時候如果注冊中心不知道該服務已經(jīng)掉線,一旦被其調(diào)用就會帶來問題。為了避免出現(xiàn)這樣的情況,注冊中心增加一個心跳檢測功能,它會對服務提供者(Provider)進行心跳檢測,比如每隔 30s 發(fā)送一個心跳,如果三次心跳結(jié)果都沒有返回值,就認為該服務已下線,趕緊更新 Consumer 的服務列表,告訴 Consumer 調(diào)用別的機器。
問題分析: 闡述了服務端掛了注冊中心如何感知的問題,你以為此問題已經(jīng)完事兒了?還沒有,你成功給自己挖了個坑,面試官可能繼續(xù)深挖,服務提供者(Provider)掛了注冊中心能解決,那注冊中心自己就不掛了嗎?三連問繼續(xù)。
3、面試官:
如果注冊中心掛了,比如你用的是 Zookeeper,如果 Zookeeper 掛了,那服務之間還能相互調(diào)用嗎?
答:首先注冊中心掛掉也要分兩種情況,如果數(shù)據(jù)庫掛了,ZK 還是能用的,因為 ZK 會緩存注冊機列表在緩存里。
其次 ZK 本身就是一個集群的,一臺機器掛了,ZK 會選舉出集群中的其他機器作為 Master 繼續(xù)提供服務,如果整個集群都掛了也沒問題,因為調(diào)用者本地會緩存注冊中心獲取的服務列表。省略和注冊中心的交互,Consumer 和 Provider 采用直連方式,這些策略都是可配置的。
問題分析: 面試是一個自由交流時間,任何一個點都可能被發(fā)散繼續(xù)深入挖掘,刨根問題,總有你覆蓋不到的知識盲區(qū),目的不是為難你,是想了解你的技術(shù)沉淀深度。
4、面試官:
你對 RPC 了解的很透徹,那你能否自己寫一個 RPC 框架?可以簡答描述下思路也行。
答:這個問題,雖然沒有自己動手寫過,但是我閱讀過源碼,大致實現(xiàn)思路是這樣的。(畫圖給面試官)
- 客戶端 invoke 方法編寫,使用 JDK 的動態(tài)代理技術(shù),客戶端調(diào)用遠程服務方法時調(diào)用的是 InvocationHandler 的 invoke 方法。
- 客戶端 Filter 方法編寫,完善的 RPC 框架少不了監(jiān)控、路由、降級、鑒權(quán)等功能。
- 創(chuàng)建 Socket,在 Filter 方法中實現(xiàn) Client.write 方法,其邏輯為從連接池(ChannelPool)中獲取連接,然后將數(shù)據(jù)寫進 Channel。
- 實現(xiàn)數(shù)據(jù)序列化、壓縮,目的減少網(wǎng)絡傳輸?shù)臄?shù)據(jù)量,向服務端發(fā)送 request 數(shù)據(jù),這里可以使用 Netty 異步通訊框架。
- 服務端收到客戶端發(fā)過的消息后,從 Channel 中將消息讀出來之前,也會先經(jīng)反序列化解壓。
- 請求就到了服務端 Filter 中。請求依次經(jīng)過監(jiān)控、鑒權(quán)方法。
- 根據(jù)客戶端傳遞來的服務信息和參數(shù),通過反射調(diào)用相應的業(yè)務服務并拿到業(yè)務處理結(jié)果。然后在 ResponseFilter 中將返回結(jié)果寫入 Channel。
- 服務端序列化、壓縮等,發(fā)送給客戶端。
- 客戶端收到消息后,經(jīng)過客戶端反序列化、解壓縮,后交給 ResponseThreadPoolProcessor 線程池處理。
- ResponseThreadPoolProcessor 收到消息后,就將結(jié)果返回給之前的方法調(diào)用,整個調(diào)用請求就結(jié)束了。
面試官: 可以可以,確實是看了,這個問題就到這。(面試官心理:雖然目前項目里不會讓你真正去寫一個 RPC 框架,知其然知其所以然,遇到這類 RPC 相關(guān)問題一定能搞定了,項目組正好缺一個這樣的人)
深入分析
已經(jīng)有 http 協(xié)議接口,或者說 RestFul 接口,為什么還要使用 RPC 技術(shù)?
在接?不多的情況下,使用 http 確實是一個明智的選擇,比如在初創(chuàng)企業(yè),我們不確定業(yè)務能順利開展下去,可能面臨隨時倒閉,開發(fā)人員也不足,這個時候使用簡潔高效的技術(shù),先把東西做出來是最明智的選擇,無需一步登天。
系統(tǒng)與系統(tǒng)交互較少的情況下,使用 http 協(xié)議優(yōu)點顯而易見:開發(fā)簡單、測試也比較直接、部署方便,利用現(xiàn)成的 http 協(xié)議進行系統(tǒng)間通訊,如果業(yè)務真的慢慢做大,系統(tǒng)也慢慢擴大,RPC 框架的好處就顯示出來 了,?先 RPC 支持長鏈接,通信不必每次都要像 http 一樣去重復 3 次握?,減少了網(wǎng)絡開銷。
其次就是 RPC 框架一般都有注冊中心模塊,有完善的監(jiān)控管理功能,服務注冊發(fā)現(xiàn)、服務下線、服務動態(tài)擴展等都方便操作,服務化治理效率大大提高。
基于 TCP 協(xié)議實現(xiàn)的 RPC,能更靈活地對協(xié)議字段進行定制,相比 http 能減少網(wǎng)絡傳輸字節(jié)數(shù),降低網(wǎng)絡開銷(握手)提高性能。實現(xiàn)更大的吞吐量和并發(fā)數(shù),但是需要更多的關(guān)注底層復雜的細節(jié), 對開發(fā)人員的要求也高,增加開發(fā)成本。
總結(jié)
在面試官奪命三連問的攻擊下,前三個題目一定要掌握,最后一個加分項徒手寫 RPC 深入分析,可以大大拉升面試官對你的好感,只要有亮點,即使其他問題答得不好,那么問題也不大。
RPC 工作原理總結(jié):
Provider
:服務提供方,CS 模型中的 Server。
Consumer
: 調(diào)用遠程服務服務消費方,CS 模型中的 Client。
Registry
:服務注冊與發(fā)現(xiàn)的服務管理中心。
Monitor
:統(tǒng)計服務的調(diào)用次數(shù)和調(diào)用時間的監(jiān)控中心。
Container
:服務運行容器,如 jetty。
RPC 執(zhí)行過程總結(jié):
- 服務容器負責啟動,加載,運行服務提供者。
- 服務提供者在啟動時,向注冊中心注冊自己提供的服務,暴露自己的 IP 和端口信息。
- 服務消費者在啟動時,向注冊中心訂閱自己所需的服務。
- 注冊中心返回服務提供者列表給消費者,如果有變更,注冊中心將基于長連接推送給數(shù)據(jù)消費者。
- 服務消費者,從提供這地址列表中,基于軟負載均衡算法,選一臺提供者進行調(diào)用,如果調(diào)用失敗,再選另外一臺服務調(diào)用。
- 服務消費者和提供者,在內(nèi)存中累計調(diào)用次數(shù)和調(diào)用時間,定時發(fā)送一次統(tǒng)計數(shù)據(jù)到監(jiān)控中心。
以上就是公司一般使用的分布式RPC框架及其原理的詳細內(nèi)容,更多關(guān)于分布式RPC框架原理的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringCloud使用集中配置組件Config規(guī)避信息泄露
項目應用中,數(shù)據(jù)庫連接信息、Access-key、Secret-key等由于其及其敏感和特殊性,一旦泄露出去就很可能會使得應用遭到黑客攻擊,例如數(shù)據(jù)庫賬號密碼泄露可能導致“拖庫”,甚至數(shù)據(jù)丟失。此等事件偶有發(fā)生,那么,在分布式微服務項目中,怎么避免這種情況呢2022-07-07Java 使用POI生成帶聯(lián)動下拉框的excel表格實例代碼
本文通過實例代碼給大家分享Java 使用POI生成帶聯(lián)動下拉框的excel表格,代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2017-09-09