跳到主要内容
版本:2.10.x(Latest)

基本介绍

GoFrame 框架提供了服务注册发现组件,由 gsvc 组件负责管理。该组件主要定义了服务注册发现的标准接口,采用接口化设计,具体实现由社区组件提供。开发者可以在 https://github.com/gogf/gf/tree/master/contrib/registry 中找到多种注册发现的实现,包括 etcdzookeeperpolarisconsulnacos 等主流注册中心。开发者可以根据项目需求灵活选择,也可以根据 gsvc 组件的接口定义实现自己的注册发现组件。

组件启用

服务注册发现组件采用插件化设计,只有在引入具体的接口实现并配置后才会启用。例如,使用 etcd 实现注册发现的方式如下:

package main

import (
"github.com/gogf/gf/contrib/registry/etcd/v2"
"github.com/gogf/gf/v2/net/gsvc"
)

func main() {
gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`))

// ...
}

常用组件

组件名称文档说明备注
filehttps://github.com/gogf/gf/tree/master/contrib/registry/file仅用于单机测试
etcdhttps://github.com/gogf/gf/tree/master/contrib/registry/etcd
polarishttps://github.com/gogf/gf/tree/master/contrib/registry/polaris
zookeeperhttps://github.com/gogf/gf/tree/master/contrib/registry/zookeeper
consulhttps://github.com/gogf/gf/tree/master/contrib/registry/consul
nacoshttps://github.com/gogf/gf/tree/master/contrib/registry/nacos

更多组件,请参考: https://github.com/gogf/gf/tree/master/contrib/registry

使用示例

HTTP

可以使用 gsvc.SetRegistry(etcd.New(127.0.0.1:2379)) 设置使用 etcd 作为注册发现的实现。其中 etcd.New 方法通过社区组件创建一个 gsvc.Registry 接口的实现对象,然后通过 gsvc.SetRegistry 方法将其设置为全局默认的注册发现组件。

server.go

package main

import (
"github.com/gogf/gf/contrib/registry/etcd/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/net/gsvc"
)

func main() {
gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`))

s := g.Server(`hello.svc`)
s.BindHandler("/", func(r *ghttp.Request) {
g.Log().Info(r.Context(), `request received`)
r.Response.Write(`Hello world`)
})
s.Run()
}

client.go

客户端同样需要设置相同的注册发现组件,并通过 client.SetDiscovery 方法启用服务发现功能:

package main

import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gsvc"
"github.com/gogf/gf/v2/os/gctx"

"github.com/gogf/gf/contrib/registry/etcd/v2"
)

func main() {
gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`))

var (
ctx = gctx.New()
client = g.Client()
)
client.SetDiscovery(gsvc.GetRegistry())
res := client.GetContent(ctx, `http://hello.svc/`)
g.Log().Info(ctx, res)
}

执行后,服务端输出:

$ go run server.go
2023-03-15 20:55:56.256 [INFO] pid[3358]: http server started listening on [:60700]
2023-03-15 20:55:56.256 [INFO] openapi specification is disabled
2023-03-15 20:55:56.256 [DEBU] service register: &{Head: Deployment: Namespace: Name:hello.svc Version: Endpoints:10.35.12.81:60700 Metadata:map[insecure:true protocol:http]}
2023-03-15 20:55:56.297 [DEBU] etcd put success with key "/service/default/default/hello.svc/latest/10.35.12.81:60700", value "{"insecure":true,"protocol":"http"}", lease "7587869265945813002"

SERVER | DOMAIN | ADDRESS | METHOD | ROUTE | HANDLER | MIDDLEWARE
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
hello.svc | default | :60700 | ALL | / | main.main.func1 |
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------
hello.svc | default | :60700 | ALL | /* | github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing | GLOBAL MIDDLEWARE
------------|---------|---------|--------|-------|-----------------------------------------------------------------|--------------------

2023-03-15 20:56:45.739 [INFO] {880eaa8104994c17ffb384495cd4c613} request received

客户端输出:

$ go run client.go
2023-03-15 20:56:45.739 [INFO] {880eaa8104994c17ffb384495cd4c613} Hello world

GRPC

注意

对于 gRPC 协议,必须使用 grpcx.Resolver 模块来设置服务注册发现组件。当服务端在 config.yaml 中没有设置 grpc.name 时,默认服务名称为 default

server.go

代码中的 etcd.New 方法通过社区组件创建一个 gsvc.Registry 接口的实现对象,然后通过 grpcx.Resolver.Register 方法设置为全局的 gRPC 注册发现组件。

package main

import (
"github.com/gogf/gf/contrib/registry/etcd/v2"
"github.com/gogf/gf/contrib/rpc/grpcx/v2"
"github.com/gogf/gf/example/registry/etcd/grpc/controller"
)

func main() {
grpcx.Resolver.Register(etcd.New("127.0.0.1:2379"))

s := grpcx.Server.New()
controller.Register(s)
s.Run()
}

config.yaml

服务端默认的配置文件:

grpc:
name: "demo" # 服务名称
address: ":8000" # 自定义服务监听地址
logPath: "./log" # 日志存储目录路径
logStdout: true # 日志是否输出到终端
errorLogEnabled: true # 是否开启错误日志记录
accessLogEnabled: true # 是否开启访问日志记录
errorStack: true # 当产生错误时,是否记录错误堆栈

client.go

package main

import (
"github.com/gogf/gf/contrib/registry/etcd/v2"
"github.com/gogf/gf/contrib/rpc/grpcx/v2"
"github.com/gogf/gf/example/registry/etcd/grpc/protobuf"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
)

func main() {
grpcx.Resolver.Register(etcd.New("127.0.0.1:2379"))

var (
ctx = gctx.New()
conn = grpcx.Client.MustNewGrpcClientConn("demo")
client = protobuf.NewGreeterClient(conn)
)
res, err := client.SayHello(ctx, &protobuf.HelloRequest{Name: "World"})
if err != nil {
g.Log().Error(ctx, err)
return
}
g.Log().Debug(ctx, "Response:", res.Message)
}

执行后,服务端输出:

$ go run server.go
2023-03-15 21:06:57.204 [DEBU] service register: &{Head: Deployment: Namespace: Name:demo Version: Endpoints:10.35.12.81:61978 Metadata:map[protocol:grpc]}
2023-03-15 21:06:57.257 [DEBU] etcd put success with key "/service/default/default/demo/latest/10.35.12.81:61978", value "{"protocol":"grpc"}", lease "7587869265945813015"
2023-03-15 21:06:57.257 [INFO] pid[5786]: grpc server started listening on [:61978]
2023-03-15 21:07:04.955 {08f0aead94994c1731591d2b653ddc18} /protobuf.Greeter/SayHello, 0.002ms, name:"World", message:"Hello World"

客户端输出:

$ go run client.go
2023-03-15 21:07:04.950 [DEBU] Watch key "/service/default/default/demo/latest/"
2023-03-15 21:07:04.952 [DEBU] client conn updated with addresses [{"Addr":"10.35.12.81:61978","ServerName":"demo","Attributes":{},"BalancerAttributes":null,"Type":0,"Metadata":null}]
2023-03-15 21:07:04.953 [DEBU] client conn updated with addresses [{"Addr":"10.35.12.81:61978","ServerName":"demo","Attributes":{},"BalancerAttributes":null,"Type":0,"Metadata":null}]
2023-03-15 21:07:04.955 [DEBU] {08f0aead94994c1731591d2b653ddc18} Response: Hello World