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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深度解析dubbo在线运维Qos

發(fā)布時間:2023/12/18 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深度解析dubbo在线运维Qos 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

      • 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 是主要處理我們命令的

@Overrideprotected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {if (StringUtils.isBlank(msg)) {// 是否是空消息ctx.writeAndFlush(QosProcessHandler.prompt);// 將dubbo> 寫回去} else {CommandContext commandContext = TelnetCommandDecoder.decode(msg);commandContext.setRemote(ctx.channel());// 設(shè)置channeltry {String result = commandExecutor.execute(commandContext);if (StringUtils.equals(QosConstants.CLOSE, result)) {// 是否返回closectx.writeAndFlush(getByeLabel()).addListener(ChannelFutureListener.CLOSE);} else {// 將結(jié)果寫回去 xxx /r/n dubbo>ctx.writeAndFlush(result + QosConstants.BR_STR + QosProcessHandler.prompt);}} catch (NoSuchCommandException ex) {ctx.writeAndFlush(msg + " :no such command");ctx.writeAndFlush(QosConstants.BR_STR + QosProcessHandler.prompt);log.error("can not found command " + commandContext, ex);} catch (Exception ex) {ctx.writeAndFlush(msg + " :fail to execute commandContext by " + ex.getMessage());ctx.writeAndFlush(QosConstants.BR_STR + QosProcessHandler.prompt);log.error("execute commandContext got exception " + commandContext, ex);}}}

這里首先判斷消息是不是空,空消息就將 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ù)提供者接口看看:

public String listProvider() {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("As Provider side: ");//通過ApplicationModel獲取所有的provider,這個是服務(wù)注冊上的時候添加到ApplicationModel 里面的Collection<ProviderModel> ProviderModelList = ApplicationModel.allProviderModels();TTable tTable = new TTable(new TTable.ColumnDefine[]{new TTable.ColumnDefine(TTable.Align.MIDDLE),new TTable.ColumnDefine(TTable.Align.MIDDLE)});//HeadertTable.addRow("Provider Service Name", "PUB");//Contentfor (ProviderModel providerModel : ProviderModelList) {tTable.addRow(providerModel.getServiceName(), isReg(providerModel.getServiceName()) ? "Y" : "N");}stringBuilder.append(tTable.rendering());return stringBuilder.toString();}

這邊有兩個點: 一個是通過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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。