当前位置: 首页>资讯 >

Golang基于泛化调用与Nacos实现Dubbo代理 世界热点

来源: 脚本之家 | 时间: 2023-04-06 06:03:16 |

目录
前言准备实现项目结构go.mod返回数据格式获取 nacos 元信息泛化调用提供 http 服务启动效果

前言

由于工作中使用的 rpc 框架是 dubbo,经常需要调试不同环境的 dubbo 接口,例如本地环境、开发环境和测试环境。而为了统一管理 http 接口和 dubbo 接口,希望使用统一的调试工具,例如 PostMan 或 ApiPost 等,因此萌生了开发一个 dubbo 的 http 代理工具的念头。

准备

由于是通用的 dubbo 代理,因此肯定需要使用泛化调用。而我们使用的注册中心是 nacos,因此也需要使用 nacos-sdk 来获取 provider 的实例信息。

实现

项目结构


├── dubbo/
│ ├─ generic.go # 泛化调用 dubbo 接口
│ ├─ models.go # 数据模型
│ └─ nacos.go # 获取 nacos 元信息
├── web/
│ └─ server.go # 对外 http 接口

├── main.go # main 入口函数
└── 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
)

返回数据格式

dubbo/models.go:

type DataResult struct {
	Env     string `json:"env,omitempty"`  // 当前调用环境
	Code    string `json:"code,omitempty"` // 返回结果码
	Data    any    `json:"data,omitempty"` // 返回结果
	Message string `json:"message,omitempty"` // 返回消息
}

获取 nacos 元信息

根据环境创建 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
}

获取服务实例

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
}

泛化调用

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()

泛化调用

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行要根据业务自身的返回数据格式包装结果:

/*
	这个例子的 dubbo 调用都会返回通过的结构:
	{
		"code": "",
		"message": "",
		"data": // 真正的调用结果
	}
*/
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 服务

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"))
}

启动

main.go:

package main

import "dubbo-proxy/web"

func main() {
	web.Run()
}

效果

以上就是Golang基于泛化调用与Nacos实现Dubbo代理的详细内容,更多关于Golang Dubbo代理的资料请关注脚本之家其它相关文章!

关键词:

 

热文推荐

Golang基于泛化调用与Nacos实现Dubbo代理 世界热点

这篇文章主要为大家详细介绍了Golang如何基于泛化调用与Nacos实现Dubbo代理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

2023-04-06

普集村_对于普集村简单介绍

1、普集村隶属于安徽省马鞍山市当涂县江心乡,位于江心乡东部,全村耕地面积2218亩,其中水田350亩,旱地1768亩,企

2023-04-06

王铉_关于王铉介绍-环球简讯

王铉,关于王铉介绍这个很多人还不知道,我们一起来看看!1、王铉,副教授,中央音乐学院电子音乐作曲博士,是中国培养的第一批电子音乐作曲博

2023-04-05

俄罗斯一男子19楼坠落后自行上救护车:还给医务人员唱了歌 全球时讯

俄罗斯一男子19楼坠落后自行上救护车:还给医务人员唱了歌

2023-04-05

拜登又遇到头疼事,前面走龙卷风后面到阿肯色州遭遇极端天气 微头条

突然,一场致命的龙卷风席卷了美国南部和中西部地区,最主要是阿肯色州,其龙卷风威力足以摧毁观景楼剧院的屋顶,附近数百名民众被困在里面,

2023-04-05

绿豆芽生长过程解说(每一个生命的生长过程都是有一定阶段的)

每一个生命的生长过程都是有一定阶段的,无论是动物还是植物。动物从幼体到成年,植物从种子发芽到开花结果。绿豆芽也是一样,对我们来说不仅

2023-04-05

张继科不装了?刘国梁爱徒效仿女篮李梦失败,国乒藏獒阴谋被撕碎

北京时间4月5日,国乒昔日有着藏獒之称的大满贯选手张继科的丑闻不断升级,近期关于张继科的各种黑料丑闻在社交媒体上霸占着热搜榜前列,足以

2023-04-05

一毕业就失业,为何大学生依旧不愿回农村?|全球微头条

近日,广东出台动员方案,将动员30万青年“下乡返乡兴乡”,助力“百千万工程”,为鼓励大学生返乡带来了积极影响。随着经济的高速发展,城镇

2023-04-05

春来草自青_春来草自青

1、有诗曰:“微雨夜来过,不知春草生。2、”初春时节,细雨在夜里静悄悄的降落,睡梦中的人儿无知无觉。3、次日出门,惊喜

2023-04-05

康普化学:4月3日召开业绩说明会,投资者参与|头条焦点

2023年4月4日康普化学834033发布公告称公司于2023年4月3日召开业绩说明会具体内容如下问公司就投资者在本次说明会中出的进行了回复答投资者您

2023-04-05

中央气象台:广东福建等地将有强对流天气|当前热议

【中央气象台:广东福建等地将有强对流天气】预计4月5日08时至6日08时,福建南部、广西东部、广东中部和东北部等地的部分地区将有短时强降水天

2023-04-05

格拉哈姆·希尔_关于格拉哈姆·希尔简述_每日时讯

1、英国43岁清洁工格拉哈姆·希尔2008年5月打扫街道时,在一个垃圾箱中发现了总面值达1万英镑的碎钞。2、由于无法找到失主,警方判定这笔巨款

2023-04-05

全球新消息丨excel表格打印出来很小excel打印怎么铺满a4纸_excel表格打印出来很小

1、如果你要达到所见即所得的比例效果,可以按以下步骤操作: "文件 "菜单- "页面设置 ",在这里面有一个 "缩放比例 ",请将它

2023-04-05

图解英力股份年报:第四季度单季净利润同比减641.42%

英力股份2022年报显示公司主营收入1372亿元同比下降1878归母净利润279386万元同比下降14398扣非净利润438669万元同比下降19407其中2022年第四

2023-04-04

高考满分作文800字 且放云帆济沧海_高考满分作文800字 世界快播

抄写作文网小编为大家提供高考满分作文800字且放云帆济沧海_高考满分作文800字来供大家参考,欢迎阅读。带你走近大自然-2020高考满分作文800字

2023-04-04

西安土拍市场“活”了?

西安土拍市场“活”了?

2023-04-04

安徽:预计今年小麦赤霉病自然发生面积约4100万亩

(记者张强)记者4日从安徽省农业农村厅召开的新闻发布会上获悉,据预测,2023年小麦赤霉病在安徽大流行风险高。据安徽省植物保护总站副站长何振

2023-04-04

今日精选:百万亚瑟王

1、《百万亚瑟王》,又名《扩散性百万亚瑟王》。2、本作是玩家从3种类型的亚瑟王当中选择一个来完成游戏内容。3、在【扩散性

2023-04-04

铁路货运为市场经济注入满满信心|环球播资讯

4月1日零时起,全国铁路实行新的货物列车运行图。调图后,全国铁路货运能力结构进一步优化,国内高附加值快运货物、煤炭等大宗货物和国际联运

2023-04-04

清明食俗,福建各地怎么吃?

[新闻页-台海网]元宵节吃汤圆、端午节吃粽子……而清明节,它的食俗文化也是丰富多彩的。说到清明节吃什么?福建各地都有不一

2023-04-04

资讯

Golang基于泛化调用与Nacos实现Dubbo代理 世界热点

这篇文章主要为大家详细介绍了Golang如何基于泛化调用与Nacos实现Dubbo代理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

2023-04-06     
普集村_对于普集村简单介绍

1、普集村隶属于安徽省马鞍山市当涂县江心乡,位于江心乡东部,全村耕地面积2218亩,其中水田350亩,旱地1768亩,企

2023-04-06     
王铉_关于王铉介绍-环球简讯

王铉,关于王铉介绍这个很多人还不知道,我们一起来看看!1、王铉,副教授,中央音乐学院电子音乐作曲博士,是中国培养的第一批电子音乐作曲博

2023-04-05     
俄罗斯一男子19楼坠落后自行上救护车:还给医务人员唱了歌 全球时讯

俄罗斯一男子19楼坠落后自行上救护车:还给医务人员唱了歌

2023-04-05     
拜登又遇到头疼事,前面走龙卷风后面到阿肯色州遭遇极端天气 微头条

突然,一场致命的龙卷风席卷了美国南部和中西部地区,最主要是阿肯色州,其龙卷风威力足以摧毁观景楼剧院的屋顶,附近数百名民众被困在里面,

2023-04-05     
绿豆芽生长过程解说(每一个生命的生长过程都是有一定阶段的)

每一个生命的生长过程都是有一定阶段的,无论是动物还是植物。动物从幼体到成年,植物从种子发芽到开花结果。绿豆芽也是一样,对我们来说不仅

2023-04-05