【注册中心】Consul服务发现、健康检查——基于「Python」「Golang」「gRPC」

文章目录

  • 前言
    • 技术选型:
  • 一、consul是什么?
  • 二、使用步骤
    • 1.安装
    • 2.访问
    • 3.访问dns
  • 三、consul的api接口
    • python篇
      • 1.添加服务&设置健康检查
      • 2.删除服务
      • 3.查找服务
    • golang篇
      • 1.服务注册&健康检查
      • 2.获取所有服务
      • 3.获取指定服务
  • 四、配置到grpc
    • 1.srv集成consul——基于python grpc的proto生成pb2.py——注册健康检查
    • 1.gin grpc集成consul
  • 总结


前言

当我们新添加一个微服务实例的时候,微服务就会将自己的 ip与port 发送到注册中心,在注册中心里面记录起来。当APl gateway需要访问某些微服务的时候,就会去注册中心取到相应的ip与port。从而实现自动化操作。

技术选型:

【注册中心】Consul服务发现、健康检查——基于「Python」「Golang」「gRPC」_第1张图片


一、consul是什么?

Consul 简化了分布式环境中的服务的注册和发现流程,通过 HTTP 或者 DNS 接口发现。支持外部 SaaS 提供者等。
【注册中心】Consul服务发现、健康检查——基于「Python」「Golang」「gRPC」_第2张图片

二、使用步骤

grpc健康检查重要点:
1.check = {
“GRPC": rtipH:{port}","GRPCUseTLS": False,"Timeout": "5s"","Interval": "5s",
"DeregisterCriticalServiceAfter": "5s",
}
2.一定要确保网络是通的
3.一定要确保srv服务监听端口是对外可访问的
4.GRPC一定要自己填写

1.安装

代码如下(示例):

docker run -d -p 8500:8500 -p 8300:8300 -p 8301:8301 -p 8302:8302 -p 8600:8600/udp consul consul agent -dev -client=0.0.0.0
docker container update --restart=always 容器名字

2.访问

代码如下(示例):

浏览器访问:地址:8500

该处使用的url网络请求的数据。

3.访问dns

consul提供dns功能,可以让我们通过,可以通过dig命令行来测试,consul默认的dns端口是8600,命令行:

dig @地址 -p 8600 consul.service.onsul SRV
liunx安装dig命令:yum insatll bind-utils

consul是默认生成的 后面是dns
【注册中心】Consul服务发现、健康检查——基于「Python」「Golang」「gRPC」_第3张图片

三、consul的api接口

官网详细使用:https://developer.hashicorp.com/consul/api-docs/agent/service

python篇

1.添加服务&设置健康检查

import requests

headers = {
    # "contentType": "application/json"
    "Content-Type": "application/json"
}


def register(name, id, address, port):
    url = "http://192.168.10.130:8500/v1/agent/service/register"
    rsp = requests.put(url, headers=headers, json={
        "Name": name,
        "ID": id,
        "Tags": ["mxshop", "bobby", "imooc", "grpc"],
        "Address": address,
        "Port": port,
        "Check": {
            # "HTTP": f"http://{address}:{port}/health",
            "GRPC": f"{address}:{port}",
            "GRPCUseTLS": False,
            "Timeout": "5s",  # 超时时间
            "Interval": "5s",  # 五秒检测一次
            "DeregisterCriticalServiceAfter": "15s",  # 五秒钟检查不到 就移除服务a
        }
    })
    if rsp.status_code == 200:
        print("注册成功")
    else:
        print(f"注册失败{rsp.status_code}")
if __name__ == '__main__':
	register("mxshop-web", "mxshop-web", "10.231.72.37", 50051)

2.删除服务

def deregister(id):
    url = f"http://192.168.10.130:8500/v1/agent/service/deregister/{id}"
    rsp = requests.put(url, headers=headers)
    if rsp.status_code == 200:
        print("注销成功")
    else:
        print(f"注销失败{rsp.status_code}")
        
def del_all():
	rsp = c.agent.services()
	for key, value in rsp.items():
	    # print(key)
	    rsp = c.agent.service.deregister(key)  # 注销所有

if __name__ == '__main__':
    deregister("mxshop-web")

3.查找服务

def filter_service(name):
    url = "http://192.168.10.130:8500/v1/agent/services"
    params = {
        "filter": f'Service == "{name}"',
    }
    rsp = requests.get(url, params=params).json()
    for k, v in rsp.items():
        print(k)
if __name__ == '__main__':
    filter_service("mxshop-web")

golang篇

1.服务注册&健康检查

package main

import (
	"fmt"
	"github.com/hashicorp/consul/api"
)
func Register(address string, port int, name string, tags []string, id string) error {
	cfg := api.DefaultConfig()
	cfg.Address = "192.168.10.130:8500"
	client, err := api.NewClient(cfg)
	if err != nil {
		panic(err)
	}
	registration := new(api.AgentServiceRegistration)
	registration.Name = name
	registration.ID = id
	registration.Port = port
	registration.Tags = tags
	registration.Address = address
	//生成对应的检查对象
	check := &api.AgentServiceCheck{
		HTTP:                           "http://10.231.72.37:8021/health",
		Timeout:                        "5s",
		Interval:                       "5s",
		DeregisterCriticalServiceAfter: "10s",
	}
	registration.Check = check
	err = client.Agent().ServiceRegister(registration)
	if err != nil {
		panic(err)
	}
	return nil
}
func main() {
	_ = Register("10.231.72.37", 8021, "user-web", []string{"mxshop", "bobby"}, "user-web")
}

2.获取所有服务

package main

import (
	"fmt"
	"github.com/hashicorp/consul/api"
)
func AllServices() {
	cfg := api.DefaultConfig()
	cfg.Address = "192.168.10.130: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 main() {
	AllServices()
}

3.获取指定服务

package main

import (
	"fmt"
	"github.com/hashicorp/consul/api"
)
func FilterSerivice(name string) {
	cfg := api.DefaultConfig()
	cfg.Address = "192.168.10.130:8500"
	client, err := api.NewClient(cfg)
	if err != nil {
		panic(err)
	}
	data, err := client.Agent().ServicesWithFilter(fmt.Sprintf(`Service == "%s"`,name))
	if err != nil {
		panic(err)
	}
	for key, _ := range data {
		fmt.Println(key)
	}
}

func main() {
	FilterSerivice("user-web")
}

四、配置到grpc

protobuf版本<=3.19.0

链接:https://pan.baidu.com/s/1oMPPVHLglDXafTUGP_hewg 
提取码:e2if

1.srv集成consul——基于python grpc的proto生成pb2.py——注册健康检查

base抽象基类

import abc
import six


@six.add_metaclass(abc.ABCMeta)
class Register():
    @abc.abstractmethod
    def register(self, name, id, address, port, tags, check):
        pass

    @abc.abstractmethod
    def deregister(self, service_id):
        pass

    @abc.abstractmethod
    def get_all_service(self):
        pass

    @abc.abstractmethod
    def filter_service(self, filter):
        pass

consul服务注册&健康检查&查找服务&删除服务

from common.register import base
import consul
import requests


class ConsulRegister(base.Register):
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.c = consul.Consul(host=host, port=port)

    def register(self, name, id, address, port, tags, check) -> bool:
        if check is None:
            check = {
                # "HTTP": f"http://{address}:{port}/health",
                "GRPC": f"{address}:{port}",
                "GRPCUseTLS": False,
                "Timeout": "5s",  # 超时时间
                "Interval": "5s",  # 五秒检测一次
                "DeregisterCriticalServiceAfter": "15s",  # 五秒钟检查不到 就移除服务a
            }
        else:
            check = check
        return self.c.agent.service.register(name=name, service_id=id,
                                             address=address, port=port, tags=tags, check=check)

    def deregister(self, service_id):
        return self.c.agent.service.deregister(service_id)

    def get_all_service(self):
        return self.c.agent.services()

    def filter_service(self, filter):
        url = f"http://{self.host}:{self.port}/v1/agent/services"
        params = {
            "filter": filter,
        }
        return requests.get(url, params=params).json()

注册到grpc当中

 # 注册健康检查
from common.grpc_health.v1 import health_pb2_grpc, health_pb2
from common.grpc_health.v1 import health
import grpc

server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
health_servicer = health.HealthServicer()
health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server)

logger.info(f"服务注册开始")
register = consul.ConsulRegister(settings.CONSUL_HOST, settings.CONSUL_PORT)
if not register.register(name=settings.SERVICE_NAME, id=settings.SERVICE_NAME,address=args.ip,port=args.port,
 tags=settings.SERVICE_TAGS, check=None):
        logger.info("服务注册失败")
        sys.exit(0)

1.gin grpc集成consul

package initialize

import (
	"fmt"

	"github.com/hashicorp/consul/api"
	"go.uber.org/zap"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"

	"mxshop-api/user-web/global"
	"mxshop-api/user-web/proto"
)

func InitSrvConn() {
	cfg := api.DefaultConfig()
	//这个是我debug.yaml映射的struct   自己需要填充即可
	consulInfo := global.ServerConfig.ConsulInfo
	//连接consul
	cfg.Address = fmt.Sprintf("%s:%d", consulInfo.Host, consulInfo.Port)
	//用来获取consul对应的host:port
	userSrvHost := ""
	userSrvPort := 0
	client, err := api.NewClient(cfg)
	if err != nil {
		panic(err)
	}
	//查询指定的consul
	data, err := client.Agent().ServicesWithFilter(fmt.Sprintf("Service == \"%s\"", global.ServerConfig.UserSrvConfig.Name))
	//data, err := client.Agent().ServicesWithFilter(fmt.Sprintf(`Service == "%s"`,global.ServerConfig.UserSrvConfig.Name))
	if err != nil {
		panic(err)
	}
	//赋值 | (key,value)ID和返回的指定详细consul
	for _, value := range data {
		userSrvHost = value.Address
		userSrvPort = value.Port
		break
	}
	if userSrvHost == "" {
		zap.S().Fatal("[InitSrvConn] 连接 【用户服务失败】")
		return
	}
	//拨号连接用户grpc服务器
	userConn, err := grpc.Dial(fmt.Sprintf("%s:%d", userSrvHost,
		userSrvPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		zap.S().Errorw("[GetUserList] 连接 【用户服务失败】",
			"msg", err.Error(),
		)
	}
	//1.后续的用户服务下线了 2.该端口了 3.改ip了   负载均衡来做
	//2.已经事先创立好了连接,这样后续就不用进行再次tcp的三次握手
	//3.一个连接多个groutine共用,性能-连接池
	userSrcClient := proto.NewUserClient(userConn)
	global.UserSrvClient = userSrcClient

}

启动gin时初始化

package main
func main() {
	//初始化srv的连接
	initialize.InitSrvConn()
	zap.S().Debugf("启动服务器,端口:%d", global.ServerConfig.Port)
	if err := Router.Run(fmt.Sprintf(":%d", global.ServerConfig.Port)); err != nil {
		zap.S().Panic("启动失败:", err.Error())
	}
}

总结

grpc健康检查重要点:
1.check = {
“GRPC": rtipH:{port}","GRPCUseTLS": False,"Timeout": "5s"","Interval": "5s",
"DeregisterCriticalServiceAfter": "5s",
}
2.一定要确保网络是通的
3.一定要确保srv服务监听端口是对外可访问的
4.GRPC一定要自己填写

python和golang的consul的服务注册、健康检查、服务发现

集成到python的srv

集成到golang的gin

你可能感兴趣的:(python,consul,golang,服务发现,docker)