掘金 后端 ( ) • 2024-04-20 15:51

在现代的软件开发实践中,RabbitMQ作为一个广泛使用的消息队列服务,其健康状态的监控至关重要。rabbitmqctl cluster_status命令能够提供RabbitMQ集群的当前状态,了解其运行情况对于系统的稳定运行非常关键。本文将通过Go语言来解析该命令的JSON格式输出,并展示如何将这些数据有效地结构化,以便进一步处理。

1683714461087.png

JSON输出结构解析

首先,我们需要了解rabbitmqctl cluster_status --formatter json命令输出的JSON结构。这里是一个示例输出:

{
  "alarms": [],
  "cluster_name": "rabbit@pam-rabbitmq",
  "disk_nodes": ["rabbit@pam-rabbitmq"],
  "feature_flags": [
    {
      "desc": "Count unroutable publishes to be dropped in stats",
      "doc_url": "",
      "name": "drop_unroutable_metric",
      "provided_by": "rabbitmq_management_agent",
      "stability": "stable",
      "state": "enabled"
    }
  ],
  "listeners": {
    "rabbit@pam-rabbitmq": [
      {
        "interface": "[::]",
        "node": "rabbit@pam-rabbitmq",
        "port": 15692,
        "protocol": "http/prometheus",
        "purpose": "Prometheus exporter API over HTTP"
      }
    ]
  },
  "maintenance_status": {"rabbit@pam-rabbitmq": "not under maintenance"},
  "partitions": {},
  "ram_nodes": [],
  "running_nodes": ["rabbit@pam-rabbitmq"],
  "versions": {
    "rabbit@pam-rabbitmq": {
      "erlang_version": "24.1.7",
      "rabbitmq_name": "RabbitMQ",
      "rabbitmq_version": "3.8.26"
    }
  }
}

定义Go结构体

为了解析上述JSON数据,我们需要定义一系列匹配JSON结构的Go结构体。以下是结构体定义:

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

// ClusterStatus 定义顶层的JSON结构
type ClusterStatus struct {
    Alarms            []interface{}  `json:"alarms"`
    ClusterName       string         `json:"cluster_name"`
    DiskNodes         []string       `json:"disk_nodes"`
    FeatureFlags      []FeatureFlag  `json:"feature_flags"`
    Listeners         map[string][]Listener `json:"listeners"`
    MaintenanceStatus map[string]string      `json:"maintenance_status"`
    Partitions        map[string]interface{} `json:"partitions"`
    RamNodes          []interface{}          `json:"ram_nodes"`
    RunningNodes      []string               `json:"running_nodes"`
    Versions          map[string]VersionInfo `json:"versions"`
}

// FeatureFlag 定义feature_flags数组中的项
type FeatureFlag struct {
    Description string `json:"desc"`
    DocURL      string `json:"doc_url"`
    Name        string `json:"name"`
    ProvidedBy  string `json:"provided_by"`
    Stability   string `json:"stability"`
    State       string `json:"state"`
}

// Listener 定义listeners字典中的项
type Listener struct {
    Interface string `json:"interface"`
    Node      string `json:"node"`
    Port      int    `json:"port"`
    Protocol  string `json:"protocol"`
    Purpose   string `json:"purpose"`
}

// VersionInfo 定义versions字典中的版本信息
type VersionInfo struct {
    ErlangVersion   string `json:"erlang_version"`
    RabbitmqName    string `json:"rabbitmq_name"`
    RabbitmqVersion string `json:"rabbitmq_version"`
}



// parseJSON 解析JSON数据到结构体
func parseJSON(data string) *ClusterStatus {
    var status ClusterStatus
    err := json.Unmarshal([]byte(data), &status)
    if err != nil {
        log.Fatal(err)
    }
    return &status
}

func main() {
    jsonData := `{"alarms":[],"cluster_name":"rabbit@pam-rabbitmq","disk_nodes":["rabbit@pam-rabbitmq"],"feature_flags":[{"desc":"Count unroutable publishes to be dropped in stats","doc_url":"","name":"drop_unroutable_metric","provided_by":"rabbitmq_management_agent","stability":"stable","state":"enabled"}],"listeners":{"rabbit@pam-rabbitmq":[{"interface":"[::]","node":"rabbit@pam-rabbitmq","port":15692,"protocol":"http/prometheus","purpose":"Prometheus exporter API over HTTP"}]},"maintenance_status":{"rabbit@pam-rabbitmq":"not under maintenance"},"partitions":{},"ram_nodes":[],"running_nodes":["rabbit@pam-rabbitmq"],"versions":{"rabbit@pam-rabbitmq":{"erlang_version":"24.1.7","rabbitmq_name":"RabbitMQ","rabbitmq_version":"3.8.26"}}}`
    status := parseJSON(jsonData)
    fmt.Printf("Cluster Name: %s\n", status.ClusterName)
    fmt.Printf("Running Nodes: %v\n", status.RunningNodes)
    for _, flag := range status.FeatureFlags {
        fmt.Printf("Feature: %s, State: %s\n", flag.Name, flag.State)
    }
}

代码解析与执行

1701893814254.png

在上面的代码中,我们首先定义了一系列结构体,用于反序列化JSON数据。parseJSON函数用于将JSON字符串解析为ClusterStatus结构体实例。在main函数中,我们实例化了一个JSON字符串,并调用parseJSON函数来解析它,然后打印出一些核心信息来验证解析的正确性。

通过这个例子,我们可以学习到如何使用Go语言处理JSON数据,以及如何根据需要设计合适的数据结构。这些技能在开发中间件、APIs或进行数据交换时非常有用。