Go-服务注册和发现,负载均衡,配置中心

文章目录

  • 什么是服务注册和发现
    • 技术选型
  • Consul 的安装和配置
    • 1. 安装
    • 2. 访问
    • 3. 访问dns
  • Consul 的api接口
  • go操作consul
  • grpc下的健康检查
    • grpc的健康检查规范
    • 动态获取可用端口号
  • 负载均衡策略
    • 1. 什么是负载均衡
    • 2. 负载均衡策略
      • 1. 集中式load balance
      • 2. 进程内load balance
      • 3. 独立进程load balance
  • 常见的负载均衡算法
    • 1. 轮询(Round Robin)法
    • 2. 随机法
    • 3. 源地址哈希法
    • 4. 加权轮询(Weight Round Robin)法
    • 5. 加权随机(Weight Random)法
    • 6. 最小连接数法
  • grpc负载均衡策略
  • 为什么需要分布式配置中心
    • 分布式配置中心选型
    • nacos的基本使用
    • gin集成nacos
    • 如何将nacos中的配置映射成go的struct

什么是服务注册和发现

假如这个产品已经在线上运行,有一天运营想搞一场促销活动,那么我们相对应的【用户服务】可能就要新开启三个微服务实例来支撑这场促销活动。而与此同时,作为苦逼程序员的你就只有手动去 API gateway 中添加新增的这三个微服务实例的 ip 与port ,一个真正在线的微服务系统可能有成百上千微服务,难道也要一个一个去手动添加吗?有没有让系统自动去实现这些操作的方法呢?答案当然是有的。
当我们新添加一个微服务实例的时候,微服务就会将自己的 ip 与 port 发送到注册中心,在注册中心里面记录起来。当 API gateway 需要访问某些微服务的时候,就会去注册中心取到相应的 ip 与 port。从而实现自动化操作。

技术选型

Consul 与其他常见服务发现框架对比

image.png

Consul 的安装和配置

1. 安装

docker run -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600/ud
docker container update --restart=always 容器名字

2. 访问

浏览器访问 127.0.0.1:8500

3. 访问dns

consul提供dns功能,可以让我们通过, 可以通过dig命令行来测试,consul默认的dns端口是8600, 命令行:
linux下的dig命令安装:
yum install bind-utils

dig @192.168.1.103 -p 8600 consul.service.consul SRV 

windows下载dig命令 :dig.zip

Consul 的api接口

  1. 添加服务
    https://www.consul.io/api-docs/agent/service#register-service
  2. 删除服务
    https://www.consul.io/api-docs/agent/service#deregister-service
  3. 设置健康检查
    https://www.consul.io/api-docs/agent/check
  4. 同一个服务注册多个实例
  5. 获取服务
    https://www.consul.io/api-docs/agent/service#list-services

go操作consul

package main
	import (
		"fmt"
		"github.com/hashicorp/consul/api"
	)
func Register(address string, port int, name string, tags []string, id string) er
	cfg := api.DefaultConfig()
	cfg.Address = "192.168.1.103:8500"
	client, err := api.NewClient(cfg)
	if err != nil {
		panic(err)
	}
	//⽣成对应的检查对象
	check := &api.AgentServiceCheck{
	HTTP: "http://192.168.1.102:8021/health",
	Timeout: "5s",
	Interval: "5s",
	DeregisterCriticalServiceAfter: "10s",
}
	//⽣成注册对象
	registration := new(api.AgentServiceRegistration)
	registration.Name = name
	registration.ID = id
	registration.Port = port
	registration.Tags = tags
	registration.Address = address
	registration.Check = check
	err = client.Agent().ServiceRegister(registration)
	if err != nil {
	panic(err)
	}
		return nil
	}
func AllServices(){
	cfg := api.DefaultConfig()
	cfg.Address = "192.168.1.103:8500"
	client, err := api.NewClient(cfg)
	if err != nil {
		panic(err)
	}
	data, err := client.Agent().Services()
	if err != nil {
		panic(err)
	}
	for key, _ := range data{
	fmt.Println(key)
	}
}
func FilterSerivice(){
	cfg := api.DefaultConfig()
	cfg.Address = "192.168.1.103:8500"
	client, err := api.NewClient(cfg)
	if err != nil {
		panic(err)
	}
	data, err := client.Agent().ServicesWithFilter(`Service == "user-web"`)
	if err != nil {
		panic(err)
	}
	for key, _ := range data{
		fmt.Println(key)
	}
}
func main(){
	//_ = Register("192.168.1.102", 8021, "user-web", []string{"mxshop", "bobby"}
	//AllServices()
	FilterSerivice()
}

grpc下的健康检查

grpc的健康检查规范

官方文档

grpc健康检查重要点:

1. check = {
“GRPC”: f’{ip}:{port}’,
“GRPCUseTLS”: False,
“Timeout”: “5s”,
“Interval”: “5s”,
“DeregisterCriticalServiceAfter”: “5s”,
}
  1. 一定要确保网络是通的
  2. 一定要确保srv服务监听端口是对外可访问的
  3. GRPC一定要自己填写

动态获取可用端口号

package utils
	import (
		"net"
	)
	func GetFreePort() (int, error) {
		addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
		if err != nil {
		return 0, err
	}
	l, err := net.ListenTCP("tcp", addr)
	if err != nil {
		return 0, err
	}
	defer l.Close()
	return l.Addr().(*net.TCPAddr).Port, nil
}

负载均衡策略

1. 什么是负载均衡

image.png

2. 负载均衡策略

1. 集中式load balance

集中式LB方案,如下图。首先,服务的消费方和提供方不直接耦合,而是在服务消费者和服务提供者之间有一个独立的LB(LB通常是专门的硬件设备如F5,或者基于软件如LVS,HAproxy等实现)。

image.png

LB上有所有服务的地址映射表,通常由运维配置注册,当服务消费方调用某个目标服务时,它向LB发起请求,由LB以某种策略(比如Round-Robin)做负载均衡后将请求转发到目标服务。

服务消费方如何发现LB呢?通常的做法是通过DNS,运维人员为服务配置一个DNS域名,这个域名指向LB。
这种方案基本可以否决,因为它有致命的缺点:所有服务调用流量都经过load balance服务器,所以load balance服务器成了系统的单点,一旦LB发生故障对整个系统的影响是灾难性的。为了解决这个问题,必然需要对这个load balance部件做分布式处理(部署多个实例,冗余,然后解决一致性问题等全家桶解决方案),但这样做会徒增非常多的复杂度。

2. 进程内load balance

进程内load balance。将load balance的功能和算法以sdk的方式实现在客户端进程内。先看架构图:

image.png

可看到引入了第三方:服务注册中心。它做两件事:

  1. 维护服务提供方的节点列表,并检测这些节点的健康度。检测的方式是:每个节点部署成功,都通知服务注册中心;然后一直和注册中心保持心跳。
  2. 允许服务调用方注册感兴趣的事件,把服务提供方的变化情况推送到服务调用方。这种方案下,整个load balance的过程是这样的:
  3. 服务注册中心维护所有节点的情况。
  4. 任何一个节点想要订阅其他服务提供方的节点列表,向服务注册中心注册。
  5. 服务注册中心将服务提供方的列表(以长连接的方式)推送到消费方。
  6. 消费方接收到消息后,在本地维护一份这个列表,并自己做load balance。

可见,服务注册中心充当什么角色?它是唯一一个知道整个集群内部所有的节点情况的中心。所以对它的可用性要求会非常高,这个组件可以用Zookeeper实现。
这种方案的缺点是:每个语言都要研究一套sdk,如果公司内的服务使用的语言五花八门的话,这方案的成本会很高。第二点是:后续如果要对客户库进行升级,势必要求服务调用方修改代码并重新发布,所以该方案的升级推广有不小的阻力。

3. 独立进程load balance

该方案是针对第二种方案的不足而提出的一种折中方案,原理和第二种方案基本类似,不同之处是,他将LB和服务发现功能从进程内移出来,变成主机上的一个独立进程,主机上的一个或者多个服务要访问目标服务时,他们都通过同一主机上的独立LB进程做服务发现和负载均衡。如图

image.png

这个方案解决了上一种方案的问题,不需要为不同语言开发客户库,LB的升级不需要服务调用方改代码。
但新引入的问题是:这个组件本身的可用性谁来维护?还要再写一个watchdog去监控这个组件?另外,多了一个环节,就多了一个出错的可能,线上出问题了,也多了一个需要排查的环节。

常见的负载均衡算法

在分布式系统中,多台服务器同时提供一个服务,并统一到服务配置中心进行管理,消费者通过查询服务配置中心,获取到服务到地址列表,需要选取其中一台来发起RPC远程调用。如何选择,则取决于具体的负载均衡算法,对应于不同的场景,选择的负载均衡算法也不尽相同。负载均衡算法的种类有很多种,常见的负载均衡算法包括轮询法、随机法、源地址哈希法、加权轮询法、加权随机法、最小连接法等,应根据具体的使用场景选取对应的算法。

1. 轮询(Round Robin)法

轮询很容易实现,将请求按顺序轮流分配到后台服务器上,均衡的对待每一台服务器,而不关心服务器实际的连接数和当前的系统负载。

2. 随机法

通过系统随机函数,根据后台服务器列表的大小值来随机选取其中一台进行访问。由概率概率统计理论可以得知,随着调用量的增大,其实际效果越来越接近于平均分配流量到后台的每一台服务器,也就是轮询法的效果。

3. 源地址哈希法

源地址哈希法的思想是根据服务消费者请求客户端的IP地址,通过哈希函数计算得到一个哈希值,将此哈希值和服务器列表的大小进行取模运算,得到的结果便是要访问的服务器地址的序号。采用源地址哈希法进行负载均衡,相同的IP客户端,如果服务器列表不变,将映射到同一个后台服务器进行访问。

4. 加权轮询(Weight Round Robin)法

不同的后台服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不一样。跟配置高、负载低的机器分配更高的权重,使其能处理更多的请求,而配置低、负载高的机器,则给其分配较低的权重,降低其系统负载,加权轮询很好的处理了这一问题,并将请求按照顺序且根据权重分配给后端。

5. 加权随机(Weight Random)法

加权随机法跟加权轮询法类似,根据后台服务器不同的配置和负载情况,配置不同的权重。不同的是,它是按照权重来随机选取服务器的,而非顺序。

6. 最小连接数法

前面我们费尽心思来实现服务消费者请求次数分配的均衡,我们知道这样做是没错的,可以为后端的多台服务器平均分配工作量,最大程度地提高服务器的利用率,但是,实际上,请求次数的均衡并不代表负载的均衡。因此我们需要介绍最小连接数法,最小连接数法比较灵活和智能,由于后台服务器的配置不尽相同,对请求的处理有快有慢,它正是根据后端服务器当前的连接情况,动态的选取其中当前积压连接数最少的一台服务器来处理当前请求,尽可能的提高后台服务器利用率,将负载合理的分流到每一台服务器。

grpc负载均衡策略

  1. grpc的负载均衡策略
    文档

  2. go使用grpc负载均衡
    文档

  3. 关于serverconfig
    官方文档

  4. go的grpc测试

package main
	import (
		"OldPackageTest/grpclb_test/proto"
		"context"
		"fmt"
		"log"
		_ "github.com/mbobakov/grpc-consul-resolver" // It's important
		"google.golang.org/grpc"
	)
func main() {
	conn, err := grpc.Dial(
	"consul://192.168.1.103:8500/user-srv?wait=14s&tag=srv",
	grpc.WithInsecure(),
	grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy": "round_robin"}`),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	for i := 0; i<10; i++{
		userSrvClient := proto.NewUserClient(conn)
		rsp, err := userSrvClient.GetUserList(context.Background(), &proto.PageIn
		Pn: 1,
		PSize: 2,
	})
	if err != nil {
		panic(err)
	}
	for index, data := range rsp.Data{
		fmt.Println(index, data)
		}
	}
}

为什么需要分布式配置中心

我们现在有一个项目,使用gin进行开发的,配置文件的话我们知道是一个叫做config.yaml的文件。
我们也知道这个配置文件会在项目启动的时候被加载到内存中进行使用的。
考虑两种情况:
a. 添加配置项
ⅰ. 你现在的用户服务有10个部署实例,那么添加配置项你得去十个地方修改配置文件还得重新启动等。
ⅱ. 即使go的viper能完成修改配置文件自动生效,那么你得考虑其他语言是否也能做到这点,其他的服务是否也一定会使用viper?
b. 修改配置项
大量的服务可能会使用同一个配置,比如我要更好jwt的secrect,这么多实例怎么办?
c. 开发、测试、生产环境如何隔离:
前面虽然已经介绍了viper,但是依然一样的问题,这么多服务如何统一这种考虑因素?

分布式配置中心选型

目前最主流的分布式配置中心主要是有spring cloud config、 apollo和nacos,spring cloud属于java的spring体系,我们就考虑apollo和nacos。apollo与nacos 都为目前比较流行且维护活跃的2个配置中心。
apollo是协程开源,nacos是阿里开源

  1. apollo大而全,功能完善。nacos小而全,可以对比成django和flask的区别
  2. 部署nacos更加简单。
  3. nacos不止支持配置中心还支持服务注册和发现。
  4. 都支持各种语言,不过apollo是第三方支持的,nacos是官方支持各种语言

两者都很活跃,不过看得出来nacos想要构建的生态野心更大,不过收费意图明显。

image.png

nacos的基本使用

文档

  1. 命名空间
    可以隔离配置集,将某些配置集放到某一个命名空间之下。
    命名空间我们一般用来区分 微服务

  2. 抛出一个问题: 你现在确实能够隔离微服务,但是不同的微服务的开发、测试、生产环境如何区别,组可以用来区别区别开发、测试、生产环境
  3. dataid - 配置集
    一个配置集就是一个配置文件, 实际上可以更灵活

gin集成nacos

nacos-sdk-go地址

  1. go操作nacos
package main
	import (
		"fmt"
		"time"
		"github.com/nacos-group/nacos-sdk-go/clients"
		"github.com/nacos-group/nacos-sdk-go/common/constant"
		"github.com/nacos-group/nacos-sdk-go/vo"
	)
func main(){
	sc := []constant.ServerConfig{
	{
	IpAddr: "192.168.1.103",
	Port: 8848,
	},
}
	cc := constant.ClientConfig {
	NamespaceId: "c1872978-d51c-4188-a497-4e0cd20b97d5", // 如果需要⽀持
	TimeoutMs: 5000,
	NotLoadCacheAtStart: true,
	LogDir: "tmp/nacos/log",
	CacheDir: "tmp/nacos/cache",
	RotateTime: "1h",
	MaxAge: 3,
	LogLevel: "debug",
}
configClient, err := clients.CreateConfigClient(map[string]interface{}{
	"serverConfigs": sc,
	"clientConfig": cc,
})
if err != nil {
	panic(err)
}
	content, err := configClient.GetConfig(vo.ConfigParam{
	DataId: "user-web.yaml",
	Group: "dev"})
	if err != nil {
		panic(err)
	}
	fmt.Println(content)
	err = configClient.ListenConfig(vo.ConfigParam{
		DataId: "user-web.yaml",
		Group: "dev",
	OnChange: func(namespace, group, dataId, data string) {
		fmt.Println("配置⽂件变化")
		fmt.Println("group:" + group + ", dataId:" + dataId + ", data:" + dat
		},
	})
	time.Sleep(3000 * time.Second)
}

如何将nacos中的配置映射成go的struct

转换地址: https://www.json2yaml.com/convert-yaml-to-json

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

爬虫项目-爬取股吧(东方财富)评论

1.最近帮别人爬取了东方财富股吧的帖子和评论&#xff0c;网址如下&#xff1a;http://mguba.eastmoney.com/mguba/list/zssh000300 2.爬取字段如下所示&#xff1a; 3.爬虫的大致思路如下&#xff1a;客户要求爬取评论数大于5的帖子&#xff0c;首先获取帖子链接&#xff0c…

剑指JUC原理-16.读写锁

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码&#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&…

JavaEE进阶3

传递数组: 当我们请求中,同一个参数有多个时,浏览器就会帮我们封装成一个数组 用逗号进行分割也是可以的(有的浏览器不能直接使用逗号,需要我们去转码) 传递集合: HTTP 状态码(不是后端自定义的) 2XX:成功 3XX:重定向 4XX:客户端错误 5XX:服务器错误 业务状态码:HTTP响应…

【NLP】特征提取: 广泛指南和 3 个操作教程 [Python、CNN、BERT]

什么是机器学习中的特征提取&#xff1f; 特征提取是数据分析和机器学习中的基本概念&#xff0c;是将原始数据转换为更适合分析或建模的格式过程中的关键步骤。特征&#xff0c;也称为变量或属性&#xff0c;是我们用来进行预测、对对象进行分类或从数据中获取见解的数据点的…

2.3.3 交换机的RSTP技术

实验2.3.3 交换机的RSTP技术 一、任务描述二、任务分析三、具体要求四、实验拓扑五、任务实施1.交换机的基本配置。2.开启交换机的STP。3.配置SW3A和SW3B上STP的优先级。将SW3A配置为根交换机&#xff0c;SW3B配置为备用根交换机。4.配置SW2A和SW2B的边缘接口 六、任务验收七、…

Azure 机器学习 - 使用Python SDK训练模型

目录 一、环境准备二、工作区限制三、什么是计算目标&#xff1f;四、本地计算机五、远程虚拟机六、Apache Spark 池七、Azure HDInsight八、Azure Batch九、Azure Databricks十、Azure Data Lake Analytics十一、Azure 容器实例十二、Kubernetes 了解如何用 SDK v1 将 Azure 计…

11-Docker-Redis集群部署

00-前言 在工作环境中&#xff0c;我们常常被要求配置多种集群&#xff0c;Redis 集群是最常见的入门需要掌握的集群配置方法&#xff0c;在之前的学习中&#xff0c;我们学习掌握了分布式存储的算法&#xff0c;本质上集群的部署就是通过分布式存储算法将数据分发部署好的不同…

windows上 Nexus 批量上传 maven依赖npm依赖

windows上 Nexus 批量上传 maven依赖/npm依赖 前言&#xff1a;windows系统上要有git环境&#xff0c;不然sh文件执行不了 1.批量上传maven依赖 设置脚本&#xff0c;把脚本放在依赖包的根目录执行&#xff0c;脚本名为upload.sh #!/bin/bash# 定义变量 while getopts &quo…

零信任安全:构建无懈可击的网络防护体系

随着网络技术的飞速发展&#xff0c;信息安全问题日益凸显&#xff0c;传统的安全防护手段已经无法满足复杂多变的安全需求。在此背景下&#xff0c;零信任安全模型逐渐受到广泛关注。本文将探讨零信任安全的概念、优势以及如何构建无懈可击的网络防护体系。 一、零信任安全概念…

Flink(三)【运行时架构】

前言 今天学习 Flink 的一些原理性的东西&#xff0c;比较偏概念&#xff0c;但是十分重要。有人觉得上来框框敲代码才能学到东西&#xff0c;那是狗屁不通的道理&#xff08;虽然我以前也这么认为&#xff09;。个人认为&#xff0c;学习 JavaEE那些框架&#xff0c;你上来就敲…

图的基本操作

基本操作 Adjacent(G,x,y):判断图G是否存在边<x,y>或(x,y)Neighbors(G,x):列出图G中与结点x邻接的边InsertVertex(G,x):在图G中插入顶点xDeleteVertex(G,x):从图G中删除顶点xAddEdge(G,x,y):若无向边(x,y)或有向边<x,y>不存在&#xff0c;则向图G中添加该边Remove…

安卓学习记录

文章目录 Text_View基础属性字体阴影跑马灯**activity_main.xml**MyTextview button Text_View ctrl右键可以看到属性 代码整理采用的快捷键是ctrlaltL(电脑qq锁定快捷键&#xff0c;退一下qq就行了) 基础属性 字体阴影 <?xml version"1.0" encoding"utf-…

网络安全深入学习第八课——代理与端口转发

文章目录 一、什么是代理二、正向代理三、反向代理四、正向和反向代理模拟复现 一、什么是代理 代理服务器英文全称是Proxy Server&#xff0c;其功能就是代理网络用户去取得网络信息。 形象的说&#xff1a;它是网络信息的中转站。在一般情况下&#xff0c;我们使用网络浏览…

PyCharm 无法登陆 Codeium 的解决方法

PyCharm 登陆 Codeium PyCharm 无法登陆 Codeium 的问题描述PyCharm 使用 token 登陆 Codeium PyCharm 无法登陆 Codeium 的问题描述 使用 PyCharm 登录 Codeium 时&#xff0c;单击 Login 无反应&#xff0c;单击侧边栏的 Codeium 图标也一直显示连接失败。 PyCharm 使用 to…

RHCE8 资料整理(五)

RHCE8 资料整理 第五篇 系统管理第18章 进程管理18.1 进程介绍18.2 查看进程18.3 向进程发送信号18.4 进程优先级 第19章 日志19.1 rsyslog的配置19.2 查看日志 第20章 网络时间服务器20.1 时间同步必要性20.2 配置时间服务器20.3 配置客户端 第21章 计划任务21.1 at21.2 cront…

基于Pytorch框架的LSTM算法(一)——单维度单步滚动预测(2)

#项目说明&#xff1a; 说明&#xff1a;1time_steps滚动预测代码 y_norm scaler.fit_transform(y.reshape(-1, 1)) y_norm torch.FloatTensor(y_norm).view(-1)# 重新预测 window_size 12 future 12 L len(y)首先对模型进行训练&#xff1b; 然后选择所有数据的后wind…

如何做游戏软件开发?怎么和软件开发公司合作?

随着科技的发展和普及&#xff0c;游戏软件已经成为人们日常生活和工作中不可或缺的一部分&#xff0c;许多企业也开始涉足游戏软件开发领域&#xff0c;希望能够打造出一款受欢迎的游戏&#xff0c;那么&#xff0c;如何做游戏软件开发?怎么和软件开发公司合作呢?下面我们来…

cmake vs2022编译opencv4.5.2 x86 版本

cmake 编译opencv 452 x86 版本 where is the source code 选项放置你的源文件 where to build the binaries 放置你生成结果的文件夹 点击按钮Configure,弹出提示&#xff0c;选择Win32&#xff0c;finishi 等待生成 列表中出现红色的选项&#xff0c;根据你的需要取消或…

Django框架简介

文章目录 Django框架介绍MVC与MVT模型MVCMTV 版本问题运行django注意事项 Django的下载与基本命令下载Django方式一&#xff1a;在命令界面使用pip安装方式二&#xff1a;使用pycharm安装 Django的基础命令命令行操作pycharm操作 Django项目命令行操作与Pycharm操作的区别应用D…

关于变电站综合自动化系统的案例应用分析-安科瑞 蒋静

摘 要&#xff1a;变电站综合自动化系统是将变电站内的二次设备经过功能的组合和优化设计&#xff0c;利用先进的计算机技术、通信技术、信号处理技术&#xff0c;实现对全变电站的主要设备和输、配电线路的自动监视、测量、控制、保护、并与上级调度通信的综合性自动化功能。 …