【Go】微服务架构下实现etcd服务注册与服务发现

中心网关:gateway
四个微服务:user、message、note、relationship
在这里插入图片描述

1 中心网关实现服务发现

1.1 设计EtcdDiscovery类

package entityimport ("context""fmt"clientv3 "go.etcd.io/etcd/client/v3""gonote/gateway/internal/option"messageService "gonote/message/service"noteService "gonote/note/service"relationshipService "gonote/relationship/service"userService "gonote/user/service""google.golang.org/grpc""google.golang.org/grpc/credentials/insecure""sync""time"
)type EtcdDiscovery struct {etcdClient *clientv3.ClientserviceMap map[string]interface{}mu         sync.RWMutex
}func NewEtcdDiscovery(ip string, port int) (*EtcdDiscovery, error) {etcdCli, err := clientv3.New(clientv3.Config{Endpoints:   []string{fmt.Sprintf("%v:%v", ip, port)},DialTimeout: time.Second * 3,})if err != nil {return nil, err}return &EtcdDiscovery{etcdClient: etcdCli,serviceMap: make(map[string]interface{}),}, nil
}func (ed *EtcdDiscovery) Start(serviceNames []string) {for _, serviceName := range serviceNames {resp, err := ed.etcdClient.Get(context.TODO(), serviceName)if err != nil {panic(err)}addr := string(resp.Kvs[0].Value)conn, err := grpc.Dial(addr,grpc.WithTransportCredentials(insecure.NewCredentials()))if err != nil {panic(err)}// etcd存储的是各个微服务的监听地址,通过监听地址创建服务实例switch serviceName {case option.User:grpcCli := userService.NewUserServiceClient(conn)ed.serviceMap[serviceName] = grpcClicase option.Relationship:grpcCli := relationshipService.NewRelationshipServiceClient(conn)ed.serviceMap[serviceName] = grpcClicase option.Note:grpcCli := noteService.NewNoteServiceClient(conn)ed.serviceMap[serviceName] = grpcClicase option.Message:grpcCli := messageService.NewMessageServiceClient(conn)ed.serviceMap[serviceName] = grpcCli}// 开启协程,监听etcd的变化,动态维护各个grpc服务实例go ed.watch(serviceName)}
}func (ed *EtcdDiscovery) watch(serviceName string) {watchChan := ed.etcdClient.Watch(context.TODO(), serviceName)for event := range watchChan {for _, e := range event.Events {if e.Type == clientv3.EventTypePut {addr := string(e.Kv.Value)conn, err := grpc.Dial(addr,grpc.WithTransportCredentials(insecure.NewCredentials()))if err != nil {continue}ed.mu.Lock()switch serviceName {case option.User:grpcCli := userService.NewUserServiceClient(conn)ed.serviceMap[serviceName] = grpcClicase option.Relationship:grpcCli := relationshipService.NewRelationshipServiceClient(conn)ed.serviceMap[serviceName] = grpcClicase option.Note:grpcCli := noteService.NewNoteServiceClient(conn)ed.serviceMap[serviceName] = grpcClicase option.Message:grpcCli := messageService.NewMessageServiceClient(conn)ed.serviceMap[serviceName] = grpcCli}ed.mu.Unlock()} else if e.Type == clientv3.EventTypeDelete {ed.mu.Lock()delete(ed.serviceMap, serviceName)ed.mu.Unlock()}}}
}func (ed *EtcdDiscovery) GetServiceAddr(serviceName string) interface{} {ed.mu.RLock()defer ed.mu.RUnlock()return ed.serviceMap[serviceName]
}

1.2 在web启动时,初始化EtcdDiscovery

package mainimport ("gonote/gateway/internal""gonote/gateway/internal/option""gonote/gateway/internal/util"
)func init() {util.InitLogger()util.InitWebSocketServer(64)err := util.InitRedis()if err != nil {panic(err)}util.InitKafka(option.Topic)util.InitEtcdDiscovery([]string{option.User,option.Relationship,option.Note,option.Message})
}func main() {engine := internal.Router()if err := engine.Run("0.0.0.0:9090"); err != nil {panic(err)}
}

1.3 调用EtcdDiscovery获取服务实例

举个用户注册的例子:

func UserLogin(c *gin.Context) {em := c.PostForm("email")pwd := c.PostForm("pwd")// 获取服务实例cli := util.EtcdDiscovery.GetServiceAddr(option.User).(service.UserServiceClient)// 调用服务_, err := cli.UserLogin(context.TODO(), &service.User{Email: em,Pwd:   pwd,})if err != nil {c.JSON(200, gin.H{"code": 1,"msg":  err.Error(),})return}// 生成jwt令牌token, err := util.GenToken(em)if err != nil {c.JSON(200, gin.H{"code": 1,"msg":  err.Error(),})return}// session维护长连接session := sessions.Default(c)session.Set("email", em)err = session.Save()if err != nil {c.JSON(200, gin.H{"code": 1,"msg":  err.Error(),})return}c.JSON(200, gin.H{"code": 0,"data": token,})
}

2 微服务端进行服务注册

user业务对应的微服务:

func init() {util.InitLogger()err := util.InitDB()if err != nil {panic(err)}util.InitKafka(option.Topic)util.InitEtcdCli()
}func main() {addr := option.IP + ":" + option.Portln, err := net.Listen("tcp", addr)if err != nil {panic(err)}defer ln.Close()defer util.EtcdCli.Close()defer util.KafkaCli.Close()// 服务注册_, err = util.EtcdCli.Put(context.TODO(), "user", addr)if err != nil {panic(err)}server := grpc.NewServer()service.RegisterUserServiceServer(server, &service.UserServiceImpl{})if err = server.Serve(ln); err != nil {panic(err)}
}

通过etcd命令查看相关注册信息
在这里插入图片描述

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

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

相关文章

重置vCenter的root和administrator@vsphere.local密码

1:首先要重置root密码,登录vCenter安装的ESXI主机,重启vCenter。 2::重启机器的出现下面界面的时候按e键。 3:按e后出现下面的界面。 4:在最后一行结尾处输入rw init/bin/bash ,之后按ctrl-x或者F10重启。 …

spring boot 使用 Kafka

一、Kafka作为消息队列的好处 高吞吐量:Kafka能够处理大规模的数据流,并支持高吞吐量的消息传输。 持久性:Kafka将消息持久化到磁盘上,保证了消息不会因为系统故障而丢失。 分布式:Kafka是一个分布式系统&#xff0c…

7000字详解Spring Boot项目集成RabbitMQ实战以及坑点分析

本文给大家介绍一下在 Spring Boot 项目中如何集成消息队列 RabbitMQ,包含对 RibbitMQ 的架构介绍、应用场景、坑点解析以及代码实战。 我将使用 waynboot-mall 项目作为代码讲解,项目地址:https://github.com/wayn111/waynboot-mall。本文大…

MATLAB - 仿真单摆的周期性摆动

系列文章目录 前言 本例演示如何使用 Symbolic Math Toolbox™ 模拟单摆的运动。推导摆的运动方程,然后对小角度进行分析求解,对任意角度进行数值求解。 一、步骤 1:推导运动方程 摆是一个遵循微分方程的简单机械系统。摆最初静止在垂直位置…

大数据 - Hadoop系列《四》- MapReduce(分布式计算引擎)的核心思想

上一篇: 大数据 - Hadoop系列《三》- MapReduce(分布式计算引擎)概述-CSDN博客 目录 13.1 MapReduce实例进程 13.2 阶段组成 13.4 概述 13.4.1 🥙Map阶段(映射) 13.4.2 🥙Reduce阶段执行过…

STM32F407移植OpenHarmony笔记3

接上一篇,搭建完环境,找个DEMO能跑,现在我准备尝试从0开始搬砖。 首先把/device和/vendor之前的代码全删除,这个时候用hb set命令看不到任何项目了。 /device目录是硬件设备目录,包括soc芯片厂商和board板级支持代码…

Linux 系统相关的命令

参考资料 Linux之chmod使用【linux】chmod命令详细用法 目录 一. 系统用户相关1.1 查看当前访问的主机和用户1.2 切换用户1.2.1 设置root用户密码1.2.2 普通用户和root用户切换 1.4 系统状态1.4.1 vmstat 查看当前系统的状态1.4.2 history 查看系统中输入过的命令 二. 系统文件…

图扑 HT UI 5.0 全新升级,开箱即用!

为顺应数字时代的不断发展,图扑 HT UI 5.0 在原有功能强大的界面组件库的基础上进行了全面升级,融入了更先进的技术、创新的设计理念以及更加智能的功能。HT UI 5.0 使用户体验更为直观、个性化,并在性能、稳定性和安全性等方面达到新的高度。…

githacker安装详细教程,linux添加环境变量详细教程(见标题三)

笔者是ctf小白,这两天也是遇到.git泄露的题目,需要工具来解决问题,在下载和使用的过程中也是遇到很多问题,写此篇记录经验,以供学习 在本篇标题三中有详细介绍了Linux系统添加环境变量的操作教程,以供学习 …

TensorFlow2实战-系列教程6:猫狗识别3------迁移学习

🧡💛💚TensorFlow2实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Jupyter Notebook中进行 本篇文章配套的代码资源已经上传 猫狗识别1 数据增强 猫狗识别2------数据增强 猫狗识别3------迁移学习 1、迁移学习 …

解读4篇混合类型文件Polyglot相关的论文

0. 引入 Polyglot文件指的是混合类型文件,关于混合类型文件的基础,请参考文末给出的第一个链接(参考1)。 1. Toward the Detection of Polyglot Files 1.1 主题 这篇2022年的论文,提出了Polyglot文件的检测方法。虽…

openssl3.2 - .pod文件的查看方法

文章目录 .pod文件的查看方法概述笔记初步的解决方法备注 - pod2html.bat的详细用法好像Perl就自带这个BATEND .pod文件的查看方法 概述 看到openssl源码目录下有很多.pod文件, 软件发布的帮助内容都在里面. 当make install后, 大部分的.pod都会转成html文件, 但是有一部分…

【Java程序设计】【C00215】基于SSM的勤工助学管理系统(论文+PPT)

基于SSM的勤工助学管理系统(论文PPT) 项目简介项目获取开发环境项目技术运行截图 项目简介 这个一个基于SSM的勤工助学管理系统,本系统共分为三种权限:管理员、教师和学生 管理员:首页、个人中心、教师管理、学生管理…

gdp调试—Linux

目录 介绍 使用 介绍 代码分为debug模式和release模式 如果一份代码要被调试,这份代码必须是debug Linux下编译代码默认是是release模式 如果你想代码是debug模式 必须加上 - g 小提: vim默认:命令模式 gcc默认:releas…

操作系统--进程、线程基础知识

一、进程 我们编写的代码只是一个存储在硬盘的静态文件,通过编译后就会生成二进制可执行文件,当我们运行这个可执行文件后,它会被装载到内存中,接着 CPU 会执行程序中的每一条指令,那么这个运行中的程序,就…

ModelArts加速识别,助力新零售电商业务功能的实现

前言 如果说为客户提供最好的商品是产品眼中零售的本质,那么用户的思维是什么呢? 在用户眼中,极致的服务体验与优质的商品同等重要。 企业想要满足上面两项服务,关键在于提升效率,也就是需要有更高效率的零售&#…

C++ //练习 3.8 分别用while循环和传统的for循环重写第一题的程序,你觉得哪种形式更好呢?为什么?

C Primer(第5版) 练习 3.8 练习 3.8 分别用while循环和传统的for循环重写第一题的程序,你觉得哪种形式更好呢?为什么? 环境:Linux Ubuntu(云服务器) 工具:vim 代码块 /********…

【三】【C++】类与对象(二)

类的六个默认成员函数 在C中,有六个默认成员函数,它们是编译器在需要的情况下自动生成的成员函数,如果你不显式地定义它们,编译器会自动提供默认实现。这些默认成员函数包括: 默认构造函数 (Default Constructor)&…

C++ 数论相关题目 博弈论:拆分-Nim游戏

给定 n 堆石子,两位玩家轮流操作,每次操作可以取走其中的一堆石子,然后放入两堆规模更小的石子(新堆规模可以为 0 ,且两个新堆的石子总数可以大于取走的那堆石子数),最后无法进行操作的人视为失…

PMP中的数据收集工具:打开项目成功的钥匙

在项目管理中,数据收集是关键的一环。准确、及时的数据能够为项目决策提供可靠的依据,帮助项目经理更好地监控项目进展、识别潜在风险,并制定有效的应对措施。本文将深入探讨PMP(项目管理专业)中常用的数据收集工具&am…