<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用dubbo-go搭建dubbo接口測(cè)試平臺(tái)

          共 5722字,需瀏覽 12分鐘

           ·

          2021-07-26 14:27

          背景

          http接口測(cè)試只需要一個(gè)curl命令,但dubbo協(xié)議沒(méi)有這樣的現(xiàn)成接口測(cè)試工具。通常公司內(nèi)的dubbo控制臺(tái)或其他平臺(tái)會(huì)集成一個(gè)dubbo接口測(cè)試工具。

          調(diào)用一個(gè)dubbo接口,需要知道服務(wù)名service、方法名method和參數(shù)args。

          正常的調(diào)用,調(diào)用方需引入服務(wù)提供方定義的接口jar包。

          作為接口測(cè)試平臺(tái),沒(méi)辦法引入所有提供方定義的接口jar包,可以有以下方案來(lái)解決:

          1. dubbo支持telnet協(xié)議調(diào)用dubbo接口
          2. dubbo的泛化調(diào)用可以在不引入提供方接口定義jar包的情況下對(duì)接口進(jìn)行調(diào)用

          對(duì)于方案1,實(shí)現(xiàn)成本很低,甚至可以在服務(wù)器上直接用telnet測(cè)試

          它也有缺點(diǎn)

          • 調(diào)用無(wú)法經(jīng)過(guò)filter
          • 無(wú)法攜帶隱式參數(shù)attachment

          剛好我們把方案1的優(yōu)缺點(diǎn)都踩了,我們的dubbo控制臺(tái)是go語(yǔ)言編寫,短時(shí)間快速實(shí)現(xiàn),就采用了telnet的方式。

          隨著業(yè)務(wù)的發(fā)展,流量染色,或標(biāo)簽路由等需要攜帶隱式參數(shù)。

          沒(méi)有走自定義filter,導(dǎo)致業(yè)務(wù)接口執(zhí)行不符合預(yù)期等都迫使我們升級(jí)為泛化調(diào)用。

          dubbo接口泛化調(diào)用在控制臺(tái)是go編寫的情況下也有兩個(gè)方案可選:

          1. 單獨(dú)起一個(gè)java進(jìn)程,暴露http端口,與go進(jìn)程進(jìn)行交互,泛化調(diào)用使用dubbo的java sdk進(jìn)行編寫
          2. 控制臺(tái)引入dubbo-go,使用dubbo-go進(jìn)行泛化調(diào)用

          出于對(duì)dubbo java版本的了解,方案1肯定可行,只是架構(gòu)變得復(fù)雜。

          而方案2由于dubbo-go還是比較新的項(xiàng)目,并不是很了解,所以不確定其可行性和兼容性,但如果能實(shí)現(xiàn),會(huì)大大降低架構(gòu)的復(fù)雜度。

          dubbo-go介紹

          dubbo-go是dubbo的golang實(shí)現(xiàn)版本,它出現(xiàn)的初衷是為了讓golang和java的dubbo生態(tài)互通。

          如今dubbo-go支持provider和consumer端,可以作為一個(gè)獨(dú)立的rpc框架使用,同時(shí)社區(qū)也是dubbo生態(tài)中最火的一個(gè)。

          如果要說(shuō)它的意義,我覺(jué)得除了和java互通外還有一點(diǎn)非常重要,那就是它能發(fā)揮golang協(xié)程的巨大作用,這一點(diǎn)可以用在dubbo網(wǎng)關(guān)上,如果用dubbo-go實(shí)現(xiàn)dubbo網(wǎng)關(guān),就無(wú)需糾結(jié)線程池、異步等問(wèn)題。

          泛化調(diào)用的使用

          首先provider端提供一個(gè)接口,這個(gè)不再贅述,非常簡(jiǎn)單,接口定義如下

          package org.newboo.basic.api;

          import org.newboo.basic.model.RpcResult;
          import org.newboo.basic.model.User;

          public interface MyDemoService {
              RpcResult<String> call(User user);
          }
          package org.newboo.basic.model;

          import java.io.Serializable;

          public class User implements Serializable {
              private String uid;
              private String name;
              private String remoteServiceTag;
              ...
          }

          再來(lái)編寫java版的泛化調(diào)用代碼,不引入provider方的jar包:

          ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
          // ①引用服務(wù)名
          reference.setInterface("org.newboo.basic.api.MyDemoService");
          // ②設(shè)置泛化調(diào)用標(biāo)志
          reference.setGeneric("true");

          DubboBootstrap bootstrap = DubboBootstrap.getInstance();
          bootstrap.application(new ApplicationConfig("dubbo-demo-api-consumer"))
                  .registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
                  .reference(reference)
                  .start();

          GenericService genericService = ReferenceConfigCache.getCache().get(reference);
          String[] ps = new String[1];
          // ③參數(shù)類型
          ps[0] = "org.newboo.basic.model.User";
          Object[] ags = new Object[1];
          // ④pojo參數(shù)使用map構(gòu)造
          Map<String, String> user = new HashMap<>();
          user.put("uid""1");
          user.put("name""roshi");
          user.put("remoteServiceTag""tag");
          ags[0] = user;
          // ⑤發(fā)起調(diào)用
          Object res = genericService.$invoke("call", ps, ags);
          System.out.println(res);

          關(guān)鍵的步驟已在代碼注釋中標(biāo)明

          golang版本

          直接修改的dubbo-go-samples代碼,參考https://github.com/apache/dubbo-go-samples 啟動(dòng)時(shí)需要設(shè)置配置文件路徑ENV

          var (
           appName         = "UserConsumer"
           referenceConfig = config.ReferenceConfig{
            InterfaceName: "org.newboo.basic.api.MyDemoService",
            Cluster:       "failover",
              // registry需要配置文件
            Registry:      "demoZk",
            Protocol:      dubbo.DUBBO,
            Generic:       true,
           }
          )

          func init() {
           referenceConfig.GenericLoad(appName) //appName is the unique identification of RPCService
           time.Sleep(1 * time.Second)
          }

          // need to setup environment variable "CONF_CONSUMER_FILE_PATH" to "conf/client.yml" before run
          func main() {
           call()
          }

          func call() {
            // 設(shè)置attachment
           ctx := context.WithValue(context.TODO(), constant.AttachmentKey, map[string]string{"tag":"test"})

           resp, err := referenceConfig.GetRPCService().(*config.GenericService).Invoke(
            ctx,
            []interface{}{
             "call",
             []string{"org.newboo.basic.model.User"},
             []interface{}{map[string]string{"uid":"111","name":"roshi","remoteServiceTag":"hello"}},
            },
           )
           if err != nil {
            panic(err)
           }
           gxlog.CInfo("success called res: %+v\n", resp)
          }

          這里我設(shè)置了一個(gè)attachment,也能正常被provider識(shí)別

          泛化調(diào)用原理

          泛化調(diào)用GenericService是dubbo默認(rèn)提供的一個(gè)服務(wù)。

          其提供了一個(gè)名為$invoke的方法,該方法參數(shù)有三個(gè),第一個(gè)參數(shù)是真實(shí)要調(diào)用的方法名,第二個(gè)是參數(shù)類型數(shù)組,第三個(gè)是真實(shí)的參數(shù)數(shù)組,其定義為

          public interface GenericService {
              Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException;
              ...
          }

          有了這三個(gè)參數(shù),利用反射就能調(diào)用到真實(shí)的接口了。

          java版實(shí)現(xiàn)細(xì)節(jié)

          實(shí)現(xiàn)這種泛化調(diào)用主要涉及到兩個(gè)filter:

          • consumer端的GenericImplFilter
          • provider端的GenericFilter

          consumer端的filter將generic標(biāo)志設(shè)置到attachment中,并封裝調(diào)用為GenericService.$invoke

          provider端filter判斷請(qǐng)求是generic時(shí)進(jìn)行攔截,獲取調(diào)用方法名、參數(shù)、參數(shù)值,先序列化為pojo對(duì)象,再進(jìn)行反射調(diào)用真實(shí)接口。

          dubbo-go版細(xì)節(jié)

          與java實(shí)現(xiàn)基本一致,其中g(shù)eneric_filter充當(dāng)consumer端的filter,也是將調(diào)用封裝為GenericService.$invoke,其中還涉及到一個(gè)參數(shù)類型的轉(zhuǎn)換,將map轉(zhuǎn)換為dubbo-go-hessian2.Object,這樣provider端就可以將其反序列化為Object對(duì)象。

          與其相關(guān)的版本變更如下

          • v1.3.0開(kāi)始支持泛化調(diào)用
          • v1.4.0開(kāi)始支持用戶設(shè)置attachement
          • v1.5.1開(kāi)始支持動(dòng)態(tài)tag路由
          • v1.5.7-rc1修復(fù)了直連provider時(shí)無(wú)法走filter的bug

          踩坑:v1.5.7-rc1 之前如果使用直連provider的方式,不會(huì)走filter,導(dǎo)致參數(shù)序列化出錯(cuò),provider端會(huì)報(bào)類型轉(zhuǎn)換異常

          結(jié)論

          dubbo-go的泛化調(diào)用推薦使用>=v1.5.7-rc1版本,其功能幾乎已和java版打平,甚至其實(shí)現(xiàn)都與java類似。

          使用dubbo-go構(gòu)建網(wǎng)關(guān)、接口測(cè)試平臺(tái)、或者打通golang與java技術(shù)生態(tài),不失為一個(gè)好的選擇。


          搜索關(guān)注微信公眾號(hào)"捉蟲大師",后端技術(shù)分享,架構(gòu)設(shè)計(jì)、性能優(yōu)化、源碼閱讀、問(wèn)題排查、踩坑實(shí)踐。

          瀏覽 64
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中国A毛片| 麻豆成人91精品二区三区 | 国产精品无码天天爽视频 | 欧美综合久久 | 国产69精品久久久久久久久久 |