使用Golang操作HashiCorp Consul API的实践指南

使用Golang操作HashiCorp Consul API的实践指南 我是 Golang 的新手。除了在线学习过几门课程外,我在工作中没有实际的 Golang 经验。

我们在工作中使用 consul,我正在尝试使用 consul API 来获取成员并根据某些模式进行筛选。我找到了很多关于 consul kv 的示例,但关于成员的资料却很少。即使阅读 GoDoc 文档,我也没能理解具体用法。

有人能在这方面给我一些指导,或者推荐一些好的文档吗?

1 回复

更多关于使用Golang操作HashiCorp Consul API的实践指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang中使用HashiCorp Consul API操作成员信息是一个常见的需求。以下是使用官方github.com/hashicorp/consul/api包获取和筛选Consul成员的完整示例:

首先安装Consul客户端库:

go get github.com/hashicorp/consul/api

基础使用示例:

package main

import (
	"fmt"
	"log"
	"strings"

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

func main() {
	// 创建Consul客户端配置
	config := api.DefaultConfig()
	config.Address = "localhost:8500" // Consul agent地址

	// 创建客户端
	client, err := api.NewClient(config)
	if err != nil {
		log.Fatal("创建Consul客户端失败:", err)
	}

	// 获取所有成员
	members, err := client.Agent().Members(false)
	if err != nil {
		log.Fatal("获取成员列表失败:", err)
	}

	fmt.Printf("发现 %d 个成员:\n", len(members))
	
	// 基本成员信息展示
	for _, member := range members {
		fmt.Printf("名称: %s, 地址: %s, 端口: %d, 状态: %d\n", 
			member.Name, member.Addr, member.Port, member.Status)
	}

	// 根据模式筛选成员的示例
	filteredMembers := filterMembersByPattern(members, "node")
	fmt.Printf("\n筛选后找到 %d 个成员:\n", len(filteredMembers))
	for _, member := range filteredMembers {
		fmt.Printf("筛选结果 - 名称: %s, 地址: %s\n", member.Name, member.Addr)
	}

	// 根据状态筛选的示例
	aliveMembers := filterMembersByStatus(members, 1) // 状态1表示alive
	fmt.Printf("\n活跃成员数量: %d\n", len(aliveMembers))
}

// 根据名称模式筛选成员
func filterMembersByPattern(members []*api.AgentMember, pattern string) []*api.AgentMember {
	var filtered []*api.AgentMember
	for _, member := range members {
		if strings.Contains(strings.ToLower(member.Name), strings.ToLower(pattern)) {
			filtered = append(filtered, member)
		}
	}
	return filtered
}

// 根据状态筛选成员
func filterMembersByStatus(members []*api.AgentMember, status int) []*api.AgentMember {
	var filtered []*api.AgentMember
	for _, member := range members {
		if member.Status == status {
			filtered = append(filtered, member)
		}
	}
	return filtered
}

更高级的筛选和操作示例:

package main

import (
	"fmt"
	"log"
	"regexp"

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

type MemberFilter struct {
	NamePattern   string
	Status        int
	TagKey        string
	TagValue      string
	AddressPrefix string
}

func main() {
	client, err := api.NewClient(api.DefaultConfig())
	if err != nil {
		log.Fatal(err)
	}

	// 获取局域网成员(不包含WAN成员)
	members, err := client.Agent().Members(false)
	if err != nil {
		log.Fatal(err)
	}

	// 使用高级筛选器
	filter := MemberFilter{
		NamePattern:   "^web-.*", // 正则表达式匹配以"web-"开头的节点
		Status:        1,         // 仅显示活跃节点
		AddressPrefix: "192.168", // IP地址前缀
	}

	filtered := advancedFilterMembers(members, filter)
	
	fmt.Println("高级筛选结果:")
	for i, member := range filtered {
		fmt.Printf("%d. %s (%s:%d) - Tags: %v\n", 
			i+1, member.Name, member.Addr, member.Port, member.Tags)
	}
}

func advancedFilterMembers(members []*api.AgentMember, filter MemberFilter) []*api.AgentMember {
	var result []*api.AgentMember

	for _, member := range members {
		// 状态筛选
		if filter.Status != 0 && member.Status != filter.Status {
			continue
		}

		// 名称模式筛选(正则表达式)
		if filter.NamePattern != "" {
			matched, err := regexp.MatchString(filter.NamePattern, member.Name)
			if err != nil || !matched {
				continue
			}
		}

		// 地址前缀筛选
		if filter.AddressPrefix != "" && !strings.HasPrefix(member.Addr, filter.AddressPrefix) {
			continue
		}

		// 标签筛选
		if filter.TagKey != "" {
			tagFound := false
			for _, tag := range member.Tags {
				if strings.HasPrefix(tag, filter.TagKey+"=") {
					if filter.TagValue == "" || strings.Contains(tag, "="+filter.TagValue) {
						tagFound = true
						break
					}
				}
			}
			if !tagFound {
				continue
			}
		}

		result = append(result, member)
	}

	return result
}

获取特定节点的详细信息:

func getNodeDetails(client *api.Client, nodeName string) {
	// 获取节点服务
	services, _, err := client.Catalog().Node(nodeName, nil)
	if err != nil {
		log.Printf("获取节点 %s 的服务失败: %v", nodeName, err)
		return
	}

	fmt.Printf("节点 %s 的服务:\n", nodeName)
	for _, service := range services.Services {
		fmt.Printf("  服务: %s, ID: %s, 端口: %d\n", 
			service.Service, service.ID, service.Port)
	}
}

这些示例展示了如何使用Consul API获取成员列表并进行各种模式的筛选。关键点包括:

  • 使用client.Agent().Members(false)获取局域网成员
  • 成员对象包含Name、Addr、Port、Status、Tags等字段
  • 可以根据业务需求实现自定义筛选逻辑

在实际使用时,需要根据你的Consul集群配置调整连接参数,并处理可能的错误情况。

回到顶部