深度解析dubbo在线运维Qos
文章目錄
-
-
- 1. dubbo的Qos
- 2.dubbo Qos簡單使用
-
- 2.1 ls
- 2.2 online
- 2.3 offline
- 2.4 help
- 2.5 quit
- 3.dubbo Qos 源碼剖析
-
- 3.1 Qos服務(wù)器創(chuàng)建時機
- 3.2 QosProtocolWrapper
- 3.3 com.alibaba.dubbo.qos.server.Server
- 3.4 com.alibaba.dubbo.qos.server.handler.QosProcessHandler
- 3.4 BaseCommand
-
- 3.4.1 ls
- 3.4.2 online
- 3.4.3 offline
- 3.4.4 help
- 3.4.5 quit
- 4.總結(jié)
-
注:本文基于dubbo v2.6.1
1. dubbo的Qos
QoS的英文全稱為"Quality of Service",中文名為"服務(wù)質(zhì)量"。在dubbo 2.5.8 新版本增加了 QOS 模塊,提供了新的 telnet 命令支持。dubbo管它叫在線運維命令,我們可以通過它能夠看到服務(wù)提供者狀態(tài),服務(wù)調(diào)用者狀態(tài),現(xiàn)在dubbo提供了 ls , online,offline,help ,quit命令。
命令
用途
ls
能夠列出來該實例服務(wù)提供者與調(diào)用者狀態(tài)
online
服務(wù)上線,可以指定某個接口,也可以什么也不指定,這樣就是全部
offline
服務(wù)下線,可以指定某個接口,也可以什么也不指定,這樣就是全部
help
查看命令的用途,不帶參數(shù)顯示全部命令,帶參數(shù)只顯示指定的
quit
退出Qos
2.dubbo Qos簡單使用
我們可以在dubbo的配置文件配置參數(shù),我這里是使用的xml的形式,其他形式可以看下官網(wǎng)文檔:官網(wǎng)文檔(文檔講的很詳細(xì),而且是中文)
<dubbo:application name="dubbo-consumer"><dubbo:parameter key="qos.enable" value="true"/><dubbo:parameter key="qos.accept.foreign.ip" value="false"/><dubbo:parameter key="qos.port" value="8108"/> </dubbo:application>qos.enable :表示是否開始Qos
qos.accept.foreign.ip: 允許訪問的ip,缺省就是false,表示任何ip都可訪問
qos.port: Qos提供服務(wù)的端口
接下來我啟動服務(wù),然后在終端上使用telnet的方式連接dubbo Qos
2.1 ls
可以看到服務(wù)提供服務(wù)與調(diào)用服務(wù)的狀態(tài)
這個 Provider Service Name 就是服務(wù)提供者名字 , PUB 就是狀態(tài) N是未注冊,就是沒有注冊到注冊中心,其實服務(wù)下線功能就是從注冊中心unregister ,Y表示服務(wù)在線,就是注冊到注冊中心了。
2.2 online
服務(wù)上線,就是將服務(wù)注冊到注冊中心上去,后面可以帶個參數(shù),參數(shù)是指定具體上線的接口,不帶參數(shù)表示全部服務(wù)接口(這個得是你標(biāo)識的,比如說使用了dubbo @Service注解)都注冊到注冊中心去。
我們ls小節(jié)的時候可以看到com.xuzhaocai.dubbo.provider.IUserInfoService 是N,我們可以使用online來進(jìn)行服務(wù)上線
我們可以看到服務(wù)狀態(tài)是Y了,這其實就是注冊中心 調(diào)用register(),我們在后面可以看到具體代碼實現(xiàn)。
2.3 offline
offline 是服務(wù)下線,跟online一個使用方法,這里就不再贅述了。
2.4 help
幫助,可以指定具體的cmd,這樣就顯示指定cmd的幫助
不指定的話顯示全部的命令
2.5 quit
退出Qos,你不用這個quit可以試試,看看能不能退出去,我mac直接使用ctrl+c 反正不行。
注: 我這里就不再詳細(xì)說明這個用法了,這東西官網(wǎng)文檔很詳細(xì),而且使用也簡單,主要是場景 ,直接源碼搞起
3.dubbo Qos 源碼剖析
3.1 Qos服務(wù)器創(chuàng)建時機
其實在dubbo進(jìn)行服務(wù)暴露與服務(wù)引用的時候,我們都見過Exporter<?> exporter = protocol.export(wrapperInvoker); (com.alibaba.dubbo.config.ServiceConfig#doExportUrlsFor1Protocol)或者refprotocol.refer(interfaceClass, urls.get(0));(com.alibaba.dubbo.config.ReferenceConfig#createProxy) ,我們知道這個protocol成員是這個樣子
根據(jù)dubbo spi 自適應(yīng)的規(guī)則,實際上執(zhí)行的是 url中protocol 參數(shù)值對應(yīng)的那個實現(xiàn)類,我們這個場景下就是RegistryProtocol 實現(xiàn)類,然后dubbo spi 還會幫你setter 注入 ,wrapper 包裝
我們可以看下都有哪些Protocol 包裝實現(xiàn)類
v2.6.1 這個版本就這些。
我們獲得的RegistryProtocol對象,其實外面是包了這幾個wrapper類,就像下圖這個樣子(當(dāng)然這個順序不一定是這個樣子的,他這邊沒有對順序做要求)
所以我們在服務(wù)暴露或者服務(wù)引用的時候,就會走這個QosProtocolWrapper類。
3.2 QosProtocolWrapper
我們可以看到export與refer方法,判斷如果protocol=registry,接著進(jìn)入這個startQosServer(url)
看下這 startQosServer方法。
這個方法中我們可以看到就是判斷qos.enable 啟動參數(shù),然后 判斷是否已經(jīng)啟動,這個玩意一個服務(wù)實例就只能啟動一次,再就是獲得一個Server對象,將用戶設(shè)置的一些參數(shù)值設(shè)置進(jìn)去,然后調(diào)用start方法。
我們來看下這個Server類
3.3 com.alibaba.dubbo.qos.server.Server
我們這里是創(chuàng)建了一個netty的server,開始的時候使用cas判斷啟動狀態(tài),添加了一個QosProcessHandler消息處理類,我們的命令就是到這里面處理的。我們看下這個QosProcessHandler 類,傳入?yún)?shù)就是welcome歡迎語跟允許的ip。
我們來看下的這個QosProcessHandler消息處理類
3.4 com.alibaba.dubbo.qos.server.handler.QosProcessHandler
當(dāng)消息連接上的時候,會調(diào)用channelActive方法,我們可以看到,它將這個welcome 歡迎語與 dubbo> 這個開始頭發(fā)出去了。
也就是這個東西
接著我們再輸入命令的時候,就會到decode 方法中,首先判斷buffer里面有沒有能讀的字節(jié),如果沒有直接返回,獲取一個字節(jié),判斷是不是http請求,因為Dubbo Qos 是支持http 與telnet的。
這里就會相應(yīng)的添加handler,我們可以看到,他這個handler是動態(tài)添加與刪除的,每一次訪問都要添加與刪除。
我們這里使用的是telnet ,我們看下telnet的是怎樣實現(xiàn)的,http 的也就同理了。
接下來我們看下這個TelnetProcessHandler 處理類,那四個都是netty的,做相應(yīng)輔助功能的,比如說使用行解析,使用utf-8解碼,然后空閑時間,TelnetProcessHandler 是主要處理我們命令的
這里首先判斷消息是不是空,空消息就將 dubbo>這個返回給客戶端
然后將消息解析成 CommandContext, 也就是CommandContext commandContext = TelnetCommandDecoder.decode(msg); 這句,就是將消息解析成cmd與參數(shù),調(diào)用CommandContext工廠創(chuàng)建CommandContext 對象。
接著就是使用CommandExecutor 執(zhí)行這個命令,也就是這句String result = commandExecutor.execute(commandContext);
我們來看下這個DefaultCommandExecutor的execute方法,先是通過命令獲取對應(yīng)的BaseCommand實現(xiàn)類,沒有找到對應(yīng)的話就拋出NoSuch的異常。有的話直接調(diào)用execute執(zhí)行。
這個BaseCommand我們后面再說,這個執(zhí)行結(jié)果返回,接著回到TelnetProcessHandler 的channelRead0方法中,如果這個執(zhí)行結(jié)果是close的話,就寫回"BYE! ";這個字符串,并且添加ChannelFutureListener.CLOSE 這個listener。
如果是正常執(zhí)行結(jié)果的話,寫回去就可以了。
現(xiàn)在我們來看下這個BaseCommand的定義以它的子類們
3.4 BaseCommand
這個是就是命令的接口,是基于dubbo spi的,所有Qos命令都要實現(xiàn)它,然后重寫execute方法。
看下它的實現(xiàn)類
下面我們就挨個看看
3.4.1 ls
ls 這個命令是獲取該實例服務(wù)提供者接口與調(diào)用者接口及狀態(tài)。
我們來看看代碼實現(xiàn)
調(diào)用了listProvider()獲取了服務(wù)提供者接口,調(diào)用了服務(wù)調(diào)用者接口。
我們這里拿獲取服務(wù)提供者接口看看:
這邊有兩個點: 一個是通過ApplicationModel 獲取所有的provider,這個ApplicationModel 類,里面其實維護(hù)了幾個map,其中就有本實例服務(wù)提供者與服務(wù)調(diào)用者接口列表,當(dāng)我們在暴露服務(wù)完成的時候,就會向ApplicationModel 這個類里面添加對應(yīng)的服務(wù)提供者的信息,也就是走的這個方法
每當(dāng)我們服務(wù)引用完,創(chuàng)建完proxy代理類的時候,就會往ApplicationModel 這個類里面添加對應(yīng)的服務(wù)調(diào)用者的信息,也就是走的這個方法
所以我們就能拿到本實例的服務(wù)提供者接口了。接著往下看就是創(chuàng)建TTable ,是兩列的,然后遍歷服務(wù)提供者接口列表添加行。
到最后就是rendering 渲染了,在循環(huán)的時候其實還有一個點,使用isReg(providerModel.getServiceName()) “Y” : “N”) 是否在線,這里面判斷的其實還是invoker包裝類的isReg,注冊到注冊中心后設(shè)置這個標(biāo)識。
同理本實例服務(wù)提供者也是這個樣子獲取的,到這里我們這個ls命令處理就完成了。
3.4.2 online
com.alibaba.dubbo.qos.command.impl.Online 服務(wù)上線。
這個online 命令使用參數(shù)的,如果用戶沒有指定,就是.*,在下面匹配上就會匹配到。
首先是判斷參數(shù),接著就是從ApplicationModel 獲取本實例服務(wù)提供者列表,遍歷,看看是否符合你傳過來的參數(shù),,符合就設(shè)置hasService = true,接著就是根據(jù)serviceName從本地注冊表中獲取對應(yīng)的ProviderInvokerWrapper列表,遍歷判斷如果對應(yīng)的狀態(tài)是在線的(這里還是判斷的isReg),就跳過,否則獲取對應(yīng)的注冊中心,進(jìn)行注冊,同時將isReg狀態(tài)設(shè)置成true。
3.4.3 offline
com.alibaba.dubbo.qos.command.impl.Offline 服務(wù)下線,我們看下代碼,它這個與online差不多,它這個循環(huán)判斷服務(wù)沒有在線就跳過去,在線的就調(diào)用注冊中心的unregister()方法進(jìn)行服務(wù)下線,同時設(shè)置isReg服務(wù)在線狀態(tài)為false。
3.4.4 help
com.alibaba.dubbo.qos.command.impl.Help 幫助文檔作用,可以傳參數(shù) 指定需要幫助的命令,也可以不指定,那就是顯示全部命令的幫助。直接上代碼
我們看下這行所有命令的,這個指定命令的原理也差不多
就是使用CommandHelper.getAllCommandClass() 獲取所有的BaseCommand 子類class對象,他這個使用dubbo spi獲取所有子類的
然后獲取子類上面的@Cmd注解,就像offline上面這個,name就是命令,summary就是說明 ,example 就是列子
3.4.5 quit
com.alibaba.dubbo.qos.command.impl.Quit 退出 ,這就是直接返回了close,然后TelnetProcessHandler就會處理這個close進(jìn)行退出。
4.總結(jié)
到這里我們dubbo 在線運維Qos 就解析完成了,概括一下,首先是講了 dubbo Qos ,然后簡單使用了一下,最后就是咱們的源碼解析了,從Qos服務(wù)器啟動時機到每一個commad命令的執(zhí)行原理。這個Qos 使用簡單,主要還是它的使用場景,正如dubbo 官方文檔說的,服務(wù)上線 服務(wù)下線的使用場景。
總結(jié)
以上是生活随笔為你收集整理的深度解析dubbo在线运维Qos的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。