Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

基本介绍

GoFrame框架提供了服务注册发现组件,由gsvc组件管理,该组件主要定义了注册发现的接口,具体的实现由社区组件提供: https://github.com/gogf/gf/tree/master/contrib/registry 。目前社区组件提供了多种注册发现的实现,如 etcd, zookeeper, polaris等,开发者根据需要插拔使用,也可以根据gsvc组件的接口定义实现自己的注册发现组件。

组件启用

注册发现组件只有在引入具体的接口实现时才会启用。例如,使用etcd实现注册发现的使用方式:

Code Block
languagego
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`))
	
    // ...
}

常用组件

更多组件,请参考: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

Code Block
languagego
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

Code Block
languagego
package main

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

func main() {
	gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`))
	ctx := gctx.New()
	res := g.Client().GetContent(ctx, `http://hello.svc/`)
	g.Log().Info(ctx, res)
}

执行后,服务端输出:

Code Block
languagexml
$ 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

客户端输出:

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

GRPC

Note

如果是GRPC协议,必须使用grpcx.Resolvergrpcx模块来设置服务注册发现组件。Server 端未在 config.yaml 中设置 grpc.name 值时,默认值是 default

server.go

代码中的etcd.New表示通过社区组件创建一个gsvc.Registry的接口实现对象,并通过grpcx.Resolver.Register设置全局的grpc注册发现接口实现对象。

Code Block
languagego
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

服务端默认的配置文件:


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


client.go

Code Block
languagego
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)
}

执行后,服务端输出:

Code Block
languagexml
$ 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"

客户端输出:

Code Block
languagexml
$ 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

常见问题

在全局启用服务注册发现时,如何关闭特定请求的发现特性

问题:在使用gclient时,如果全局开启了服务注册发现特性,那么gclient的所有请求都将走发现服务。但是针对不是在服务注册发现中维护的服务,例如一个IP:PORT的地址请求或者一个外网请求服务,也会走发现服务,并且会引起服务找不到而报错。如何避免这样的问题?

回答:在全局启用服务发现特性时,gclient请求默认会使用全局设置的发现服务,如果特定的请求不使用发现服务,那么可以通过请求默认情况下会使用全局设置的发现服务,如果特定的请求不使用发现服务,那么可以通过gclient.ClientDiscovery(nil)链式操作方法来关闭当前请求的发现服务,或者SetDiscovery(nil)配置方法来关闭当前客户端的发现服务。这样请求就不会走发现服务啦。

例子

Code Block
languagego
// 通过链式操作方法来关闭当前请求的发现服务
g.Client().Discovery(nil).Get(ctx, "http://192.168.1.1/api/v1/user")

// 通过配置方法来关闭当前客户端的发现服务
client := g.Client()
client.SetDiscovery(nil)
client.Get(ctx, "http://192.168.1.1/api/v1/user")






·

Panel
titleContent Menu

Table of Contents