地址:https://github.com/go-micro/go-micro

grpc-test-demo:https://gitee.com/jn-shao/go-gmicro-rpc-test.git

go-micro api网关:

api网关替换为kong ,使用consul做dns服务器。

​ 旧项目用的是http->go-micro v3 rpc,后端全都是自己的rpc,proto定义数据格式如下:

message Request {
string method = 1;
string path = 2;
map<string, Pair> header = 3;
map<string, Pair> get = 4;
map<string, Pair> post = 5;
string body = 6;
string url = 7;
} message Response {
int32 statusCode = 1;
map<string, Pair> header = 2;
string body = 3;
}

不通用,非restful,参数动态前后端参数处理很麻烦,后续换网关,调整服务都很被动,go-micro v3不熟悉,发现go-micro v3 将server和client抽象出来有各自的管道处理(middleware),所以链路、熔断限流这些中间件使用框架本身封装的不需要动,只需使用插件替换server和client,改造难度不是很大,索性研究下全部替换掉。

注:服务名不能使用 . 不然dns会解析不到ip,可以通过下面命令测试自己的服务:

$ dig @<consul ip> -p 8600 <服务名>.service.consul SRV

api:

server转为http restful 替换为gin路由器https://github.com/go-micro/plugins/tree/main/v3/server/http

​ 官方例子可以看出插件是把路由器放进去,可以直接替换gin,简单来讲http基础包封装的http框架即实现Handler的ServeHTTP方法的都可以替换

client转为grpc client:https://github.com/go-micro/plugins/tree/main/v3/client/grpc

部分修改代码:

package initialize

func Routers() *gin.Engine {
Router := gin.Default() ApiGroup := Router.Group("/v1")
router.InitPodRouter(ApiGroup) return Router
}

package main

	......
srv := httpServer.NewServer(
func(options *server.Options) {
options.Advertise = serviceHost + ":" + servicePort
},
server.Name("podApi"),
server.Version("latest"),
)
mux := initialize.Routers()
if err := srv.Handle(srv.NewHandler(mux)); err != nil {
common.Fatal(err)
}
service := micro.NewService(
//开启gin http server
micro.Server(srv),
//使用grpc client
micro.Client(grpcClient.NewClient(client.RequestTimeout(time.Second*5))),
......
)
......
global.PodService = go_micro_service_pod.NewPodService("podSrv", service.Client())
......

srv:

server转为grpc server:https://github.com/go-micro/plugins/tree/main/v3/server/grpc

部分修改代码:

package main

......
service := micro.NewService(
//开启grpc server
micro.Server(grpcServer.NewServer(func(options *server.Options) {
options.Advertise = global.ServerConfig.Host + ":" +
strconv.FormatUint(global.ServerConfig.Port, 10)
})),
......
)

配置中心consul:

​ 旧项目注册中心和配置中心使用的都是consul,这里配置中心替换为nacos,使用go-micro v3封装的confighttps://github.com/go-micro/plugins/tree/main/v3/config/source

​ viper:https://github.com/spf13/viper

​ nacos-sdk-go:https://github.com/nacos-group/nacos-sdk-go

​ 部分修改代码:

package initialize

var configFileName = "config.yaml"

func InitConfig() {

	var nacosConfig localconfig.NacosConfig

	if err := GetLocalConfig(configFileName, &nacosConfig); err != nil {
common.Fatal(err)
} config, err := GetNacosConfig(nacosConfig.Host, nacosConfig.Port, nacosConfig.Namespace,
nacosConfig.DataId, nacosConfig.Group)
if err != nil {
common.Fatal(err)
} if err := config.Get().Scan(&global.ServerConfig); err != nil {
common.Fatal(err)
}
} func GetLocalConfig(localConfigFileName string, config interface{}) error {
v := viper.New()
v.SetConfigFile(localConfigFileName)
if err := v.ReadInConfig(); err != nil {
return err
} if err := v.Unmarshal(config); err != nil {
return err
} fmt.Printf("本地配置信息:%+v", config)
zap.S().Infof("本地配置信息:%+v", config)
// 动态监控
func() {
v.WatchConfig()
v.OnConfigChange(func(e fsnotify.Event) {
fmt.Printf("本地配置文件产生变化:%s", e.Name)
zap.S().Infof("本地配置文件产生变化:%s", e.Name)
_ = v.ReadInConfig() // 读取配置数据
_ = v.Unmarshal(config)
fmt.Printf("本地配置信息:%+v", config)
zap.S().Infof("本地配置信息:%+v", config)
})
}() return nil
} func GetNacosConfig(host string, port uint64, namespace string, dataId string, group string) (config.Config, error)
clientConfig := constant.ClientConfig{
NamespaceId: namespace,
TimeoutMs: 5000,
NotLoadCacheAtStart: true,
LogDir: "tmp/nacos/log",
CacheDir: "tmp/nacos/cache",
LogLevel: "debug",
}
nacosSource := nacos.NewSource(
nacos.WithAddress([]string{host + ":" + strconv.FormatUint(port, 10)}),
nacos.WithClientConfig(clientConfig),
nacos.WithDataId(dataId),
nacos.WithGroup(group),
)
conf, err := config.NewConfig()
if err != nil {
return conf, err
}
err = conf.Load(nacosSource)
return conf, err
}

注·:

(1)clientConfig中的LogDir和CacheDir要手动创建

(2)此处有一个坑,遇到nacos v1和v2兼容性问题,v2多开了一个9848 grpc端口,nacos-sdk-go v2配置http无效,都会转成grpc请求9848端口获取配置信息,当然使用nacos-sdk-go v1请求8848是没问题的,但go-micro v3 插件依赖的是nacos-sdk-go v2,前期没注意按照v1部署,需打开9848端口。被这个bug:https://github.com/nacos-group/nacos-sdk-go/issues/531干扰了,官方应该是有意将9848专门负责拉取配置信息,并且兼容v1版本

​ nacos-docker:https://github.com/nacos-group/nacos-docker

// 获取容器ip
$ docker image inspect --format='{{json .NetworkSettings.IPAddress}}' <nacos容器>
// 映射端口
$ iptables -t nat -A DOCKER -p tcp --dport 9848 -j DNAT --to-destination <nacos ip>:9848

go-micro v3 rpc服务一次改造经历的更多相关文章

  1. 为什么需要 RPC 服务?

    链接:https://www.jianshu.com/p/362880b635f0 在传统的开发模式中,我们通常将系统的各个服务部署在单台机器,随着服务的扩展,这种方式已经完全无法满足系统大规模的扩展 ...

  2. 基于APM实现RPC服务和消息队列的指定消费

    本文内容是基于公司现有框架整理的一篇专利文章.该框架包含完整的一套DevOps流程,包括工单系统(容器申请.服务部署等)\配置中心\路由配置中心\服务治理平台\消息治理平台\葛朗台(基于Docker+ ...

  3. go-micro开发RPC服务的方法及其运行原理

    go-micro是一个知名的golang微服务框架,最新版本是v4,这篇文章将介绍go-micro v4开发RPC服务的方法及其运作原理. 基本概念 go-micro有几个重要的概念,后边开发RPC服 ...

  4. 基于netty轻量的高性能分布式RPC服务框架forest<下篇>

    基于netty轻量的高性能分布式RPC服务框架forest<上篇> 文章已经简单介绍了forest的快速入门,本文旨在介绍forest用户指南. 基本介绍 Forest是一套基于java开 ...

  5. 基于netty轻量的高性能分布式RPC服务框架forest<上篇>

    工作几年,用过不不少RPC框架,也算是读过一些RPC源码.之前也撸过几次RPC框架,但是不断的被自己否定,最近终于又撸了一个,希望能够不断迭代出自己喜欢的样子. 顺便也记录一下撸RPC的过程,一来作为 ...

  6. Thrift 个人实战--Thrift RPC服务框架日志的优化

    前言: Thrift作为Facebook开源的RPC框架, 通过IDL中间语言, 并借助代码生成引擎生成各种主流语言的rpc框架服务端/客户端代码. 不过Thrift的实现, 简单使用离实际生产环境还 ...

  7. Thrift 个人实战--RPC服务的发布订阅实现(基于Zookeeper服务)

    前言: Thrift作为Facebook开源的RPC框架, 通过IDL中间语言, 并借助代码生成引擎生成各种主流语言的rpc框架服务端/客户端代码. 不过Thrift的实现, 简单使用离实际生产环境还 ...

  8. 基于开源Dubbo分布式RPC服务框架的部署整合

    一.前言 Dubbo 作为SOA服务化治理方案的核心框架,用于提高业务逻辑的复用.整合.集中管理,具有极高的可靠性(HA)和伸缩性,被应用于阿里巴巴各成员站点,同时在包括JD.当当在内的众多互联网项目 ...

  9. Metasploit RPC服务共享

    1) 启动一个新的MSF RPC服务,-P参数后面指定连接到的RPC服务需要提供的口令,-U参数指定连接所需输入的用户名,使用-a 0.0.0.0将RPC服务绑定到所有的网络地址,否则服务默认只绑定到 ...

  10. RPC服务的发布订阅实现Thrift

    Thrift 个人实战--RPC服务的发布订阅实现(基于Zookeeper服务) 前言: Thrift作为Facebook开源的RPC框架, 通过IDL中间语言, 并借助代码生成引擎生成各种主流语言的 ...

随机推荐

  1. 03_配置Java环境变量

    配置Java环境变量 右键我的电脑-属性-高级系统设置-环境变量 系统变量-新建-变量名JAVA_HOME,变量值为JDK安装路径 系统变量-新建-变量名CLASSPATH,变量值为英文输入法下的. ...

  2. C/C++ 宏定义

    宏定义(无参宏定义和带参宏定义) 宏定义是比较常用的预处理指令,即使用"标识符"来表示"替换列表"中的内容.标识符称为宏名,在预处理过程中,预处理器会把源程序中 ...

  3. .Net下的分布式唯一ID

    分布式唯一ID,顾名思义,是指在全世界任何一台计算机上都不会重复的唯一Id. 在单机/单服务器/单数据库的小型应用中,不需要用到这类东西.但在高并发.海量数据.大型分布式应用中,这类却是构建整个系统的 ...

  4. 影响 erp 系统实施成功的因素是什么?

    影响ERP系统实施成功的因素很多,主要有以下几点:企业一把手是否大力支持.实施顾问是否专业负责.ERP系统是否强大灵活且适用三个方面!没有企业一把手的大力支持,ERP的应用基本上不可能获得成功.ERP ...

  5. Go实现优雅关机与平滑重启

    前言 优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种对客户端友好的关机方式.而执行Ctrl+C关闭服务端时,会强制结束进程导致正在访问的请求出 ...

  6. Windows应急响应——敬请期待!

    检查内容 进程.服务.用户.网络连接.漏洞补丁.木马查杀. 工具 火绒剑. 防护措施 杀毒软件

  7. Python 根据两个字段排序 中文排序 汉字排序 升序 降序

    Python3写法 代码 # -*- coding: utf-8 -*- # 需求:年龄倒序,姓名正序 from itertools import chain from pypinyin import ...

  8. 这次彻底读透 Redis

    1. Redis 管道 我们通常使用 Redis 的方式是,发送命令,命令排队,Redis 执行,然后返回结果,这个过程称为Round trip time(简称RTT, 往返时间).但是如果有多条命令 ...

  9. 【神经网络】softmax回归

    前言 softmax回归为一种分类模型. 基本原理 由于softmax回归也是一种线性叠加算法,且需要输出离散值. 很自然地想到,可以取值最大的输出为置信输出.更进一步想到,如果有三个人A.B.C分别 ...

  10. JAVA-注解之 TODO、FIXME、XXX

    TODO.FIXME.XXX    //TODO : 表示待实现的功能    //FIXME: 代码存在Bug,不能Run或运行结果不正确,需要修复    //XXX  : 勉强可以工作,但是实现的方 ...