一、简介

关于服务注册和服务发现介绍,我前面的文章有介绍过 - 服务注册和发现的文章

作为服务中心的软件有很多,比如 etcd,consul,nacos,zookeeper 等都可以作为服务中心。

go-kratos 把这些服务中心的功能作为插件,集成进了 kratos 中。

下面就用 etcd 作为服务中心来说说 kratos 里服务注册和服务发现功能的使用。

二、服务注册和服务发现

2.1 接口定义

从 go-kratos 服务注册和发现文档中,我们知道它的接口定义非常简单:

注册和反注册服务:

type Registrar interface {
// 注册实例
Register(ctx context.Context, service *ServiceInstance) error
// 反注册实例
Deregister(ctx context.Context, service *ServiceInstance) error
}

获取服务:

type Discovery interface {
// 根据 serviceName 直接拉取实例列表
GetService(ctx context.Context, serviceName string) ([]*ServiceInstance, error)
// 根据 serviceName 阻塞式订阅一个服务的实例列表信息
Watch(ctx context.Context, serviceName string) (Watcher, error)
}

2.2 简单使用

服务端注册服务

使用 etcd 作为服务中心。

1.新建 etcd连接client, etcdregitry.New(client)

2.把 regitry传入 kratos.Registrar(r)

3.传入服务名称 kratos.Name("helloworld")

看官方的示例代码,server/main.go

package main

import (
"context"
"fmt"
"log" etcdregitry "github.com/go-kratos/kratos/contrib/registry/etcd/v2"
"github.com/go-kratos/kratos/v2"
"github.com/go-kratos/kratos/v2/middleware/recovery"
"github.com/go-kratos/kratos/v2/transport/grpc"
"github.com/go-kratos/kratos/v2/transport/http" pb "github.com/go-kratos/examples/helloworld/helloworld"
etcdclient "go.etcd.io/etcd/client/v3"
) type server struct {
pb.UnimplementedGreeterServer
} func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: fmt.Sprintf("welcome %+v!", in.Name)}, nil
} func main() {
// 创建 etcd client 连接
client, err := etcdclient.New(etcdclient.Config{
Endpoints: []string{"127.0.0.1:2379"},
})
if err != nil {
log.Fatal(err)
} // 初始化 http server
httpSrv := http.NewServer(
http.Address(":8080"),
http.Middleware(
recovery.Recovery(),
),
) // 初始化 grpc server
grpcSrv := grpc.NewServer(
grpc.Address(":9000"),
grpc.Middleware(
recovery.Recovery(),
),
) // 在服务器上注册服务
s := &server{}
pb.RegisterGreeterServer(grpcSrv, s)
pb.RegisterGreeterHTTPServer(httpSrv, s) // 创建一个 registry 对象,就是对 ectd client 操作的一个包装
r := etcdregitry.New(client) app := kratos.New(
kratos.Name("helloworld"), // 服务名称
kratos.Server(
httpSrv,
grpcSrv,
),
kratos.Registrar(r), // 填入etcd连接(etcd作为服务中心)
)
if err := app.Run(); err != nil {
log.Fatal(err)
}
}

etcd作为服务中心的使用步骤图解:

客户端获取服务

客户端的服务发现,主要也是 3 个步骤.

1.新建 etcd连接, 传入到 etcdregitry.New(client)

2.将 registry 传入 WithDiscovery(r)

3.获取服务WithEndpoint("discovery:///helloworld")

步骤与服务没有多大区别。

官方的示例代码,client/main.go

package main

import (
"context"
"log"
"time" "github.com/go-kratos/examples/helloworld/helloworld"
etcdregitry "github.com/go-kratos/kratos/contrib/registry/etcd/v2"
"github.com/go-kratos/kratos/v2/transport/grpc"
"github.com/go-kratos/kratos/v2/transport/http"
etcdclient "go.etcd.io/etcd/client/v3"
srcgrpc "google.golang.org/grpc"
) func main() {
client, err := etcdclient.New(etcdclient.Config{
Endpoints: []string{"127.0.0.1:2379"},
})
if err != nil {
log.Fatal(err)
} r := etcdregitry.New(client) // 传入 etcd client,也就是选择 etcd 为服务中心 connGRPC, err := grpc.DialInsecure(
context.Background(),
grpc.WithEndpoint("discovery:///helloworld"), // 服务发现
grpc.WithDiscovery(r), // 传入etcd registry
)
if err != nil {
log.Fatal(err)
}
defer connGRPC.Close() connHTTP, err := http.NewClient(
context.Background(),
http.WithEndpoint("discovery:///helloworld"),
http.WithDiscovery(r),
http.WithBlock(),
)
if err != nil {
log.Fatal(err)
}
defer connHTTP.Close() for {
callHTTP(connHTTP)
callGRPC(connGRPC)
time.Sleep(time.Second)
}
} func callHTTP(conn *http.Client) {
client := helloworld.NewGreeterHTTPClient(conn)
reply, err := client.SayHello(context.Background(), &helloworld.HelloRequest{Name: "go-kratos"})
if err != nil {
log.Fatal(err)
}
log.Printf("[http] SayHello %+v\n", reply)
} func callGRPC(conn *srcgrpc.ClientConn) {
client := helloworld.NewGreeterClient(conn)
reply, err := client.SayHello(context.Background(), &helloworld.HelloRequest{Name: "go-kratos"})
if err != nil {
log.Fatal(err)
}
log.Printf("[grpc] SayHello %+v\n", reply)
}

运行程序

1.运行etcd,没有安装etcd的请自行百度或gg安装

2.运行服务端

$ cd ./etcd/server
$ go run ./main.go
INFO msg=[HTTP] server listening on: [::]:8080
INFO msg=[gRPC] server listening on: [::]:9000

3.运行客户端

$ cd ./client
$ go run .\main.go
INFO msg=[resolver] update instances: [{"id":"8fc08b88-e37b-11ec-bb6f-88d7f62323b4","name":"helloworld","version":"","metadata":null,"endpoints":["http://192.168.56.1:8080","grpc://192.168.56.1:9000"]}]
2022/06/04 04:28:21 [http] SayHello message:"welcome go-kratos!"
2022/06/04 04:28:21 [grpc] SayHello message:"welcome go-kratos!"
INFO msg=[resolver] update instances: [{"id":"8fc08b88-e37b-11ec-bb6f-88d7f62323b4","name":"helloworld","version":"","metadata":null,"endpoints":["http://192.168.56.1:8080","grpc://192.168.56.1:9000"]}]
2022/06/04 04:28:22 [http] SayHello message:"welcome go-kratos!"
2022/06/04 04:28:22 [grpc] SayHello message:"welcome go-kratos!"
2022/06/04 04:28:23 [http] SayHello message:"welcome go-kratos!"
2022/06/04 04:28:23 [grpc] SayHello message:"welcome go-kratos!"
2022/06/04 04:28:24 [http] SayHello message:"welcome go-kratos!"
2022/06/04 04:28:24 [grpc] SayHello message:"welcome go-kratos!" ... ...

程序运行成功

看看 etcd 运行日志:

2022-06-04 04:26:03.896230 W | wal: sync duration of 1.1565369s, expected less than 1s
2022-06-04 04:26:03.991356 N | embed: serving insecure client requests on 127.0.0.1:2379, this is strongly discouraged!
2022-06-04 04:27:18.187663 W | etcdserver: request "header:<ID:7587862969930594823 > put:<key:\"/microservices/helloworld/8fc08b88-e37b-11ec-bb6f-88d7f62323b4\" value_size:162 lease:7587862969930594821 >" with result "size:4" took too long (113.4545ms) to execute

2.3 简析服务注册程序

一图解千言:

  • etcdregitry.New(client)

    这里是对 etcd client 的包装处理,那么选择的服务中心就是 etcd。也可以使用consul,zookeeper 等,kratos 对它们都有封装。

// 对 etcd client 的包装在处理
r := etcdregitry.New(client) // https://github.com/go-kratos/kratos/contrib/registry/etcd/registry.go#L56
// New creates etcd registry
func New(client *clientv3.Client, opts ...Option) (r *Registry) {
op := &options{
ctx: context.Background(),
namespace: "/microservices",
ttl: time.Second * 15,
maxRetry: 5,
}
for _, o := range opts {
o(op)
}
return &Registry{
opts: op,
client: client,
kv: clientv3.NewKV(client),
}
}
  • kratos.New()

    对应用程序初始化化,应用程序参数初始化 - 默认参数或接受传入的参数。

// https://github.com/go-kratos/kratos/blob/v2.3.1/app.go#L39
func New(opts ...Option) *App {
o := options{
ctx: context.Background(),
sigs: []os.Signal{syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT},
registrarTimeout: 10 * time.Second,
stopTimeout: 10 * time.Second,
}
... ...
return &App{
ctx: ctx,
cancel: cancel,
opts: o,
}
}
  • kratos.Name("helloworld")

    处理应用的服务参数。这个参数传入到上面 func New(opts ...Option) *App

// https://github.com/go-kratos/kratos/options.go#L41
// Name with service name.
func Name(name string) Option {
return func(o *options) { o.name = name }
}
  • kratos.Registrar(r)

    选择哪个服务中心(etcd,consul,zookeeper,nacos 等等)作为 kratos 的服务中心。

    这个参数传入到上面 func New(opts ...Option) *App

// https://github.com/go-kratos/kratos/blob/v2.3.1/options.go#L81
func Registrar(r registry.Registrar) Option {
return func(o *options) { o.registrar = r }
}
  • registrar.Register()

真正把服务注册到服务中心的是 app.Run() 这个方法里的 a.opts.registrar.Register() 方法,Register() 方法把服务实例注册到服务中心。

// https://github.com/go-kratos/kratos/app.go#L84
if err := a.opts.registrar.Register(rctx, instance); err != nil {
return err
}

参数 instance 就是方法 buildInstance() 返回的服务实例 ServiceInstance,ServiceInstance struct 包含了一个服务实例所需的字段。

// https://github.com/go-kratos/kratos/app.go#L154
func (a *App) buildInstance() (*registry.ServiceInstance, error) // https://github.com/go-kratos/kratos/registry/registry.go#L33
type ServiceInstance struct {
ID string `json:"id"`
Name string `json:"name"`
Version string `json:"version"`
Metadata map[string]string `json:"metadata"`
Endpoints []string `json:"endpoints"`
}

三、参考

Go微服务框架go-kratos实战04:kratos中服务注册和服务发现的使用的更多相关文章

  1. Taurus.MVC 微服务框架 入门开发教程:项目集成:1、服务端:注册中心、网关(提供可运行程序下载)。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...

  2. SpringCloud微服务实战:一、Eureka注册中心服务端

    1.项目启动类application.java类名上增加@EnableEurekaServer注解,声明是注册中心 1 import org.springframework.boot.SpringAp ...

  3. rc-local.service服务启动失败,导致rc.local中的开机启动服务不能启动

    chmod  +x   /etc/rc.d/rc.local 打开/etc/rc.local文件,将启动非后台执行的指令的最后添加 &,以使相关指令后台运行,然后启动服务 systemctl  ...

  4. kratos微服务框架学习笔记一(kratos-demo)

    目录 kratos微服务框架学习笔记一(kratos-demo) kratos本体 demo kratos微服务框架学习笔记一(kratos-demo) 今年大部分时间飘过去了,没怎么更博和githu ...

  5. 微服务框架Dubbo与Springcloud的区别

    微服务框架Dubbo与Springcloud的区别 微服务主要的优势如下: 1.降低复杂度 将原来偶合在一起的复杂业务拆分为单个服务,规避了原本复杂度无止境的积累.每一个微服务专注于单一功能,并通过定 ...

  6. 简单Spring Cloud 微服务框架搭建

    微服务是现在比较流行的技术,对于程序猿而言,了解并搭建一个基本的微服务框架是很有必要滴. 微服务包含的内容非常多,一般小伙伴们可以根据自己的需求不断添加各种组件.框架. 一般情况下,基本的微服务框架包 ...

  7. 面试都在问的微服务、服务治理、RPC、下一代微服务框架... 一文带你彻底搞懂!

    文章每周持续更新,「三连」让更多人看到是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) 单体式应用程序 与微服务相对的另一个概念是传统的单体式应用程序( ...

  8. silky微服务框架服务注册中心介绍

    目录 服务注册中心简介 服务元数据 主机名称(hostName) 服务列表(services) 终结点 时间戳 使用Zookeeper作为服务注册中心 使用Nacos作为服务注册中心 使用Consul ...

  9. Taurus.MVC 微服务框架 入门开发教程:项目部署:1、微服务应用程序常规部署实现多开,节点扩容。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...

  10. Taurus.MVC 微服务框架 入门开发教程:项目部署:2、让Kestrel支持绑定多个域名转发,替代Ngnix使用。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...

随机推荐

  1. java中什么是局部内部类Local inner class?

    5.局部内部类Local inner class 马克-to-win:什么叫局部内部类?内部类声明位置:1.它的外部类的范围之内.2.在几个程序块的范围之内.例如,由方法定义的块中或甚至在for循环体 ...

  2. 【每日日报】第四十七天---<div>

    1 学习HTML HTML <div> 元素是块级元素,它可用于组合其他 HTML 元素的容器. <div> 元素没有特定的含义.除此之外,由于它属于块级元素,浏览器会在其前后 ...

  3. 手动封装一个node命令集工具

    了解NPM安装模块时与项目配置文件中的bin配置发生了什么 了解nodejs在控制台中的运行环境及上下文 基于自定义命令集工具集成Yeoman 一.NPM模块安装内幕与nodejs控制台运行环境 1. ...

  4. python修改Gsettings的配置文件

    GSettings 的配置文件是 xml 格式的,文件需以 .gschema.xml 结尾,文件名通常与 id 相同.配置文件安装在 /usr/share/glib-2.0/schemas/ 目录下, ...

  5. 面试官:Zookeeper怎么解决读写、双写并发不一致问题,以及共享锁的实现原理?

    哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 今天清明假期,赶上北京玉渊潭公园 ...

  6. mpvue使用scss

    安装scss 安装命令如下,不带版本号可能会导致报错 npm i sass-loader@7.3.1 -D npm i node-sass@4.14.1 -D 然后修改 build 文件夹下的 web ...

  7. Java---变量和基本数据类型

    变量 在Java中,变量分为两种:基本类型的变量和引用类型的变量. 在Java中变量必须先定义后使用,在定义变量的时候可以给它一个初始值.如果不写初始值,默认为0或空. 变量的一个重要特点是可以重新赋 ...

  8. 微信小程序,制作属于自己的Icon图标

    前言 最近在接手一个微信小程序,发现里面的图标都是使用的image组件,看起来非常别扭,加载也不太顺畅. 就想着看看微信有没有类似自带的图标库可以使用. 有是有,就是太少了,翻来翻去好像也就 8 种, ...

  9. Ubu18下cpptest安装

    1.环境安装 sudo apt install g++ sudo apt install automake sudo apt install autoconf sudo apt install lib ...

  10. npm 报错This is probably not a problem with npm. There is likely additional logging output above.

    报错This is probably not a problem with npm. There is likely additional logging output above. 安装了一个插件后 ...