最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang基于泛化調(diào)用與Nacos實(shí)現(xiàn)Dubbo代理

 更新時(shí)間:2023年04月04日 11:33:37   作者:cipher  
這篇文章主要為大家詳細(xì)介紹了Golang如何基于泛化調(diào)用與Nacos實(shí)現(xiàn)Dubbo代理,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

前言

由于工作中使用的 rpc 框架是 dubbo,經(jīng)常需要調(diào)試不同環(huán)境的 dubbo 接口,例如本地環(huán)境、開發(fā)環(huán)境和測試環(huán)境。而為了統(tǒng)一管理 http 接口和 dubbo 接口,希望使用統(tǒng)一的調(diào)試工具,例如 PostMan 或 ApiPost 等,因此萌生了開發(fā)一個(gè) dubbo 的 http 代理工具的念頭。

準(zhǔn)備

由于是通用的 dubbo 代理,因此肯定需要使用泛化調(diào)用。而我們使用的注冊(cè)中心是 nacos,因此也需要使用 nacos-sdk 來獲取 provider 的實(shí)例信息。

實(shí)現(xiàn)

項(xiàng)目結(jié)構(gòu)


├── dubbo/                 
│    ├─ generic.go   # 泛化調(diào)用 dubbo 接口
│    ├─ models.go    # 數(shù)據(jù)模型
│    └─ nacos.go     # 獲取 nacos 元信息
├── web/                       
│    └─ server.go    # 對(duì)外 http 接口

├── main.go          # main 入口函數(shù)
└── go.mod           # 模塊描述文件

go.mod

module dubbo-proxy

go 1.20

require (
	dubbo.apache.org/dubbo-go/v3 v3.0.5
	github.com/apache/dubbo-go-hessian2 v1.12.0
	github.com/gin-gonic/gin v1.9.0
	github.com/nacos-group/nacos-sdk-go/v2 v2.1.2
)

返回?cái)?shù)據(jù)格式

dubbo/models.go:

type DataResult struct {
	Env     string `json:"env,omitempty"`  // 當(dāng)前調(diào)用環(huán)境
	Code    string `json:"code,omitempty"` // 返回結(jié)果碼
	Data    any    `json:"data,omitempty"` // 返回結(jié)果
	Message string `json:"message,omitempty"` // 返回消息
}

獲取 nacos 元信息

根據(jù)環(huán)境創(chuàng)建 nacos client

func buildClient(env string, serverCfgs []constant.ServerConfig) naming_client.INamingClient {
	client, _ := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig: constant.NewClientConfig(
				constant.WithNamespaceId(env),
				constant.WithNotLoadCacheAtStart(true),
			),
			ServerConfigs: serverCfgs,
		},
	)
	return client
}

獲取服務(wù)實(shí)例

func SelectInstance(env, servName string) (string, bool) {
	cli, ok := cliMap[env]
	if !ok {
		return "client not found from " + env, false
	}
	instances, e := cli.SelectInstances(vo.SelectInstancesParam{
		ServiceName: fmt.Sprintf("providers:%s:1.0.0:", servName),
		HealthyOnly: true,
	})
	if e != nil {
		return "instance not found, " + e.Error(), false
	}
	if len(instances) <= 0 {
		return "instance not found", false
	}
	return fmt.Sprintf("dubbo://%s:%d", instances[0].Ip, instances[0].Port), true
}

完整代碼

dubbo/nacos.go:

package dubbo

import (
	"fmt"
	"github.com/nacos-group/nacos-sdk-go/v2/clients"
	"github.com/nacos-group/nacos-sdk-go/v2/clients/naming_client"
	"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
	"github.com/nacos-group/nacos-sdk-go/v2/vo"
)

var cliMap = make(map[string]naming_client.INamingClient)

func init() {
	serverCfgs := []constant.ServerConfig{
		*constant.NewServerConfig("127.0.0.1", 6801, constant.WithContextPath("/nacos")),
	}
	cliMap["local"] = buildClient("local", serverCfgs)
	cliMap["dev"] = buildClient("develop", serverCfgs)
	cliMap["test"] = buildClient("test", serverCfgs)
}

func buildClient(env string, serverCfgs []constant.ServerConfig) naming_client.INamingClient {
	client, _ := clients.NewNamingClient(
		vo.NacosClientParam{
			ClientConfig: constant.NewClientConfig(
				constant.WithNamespaceId(env),
				constant.WithNotLoadCacheAtStart(true),
			),
			ServerConfigs: serverCfgs,
		},
	)
	return client
}

func SelectInstance(env, servName string) (string, bool) {
	cli, ok := cliMap[env]
	if !ok {
		return "client not found from " + env, false
	}
	instances, e := cli.SelectInstances(vo.SelectInstancesParam{
		ServiceName: fmt.Sprintf("providers:%s:1.0.0:", servName),
		HealthyOnly: true,
	})
	if e != nil {
		return "instance not found, " + e.Error(), false
	}
	if len(instances) <= 0 {
		return "instance not found", false
	}
	return fmt.Sprintf("dubbo://%s:%d", instances[0].Ip, instances[0].Port), true
}

泛化調(diào)用

dubbo root 配置

var dubboRoot = cfg.NewRootConfigBuilder().SetProtocols(map[string]*cfg.ProtocolConfig{
	dubbo.DUBBO: {
		Params: map[string]interface{}{
			"getty-session-param": map[string]interface{}{
				"max-msg-len": 1024000,
			},
		},
	},
}).Build()

泛化調(diào)用

func GenericInvoke(iName, method, env string, req []byte) DataResult {
	instance, ok := SelectInstance(env, iName)
	if !ok {
		return DataResult{
			Code:    "ERROR",
			Message: instance,
		}
	}
	cfg.Load(cfg.WithRootConfig(dubboRoot))
	refConf := cfg.ReferenceConfig{
		InterfaceName: iName,
		Cluster:       "failover",
		Protocol:      dubbo.DUBBO,
		Generic:       "true",
		Version:       "1.0.0",
		URL:           instance,
	}
	refConf.Init(dubboRoot)
	refConf.GenericLoad("dubbo-proxy")
	var args = utils.Unmarshal(req, &map[string]hessian.Object{})
	raw, err := refConf.GetRPCService().(*generic.GenericService).Invoke(context.Background(), method, nil, []hessian.Object{args})
	if err != nil {
		panic(err)
	}
	rawResult := raw.(map[interface{}]interface{})
	result := DataResult{
		Code:    rawResult["code"].(string),
		Message: rawResult["message"].(string),
		Data:    utils.ConvertAs(rawResult["data"], map[string]interface{}{}),
	}
	return result
}

注意25-30行要根據(jù)業(yè)務(wù)自身的返回?cái)?shù)據(jù)格式包裝結(jié)果:

/*
	這個(gè)例子的 dubbo 調(diào)用都會(huì)返回通過的結(jié)構(gòu):
	{
		"code": "",
		"message": "",
		"data": // 真正的調(diào)用結(jié)果
	}
*/
rawResult := raw.(map[interface{}]interface{})
result := DataResult{
	Code:    rawResult["code"].(string),
	Message: rawResult["message"].(string),
	Data:    rawResult["data"],
}

完整代碼

dubbo/generic.go:

package dubbo

import (
	"context"
	"dubbo-proxy/utils"
	cfg "dubbo.apache.org/dubbo-go/v3/config"
	"dubbo.apache.org/dubbo-go/v3/config/generic"
	_ "dubbo.apache.org/dubbo-go/v3/imports"
	"dubbo.apache.org/dubbo-go/v3/protocol/dubbo"
	hessian "github.com/apache/dubbo-go-hessian2"
)

var dubboRoot = cfg.NewRootConfigBuilder().SetProtocols(map[string]*cfg.ProtocolConfig{
	dubbo.DUBBO: {
		Params: map[string]interface{}{
			"getty-session-param": map[string]interface{}{
				"max-msg-len": 1024000,
			},
		},
	},
}).Build()

func GenericInvoke(iName, method, env string, req []byte) DataResult {
	instance, ok := SelectInstance(env, iName)
	if !ok {
		return DataResult{
			Code:    "ERROR",
			Message: instance,
		}
	}
	cfg.Load(cfg.WithRootConfig(dubboRoot))
	refConf := cfg.ReferenceConfig{
		InterfaceName: iName,
		Cluster:       "failover",
		Protocol:      dubbo.DUBBO,
		Generic:       "true",
		Version:       "1.0.0",
		URL:           instance,
	}
	refConf.Init(dubboRoot)
	refConf.GenericLoad("dubbo-proxy")
	var args = utils.Unmarshal(req, &map[string]hessian.Object{})
	raw, err := refConf.GetRPCService().(*generic.GenericService).Invoke(context.Background(), method, nil, []hessian.Object{args})
	if err != nil {
		panic(err)
	}
	rawResult := raw.(map[interface{}]interface{})
	result := DataResult{
		Code:    rawResult["code"].(string),
		Message: rawResult["message"].(string),
		Data:    utils.ConvertAs(rawResult["data"], map[string]interface{}{}),
	}
	return result
}

提供 http 服務(wù)

dubbo/generic.go:

package web

import (
	"dubbo-proxy/dubbo"
	"github.com/gin-gonic/gin"
	"net/http"
)

func Run() {
	router := gin.Default()
	router.POST("/:intf/:method", func(c *gin.Context) {
		intf := c.Param("intf")
		method := c.Param("method")
		env := c.Query("env")
		data, err := c.GetRawData()
		if err != nil {
		    panic(err)
		}
		res := dubbo.GenericInvoke(intf, method, env, data)
		res.Env = env
		c.JSON(http.StatusOK, res)
	})
	panic(router.Run(":7788"))
}

啟動(dòng)

main.go:

package main

import "dubbo-proxy/web"

func main() {
	web.Run()
}

效果

以上就是Golang基于泛化調(diào)用與Nacos實(shí)現(xiàn)Dubbo代理的詳細(xì)內(nèi)容,更多關(guān)于Golang Dubbo代理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • GO日志打印如何添加goroutineid

    GO日志打印如何添加goroutineid

    今天想給日志添加一個(gè)前綴,以區(qū)分不同goroutine的日志,方便做并發(fā)問題的排查,做日志跟蹤,下面給大家分享GO日志打印如何添加goroutineid,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • golang package time的用法具體詳解

    golang package time的用法具體詳解

    本篇文章主要介紹了golang package time的用法具體詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05
  • Go語言入門之基礎(chǔ)語法和常用特性解析

    Go語言入門之基礎(chǔ)語法和常用特性解析

    這篇文章主要給大家講解了Go語言的基礎(chǔ)語法和常用特性解析,比較適合入門小白,文中通過代碼示例介紹的非常詳細(xì),對(duì)我們學(xué)習(xí)Go語言有一定的幫助,需要的朋友可以參考下
    2023-07-07
  • 深入理解Go語言對(duì)象池

    深入理解Go語言對(duì)象池

    對(duì)象池是一種在編程中用于優(yōu)化資源管理的技術(shù),本文主要介紹了深入理解Go語言對(duì)象池,對(duì)象池通常通過sync.Pool包或自定義數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn),下面就來介紹一下
    2024-01-01
  • Go實(shí)現(xiàn)用戶每日限額的方法(例一天只能領(lǐng)三次福利)

    Go實(shí)現(xiàn)用戶每日限額的方法(例一天只能領(lǐng)三次福利)

    這篇文章主要介紹了Go實(shí)現(xiàn)用戶每日限額的方法(例一天只能領(lǐng)三次福利)
    2022-01-01
  • 深入理解golang中io.Writer接口的使用

    深入理解golang中io.Writer接口的使用

    io 是一個(gè) Golang 標(biāo)準(zhǔn)庫包,它為圍繞輸入和輸出的許多操作和用例定義了靈活的接口,這篇文章主要為大家介紹了Go中Writer接口的使用,需要的可以參考下
    2023-10-10
  • golang協(xié)程關(guān)閉踩坑實(shí)戰(zhàn)記錄

    golang協(xié)程關(guān)閉踩坑實(shí)戰(zhàn)記錄

    協(xié)程(coroutine)是Go語言中的輕量級(jí)線程實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于golang協(xié)程關(guān)閉踩坑的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-03-03
  • Go語言net包RPC遠(yuǎn)程調(diào)用三種方式http與json-rpc及tcp

    Go語言net包RPC遠(yuǎn)程調(diào)用三種方式http與json-rpc及tcp

    這篇文章主要為大家介紹了Go語言net包RPC遠(yuǎn)程調(diào)用三種方式分別使用http與json-rpc及tcp的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-11-11
  • 詳解Go語言中調(diào)度器的原理與使用

    詳解Go語言中調(diào)度器的原理與使用

    這篇文章主要介紹了Go語言運(yùn)行時(shí)調(diào)度器的實(shí)現(xiàn)原理,其中包含調(diào)度器的設(shè)計(jì)與實(shí)現(xiàn)原理、演變過程以及與運(yùn)行時(shí)調(diào)度相關(guān)的數(shù)據(jù)結(jié)構(gòu),希望對(duì)大家有所幫助
    2023-07-07
  • 基于Go和PHP語言實(shí)現(xiàn)爬樓梯算法的思路詳解

    基于Go和PHP語言實(shí)現(xiàn)爬樓梯算法的思路詳解

    這篇文章主要介紹了Go和PHP 實(shí)現(xiàn)爬樓梯算法,本文通過動(dòng)態(tài)規(guī)劃和斐波那契數(shù)列兩種解決思路給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05

最新評(píng)論

任丘市| 陆川县| 梓潼县| 龙海市| 临夏市| 集贤县| 桐乡市| 凌云县| 邢台县| 津南区| 灵宝市| 云浮市| 昭平县| 张家界市| 额尔古纳市| 原阳县| 五寨县| 班玛县| 镇原县| 布尔津县| 长汀县| 锡林郭勒盟| 枝江市| 鄄城县| 崇文区| 鄂温| 通江县| 灌南县| 宜兰市| 英德市| 阳朔县| 朝阳市| 扶绥县| 泰和县| 江北区| 盘锦市| 渝中区| 平泉县| 利川市| 长寿区| 杭州市|