利用go-kit组件进行服务注册与发现和健康检查的操作
本篇文章给大家分享《利用go-kit组件进行服务注册与发现和健康检查的操作》,覆盖了Golang的常见基础知识,其实一个语言的全部知识点一篇文章是不可能说完的,但希望通过这些问题,让读者对自己的掌握程度有一定的认识(B 数),从而弥补自己的不足,更好的掌握它。
在go的微服务架构中
使用go-kit组件进行开发微服务
type Reg struct {
Host string
Port int
Client consul.Client
}
func MakeReg (host string , port int) (*Reg , error) {
reg := api.DefaultConfig()
reg.Address = host + ":" + strconv.Itoa(port)
apiclient , err = api.NewClient(reg)
if err != nil {
return nil , err
}
client := consul.NewClient(apiclient)
return &Reg{Host : host , Port : port ,Client : client} , nil
}
func (r Reg) Resiter (servicename , tag , host , seviceid ,checkinter ,healthcheckhttp ,deregisterafter string , port int) bool {
congig := api.AgentServiceRegistration{
Port : port ,
Address : host ,
Name := servicename,
ID := serviceid,
Ckeck : &api.AgentServiceCheck{
Interval : checkinter,
HTTP : "http://" + host + ":" + healthcheckhttp ,
DeregisterCriticalServiceAfter : deregisterafter,
}
}
if err := r.Client.Register(&config) ; err != nil {
fmt.Println(err)
return false
}
return true
}
func (r Reg) Deregister (serviceid string) bool {
dreg := api.AgentServiceRegistration{ID : serviceid}
if err != r.Client.Deregister(&config) ; err != nil {
fmt.Println(err)
return false
}
return true
}
func (r Reg) discover (servicename , tag string ,passingonly bool) ( []*api.ServiceEntry ,error ) {
if entries ,_ ,err := r.Client.Service(servicename , tag , passingonly , nil) ;err != nil {
return nil ,err
}else{
return entries , nil
}
}
补充:go-kit 与 grpc 结合实现注册发现与负载均衡
介绍
grpc提供了简单的负载均衡,需要自己实现服务发现resolve。我们既然要使用go-kit来治理微服务,那么我们就使用go-kit的注册发现、负载均衡机制。
go-kit官方【stringsvc3】例子中使用的负载均衡方案是通过服务端转发进行,翻找下源码go-kit的服务注册发现、负载均衡在【sd】包中。下面我们介绍怎么通过go-kit进行客户端负载均衡。
go-kit提供的注册中心
1、 etcd
2、 consul
3、 eureka
4、 zookeeper
go-kit提供的负载均衡
1、 random[随机]
2、 roundRobin[轮询]
只需实现Balancer接口,我们可以很容易的增加其它负载均衡机制
type Balancer interface {
Endpoint() (endpoint.Endpoint, error)
}
etcd注册发现
etcd和zookeeper类似是一个高可用、强一致性的存储仓库,拥有服务发现功能。 我们就通过go-kit提供的etcd包来实现服务注册发现
服务端代码
服务注册
1、连接注册中心
2、注册当前服务
var (
//etcd服务地址
etcdServer = "127.0.0.1:2379"
//服务的信息目录
prefix = "/services/book/"
//当前启动服务实例的地址
instance = "127.0.0.1:50052"
//服务实例注册的路径
key = prefix + instance
//服务实例注册的val
value = instance
ctx = context.Background()
//服务监听地址
serviceAddress = ":50052"
)
//etcd的连接参数
options := etcdv3.ClientOptions{
DialTimeout: time.Second * 3,
DialKeepAlive: time.Second * 3,
}
//创建etcd连接
client, err := etcdv3.NewClient(ctx, []string{etcdServer}, options)
if err != nil {
panic(err)
}
// 创建注册器
registrar := etcdv3.NewRegistrar(client, etcdv3.Service{
Key: key,
Value: value,
}, log.NewNopLogger())
// 注册器启动注册
registrar.Register()
完整代码
package main
import (
"grpc-test/pb"
"context"
grpc_transport "github.com/go-kit/kit/transport/grpc"
"github.com/go-kit/kit/endpoint"
"google.golang.org/grpc"
"net"
"github.com/go-kit/kit/sd/etcdv3"
"github.com/go-kit/kit/log"
"time"
)
type BookServer struct {
bookListHandler grpc_transport.Handler
bookInfoHandler grpc_transport.Handler
}
//通过grpc调用GetBookInfo时,GetBookInfo只做数据透传, 调用BookServer中对应Handler.ServeGRPC转交给go-kit处理
func (s *BookServer) GetBookInfo(ctx context.Context, in *book.BookInfoParams) (*book.BookInfo, error) {
_, rsp, err := s.bookInfoHandler.ServeGRPC(ctx, in)
if err != nil {
return nil, err
}
return rsp.(*book.BookInfo),err
}
//通过grpc调用GetBookList时,GetBookList只做数据透传, 调用BookServer中对应Handler.ServeGRPC转交给go-kit处理
func (s *BookServer) GetBookList(ctx context.Context, in *book.BookListParams) (*book.BookList, error) {
_, rsp, err := s.bookListHandler.ServeGRPC(ctx, in)
if err != nil {
return nil, err
}
return rsp.(*book.BookList),err
}
//创建bookList的EndPoint
func makeGetBookListEndpoint() endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
//请求列表时返回 书籍列表
bl := new(book.BookList)
bl.BookList = append(bl.BookList, &book.BookInfo{BookId:1,BookName:"21天精通php"})
bl.BookList = append(bl.BookList, &book.BookInfo{BookId:2,BookName:"21天精通java"})
return bl,nil
}
}
//创建bookInfo的EndPoint
func makeGetBookInfoEndpoint() endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
//请求详情时返回 书籍信息
req := request.(*book.BookInfoParams)
b := new(book.BookInfo)
b.BookId = req.BookId
b.BookName = "21天精通php"
return b,nil
}
}
func decodeRequest(_ context.Context, req interface{}) (interface{}, error) {
return req, nil
}
func encodeResponse(_ context.Context, rsp interface{}) (interface{}, error) {
return rsp, nil
}
func main() {
var (
//etcd服务地址
etcdServer = "127.0.0.1:2379"
//服务的信息目录
prefix = "/services/book/"
//当前启动服务实例的地址
instance = "127.0.0.1:50052"
//服务实例注册的路径
key = prefix + instance
//服务实例注册的val
value = instance
ctx = context.Background()
//服务监听地址
serviceAddress = ":50052"
)
//etcd的连接参数
options := etcdv3.ClientOptions{
DialTimeout: time.Second * 3,
DialKeepAlive: time.Second * 3,
}
//创建etcd连接
client, err := etcdv3.NewClient(ctx, []string{etcdServer}, options)
if err != nil {
panic(err)
}
// 创建注册器
registrar := etcdv3.NewRegistrar(client, etcdv3.Service{
Key: key,
Value: value,
}, log.NewNopLogger())
// 注册器启动注册
registrar.Register()
bookServer := new(BookServer)
bookListHandler := grpc_transport.NewServer(
makeGetBookListEndpoint(),
decodeRequest,
encodeResponse,
)
bookServer.bookListHandler = bookListHandler
bookInfoHandler := grpc_transport.NewServer(
makeGetBookInfoEndpoint(),
decodeRequest,
encodeResponse,
)
bookServer.bookInfoHandler = bookInfoHandler
ls, _ := net.Listen("tcp", serviceAddress)
gs := grpc.NewServer(grpc.UnaryInterceptor(grpc_transport.Interceptor))
book.RegisterBookServiceServer(gs, bookServer)
gs.Serve(ls)
}
客户端代码
客户端流程
1、 连接注册中心
2、 获取提供的服务
3、 监听服务目录变化,目录变化更新本地缓存
4、 创建负载均衡器
5、 获取请求的 endPoint
完整代码
package main
import (
"context"
"github.com/go-kit/kit/sd/etcdv3"
"time"
"github.com/go-kit/kit/sd"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/endpoint"
"io"
"github.com/go-kit/kit/sd/lb"
"grpc-test/pb"
"fmt"
"google.golang.org/grpc"
)
func main() {
var (
//注册中心地址
etcdServer = "127.0.0.1:2379"
//监听的服务前缀
prefix = "/services/book/"
ctx = context.Background()
)
options := etcdv3.ClientOptions{
DialTimeout: time.Second * 3,
DialKeepAlive: time.Second * 3,
}
//连接注册中心
client, err := etcdv3.NewClient(ctx, []string{etcdServer}, options)
if err != nil {
panic(err)
}
logger := log.NewNopLogger()
//创建实例管理器, 此管理器会Watch监听etc中prefix的目录变化更新缓存的服务实例数据
instancer, err := etcdv3.NewInstancer(client, prefix, logger)
if err != nil {
panic(err)
}
//创建端点管理器, 此管理器根据Factory和监听的到实例创建endPoint并订阅instancer的变化动态更新Factory创建的endPoint
endpointer := sd.NewEndpointer(instancer, reqFactory, logger)
//创建负载均衡器
balancer := lb.NewRoundRobin(endpointer)
/**
我们可以通过负载均衡器直接获取请求的endPoint,发起请求
reqEndPoint,_ := balancer.Endpoint()
*/
/**
也可以通过retry定义尝试次数进行请求
*/
reqEndPoint := lb.Retry(3, 3*time.Second, balancer)
//现在我们可以通过 endPoint 发起请求了
req := struct{}{}
if _, err = reqEndPoint(ctx, req); err != nil {
panic(err)
}
}
//通过传入的 实例地址 创建对应的请求endPoint
func reqFactory(instanceAddr string) (endpoint.Endpoint, io.Closer, error) {
return func(ctx context.Context, request interface{}) (interface{}, error) {
fmt.Println("请求服务: ", instanceAddr)
conn, err := grpc.Dial(instanceAddr, grpc.WithInsecure())
if err != nil {
fmt.Println(err)
panic("connect error")
}
defer conn.Close()
bookClient := book.NewBookServiceClient(conn)
bi,_:=bookClient.GetBookInfo(context.Background(),&book.BookInfoParams{BookId:1})
fmt.Println("获取书籍详情")
fmt.Println("bookId: 1", " => ", "bookName:", bi.BookName)
bl,_ := bookClient.GetBookList(context.Background(), &book.BookListParams{Page:1, Limit:10})
fmt.Println("获取书籍列表")
for _,b := range bl.BookList {
fmt.Println("bookId:", b.BookId, " => ", "bookName:", b.BookName)
}
return nil,nil
},nil,nil
}
测试
请求测试
请求服务: 127.0.0.1:50052 获取书籍详情 bookId: 1 => bookName: 21天精通php 获取书籍列表 bookId: 1 => bookName: 21天精通php bookId: 2 => bookName: 21天精通java
负载均衡测试
1、 修改server的注册监听端口,启动多个server
instance = "127.0.0.1:50052" serviceAddress = ":50052"
2、client发起多次请求
req := struct{}{}
for i := 1; i
<p>通过返回结果中记录的请求地址,我们可以看到已经按照轮询的方式请求不同的微服务实例。</p>
<pre class="brush:plain;">
请求服务: 127.0.0.1:50051
获取书籍详情
bookId: 1 => bookName: 21天精通php
获取书籍列表
bookId: 1 => bookName: 21天精通php
bookId: 2 => bookName: 21天精通java
请求服务: 127.0.0.1:50052
获取书籍详情
bookId: 1 => bookName: 21天精通php
获取书籍列表
bookId: 1 => bookName: 21天精通php
bookId: 2 => bookName: 21天精通java
请求服务: 127.0.0.1:50051
获取书籍详情
bookId: 1 => bookName: 21天精通php
获取书籍列表
bookId: 1 => bookName: 21天精通php
bookId: 2 => bookName: 21天精通java
请求服务: 127.0.0.1:50052
获取书籍详情
bookId: 1 => bookName: 21天精通php
获取书籍列表
bookId: 1 => bookName: 21天精通php
bookId: 2 => bookName: 21天精通java
请求服务: 127.0.0.1:50051
获取书籍详情
bookId: 1 => bookName: 21天精通php
获取书籍列表
bookId: 1 => bookName: 21天精通php
bookId: 2 => bookName: 21天精通java
请求服务: 127.0.0.1:50052
获取书籍详情
bookId: 1 => bookName: 21天精通php
获取书籍列表
bookId: 1 => bookName: 21天精通php
bookId: 2 => bookName: 21天精通java
请求服务: 127.0.0.1:50051
获取书籍详情
bookId: 1 => bookName: 21天精通php
获取书籍列表
bookId: 1 => bookName: 21天精通php
bookId: 2 => bookName: 21天精通java
请求服务: 127.0.0.1:50052
获取书籍详情
bookId: 1 => bookName: 21天精通php
获取书籍列表
bookId: 1 => bookName: 21天精通php
bookId: 2 => bookName: 21天精通java
Process finished with exit code 0
以上为个人经验,希望能给大家一个参考,也希望大家多多支持golang学习网。如有错误或未考虑完全的地方,望不吝赐教。
好了,本文到此结束,带大家了解了《利用go-kit组件进行服务注册与发现和健康检查的操作》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多Golang知识!
go-kit组件使用hystrix中间件的操作
- 上一篇
- go-kit组件使用hystrix中间件的操作
- 下一篇
- Goland 断点调试Debug的操作
-
- Golang · Go教程 | 3小时前 | 格式化输出 printf fmt库 格式化动词 Stringer接口
- Golangfmt库用法与格式化技巧解析
- 140浏览 收藏
-
- Golang · Go教程 | 3小时前 |
- Golang配置Protobuf安装教程
- 147浏览 收藏
-
- Golang · Go教程 | 3小时前 |
- Golang中介者模式实现与通信解耦技巧
- 378浏览 收藏
-
- Golang · Go教程 | 3小时前 |
- Golang多协程通信技巧分享
- 255浏览 收藏
-
- Golang · Go教程 | 3小时前 |
- Golang如何判断变量类型?
- 393浏览 收藏
-
- Golang · Go教程 | 3小时前 |
- Golang云原生微服务实战教程
- 310浏览 收藏
-
- Golang · Go教程 | 4小时前 |
- Golang迭代器与懒加载结合应用
- 110浏览 收藏
-
- Golang · Go教程 | 4小时前 | 性能优化 并发安全 Golangslicemap 预设容量 指针拷贝
- Golangslicemap优化技巧分享
- 412浏览 收藏
-
- Golang · Go教程 | 4小时前 |
- Golang代理模式与访问控制实现解析
- 423浏览 收藏
-
- Golang · Go教程 | 5小时前 |
- Golang事件管理模块实现教程
- 274浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3164次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3376次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3405次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4509次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3785次使用
-
- Redis实现登录注册的示例代码
- 2022-12-30 482浏览
-
- JAVA实现JWT注册窗口,且手撸操作mysql数据库
- 2023-02-16 230浏览
-
- PHP+AJAX实现账号注册和登陆,附可用demo
- 2023-02-16 367浏览

