国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

建設(shè)一個(gè)大型網(wǎng)站大概費(fèi)用磁力王

建設(shè)一個(gè)大型網(wǎng)站大概費(fèi)用,磁力王,如何通過(guò)輕淘客做網(wǎng)站,b2c網(wǎng)上商城有哪些你好,我是何輝。今天我們來(lái)聊一聊Dubbo的大廠高頻面試題。 大廠面試,一般重點(diǎn)考察對(duì)技術(shù)理解的深度,和中小廠的區(qū)別在于,不僅要你精于實(shí)戰(zhàn),還要你深懂原理,勤于思考并針對(duì)功能進(jìn)行合理的設(shè)計(jì)。 網(wǎng)上一直流…

你好,我是何輝。今天我們來(lái)聊一聊Dubbo的大廠高頻面試題。

大廠面試,一般重點(diǎn)考察對(duì)技術(shù)理解的深度,和中小廠的區(qū)別在于,不僅要你精于實(shí)戰(zhàn),還要你深懂原理,勤于思考并針對(duì)功能進(jìn)行合理的設(shè)計(jì)。

網(wǎng)上一直流傳著“面試造火箭,工作擰螺絲”的大廠面試要求,其實(shí)原因也很簡(jiǎn)單,一來(lái)面試競(jìng)爭(zhēng)者多,需要設(shè)置門(mén)檻,二來(lái)是期望盡可能挑選出綜合素質(zhì)能力出眾的面試者,在對(duì)應(yīng)崗位上能把事情做精做細(xì),更加智能簡(jiǎn)單,最好每一次的功能迭代都是一次性的、穩(wěn)定的、高效的、靠譜的,沒(méi)有反反復(fù)復(fù)的 BUG 修改。

因?yàn)檫@樣無(wú)形中可以節(jié)省很多成本(修復(fù)BUG成本、溝通成本、人力成本、時(shí)間成本等等),簡(jiǎn)單來(lái)講,企業(yè)希望大家用最少的時(shí)間,干最多的活,而且一出手就是王炸級(jí)別的高可用、高可擴(kuò)展、高性能,穩(wěn)定靠譜地在產(chǎn)線運(yùn)行。

現(xiàn)在,你還會(huì)不會(huì)覺(jué)得大廠在面試環(huán)節(jié)故意問(wèn)各種底層原理來(lái)刁難你呢?其實(shí)面試官也犯不著為難你,只要你能力出眾,對(duì)于老江湖的伯樂(lè)面試官而言是可遇不可求的。但也不乏有點(diǎn)小心思的面試官,擔(dān)心強(qiáng)者會(huì)逐漸取代自己,不過(guò),如果你有技術(shù)、有思想、有能力,即便這一家沒(méi)面上,換一家就是了,天下之大,總有你的一席之地。

如果大廠在面試中問(wèn)到Dubbo,一般會(huì)問(wèn)框架的整體架構(gòu)、常用技術(shù)點(diǎn)背后的底層邏輯、生僻的底層技術(shù)點(diǎn),或者讓你談?wù)剬?duì)一些問(wèn)題的看法,總之,希望能從中看到你對(duì) Dubbo 框架的掌握程度,以此來(lái)評(píng)判你是否具有駕馭 Dubbo 框架的深厚功底。

如果遇到對(duì) Dubbo 特別精通的面試者,大概率會(huì)作為重要候選人,入司的話會(huì)考慮把一些核心的系統(tǒng)或功能,或偏底層的通用功能開(kāi)發(fā)交付,給這樣的人選來(lái)處理。

我也整理了常見(jiàn)的14個(gè)Dubbo大廠面試問(wèn)題,你可以先嘗試自己回答一下。

1.Dubbo 源碼分層模塊是怎樣的? 2.Dubbo 是如何掃描含有 @DubboService 這種注解的類(lèi)的? 3.Dubbo SPI 解決了 JDK SPI 的什么問(wèn)題? 4.簡(jiǎn)要描述下 Dubbo SPI 與 Spring SPI 的加載原理? 5.LinkedHashMap 可以設(shè)計(jì)成 LRU 么? 6.利用 Dubbo 框架怎么做分布式限流呢? 7.Wrapper 是怎么降低調(diào)用開(kāi)銷(xiāo)的? 8.使用 Javassist 編譯的有哪些關(guān)鍵要素環(huán)節(jié)? 9.使用 ASM 編譯有哪些基本步驟? 10.Dubbo 是怎么完成實(shí)例注入與切面攔截的? 11.服務(wù)發(fā)布的流程是怎樣的? 12.服務(wù)訂閱的流程是怎樣的? 13.消費(fèi)方調(diào)用流程是怎樣的? 14.你有研究過(guò) Dubbo 的協(xié)議幀格式么?

這些問(wèn)題,都是我們課程中講過(guò)的知識(shí)點(diǎn),所以你也可以考核一下自己的學(xué)習(xí)情況。我們來(lái)看看每個(gè)知識(shí)點(diǎn)你掌握得如何。

問(wèn)題一

  1. Dubbo 源碼分層模塊是怎樣的?

這個(gè)問(wèn)題是想對(duì) Dubbo 整體代碼分層結(jié)構(gòu)的熟悉程度,判斷你有沒(méi)有深入研究過(guò) Dubbo 框架體系,一般答到有 Config、Proxy、Cluster 層就差不多及格了,如果能至上而下縱向詳細(xì)說(shuō)出 Dubbo 的十個(gè)層次模塊,就更好了,會(huì)讓面試官刮目相看。

我們?cè)凇霸创a框架”中就通過(guò)一個(gè)簡(jiǎn)單的消費(fèi)方調(diào)用逐步分析過(guò) Dubbo 的十層模塊,如果不太記得,你可以復(fù)習(xí)鞏固一下。

主要分為三大塊,第一大塊是和business緊密相關(guān)的 Service 層,第二大塊是和RPC緊密相關(guān)的Config、Proxy、Registry、Cluster、Monitor和Protocol,剩下的第三大塊是和Remoting 緊密相關(guān)的Exchange、Transport、Serialize。

  • Service,與業(yè)務(wù)邏輯關(guān)聯(lián)緊密的一層稱(chēng)為服務(wù)層。
  • Config,專(zhuān)門(mén)存儲(chǔ)與讀取配置打交道的層次稱(chēng)為配置層。
  • Proxy,代理接口發(fā)起遠(yuǎn)程調(diào)用,或代理接收請(qǐng)求進(jìn)行實(shí)例分發(fā)處理的層次,稱(chēng)為服務(wù)代理層。
  • Registry,與注冊(cè)中心打交道的層次,稱(chēng)為注冊(cè)中心層。
  • Cluster,封裝多個(gè)提供者并承擔(dān)路由過(guò)濾和負(fù)載均衡的層次,稱(chēng)為路由層。
  • Monitor,同步調(diào)用結(jié)果的層次稱(chēng)為監(jiān)控層。
  • Protocol,封裝調(diào)用過(guò)程的層次稱(chēng)為遠(yuǎn)程調(diào)用層。
  • Exchange,封裝請(qǐng)求并根據(jù)同步異步模式獲取響應(yīng)結(jié)果的層次,稱(chēng)為信息交換層。
  • Transport,將數(shù)據(jù)通過(guò)網(wǎng)絡(luò)發(fā)送至對(duì)端服務(wù)的層次稱(chēng)為網(wǎng)絡(luò)傳輸層。
  • Serialize,把對(duì)象與二進(jìn)制進(jìn)行相互轉(zhuǎn)換的正反序列化的層次稱(chēng)為數(shù)據(jù)序列化層。

問(wèn)題二

  1. Dubbo 如何掃描含有 @DubboService 這種注解的類(lèi)?

這個(gè)問(wèn)題是想看你對(duì) Dubbo 掃描自定義注解的掌握程度,一般說(shuō)到“生成了代理”就基本沾邊及格了,如果能詳細(xì)說(shuō)出掃描器的源頭是利用了Spring掃描特性,就更好,因?yàn)槎诉@些原理,之后公司有需求,要你根據(jù)業(yè)務(wù)功能抽象插件,或者在系統(tǒng)中通過(guò)無(wú)侵入性進(jìn)行技術(shù)改造,對(duì)你來(lái)說(shuō)就是小菜一碟。

我們?cè)凇凹煽蚣堋敝蟹抡?Spring 類(lèi)掃描機(jī)制對(duì) integration 層代碼進(jìn)行改造時(shí),提到過(guò)這些。

Dubbo 利用了一個(gè) DubboClassPathBeanDefinitionScanner 類(lèi)繼承了 ClassPathBeanDefinitionScanner,充分利用 Spring 自身已有的擴(kuò)展特性來(lái)掃描自己需要關(guān)注的三個(gè)注解類(lèi),org.apache.dubbo.config.annotation.DubboService、org.apache.dubbo.config.annotation.Service、com.alibaba.dubbo.config.annotation.Service,然后完成 BeanDefinition 對(duì)象的創(chuàng)建。

在 BeanDefinition 對(duì)象的實(shí)例化完成后,在容器觸發(fā)刷新的事件過(guò)程中,通過(guò)回調(diào)了 ServiceConfig 的 export 方法完成了服務(wù)導(dǎo)出,即完成 Proxy 代理對(duì)象的創(chuàng)建,最后在運(yùn)行時(shí)就可以直接被拿來(lái)使用了。

問(wèn)題三

  1. Dubbo SPI 解決了 JDK SPI 的什么問(wèn)題?

這個(gè)問(wèn)題是想看你對(duì) Dubbo SPI 在算法性能層面的掌握,一般說(shuō)出“利用了緩存功能”就及格了,如果能說(shuō)出 JDK SPI 的不足,以及 Dubbo SPI 怎么解決不足,怎樣通過(guò)算法改善的,就更好了。能這么詳細(xì)地描述前后對(duì)比情況,說(shuō)明平常你在編寫(xiě)代碼時(shí),會(huì)主動(dòng)思考功能的性能優(yōu)化,這是一種難能可貴的自我思考意識(shí),比較受面試官的喜愛(ài)。

我們?cè)凇癝PI 機(jī)制”中通過(guò)運(yùn)行 JDK SPI 的程序,分析過(guò) JDK SPI 的不足問(wèn)題,也分析如何改善。

JDK SPI 使用一次,就會(huì)一次性實(shí)例化所有實(shí)現(xiàn)類(lèi)。為了彌補(bǔ)我們分析的 JDK SPI 的不足,Dubbo 也定義出了自己的一套 SPI 機(jī)制邏輯,既要通過(guò) O(1) 的時(shí)間復(fù)雜度來(lái)獲取指定的實(shí)例對(duì)象,還要控制緩存創(chuàng)建出來(lái)的對(duì)象,做到按需加載獲取指定實(shí)現(xiàn)類(lèi)。

Dubbo SPI 在實(shí)現(xiàn)的過(guò)程中,采用了兩種方式來(lái)優(yōu)化。

  • 方式一,增加緩存,來(lái)降低磁盤(pán)IO訪問(wèn)以及減少對(duì)象的生成。
  • 方式二,使用Map的hash查找,來(lái)提升檢索指定實(shí)現(xiàn)類(lèi)的性能。

通過(guò)兩種方式的優(yōu)化后,在面對(duì)大量高頻調(diào)用時(shí),JDK SPI 可能會(huì)出現(xiàn)磁盤(pán) IO 吞吐下降、大量對(duì)象產(chǎn)生和查詢(xún)指定實(shí)現(xiàn)類(lèi)的 O(n) 復(fù)雜度等問(wèn)題,而 Dubbo SPI 采用緩存+Map的組合方式更加友好地避免了這些情況,即使大量調(diào)用,也問(wèn)題不大。

問(wèn)題四

  1. 簡(jiǎn)要描述下 Dubbo SPI 與 Spring SPI 的加載原理?

在問(wèn)題三的基礎(chǔ)上,這是想繼續(xù)看你對(duì) Dubbo SPI 加載實(shí)現(xiàn)的底層原理的掌握程度,一般說(shuō)出“通過(guò)加載資源文件目錄的文件”就及格了,如果能詳細(xì)說(shuō)出有哪些資源目錄,然后根據(jù)自己的理解,說(shuō)明這些目錄一般存放什么類(lèi)型的 SPI 接口,就更好。

能充分說(shuō)明你不但知曉 Dubbo SPI 的優(yōu)勢(shì)點(diǎn),還能知道 Dubbo SPI 為了提供這樣的優(yōu)勢(shì),是如何完成底層實(shí)現(xiàn)的,并且還能橫向掌握 Spring SPI 的加載原理。足以說(shuō)明你不但對(duì) Dubbo SPI 有過(guò)研究,Spring SPI 這種高級(jí)特性的底層原理,也有過(guò)深入研究,那么針對(duì)工作中一些技術(shù)類(lèi)改造的需求,你應(yīng)該比較擅長(zhǎng)靈活擴(kuò)展。

我們?cè)凇癝PI 機(jī)制”的思考題答案中有講過(guò),如果不太記得,可以復(fù)習(xí)鞏固一下。

Dubbo SPI 的核心加載原理,就是加載了以下三個(gè)資源路徑下的文件內(nèi)容,資源分別為。

  • META-INF/dubbo/internal/
  • META-INF/dubbo/
  • META-INF/services/

我們自己設(shè)計(jì)的 SPI 接口,放到這 3 個(gè)資源路徑下都可以,不過(guò)從路徑的名稱(chēng)上可以看出,META-INF/dubbo/internal/ 存放的是 Dubbo 內(nèi)置的一些擴(kuò)展點(diǎn),META-INF/services/ 存放的是 Dubbo 自身的一些業(yè)務(wù)邏輯所需要的一些擴(kuò)展點(diǎn),而 META-INF/dubbo/ 存放的是上層業(yè)務(wù)系統(tǒng)自身的一些定制 Dubbo 的相關(guān)擴(kuò)展點(diǎn)。

而相比于 JDK 原生的SPI,Spring 中的 SPI 功能也很強(qiáng)大,主是通過(guò) org.springframework.core.io.support.SpringFactoriesLoader#loadFactories 方法讀取所有 jar 包的“META-INF/spring.factories”資源文件,并從文件中讀取一堆的類(lèi)似 EnableAutoConfiguration 標(biāo)識(shí)的類(lèi)路徑,把這些類(lèi)創(chuàng)建對(duì)應(yīng)的 Spring Bean 對(duì)象注入到容器中,就完成了 SpringBoot 的自動(dòng)裝配。

問(wèn)題五

  1. LinkedHashMap 可以設(shè)計(jì)成 LRU 么?

這個(gè)問(wèn)題是想看你對(duì) Map 工具類(lèi)的掌握程度,說(shuō)出通過(guò)自定義工具類(lèi)并內(nèi)部組合使用 Map,在 put 操作時(shí)進(jìn)行 LRU 功能設(shè)計(jì),在設(shè)計(jì)層面一般及格了。

如果能充分挖掘 Map 的底層特性,通過(guò)繼承 Map 并重寫(xiě) removeEldestEntry 方法來(lái)靈活擴(kuò)展為 LRU,并且還能說(shuō)出 Dubbo 框架在什么功能也對(duì)比進(jìn)行擴(kuò)展過(guò),就更好了,能充分說(shuō)明你對(duì) Map 工具類(lèi)的掌握非常深,對(duì) Map 的底層原理了解非常透徹,還能知道該特性在 Dubbo 框架中的應(yīng)用,難能可貴。

LinkedHashMap 可以設(shè)計(jì)成 LRU,在“緩存操作”那講中,我們跟蹤了一個(gè)所謂的 LRU2Cache 緩存類(lèi),它的底層實(shí)現(xiàn)原理就是繼承了 LinkedHashMap 的類(lèi),然后重寫(xiě)了父類(lèi) LinkedHashMap 中的 removeEldestEntry 方法,當(dāng) LRU2Cache 存儲(chǔ)的數(shù)據(jù)個(gè)數(shù)大于設(shè)置的容量后,會(huì)刪除最先存儲(chǔ)的數(shù)據(jù),讓最新的數(shù)據(jù)能夠保存進(jìn)來(lái)。

細(xì)節(jié)處的源碼跟蹤,我也展示在這里。

// LRU2Cache 的帶參構(gòu)造方法,在 LruCache 構(gòu)造方法中,默認(rèn)傳入的大小是 1000                  
org.apache.dubbo.common.utils.LRU2Cache#LRU2Cache(int)
public LRU2Cache(int maxCapacity) {super(16, DEFAULT_LOAD_FACTOR, true);this.maxCapacity = maxCapacity;this.preCache = new PreCache<>(maxCapacity);
}
// 若繼續(xù)放數(shù)據(jù)時(shí),若發(fā)現(xiàn)現(xiàn)有數(shù)據(jù)個(gè)數(shù)大于 maxCapacity 最大容量的話
// 則會(huì)考慮拋棄掉最古老的一個(gè),也就是會(huì)拋棄最早進(jìn)入緩存的那個(gè)對(duì)象
@Override
protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {return size() > maxCapacity;
}↓
// JDK 中的 LinkedHashMap 源碼在發(fā)生節(jié)點(diǎn)插入后
// 給了子類(lèi)一個(gè)擴(kuò)展刪除最舊數(shù)據(jù)的機(jī)制                   
java.util.LinkedHashMap#afterNodeInsertion
void afterNodeInsertion(boolean evict) { // possibly remove eldestLinkedHashMap.Entry<K,V> first;if (evict && (first = head) != null && removeEldestEntry(first)) {K key = first.key;removeNode(hash(key), key, null, false, true);}
}

問(wèn)題六

  1. 利用 Dubbo 框架怎么來(lái)做分布式限流呢?

這個(gè)問(wèn)題是想看你利用 Dubbo 過(guò)濾器的特性來(lái)處理分布式功能的掌握程度,一般答到 Filter、Redis 等關(guān)鍵詞就算是及格了,如果能總結(jié)出使用過(guò)濾器進(jìn)行限流改造的方法流程,就更好了,至少可以說(shuō)明你不但對(duì)過(guò)濾器十分了解,平時(shí)還注重方法流程的總結(jié),這些總結(jié)出來(lái)的方法流程,你應(yīng)該可以很好地平移到其他框架的學(xué)習(xí)上,快速上手新項(xiàng)目。

關(guān)鍵一點(diǎn)是需要利用 Dubbo 框架的過(guò)濾器特性,結(jié)合方法層面的參數(shù)設(shè)置,就可以很好的做到分布式限流的控制。具體可以參考“流量控制”的分布式限流方案改造。

這里也提煉下控制流量的三個(gè)關(guān)鍵環(huán)節(jié)。

  • 第一,尋找請(qǐng)求流經(jīng)的必經(jīng)之路,并在必經(jīng)之路上找到可擴(kuò)展的接口。
  • 第二,找到該接口的眾多實(shí)現(xiàn)類(lèi),研究在觸發(fā)調(diào)用的入口可以拿到哪些數(shù)據(jù),再研究關(guān)于方法的入?yún)?shù)據(jù)、方法本身信息以及方法歸屬類(lèi)的信息可以通過(guò)哪些 API 拿到。
  • 第三,根據(jù)限流的核心計(jì)算模塊,逐漸橫向擴(kuò)展,從單個(gè)方法到多個(gè)方法,從單個(gè)服務(wù)到多個(gè)服務(wù),從單個(gè)節(jié)點(diǎn)到集群節(jié)點(diǎn),盡可能周全地考慮通用處理方式,同時(shí)站在使用者的角度,做到簡(jiǎn)單易用的效果。

問(wèn)題七

  1. Wrapper 是怎么降低調(diào)用開(kāi)銷(xiāo)的?

這個(gè)問(wèn)題是想看你對(duì) Dubbo 底層處理調(diào)用時(shí)的性能開(kāi)銷(xiāo)掌握程度,一般能答到生成代理類(lèi)就沾邊了,如果能一針見(jiàn)血說(shuō)出 Wrapper 代理類(lèi),并且描述代理類(lèi)的執(zhí)行邏輯,那就更完美了。

能描述出代理類(lèi)的執(zhí)行邏輯,基本上都對(duì) Wrapper 機(jī)制有過(guò)深入研究,因?yàn)?Wrapper 代理類(lèi)是運(yùn)行時(shí)的對(duì)象,如果不刻意去斷點(diǎn)調(diào)試生成文件查看,是很難挖掘出 Wrapper 的核心內(nèi)幕的,所以,能把調(diào)用開(kāi)銷(xiāo)講明白的人,能迅速研究透各種底層框架的核心調(diào)用流程。

我們?cè)凇癢rapper 機(jī)制”中詳細(xì)講過(guò)。

首先得搞清楚,Wrapper 用在哪里了??匆欢未a,提供方是這么使用 Wrapper 來(lái)生成代理類(lèi)的。

// org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory#getInvoker
// 創(chuàng)建一個(gè) Invoker 的包裝類(lèi)
@Override
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {// 這里就是生成 Wrapper 代理對(duì)象的核心一行代碼final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);// 包裝一個(gè) Invoker 對(duì)象return new AbstractProxyInvoker<T>(proxy, type, url) {@Overrideprotected Object doInvoke(T proxy, String methodName,Class<?>[] parameterTypes,Object[] arguments) throws Throwable {// 使用 wrapper 代理對(duì)象調(diào)用自己的 invokeMethod 方法// 以此來(lái)避免反射調(diào)用引起的性能開(kāi)銷(xiāo)// 通過(guò)強(qiáng)轉(zhuǎn)來(lái)實(shí)現(xiàn)統(tǒng)一方法調(diào)用return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);}};
}

Wrapper 最終調(diào)用了 getWrapper 方法來(lái)生成一個(gè)代理類(lèi)。

  • 以源對(duì)象的類(lèi)屬性為維度,與生成的代理類(lèi)建立緩存映射關(guān)系,避免頻繁創(chuàng)建代理類(lèi)影響性能。
  • 生成了一個(gè)繼承 Wrapper 的動(dòng)態(tài)類(lèi),并且暴露了一個(gè)公有 invokeMethod 方法來(lái)調(diào)用源對(duì)象的方法。
  • 在invokeMethod 方法中,通過(guò)生成的 if...else 邏輯代碼來(lái)識(shí)別調(diào)用源對(duì)象的不同方法。

這里也總結(jié)一下原理細(xì)節(jié)的代碼流程。

總之,Wrapper 降低開(kāi)銷(xiāo)的主要有 2 個(gè)關(guān)鍵要素的原因。

  • 原因一,生成了代理類(lèi)緩存起來(lái),避免頻繁創(chuàng)建對(duì)象。
  • 原因二,代理類(lèi)中的邏輯,是通過(guò) if...else 的普通代碼進(jìn)行了強(qiáng)轉(zhuǎn)操作,轉(zhuǎn)為原始對(duì)象后繼續(xù)調(diào)用方法,而不是采用反射方式來(lái)調(diào)用方法的。

問(wèn)題八

  1. 使用 Javassist 編譯的有哪些關(guān)鍵要素環(huán)節(jié)?

這個(gè)問(wèn)題是想看你兩方面的知識(shí),一有沒(méi)有了解過(guò) Javassist,二有沒(méi)有研究過(guò)如何使用 Javassist 生成過(guò)代理對(duì)象,一般答出可以用 Javassist 生成代理對(duì)象就算是及格了,如果能詳細(xì)說(shuō)出使用 Javassist 來(lái)生成代理類(lèi)的流程步驟,說(shuō)明你確實(shí)有底層框架的開(kāi)發(fā)經(jīng)驗(yàn),具備比較深厚的抽象能力,是開(kāi)發(fā)底層功能的好苗子。

在“Compile 編譯”中,我們利用 Javassist 編寫(xiě)了實(shí)戰(zhàn)案例,也總結(jié)了方法流程。

  • 首先,設(shè)計(jì)一個(gè)代碼模板。
  • 然后,使用 Javassist 的相關(guān) API,通過(guò) ClassPool.makeClass 得到一個(gè)操控類(lèi)的 CtClass 對(duì)象,然后針對(duì) CtClass 進(jìn)行 addField 添加字段、addMethod 添加方法、addConstructor 添加構(gòu)造方法等等。
  • 最后,調(diào)用 CtClass.toClass 方法并編譯得到一個(gè)類(lèi)信息,有了類(lèi)信息,就可以實(shí)例化對(duì)象處理業(yè)務(wù)邏輯了。

問(wèn)題九

  1. 使用 ASM 編譯有哪些基本步驟?

在問(wèn)題八的基礎(chǔ)上,問(wèn)這個(gè)問(wèn)題是想再看看,你能否用更為底層的 ASM 進(jìn)行開(kāi)發(fā),大多數(shù)情況下,項(xiàng)目組很少有人會(huì)去深入研究這塊,一般能說(shuō)出可以利用非常底層的 ASM 進(jìn)行字節(jié)碼操作就算是不錯(cuò)的了,如果能詳細(xì)講出如何利用 ASM 來(lái)生成代理類(lèi),那非常厲害了。

我們?cè)凇癈ompile 編譯”中也花了大量篇幅學(xué)習(xí) ASM 的開(kāi)發(fā)步驟流程,如果不太記得,可以復(fù)習(xí)鞏固一下。

使用 ASM 編譯,流程操作和 Javassist 有點(diǎn)類(lèi)似。

  • 首先,還是設(shè)計(jì)一個(gè)代碼模板。
  • 其次,通過(guò) IDEA 的協(xié)助得到代碼模板的字節(jié)碼指令內(nèi)容。
  • 然后,使用 Asm 的相關(guān) API 依次將字節(jié)碼指令翻譯為 Asm 對(duì)應(yīng)的語(yǔ)法,比如創(chuàng)建 ClassWriter 相當(dāng)于創(chuàng)建了一個(gè)類(lèi),繼續(xù)調(diào)用 ClassWriter.visitMethod 方法相當(dāng)于創(chuàng)建了一個(gè)方法等等,對(duì)于生僻的字節(jié)碼指令實(shí)在找不到對(duì)應(yīng)的官方文檔的話,可以通過(guò)“MethodVisitor + 字節(jié)碼指令”來(lái)快速查找對(duì)應(yīng)的 Asm API。
  • 最后,調(diào)用 ClassWriter.toByteArray 得到字節(jié)碼的字節(jié)數(shù)組,傳遞到 ClassLoader.defineClass 交給 JVM 虛擬機(jī)得出一個(gè) Class 類(lèi)信息。

問(wèn)題十

  1. Dubbo 是怎么完成實(shí)例注入與切面攔截的?

這個(gè)問(wèn)題考察 Dubbo 框架中,實(shí)例對(duì)象創(chuàng)建過(guò)程中的擴(kuò)展機(jī)制。一般答到具有 setter 注入的特性原理就算是及格了,如果能更為詳細(xì)地描述前置、后置等擴(kuò)展機(jī)制,以及如何進(jìn)行構(gòu)造方法注入變?yōu)榘b對(duì)象等底層原理,就非常漂亮了。

如果你能把這種對(duì)象創(chuàng)建過(guò)程的原理弄得非常透徹,其他框架的對(duì)象創(chuàng)建過(guò)程都是類(lèi)似的,研究起來(lái)就會(huì)輕而易舉。我們?cè)凇皩?shí)例注入”中詳細(xì)跟蹤了源碼。

Dubbo 完成實(shí)例注入,主要是當(dāng) ExtensionLoader 的 getExtension 方法被調(diào)用時(shí),才會(huì)酌情考慮是取緩存對(duì)象,還是直接創(chuàng)建對(duì)象并進(jìn)行實(shí)例注入。

直接創(chuàng)建對(duì)象的過(guò)程,主要是通過(guò)反射創(chuàng)建出來(lái)一個(gè)嬰兒對(duì)象,然后經(jīng)歷前置初始化前置處理(postProcessBeforeInitialization)、注入擴(kuò)展點(diǎn)(injectExtension)、初始化后置處理(postProcessAfterInitialization)三個(gè)階段,經(jīng)過(guò)三段處理的對(duì)象,我們暫且稱(chēng)為“原始對(duì)象”。

然后,這個(gè)原始對(duì)象,會(huì)根據(jù) getExtension 傳入的 wrap 變量,決定是否需要將原始對(duì)象再次進(jìn)行包裹處理,若需要包裹,會(huì)將該 SPI 接口的所有包裝類(lèi)排序好,以套娃的形式,將原始對(duì)象層層包裹。而包裝類(lèi)上可以設(shè)置 @Wrapper 注解,結(jié)合注解,有 3 種情況決定是否需要包裝。

  • 無(wú) @Wrapper 注解,則需要包裝。
  • 有 @Wrapper 注解,但是注解中的 matches 字段值為空,則需要包裝。
  • 有 @Wrapper 注解,但是注解中的 matches 字段值包含入?yún)⒌臄U(kuò)展點(diǎn)名稱(chēng),并且 mismatches 字段值不包含入?yún)⒌臄U(kuò)展點(diǎn)名稱(chēng),則需要包裝。

不過(guò)重點(diǎn)要關(guān)注 injectExtension 方法,該方法中會(huì)從根據(jù)對(duì)象的 setter 方法獲取擴(kuò)展點(diǎn)名稱(chēng),然后直接從容器中找到對(duì)應(yīng)的實(shí)例,完成實(shí)例注入。

總而言之,創(chuàng)建擴(kuò)展點(diǎn)對(duì)象的時(shí)候,不但會(huì)通過(guò) setter 方法進(jìn)行實(shí)例注入,而且還會(huì)通過(guò)包裝類(lèi)層層包裹,就像這樣:

問(wèn)題十一

  1. 服務(wù)發(fā)布的流程是怎樣的?

這個(gè)問(wèn)題考察你平常編寫(xiě)提供方服務(wù)時(shí),對(duì)提供服務(wù)能力流程的掌握,一般能提到服務(wù)導(dǎo)出開(kāi)啟了Netty服務(wù)就算是及格了,如果能從所使用的注解開(kāi)始,劃分流程步驟分別講解,那樣就更好,因?yàn)槟隳馨逊?wù)發(fā)布流程研究得非常透徹,說(shuō)明你對(duì) Dubbo 怎么提供服務(wù)能力的體系流程比較關(guān)注,想必在日常開(kāi)發(fā)編碼時(shí),對(duì)整個(gè)需求實(shí)現(xiàn)的流程體系把控也不會(huì)差。

在“發(fā)布流程”中,我們針對(duì)提供方的架構(gòu)示意圖,展開(kāi)了詳細(xì)的源碼分析。

服務(wù)發(fā)布的流程,主要可以從配置、導(dǎo)出、注冊(cè)三方面描述。

  • 配置流程,通過(guò)掃描指定包路徑下含有 @DubboService 注解的 Bean 定義,把掃描出來(lái)的 Bean 定義屬性,全部轉(zhuǎn)移至新創(chuàng)建的 ServiceBean 類(lèi)型的 Bean 定義中,為后續(xù)導(dǎo)出做準(zhǔn)備。
  • 導(dǎo)出流程,主要有兩塊,一塊是 injvm 協(xié)議的本地導(dǎo)出,一塊是暴露協(xié)議的遠(yuǎn)程導(dǎo)出,遠(yuǎn)程導(dǎo)出與本地導(dǎo)出有著實(shí)質(zhì)性的區(qū)別,遠(yuǎn)程導(dǎo)出會(huì)使用協(xié)議端口,通過(guò) Netty 綁定來(lái)提供端口服務(wù)。
  • 注冊(cè)流程,其實(shí)是遠(yuǎn)程導(dǎo)出的一個(gè)分支流程,會(huì)將提供方的服務(wù)接口信息,通過(guò) Curator 客戶(hù)端,寫(xiě)到 Zookeeper 注冊(cè)中心服務(wù)端去。

問(wèn)題十二

  1. 服務(wù)訂閱的流程是怎樣的?

在上一個(gè)問(wèn)題“提供方服務(wù)發(fā)布流程”的基礎(chǔ)上,再看看你對(duì)消費(fèi)方服務(wù)訂閱流程的掌握程度,一般能提到從注冊(cè)中心獲取提供方信息就算及格了,如果能詳細(xì)說(shuō)出具體的流程,并與服務(wù)發(fā)布建立流程對(duì)比,就更好了,起碼能說(shuō)明你是非常細(xì)心的,在提供方和消費(fèi)方之間發(fā)現(xiàn)了可對(duì)比的流程環(huán)節(jié),在對(duì)比中,發(fā)現(xiàn)問(wèn)題,研究問(wèn)題,這種學(xué)習(xí)方式是值得稱(chēng)贊的。

我們?cè)凇坝嗛喠鞒獭敝型ㄟ^(guò)與服務(wù)發(fā)布建立對(duì)比關(guān)系,邊猜測(cè)邊驗(yàn)證,進(jìn)行了詳細(xì)的流程分析。

相比于服務(wù)的發(fā)布流程,服務(wù)訂閱流程大體類(lèi)似,概括起來(lái)有 4 個(gè)步驟。

  • 首先,在程序上,往往會(huì)通過(guò) @DubboReference 注解來(lái)標(biāo)識(shí)需要訂閱哪些接口的服務(wù),并使用這些服務(wù)進(jìn)行調(diào)用。在源碼跟蹤上,可以通過(guò)該注解一路探索出背后的核心類(lèi) ReferenceConfig。
  • 緊接著,在ReferenceConfig 的 get 方法會(huì)先后進(jìn)行本地引用與遠(yuǎn)程引用的兩大主干流程。
  • 然后,在本地引用環(huán)節(jié)中使用的 invoker 對(duì)象是從 InjvmProtocol 中 exporterMap 獲取到的。而在遠(yuǎn)程引用環(huán)節(jié)中,創(chuàng)建 invoker 的核心邏輯是在 RegistryProtocol 的 doCreateInvoker 方法中完成的。
  • 最后,在這段 doCreateInvoker 邏輯中,還進(jìn)行了消費(fèi)者注冊(cè)和接口訂閱邏輯,訂閱邏輯的本質(zhì)就是啟動(dòng)環(huán)節(jié)從注冊(cè)中心拉取一遍接口的所有提供方信息,然后為這些接口添加監(jiān)聽(tīng)操作,以便在后續(xù)的環(huán)節(jié)中,提供方有任何變化,消費(fèi)方這邊也能通過(guò)監(jiān)聽(tīng)策略,及時(shí)感知到提供方節(jié)點(diǎn)的變化。

消費(fèi)方訂閱的整體流程,也給你總結(jié)了圖片。

問(wèn)題十三

  1. 消費(fèi)方調(diào)用流程是怎樣的?

在掌握服務(wù)發(fā)布、服務(wù)訂閱的基礎(chǔ)上,考核你對(duì)消費(fèi)方調(diào)用流程的掌握程度。

通過(guò)生成的 Proxy 代理,在 Cluster 集群擴(kuò)展器中,負(fù)載均衡通過(guò) Transport 層的 Netty 通信框架發(fā)送數(shù)據(jù),說(shuō)到這里就基本及格了,如果能像講述十層模塊一樣,自上而下說(shuō)出調(diào)用環(huán)節(jié)設(shè)計(jì)的層次模塊和關(guān)鍵核心方法或類(lèi),就更好了,可以說(shuō)明你平時(shí)非常注重底層原理流程的研究,是個(gè)不可多得的人才。

我們?cè)凇罢{(diào)用流程”中,從消費(fèi)方的簡(jiǎn)單調(diào)用代碼開(kāi)始,詳細(xì)分析了,如果不太記得,可以復(fù)習(xí)鞏固一下。

這里我就用一張圖總結(jié)。消費(fèi)方的調(diào)用流程,比較簡(jiǎn)單,只要順著消費(fèi)方代碼調(diào)用的地方,順著一路往下追蹤,就能抓出整個(gè)調(diào)用流程。

問(wèn)題十四

  1. 你有研究過(guò) Dubbo 的協(xié)議幀格式么?

這個(gè)問(wèn)題是想看你對(duì)數(shù)據(jù)收發(fā)底層協(xié)議格式的掌握程度,一般能提到“定長(zhǎng)+變長(zhǎng)的協(xié)議格式”就及格了,如果能詳細(xì)說(shuō)出 Dubbo 協(xié)議幀格式的細(xì)節(jié)字段,那就更好,說(shuō)明你在數(shù)據(jù)收發(fā)粘包、半包這塊了解深入,操控底層 Socket 進(jìn)行數(shù)據(jù)收發(fā)基本上沒(méi)什么問(wèn)題。

我們?cè)凇皡f(xié)議編解碼”中通過(guò)在 NettyCodecAdapter 中進(jìn)行了斷點(diǎn),詳細(xì)研究了編解碼代碼,如果不太記得,可以復(fù)習(xí)鞏固一下。

Dubbo 的協(xié)議幀本質(zhì)就是“定長(zhǎng) + 變長(zhǎng)”的整個(gè)報(bào)文格式。

  • magic high:魔術(shù)高位,占用 8 bit,也就是 1 byte。該值固定為 0xda,是一種標(biāo)識(shí)符。
  • magic low:魔術(shù)低位,占用 8 bit,也就是 1 byte。該值固定為 0xbb,也是一種標(biāo)識(shí)符。

魔術(shù)低位和魔術(shù)高位合并起來(lái)就是 0xdabb,代表著 dubbo 數(shù)據(jù)協(xié)議報(bào)文的開(kāi)始。如果從通信 socket 收到的報(bào)文不是以 0xdabb 開(kāi)始的,可以認(rèn)為是非法報(bào)文。

  • request flag and serialization id:請(qǐng)求類(lèi)型和序列化方式,占用 8 bit,也就是 1 byte。前面 4 bit 是請(qǐng)求類(lèi)型,后面 4 bit 是序列化方式,合起來(lái)用 1 個(gè) byte 來(lái)表示。

  • response status:響應(yīng)碼,占用 8 bit,也是 1 byte。因?yàn)橐呀?jīng)明確是響應(yīng)碼了,所以一個(gè)請(qǐng)求發(fā)送出去的時(shí)候,不用填充這個(gè)值,響應(yīng)回來(lái)的時(shí)候,這里就有值了。

  • 但是這個(gè)響應(yīng)碼,并不是那些真實(shí)業(yè)務(wù)數(shù)據(jù)功能的響應(yīng)碼,而是 Dubbo 通信層面的錯(cuò)誤碼*,比如通信響應(yīng)成功碼、消費(fèi)方超時(shí)碼、服務(wù)方超時(shí)碼、請(qǐng)求格式錯(cuò)誤碼等等,都是一些 Dubbo 框架自己易于通信識(shí)別錯(cuò)誤的碼,并非那些真正上層業(yè)務(wù)功能的錯(cuò)誤碼。

  • request id:請(qǐng)求唯一ID,占用 64 bit,也就是 8 byte。標(biāo)識(shí)請(qǐng)求的唯一性,用來(lái)證明你收到的響應(yīng),就是你曾經(jīng)發(fā)出去的請(qǐng)求返回來(lái)的數(shù)據(jù)。

  • body length:報(bào)文體長(zhǎng)度,占用 32 bit,也就是 4 byte。體現(xiàn)真正的業(yè)務(wù)報(bào)文數(shù)據(jù)到底有多長(zhǎng)。

因?yàn)檎鎸?shí)的業(yè)務(wù)數(shù)據(jù)有大有小,如果報(bào)文里不告知業(yè)務(wù)數(shù)據(jù)的長(zhǎng)度,服務(wù)方就不知道要讀取多長(zhǎng)的字節(jié),所以,就需要知道業(yè)務(wù)報(bào)文數(shù)據(jù)到底有多長(zhǎng)。當(dāng)客戶(hù)端發(fā)送數(shù)據(jù)時(shí),把要發(fā)送的業(yè)務(wù)數(shù)據(jù)報(bào)文計(jì)算一下長(zhǎng)度后,放到這個(gè)位置,服務(wù)方看到該長(zhǎng)度后,就會(huì)讀取指定長(zhǎng)度的字節(jié),讀完就結(jié)束,也就收到了一個(gè)完整的報(bào)文數(shù)據(jù)。

  • body content:報(bào)文體數(shù)據(jù),占用的 bit 未知,占用的 byte 字節(jié)個(gè)數(shù)也未知。這里是我們真正業(yè)務(wù)數(shù)據(jù)的內(nèi)容,至于真正的業(yè)務(wù)數(shù)據(jù)的長(zhǎng)度有多長(zhǎng),完全由報(bào)文體長(zhǎng)度決定。

Dubbo 的協(xié)議幀格式,整體不難,我們只需要按照上面的幀格式一步步構(gòu)建出這樣的字節(jié)數(shù)組出來(lái),然后利用 socket,write 出去就可以了。服務(wù)方在接收數(shù)據(jù)的時(shí)候,也是一樣,嚴(yán)格按照?qǐng)?bào)文格式進(jìn)行解析,不是 oxdabb 開(kāi)頭的就直接丟棄,是的話就繼續(xù)往后讀取,按照數(shù)據(jù)幀格式,直到讀完整個(gè)報(bào)文為止。

面試小技巧

這 14 個(gè)大廠常見(jiàn)的面試題,總的來(lái)說(shuō),都是比較偏底層的知識(shí)點(diǎn),你在完成日常需求開(kāi)發(fā)后,如果能再研究一下框架,提升自己駕馭框架的能力,回答這些問(wèn)題應(yīng)該比較輕松。

像這種偏底層面試問(wèn)題,切記,撿重要環(huán)節(jié)分步驟回答,千萬(wàn)不要想自己平常是怎么看源碼的,就憑記憶從上到下,一把梭哈講,這樣會(huì)讓面試官覺(jué)得你毫無(wú)主次,沒(méi)有邏輯概念。

針對(duì)這種底層原理分析類(lèi)的問(wèn)題,我給你個(gè)小建議:

  • 拿到問(wèn)題,先沉思幾秒,快速在腦海中回憶自己曾經(jīng)研究的整個(gè)過(guò)程。
  • 回答時(shí),把剛剛回憶的流程分為幾個(gè)步驟,一般不超過(guò)4步,太多反而會(huì)顯得啰嗦。
  • 針對(duì)每個(gè)步驟,撿關(guān)鍵的講,能體現(xiàn)源碼的關(guān)鍵類(lèi)也最好說(shuō)出來(lái),顯得你不但有過(guò)深入研究,還非常專(zhuān)業(yè)細(xì)致。
  • 回答后,記得談一下自己對(duì)這個(gè)問(wèn)題的看法,實(shí)在沒(méi)有啥看法不說(shuō)也行。 好,中小廠和大廠的高頻面試題和面試技巧,我們就都講完了。

期待你在技術(shù)這條道路上精益求精,既要精通技術(shù)實(shí)戰(zhàn),也要深懂底層原理,更要做思考的引領(lǐng)者,讓自己在技術(shù)路上越走越遠(yuǎn),越走越香。

文章來(lái)源:極客時(shí)間《Dubbo 源碼剖析與實(shí)戰(zhàn)》

http://m.aloenet.com.cn/news/32801.html

相關(guān)文章:

  • 主流門(mén)戶(hù)網(wǎng)站百度關(guān)鍵詞搜索推廣
  • 怎樣設(shè)計(jì)網(wǎng)頁(yè)教程關(guān)鍵詞優(yōu)化外包
  • 鄭州電力高等專(zhuān)科學(xué)校哪個(gè)專(zhuān)業(yè)好重慶seo和網(wǎng)絡(luò)推廣
  • 可視化網(wǎng)站制作軟件站長(zhǎng)之家ppt素材
  • 深圳html5網(wǎng)站建設(shè)搜索引擎營(yíng)銷(xiāo)sem
  • 遼寧網(wǎng)站推廣的目的網(wǎng)絡(luò)運(yùn)營(yíng)是做什么的工作
  • 做外國(guó)網(wǎng)站買(mǎi)域名推廣賺錢(qián)一個(gè)2元
  • 網(wǎng)站建設(shè)后期維護(hù)小魔仙網(wǎng)絡(luò)廣告宣傳平臺(tái)
  • 企業(yè)網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃方案范文免費(fèi)seo教程資源
  • wordpress 添加搜索引擎北京網(wǎng)絡(luò)seo
  • 三合一網(wǎng)站建設(shè)方案深圳市網(wǎng)絡(luò)營(yíng)銷(xiāo)推廣服務(wù)公司
  • b2b網(wǎng)站建設(shè)開(kāi)發(fā)china東莞seo
  • 網(wǎng)站的服務(wù)有哪些seo外鏈工具有用嗎
  • 南陽(yáng)網(wǎng)站建設(shè)大旗電商電商網(wǎng)站訂煙
  • wordpress投訴功能qq群怎么優(yōu)化排名靠前
  • 多媒體網(wǎng)站開(kāi)發(fā)實(shí)驗(yàn)報(bào)告做企業(yè)網(wǎng)站建設(shè)的公司
  • 網(wǎng)頁(yè)搜索工具新站seo優(yōu)化快速上排名
  • wordpress推廣升級(jí)vipseo做什么網(wǎng)站賺錢(qián)
  • 學(xué)網(wǎng)站建設(shè)怎么樣tool站長(zhǎng)工具
  • 網(wǎng)站的懲罰期要怎么做廣告安裝接單app
  • 國(guó)外設(shè)計(jì)網(wǎng)站dooor企業(yè)營(yíng)銷(xiāo)策劃書(shū)模板
  • 網(wǎng)站中qq跳轉(zhuǎn)怎么做的推廣公司經(jīng)營(yíng)范圍
  • 網(wǎng)站文化建設(shè)石家莊百度seo代理
  • 設(shè)計(jì)師論壇seo包年優(yōu)化
  • 做網(wǎng)站運(yùn)營(yíng)買(mǎi)什么電腦揚(yáng)州seo推廣
  • 銅仁建設(shè)集團(tuán)招聘信息網(wǎng)站seo快速優(yōu)化軟件網(wǎng)站
  • 做網(wǎng)站接項(xiàng)目seo網(wǎng)站是什么意思
  • 個(gè)人作品展示網(wǎng)站模板營(yíng)銷(xiāo)型網(wǎng)站策劃書(shū)
  • 做網(wǎng)站服務(wù)器在哪買(mǎi)微商引流人脈推廣軟件
  • 做一個(gè)網(wǎng)站維護(hù)多少錢(qián)快速排名新