性能提升是我們追求的一個(gè)目標(biāo),合理的設(shè)計(jì)和實(shí)現(xiàn)有助于應(yīng)對(duì)較多的復(fù)雜場(chǎng)景。有時(shí),可能一個(gè)小小的改動(dòng)點(diǎn)就能帶來(lái)意想不到的效果。在本文中,將簡(jiǎn)單的介紹下標(biāo)簽路由的優(yōu)化點(diǎn)。
標(biāo)簽路由
路由規(guī)則在發(fā)起一次RPC調(diào)用前起到過(guò)濾目標(biāo)服務(wù)器地址的作用,過(guò)濾后的地址列表,將作為消費(fèi)端最終發(fā)起RPC調(diào)用的備選地址。
Dubbo一般包含兩類路由機(jī)制:
- 條件路由。支持以服務(wù)或者
Consumer應(yīng)用為粒度配置路由規(guī)則。 - 標(biāo)簽路由。以
Provider應(yīng)用為粒度配置路由規(guī)則。
標(biāo)簽路由通過(guò)將某一個(gè)或者多個(gè)服務(wù)的提供者劃分到同一個(gè)分組,約束流量只在指定分組中流轉(zhuǎn),從而實(shí)現(xiàn)流量隔離的目的,從而實(shí)現(xiàn)流量隔離的目的,可以作為藍(lán)綠發(fā)布、灰度發(fā)布等場(chǎng)景的能力基礎(chǔ)。
在標(biāo)簽路由中,請(qǐng)求標(biāo)簽的作用域?yàn)槊恳淮蝘nvocation,使用attachment來(lái)傳遞請(qǐng)求標(biāo)簽,注意保存在attachment中的值將會(huì)在一次完整的遠(yuǎn)程調(diào)用中持續(xù)傳遞。
客戶端獲取invoker列表時(shí),需調(diào)用org.apache.dubbo.rpc.cluster.directory.AbstractDirectory#doList方法,本文選擇RegistryDirectory#doList的具體實(shí)現(xiàn)方法進(jìn)行解析。

其中紅線部分是根據(jù)路由機(jī)制過(guò)濾獲取invoker列表。

遍歷所有的路由規(guī)則進(jìn)行過(guò)濾,本文只分析其中的標(biāo)簽路由TagRouter。

在具體路由過(guò)濾時(shí),會(huì)根據(jù)設(shè)置的規(guī)則設(shè)置不同的過(guò)濾策略。
比如,在標(biāo)簽路由中首先會(huì)通過(guò)動(dòng)態(tài)標(biāo)簽過(guò)濾,根據(jù)標(biāo)簽獲取地址列表,然后根據(jù)地址列表匹配要需要的invokes。

最終都會(huì)調(diào)用filterInvoker方法執(zhí)行過(guò)濾規(guī)則。
這里涉及到了一個(gè)性能優(yōu)化點(diǎn)。
上述的紅色區(qū)域是后續(xù)新增的代碼,較早的代碼不包含上述紅色區(qū)域。
為什么后續(xù)又添加紅色區(qū)域代碼呢?
首先看下一位大佬提出的問(wèn)題。

之所以會(huì)這樣,是因?yàn)镃ollectors.toList()會(huì)創(chuàng)建一個(gè)新的List存儲(chǔ)過(guò)濾的結(jié)果。
如果根據(jù)過(guò)濾規(guī)則沒(méi)有過(guò)濾掉任何一個(gè)invoker,仍然和原先的內(nèi)容一致,實(shí)際我們需要額外再創(chuàng)建一個(gè)新的List,所以加入了后續(xù)代碼,當(dāng)沒(méi)有發(fā)生變化時(shí),直接返回原先的List。這樣操作有助于減少內(nèi)存。
具體的解釋可以參考下面的圖片。
