Go微服务: go-micro集成consul的注册中心和配置中心

news2024/11/16 16:00:02

微服务与注册中心的关系图

  • 这个图很好说明了微服务之间的关系,以及consul注册中心的重要性

环境准备


1 )consul 集群

  • 假设consul 集群已经搭建,已有5台server和2台client
  • 这里2台client被nginx做负载均衡,假设最终本地的访问地址是: http://localhost:8500
  • 如何做 consul 环境搭建,请在我的博客列表中搜索关键字: “consul”

2 )consul 中设置mysql的配置文件

  • 假设目前只有一个数据中心,如果有多个,则配置多个即可
  • 在consul的ui界面上的 Key / Value 菜单中配置,点击 Create 按钮
  • Key or folder 中 填入:micro/config/mysql
  • Value 中填入下面的json文件
    {
    	"host": "127.0.0.1",
    	"port": 3307,
    	"user": "root",
    	"pwd": "123456_mysql",
    	"database": "micro"
    }
    
  • 以上只是举例一种简单的mysql的配置,到生产环境,则进行生产的配置
  • 以此我们就完成了 consul 的搭建和配置 (搭建部分这里省略)

go-micro 代码集成


1 )结构介绍

  • 在当前项目中,假设目前当前模块仓库是 gitee.com/go-micro-services/category
  • 从命名中我们知道,当前这个仓库会同步到远程,不做赘述
  • common 目录作为通用的工具函数目录
  • domain 目录中分别定义了三个目录:model, repository, service
    • model 是定义的实体类,数据模型
    • repository 是基本数据库操作类,编写与数据库的映射关系
    • service 是基于repository封装的业务类
  • handler 目录暴露出来的服务
    • 在 proto 里面生成的服务,必须在 handler 中有所体现

2 )common 核心代码参考 common/config.go

package common

import (
	"encoding/json"
	"log"

	"github.com/hashicorp/consul/api"
)

// 定义一个map,key是字符串,value是api客户端或nil
var consulClients = make(map[string]*api.Client)

// 获取配置中心客户端
func getConsulClient(address string) (*api.Client, error) {
	// 1. 从map中获取客户端
	client := consulClients[address]
	// 2. 如果存在,则直接返回
	if client != nil {
		return client, nil
	}
	// 3. 如果不存在,则新建
	config := api.DefaultConfig()
	config.Address = address
	client, err := api.NewClient(config)
	if err == nil {
		consulClients[address] = client // 没有错误进行挂载
	}
	// 4. 返回
	return client, err
}

// 设置配置中心
func getConsulConfig(Address string, path string) (*api.KVPair, error) {
	// 1. 获取 Consul客户端
	client, clientErr := getConsulClient(Address)
	if clientErr != nil {
		log.Fatal(clientErr)
	}

	// 2. 创建KV客户端
	kv := client.KV()

	// 3. 基于path读取pair
	pair, _, getErr := kv.Get(path, nil)
	return pair, getErr
}

func GetConsulMysqlConfig(address string, path string) (MysqlConfig, error) {
	// 1. 获取 pair
	pair, consulErr := getConsulConfig(address, path)
	if consulErr != nil {
		log.Fatal(consulErr)
	}

	// 2. 解析JSON字符串为 MysqlConfig 结构体
	var mysqlConfig MysqlConfig
	err := json.Unmarshal(pair.Value, &mysqlConfig)
	return mysqlConfig, err
}
  • 可以看到,在上述代码中使用一个map来缓存客户端的创建过程
  • 以便后期可能调用其他可能的consul服务进行了扩展,提升一个性能
  • 同时,这里也有个mysql的配置封装

3 )main.go 核心代码

package main

import (
	"fmt"
	"log"
	"strconv"

	"github.com/go-micro/plugins/v4/registry/consul"
	"go-micro.dev/v4"
	"go-micro.dev/v4/registry"

	"gitee.com/go-micro-services/category/common"

	"gitee.com/go-micro-services/category/domain/repository"
	"gitee.com/go-micro-services/category/domain/service"
	"gitee.com/go-micro-services/category/handler"
	pbcategory "gitee.com/go-micro-services/category/proto/category"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

var (
	serviceName = "go.micro.service.category"
	version     = "latest"
	host        = "127.0.0.1"
	port        = 8500
	address     = host + ":" + strconv.Itoa(port)
	configPath  = "/micro/config/mysql"
)

func main() {
	// 1. 注册中心
	consulReg := consul.NewRegistry(
		registry.Addrs(address),
	)

	// 2. 创建服务
	srv := micro.NewService()
	srv.Init(
		micro.Name(serviceName),
		micro.Version(version),
		micro.Registry(consulReg),
	)

	// 3. 从配置中心获取mysql配置并创建处理
	mysqlConfig, consulConfigErr := common.GetConsulMysqlConfig(address, configPath)
	if consulConfigErr != nil {
		log.Fatal(consulConfigErr)
	}
	mysqlUrl := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", mysqlConfig.User, mysqlConfig.Pwd, mysqlConfig.Host, mysqlConfig.Port, mysqlConfig.Database)
	db, dbErr := gorm.Open("mysql", mysqlUrl)
	if dbErr != nil {
		log.Fatal(dbErr)
	}
	defer db.Close()
	db.SingularTable(false) // true 则 表就是单数

	// 数据库表初始化,只执行一次, 如果本来就设计好了,则无需下面2行
	// rp := repository.NewCategoryRepository(db)
	// rp.InitTable()

	// 4. 创建服务实例
	categoryDataService := service.NewCategoryDataService(repository.NewCategoryRepository(db))

	// 5. 注册 handler
	if handlerErr := pbcategory.RegisterCategoryHandler(srv.Server(), &handler.Category{CategoryDataService: categoryDataService}); handlerErr != nil {
		log.Fatal(handlerErr)
	}

	// 6. 运行服务
	if runErr := srv.Run(); runErr != nil {
		log.Fatal(runErr)
	}
}
  • 以上展示了服务集成的所有步骤,从 consul 配置中心中获取配置信息
  • 之后基于这些数据连接mysql, 进行数据和服务的初始化
  • 这里代码一目了然,不再一一进行解释

4 )其他说明

  • 这里不对其他模块的代码做一一说明,我们的目的是在go-micro中集成完成 consul
  • 这里 category 这个代码仓库是一个微服务,也就是说,每个微服务都需要注册到consul, 以便对微服务进行有效的管理
  • 同时,后期网关在调用微服务的时候,网关服务也要注册到consul中
  • 其他不是本文核心代码不做举例

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

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

相关文章

rocketmq和rabbitmq总是分不清?

1. 官方解答 摘自百度搜索: 2. 通俗易懂的回答

蓝桥杯:握手问题和小球反弹问题

试题 A: 握手问题 本题总分: 5 分 【问题描述】 小蓝组织了一场算法交流会议,总共有 50 人参加了本次会议。在会议上, 大家进行了握手交流。按照惯例他们每个人都要与除自己以外的其他所有人进行一次握手(且仅有一次&#x…

Hadoop概述及集群搭建

文章目录 一、Hadoop介绍二、Hadoop发展简史三、Hadoop核心组件四、Hadoop架构变迁1、Hadoop 1.02、Hadoop 2.03、Hadoop 3.0 五、Hadoop集群简介六、Hadoop部署模式七、Hadoop 集群搭建第一步:创建虚拟机第二步:安装Linux镜像第三步:网络配置…

Spring Cloud 集成 RabbitMQ

目录 前言步骤引入相关maven依赖添加相关配置 使用方法配置消息序列化创建第一个消息队列和交换机使用方法 总结 前言 在当今的微服务架构盛行的时代,消息队列作为一种重要的通信机制,在分布式系统中扮演着不可或缺的角色。RabbitMQ,作为一款…

(七)C++自制植物大战僵尸游戏关卡数据加载代码讲解

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/xjvbb 打开LevelData.h和LevelData.cpp文件。文件位置如下图所示。 LevelData.h 此头文件中定义了两个类,分别是OpenLevelData、LevelData,其中OpenLevelData用于加载文件数据。LevelData解析数据…

ansible创建用户账户和更新ansible库的密钥

1.创建⽤户帐户 从 http://materials/user_list.yml 下载要创建的⽤户的列表,并将它保存到 /home/greg/ansible 在本次考试中使⽤在其他位置创建的密码库 /home/greg/ansible/locker.yml 。创建名为 /home/greg/ansible/users.yml 的 playbook ,从⽽…

攻防世界13-simple_php

13-simple_php <?php show_source(*__FILE__*);//高亮文件 include("config.php");//文件包含在内 $a$_GET[a];//获得a $b$_GET[b];//获得b if($a0 and $a){ //判断a是否满足条件echo $flag1; //满足就输出flag1 } if(is_numeric($b)){ //判断b的条件&#x…

解决方案ImportError: cannot import name ‘BertTokenizerFast‘ from ‘transformers‘

文章目录 一、现象二、解决方案 一、现象 从transformers 库调用该包的时候 from transformers import BertTokenizer, AdamW, BertTokenizerFast报错显示 ImportError: cannot import name ‘BertTokenizerFast’ from ‘transformers’ 二、解决方案 追溯查看transforme…

【OpenGL开发】PyQt在关闭应用程序时没有运行析构函数的问题

PyQt在关闭应用程序时没有运行析构函数的问题 目录 一、说明二、python的析构函数三、QT5 存在一些问题四、PyQt5 存在一些问题五、OpenGL的析构问题 一、说明 应用QT做程序界面&#xff0c;在程序退出的时候&#xff0c;需要调用析构函数释放资源&#xff0c;这个操作在Pytho…

跟TED演讲学英文:Why AI is incredibly smart and shockingly stupid by Yejin Choi

Why AI is incredibly smart and shockingly stupid Link: https://www.ted.com/talks/yejin_choi_why_ai_is_incredibly_smart_and_shockingly_stupid Speaker: Yejin Choi Date: April 2023 文章目录 Why AI is incredibly smart and shockingly stupidIntroductionVocabul…

通过调用Vcenter-Api获取Vcenter中服务器信息

通过调用Vcenter-Api获取Vcenter中服务器信息 文章目录 通过调用Vcenter-Api获取Vcenter中服务器信息1. 获取Vmware API帮助文档2. 获取访问凭证3. 获取服务器清单4. 获取服务器更多信息5. 获取虚机更多信息6. 获取磁盘信息7. 获取操作系统相关 1. 获取Vmware API帮助文档 htt…

面试八股——Spring——AOP与事务

AOP的定义 事务的实现 事务的失效场景 异常捕获处理 下图中由于②导致异常&#xff1a; 原因&#xff1a; 解决办法&#xff1a;自己抛出一个非检查异常&#xff08;具体原因看“抛出检查异常”&#xff09;。 抛出检查异常 由于①出错&#xff0c;导致抛出了检查异常 原因&…

[linux api] of_irq_init

总结: 以如下级联的中断控制器为例: of_irq_init会确保先初始化父控制器再初始化子控制器,也即整体按照层序遍历的顺序进行初始化,以上图为例,其初始化顺序为: intc0intc1-2intc3-6具体实现则分为两个阶段: 第一阶段 遍历所有设备节点,并与参数matches进行匹配,找…

Servlet实现常用功能及其他方法

getParameter 获取body或url中指定的key/value值 String classIdreq.getParameter("classId"); getQueryString 获取请求的所有查询参数key,values1 String queryStringreq.getQueryString(); from表单提交 前端通过from表单提交用户名和密码 <!DOCTYPE htm…

# 达梦sql查询 Sql 优化

达梦sql查询 Sql 优化 文章目录 达梦sql查询 Sql 优化注意点测试数据单表查询 Sort 语句优化优化过程 多表关联SORT 优化函数索引的使用 注意点 关于优化过程中工具的选用&#xff0c;推荐使用自带的DM Manage&#xff0c;其它工具在查看执行计划等时候不明确在执行计划中命中…

计算机网络常问面试题

一.HTTPS是如何保证安全传输的 https通过使⽤对称加密、⾮对称加密、数字证书等⽅式来保证数据的安全传输。 客户端向服务端发送数据之前&#xff0c;需要先建⽴TCP连接&#xff0c;所以需要先建⽴TCP连接&#xff0c;建⽴完TCP连接后&#xff0c;服务端会先给客户端发送公钥…

网络网络层之(2)ARP协议

网络网络层之(2)ARP协议 Author&#xff1a;Once Day Date: 2024年4月1日 漫漫长路&#xff0c;有人对你笑过嘛… 全系列文档可参考专栏&#xff1a;通信网络技术_Once-Day的博客-CSDN博客。 参考文档: 《TCP/IP详解卷一》arp(8) - Linux manual page (man7.org)彻底搞懂系…

配置香橙派摄像头服务每次开机自动启动

目录 1.创建一个mjpg.sh脚本 2.在脚本中添加以下内容 3.增加可执行权限 4.在/etc/xdg/autostart/下创建mjpg.desktop 文件输入以下内容 1.创建一个mjpg.sh脚本 touch mjpg.sh 2.在脚本中添加以下内容 #!/bin/bash cd /home/orangepi/Myorangepi/zhinenglajitong/mjpg-stre…

分布式幂等性

1. 什么是幂等性&#xff1f; 幂等性是指在分布式系统中&#xff0c;一个操作多次执行的结果与其执行一次的结果相同。设计具有幂等性的分布式系统可以有效避免数据不一致和重复处理的问题。 幂等系统的应用场景 在微服务架构下&#xff0c;由于分布式天然特性的时序问题, 以…

解决动态规划问题

文章目录 动态规划的定义动态规划的核心思想青蛙跳阶问题解法一&#xff1a;暴力递归解法二&#xff1a;带备忘录的递归解法&#xff08;自顶向下&#xff09;解法三&#xff1a;动态规划&#xff08;自底向上&#xff09; 动态规划的解题套路什么样的问题考虑使用动态规划&…