go-zero集成nacos踩坑记

1.创建项目

编写app.api

syntax = "v1"

type (
	UserLoginReq struct{}
	UserInfoReq  {
		Id int64 `path:"id"`
	}
	UserLoginResp      struct{}
	UserInfoResp       struct{}
	UserInfoUpdateReq  struct{}
	UserInfoUpdateResp struct{}
)

type (
	UserRoleReq        struct{}
	UserRoleResp       struct{}
	UserRoleUpdateReq  struct{}
	UserRoleUpdateResp struct{}
	UserRoleAddReq     struct{}
	UserRoleAddResp    struct{}
	UserRoleDeleteReq  struct{}
	UserRoleDeleteResp struct{}
)

type (
	UserClassReq        struct{}
	UserClassResp       struct{}
	UserClassUpdateReq  struct{}
	UserClassUpdateResp struct{}
	UserClassAddReq     struct{}
	UserClassAddResp    struct{}
	UserClassDeleteReq  struct{}
	UserClassDeleteResp struct{}
)

@server (
	prefix: /v1
	group:  user
	//signature: true
	middleware: UserAgentMiddleware
)
service user-api {
	@handler UserLogin
	post /user/login (UserLoginReq) returns (UserLoginResp)

	@handler getUserInfo
	get /user/info/:id (UserInfoReq) returns (UserInfoResp)

	@handler UserInfoUpdate
	post /user/info/update (UserInfoUpdateReq) returns (UserInfoUpdateResp)

	@handler UserList
	get /user/list returns ([]UserInfoResp)
}

@server (
	prefix: /v1
	group:  role
)
service user-api {
	@handler UserRoleList
	get /user/role/list returns ([]UserRoleResp)

	@handler UserRoleUpdate
	get /user/role/update (UserRoleUpdateReq) returns (UserRoleUpdateResp)

	@handler UserRoleInfo
	get /user/role/info (UserRoleReq) returns (UserRoleResp)

	@handler UserRoleAdd
	get /user/role/add (UserRoleAddReq) returns (UserRoleAddResp)

	@handler UserRoleDelete
	get /user/role/delete (UserRoleDeleteReq) returns (UserRoleDeleteResp)
}

@server (
	prefix: /v1
	group:  class
)
service user-api {
	@handler UserClassList
	get /user/class/list returns ([]UserClassResp)

	@handler UserClassUpdate
	get /user/class/update (UserClassUpdateReq) returns (UserClassUpdateResp)

	@handler UserClassInfo
	get /user/class/info (UserClassReq) returns (UserClassResp)

	@handler UserClassAdd
	get /user/class/add (UserClassAddReq) returns (UserClassAddResp)

	@handler UserClassDelete
	get /user/class/delete (UserClassDeleteReq) returns (UserClassDeleteResp)
}

编写deposit.proto文件

syntax = "proto3";

package mock;

option go_package = "./mock";

message DepositRequest {
  float amount = 1;
}

message DepositResponse {
  bool ok = 1;
}

service DepositService {
  rpc Deposit(DepositRequest) returns (DepositResponse);
}

分别使用如下命令生成代码

goctl api go --api app.api --dir ../ --style go_zero
goctl rpc protoc deposit.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=../ --style go_zero -m

2.安装依赖

go get -u github.com/zeromicro/zero-contrib/zrpc/registry/nacos

3.修改grpc服务端代码

package main

import (
	"flag"
	"fmt"
	"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
	"github.com/zeromicro/zero-contrib/zrpc/registry/nacos"

	"github.com/zeromicro/go-zero/core/conf"
	"github.com/zeromicro/go-zero/core/service"
	"github.com/zeromicro/go-zero/zrpc"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
	"service/internal/config"
	depositserviceServer "service/internal/server/depositservice"
	"service/internal/svc"
	"service/proto/pb/mock"
)

var configFile = flag.String("f", "etc/deposit.yaml", "the config file")

func main() {
	flag.Parse()

	var c config.Config
	conf.MustLoad(*configFile, &c)
	ctx := svc.NewServiceContext(c)

	s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
		mock.RegisterDepositServiceServer(grpcServer, depositserviceServer.NewDepositServiceServer(ctx))

		if c.Mode == service.DevMode || c.Mode == service.TestMode {
			reflection.Register(grpcServer)
		}
	})
	defer s.Stop()
	// 注册服务
	sc := []constant.ServerConfig{
		*constant.NewServerConfig(c.Nacos.Ip, c.Nacos.Port),
	}

	cc := &constant.ClientConfig{
		NamespaceId:         c.Nacos.Namespace,
		TimeoutMs:           50000,
		NotLoadCacheAtStart: c.Nacos.NotLoadCacheAtStart,
		LogDir:              "/tmp/nacos/log",
		CacheDir:            "/tmp/nacos/cache",
		LogLevel:            c.Nacos.LogLevel,
	}
	opts := nacos.NewNacosConfig(c.RpcServerConf.Name, c.ListenOn, sc, cc)
	nacos.RegisterService(opts)
	fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
	s.Start()
}

 配置文件

Name: deposit
ListenOn: 0.0.0.0:8080
#Etcd:
  #Hosts:
    #- 172.18.0.30:2379
  #Key: deposit
Nacos:
  Ip: 172.18.0.145
  Port: 8848
  Namespace: local_test
  NotLoadCacheAtStart: true
  LogLevel: debug
Log:
  Encoding: plain

4.修改客户端代码

import 加上 _ "github.com/zeromicro/zero-contrib/zrpc/registry/nacos"

主要目的是让执行init方法,注册nacos的解析builder

func init() {
	resolver.Register(&builder{})
}

完整代码

package main

import (
	"flag"
	"fmt"
	"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
	"github.com/zeromicro/zero-contrib/zrpc/registry/nacos"

	"github.com/zeromicro/go-zero/core/conf"
	"github.com/zeromicro/go-zero/core/service"
	"github.com/zeromicro/go-zero/zrpc"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
	"service/internal/config"
	depositserviceServer "service/internal/server/depositservice"
	"service/internal/svc"
	"service/proto/pb/mock"
)

var configFile = flag.String("f", "etc/deposit.yaml", "the config file")

func main() {
	flag.Parse()

	var c config.Config
	conf.MustLoad(*configFile, &c)
	ctx := svc.NewServiceContext(c)

	s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
		mock.RegisterDepositServiceServer(grpcServer, depositserviceServer.NewDepositServiceServer(ctx))

		if c.Mode == service.DevMode || c.Mode == service.TestMode {
			reflection.Register(grpcServer)
		}
	})
	defer s.Stop()
	// 注册服务
	sc := []constant.ServerConfig{
		*constant.NewServerConfig(c.Nacos.Ip, c.Nacos.Port),
	}

	cc := &constant.ClientConfig{
		NamespaceId:         c.Nacos.Namespace,
		TimeoutMs:           50000,
		NotLoadCacheAtStart: c.Nacos.NotLoadCacheAtStart,
		LogDir:              "/tmp/nacos/log",
		CacheDir:            "/tmp/nacos/cache",
		LogLevel:            c.Nacos.LogLevel,
	}
	opts := nacos.NewNacosConfig(c.RpcServerConf.Name, c.ListenOn, sc, cc)
	nacos.RegisterService(opts)
	fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
	s.Start()
}

配置文件

Name: user-api
Host: 0.0.0.0
Port: 8888
Timeout: -1
DepositServiceConf:
 # Etcd:
    #Hosts:
      #- 172.18.0.30:2379
    #Key: deposit
  Timeout: -1
  Target: nacos://172.18.0.145:8848/deposit?namespaceid=local_test
Log:
  Encoding: plain

其他业务代码与ETCD方式一样,自己可以调试一下

个人集成nacos使用的zero-contrib版本v1.1.0,目前最新的,发现一直调不通,一直报错

GOROOT=D:\Program Files\Go\go1.20.7 #gosetup
GOPATH=D:\Program Files\Go #gosetup
"D:\Program Files\Go\go1.20.7\bin\go.exe" build -o C:\Users\27383\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_client.exe -gcflags "all=-N -l" client #gosetup
"D:\Program Files\JetBrains\GoLand 2023.1.2\plugins\go-plugin\lib\dlv\windows\dlv.exe" --listen=127.0.0.1:61692 --headless=true --api-version=2 --check-go-version=false --only-same-user=false exec C:\Users\27383\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\___go_build_client.exe --
API server listening at: 127.0.0.1:61692
2023-09-23T16:47:40.823+0800    INFO    nacos_client/nacos_client.go:65 logDir:<C:\Users\27383\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\log> cacheDir:<C:\Users\27383\AppData\Local\JetBrains\GoLand2023.1\tmp\GoLand\cache>
2023-09-23T16:47:48.662+08:00    info   [Nacos resolver] Watch has been finished        caller=nacos@v0.0.0-20230807142214-5952d42ba776/resolver.go:70
2023/09/23 16:47:48 rpc dial: nacos://172.18.0.145:8848/deposit?namespaceid=local_test, error: context deadline exceeded, make sure rpc service "deposit?namespaceid=local_test" is already started

goroutine 1 [running]:
runtime/debug.Stack()
        D:/Program Files/Go/go1.20.7/src/runtime/debug/stack.go:24 +0x7a
github.com/zeromicro/go-zero/core/logx.Must({0x3286fc0, 0xc0002918a0})
        D:/Program Files/Go/pkg/mod/github.com/zeromicro/go-zero@v1.5.4/core/logx/logs.go:225 +0x65
github.com/zeromicro/go-zero/zrpc.MustNewClient({{{0x0, 0x0, 0x0}, {0x0, 0x0}, 0x0, {0x0, 0x0}, {0x0, 0x0}, ...}, ...}, ...)
        D:/Program Files/Go/pkg/mod/github.com/zeromicro/go-zero@v1.5.4/zrpc/client.go:45 +0x13d
client/internal/svc.NewServiceContext({{{{0xc000114af0, 0x8}, {{...}, {...}, {...}, {...}, {...}, {...}, 0x0, 0x0, ...}, ...}, ...}, ...})
        D:/Program Files/Go/IdeaProject/gozero/client/internal/svc/service_context.go:26 +0x105
main.main()
        D:/Program Files/Go/IdeaProject/gozero/client/user.go:26 +0x198
2023-09-23T16:47:48.662+08:00    fatal  rpc dial: nacos://172.18.0.145:8848/deposit?namespaceid=local_test, error: context deadline exceeded, make sure rpc service "deposit?namespaceid=local_test" is already started

goroutine 1 [running]:
runtime/debug.Stack()
        D:/Program Files/Go/go1.20.7/src/runtime/debug/stack.go:24 +0x7a
github.com/zeromicro/go-zero/core/logx.Must({0x3286fc0, 0xc0002918a0})
        D:/Program Files/Go/pkg/mod/github.com/zeromicro/go-zero@v1.5.4/core/logx/logs.go:225 +0x65
github.com/zeromicro/go-zero/zrpc.MustNewClient({{{0x0, 0x0, 0x0}, {0x0, 0x0}, 0x0, {0x0, 0x0}, {0x0, 0x0}, ...}, ...}, ...)
        D:/Program Files/Go/pkg/mod/github.com/zeromicro/go-zero@v1.5.4/zrpc/client.go:45 +0x13d
client/internal/svc.NewServiceContext({{{{0xc000114af0, 0x8}, {{...}, {...}, {...}, {...}, {...}, {...}, 0x0, 0x0, ...}, ...}, ...}, ...})
        D:/Program Files/Go/IdeaProject/gozero/client/internal/svc/service_context.go:26 +0x105
main.main()
        D:/Program Files/Go/IdeaProject/gozero/client/user.go:26 +0x198


Debugger finished with the exit code 0


然后漫长的调试跟源码发现问题,这里实际上是zero-contrib v1.1.0的bug引起的,看如下相关截图

        简单理解就是由于 客户端启动的时候会加载本地缓存导致的,客户端加载到服务后会已文件的方式缓存到本地磁盘,下次启动的时候再次从磁盘加载,然后与远端naocs服务请求做对比,如果发现服务没有变化导致相关关键代码没有执行

        实际上客户端使用本地缓存也是为了保证服务的稳定性,比如客户端访问不到nacos的情况下,可以加载本地缓存使用服务,不会导致整个服务不可用

        不过这里最简单的修改方式是直接不使用缓存,官方没有给相关的配置option给用户手动设置,只能手动修改源码解决,但是这种方式只是临时解决方案,实际上还是需要想办法触发关键代码来解除阻塞,后续有时间再pr相关代码进行修复

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王柳敬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值