Go微服务框架go-kratos实战04:kratos中服务注册和服务发现的使用

🚀 优质资源分享 🚀

学习路线指引(点击解锁)知识定位人群定位
🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
💛Python量化交易实战💛入门级手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

一、简介

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

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

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

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

image-20220603213155270

二、服务注册和服务发现

2.1 接口定义

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

注册和反注册服务:

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

获取服务:

Copytype 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®

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

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

Copypackage mainimport ("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 serverhttpSrv := http.NewServer(http.Address(":8080"),http.Middleware(recovery.Recovery(),),)// 初始化 grpc servergrpcSrv := 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作为服务中心的使用步骤图解:
image-20220604032611364

客户端获取服务

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

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

2.将 registry 传入 WithDiscovery®

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

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

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

Copypackage mainimport ("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.运行服务端

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

3.运行客户端

Copy$ 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 运行日志:

Copy2022-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: put:" with result "size:4" took too long (113.4545ms) to execute

2.3 简析服务注册程序

一图解千言:

image-20220604043508393

  • etcdregitry.New(client)

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

Copy// 对 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()

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

Copy// 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

Copy// 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®

选择哪个服务中心(etcd,consul,zookeeper,nacos 等等)作为 kratos 的服务中心。
这个参数传入到上面 func New(opts ...Option) *App

Copy// 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() 方法把服务实例注册到服务中心。

Copy// 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 包含了一个服务实例所需的字段。

Copy// 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"`
}

三、参考

  • https://go-kratos.dev/docs/component/registry 服务注册和服务发现
  • https://github.com/go-kratos/examples/blob/main/registry/etcd etcd registry
  • https://github.com/go-kratos/kratos

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400938.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我注册了某音帐号之后。。。(内涵推荐算法)

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…

第5讲++创建管理数据库

实例 create database db on (namedb51,filenameD:\xxx\db51.mdf,size100,maxsize200,filegrowth20 ), (namedb52,filenameD:\xxx\db52.ndf,size100,maxsize200,filegrowth20 ), (namedb53,filenameD:\xxx\db53.ndf,size100,maxsize200,filegrowth20 ) log on (namedb5log1,fi…

R数据分析:如何简洁高效地展示统计结果

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…

实现权重计算

今天试图实现内部点权重的计算。在论文中,权重的计算过程是这样的:其中solveNNLS是求解这个方程s为表面点,q为内部点发现两种方法:1.一种是把内部点位置表示成表面点的线性组合2.另一种是把内部点的位移表示成表面点的线性组合第2种可以化成内…

Android LBS系列05 位置策略(一)

Location Strategies 定位的实现 在Android系统上实现定位主要是通过GPS或者是基于网络的定位方法。 GPS是精度最高的,但是它只在户外有用,并且很耗电,并且首次定位花费时间较长。 基于网络的定位利用通信网络蜂窝基站和Wi-Fi信号&#xff0c…

ABP官方文档翻译 3.1 实体

实体 实体类聚合根类 领域事件常规接口 审计软删除激活/失活实体实体改变事件IEntity接口实体是DDD(领域驱动设计)的核心概念之一。Eric Evans描述它为"An object that is not fundamentally defined by its attributes, but rather by a thread of continuity and identi…

目标检测之线段检测---lsd line segment detector

(1)线段检测应用背景 (2)线段检测原理简介 (3)线段检测实例 a line segment detector (4)hough 变换和 lsd 的区别 ---------------------author:pkf ------------------…

利用Mac创建一个 IPv6 WIFI 热点

标签: iOSIPv6Create NAT64 NetWork创建NAT64网络2016-05-20 10:58 14156人阅读 评论(11) 收藏 举报分类:开发技巧(8) 版权声明:本文为博主原创文章,未经博主允许不得转载。 苹果商店6月1日起,强…

经典电影

那些经典的电影,第一波!! 《怦然心动》,欧美电影——布莱斯全家搬到小镇,邻家女孩朱丽前来帮忙。她对他一见钟情,心愿是获得他的吻。两人是同班同学,她一直想方设法接近他,但是他避之…

go-zero 微服务实战系列(一、开篇)

🚀 优质资源分享 🚀 学习路线指引(点击解锁)知识定位人群定位🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一…

大数据时代,怎么做全渠道的营销

大数据时代,怎么做全渠道的营销 营销在中国有很多变化,1978年之前主要是计划经济的时代,寻求政府的保护。1984年进入商品经济之后,中国企业通过大规模的扩大生产,扩大工厂得到生产效率。1992年进入市场经济之后,会涌现…

oracle slient静默安装并配置数据库及仅安装数据库不配置数据库shell

oracle slient静默安装并配置数据库及仅安装数据库不配置数据库shell <1&#xff0c;>仅安装数据库软件不配置数据库 ./x86oracle.sh /ruiy/ocr/DBSoftware/app/oracle /ruiy/ocr/DBSoftware/app/oraInventory /ruiy/ins_soft.rsp <2&#xff0c;>静默安装数据库软…

hdu 2048 神、上帝以及老天爷

题解&#xff1a; 本题主要思路是&#xff0c;算出i个人的总选择数a和以悲剧结尾的总选择数b&#xff0c;然后b/a&#xff0c;完成。属于递推题&#xff1a; 图中横杠代表人&#xff0c;竖杠代表签名。Ai代表i个人共有A[i]个选择&#xff0c;Bi起过度作用。因为最多有20人&…

探究Presto SQL引擎(3)-代码生成

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

【学习笔记】计算几何

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

支持自动水平拆分的高性能分布式数据库TDSQL

随着互联网应用的广泛普及&#xff0c;海量数据的存储和访问成为系统设计的瓶颈问题。对于大型的互联网应用&#xff0c;每天几十亿的PV无疑对数据库造成了相当高的负载。给系统的稳定性和扩展性造成了极大的问题。通过数据的切分来提高系统整体性能&#xff0c;扩充系统整体容…

一些有趣的B+树优化实验

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

Tarjan的强联通分量

求强联通分量有很多种。 《C信息学奥赛一本通》 中讲过一个dfs求强联通分量的算法Kosdaraju&#xff0c;为了骗字数我就待会简单的说说。然而我们这篇文章的主体是Tarjan&#xff0c;所以我肯定说完之后再赞扬一下Tarjan大法好是不是 首先我们讲一下强联通分量 强联通分量指的…

XXE漏洞

简介 XXE (XML External Entity Injection) 漏洞发生在应用程序解析 XML 输入时&#xff0c;没有禁止外部实体的加载。 简单的理解&#xff0c;一个实体就是一个变量&#xff0c;可以在文档中的其他位置引用该变量。 实体主要分为四种&#xff1a; 内置实体 (Built-in entities…

Linq之Expression高级篇(常用表达式类型)

目录 写在前面 系列文章 变量表达式 常量表达式 条件表达式 赋值表达式 二元运算符表达式 一元运算符表达式 循环表达式 块表达式 总结 写在前面 首先回顾一下上篇文章的内容&#xff0c;上篇文章介绍了表达式树的解析和编译。如果忘记了&#xff0c;可以通过下面系列文章提供的…