为什么有这篇文章?
虽然go-kratos提供了非常方便的对服务注册和发现配置的封装。我们能很轻松地把我们选定组件(consul,etcd,dicovery等等)注入到初始化地流程中。
但由于go-kratos框架强依赖Google wire进行依赖注入(DI),而官方教程并没有完整展示生产级的注册服务实例和服务发现的方法,所以我整理出了这篇文章。
本文以etcd为例。
本文的完整代码可以在这里找到,示例代码。
项目目录
svc-b├── api│ └── helloworld│ └── v1│ ├── error_reason.pb.go│ ├── error_reason.proto│ ├── greeter_grpc.pb.go│ ├── greeter_http.pb.go│ ├── greeter.pb.go│ └── greeter.proto├── cmd│ └── svc-b│ ├── main.go│ ├── wire_gen.go│ └── wire.go├── configs│ └── config.yaml├── Dockerfile├── go.mod├── go.sum├── internal│ ├── biz│ │ ├── biz.go│ │ ├── greeter.go│ │ └── README.md│ ├── conf│ │ ├── conf.pb.go│ │ └── conf.proto│ ├── data│ │ ├── data.go│ │ ├── greeter.go│ │ └── README.md│ ├── server│ │ ├── grpc.go│ │ ├── http.go│ │ ├── registry.go│ │ └── server.go│ └── service│ ├── greeter.go│ ├── README.md│ └── service.go├── LICENSE├── Makefile├── openapi.yaml├── README.md└── third_party
步骤
更改config.yaml
registry:etcd:endpoints:- "127.0.0.1:2379"
更改internal/conf/conf.proto
在 Kratos 中,Bootstrap(引导程序)并不是一个具有复杂逻辑的运行组件,而是整个服务配置文件的“根节点”或“入口字典”。
go-kratos使用protobuf保证了Bootstrap的类型安全。
新增字段
message Bootstrap {Server server = 1;Data data = 2;Registry registry = 3;
}message Registry {message Etcd {repeated string endpoints = 1;}Etcd etcd = 1;
}
接着执行make config
新增internal/server/registry.go
package serverimport ("svc-b/internal/conf" // 替换为你的真实项目路径"github.com/go-kratos/kratos/contrib/registry/etcd/v2""github.com/go-kratos/kratos/v2/registry"clientv3 "go.etcd.io/etcd/client/v3"
)// NewEtcdClient 创建 etcd 客户端
func NewEtcdClient(c *conf.Registry) *clientv3.Client {client, err := clientv3.New(clientv3.Config{Endpoints: c.Etcd.Endpoints,})if err != nil {panic(err) // 启动时连不上 etcd 直接 panic 是合理的设计}return client
}// NewRegistrar 创建 Kratos 服务注册器
func NewRegistrar(client *clientv3.Client) registry.Registrar {return etcd.New(client)
}// NewDiscovery 创建 Kratos 服务发现器 (如果你同时需要调用其他服务)
func NewDiscovery(client *clientv3.Client) registry.Discovery {return etcd.New(client)
}
注册到internal/server的ProviderSet
var ProviderSet = wire.NewSet(NewGRPCServer, NewHTTPServer, NewEtcdClient, NewRegistrar, NewDiscovery)
修改cmd/服务名/wire.go
func wireApp(*conf.Server, *conf.Data, *conf.Registry, log.Logger) (*kratos.App, func(), error) { // <-- 新增 *conf.Registrypanic(wire.Build(server.ProviderSet, data.ProviderSet, biz.ProviderSet, service.ProviderSet, newApp))
}
修改cmd/服务名/main.go中的newApp
func newApp(logger log.Logger, gs *grpc.Server, hs *http.Server, rr registry.Registrar) *kratos.App { // <-- 修改函数签名return kratos.New(kratos.ID(id),kratos.Name(Name),kratos.Version(Version),kratos.Metadata(map[string]string{}),kratos.Logger(logger),kratos.Server(gs,hs,),kratos.Registrar(rr), // <-- 把Registry放进来)
}
应用更改
main.go:
app, cleanup, err := wireApp(bc.Server, bc.Data, bc.Registry, logger)if err != nil {panic(err)}defer cleanup()
运行
make generate
结尾
这样子,你就可以在服务中使用etcd了。
完整代码在这里。
