背景:因为公司中的机器比较老。我们的云上监控规定,使用的token的方式来监控,所以无法监控我们的etcd集群,我这里提供的一个etcd数据转发功能,能让监控到etcd集群
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"net/http"
"os"
"sync"
"time"
)
var (
requestCount int
lastTimestamp time.Time
mu sync.Mutex
)
const (
maxRequests = 10
resetDuration = time.Minute
)
func fetchEtcdMetrics(certPath, keyPath, caPath string) (string, error) {
etcdEndpoint := "https://127.0.0.1:2379"
monitorEndpoint := etcdEndpoint + "/metrics"
// 读取证书、密钥和 CA 证书
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
if err != nil {
return "", fmt.Errorf("加载证书和密钥失败:%v", err)
}
caCert, err := os.ReadFile(caPath)
if err != nil {
return "", fmt.Errorf("读取 CA 证书失败:%v", err)
}
// 创建自定义的 tls.Config
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: x509.NewCertPool(),
}
// 添加 CA 证书到 RootCAs
if ok := tlsConfig.RootCAs.AppendCertsFromPEM(caCert); !ok {
return "", fmt.Errorf("添加 CA 证书到 RootCAs 失败")
}
// 创建带有 TLS 配置的 HTTP 客户端
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
}
// 创建 HTTP GET 请求
req, err := http.NewRequest("GET", monitorEndpoint, nil)
if err != nil {
return "", fmt.Errorf("创建 HTTP 请求失败:%v", err)
}
// 发送 HTTP 请求并获取响应
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("获取 etcd 指标失败:%v", err)
}
defer resp.Body.Close()
// 检查响应状态码
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("获取 etcd 指标失败。状态码:%d", resp.StatusCode)
}
// 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("读取响应体失败:%v", err)
}
return string(body), nil
}
func fetchEtcdMetricsHandler(w http.ResponseWriter, r *http.Request) {
mu.Lock()
defer mu.Unlock()
now := time.Now()
if now.Sub(lastTimestamp) > resetDuration {
requestCount = 0
lastTimestamp = now
}
if requestCount >= maxRequests {
http.Error(w, "请求频率过高", http.StatusTooManyRequests)
return
}
requestCount++
certPath := os.Args[1]
keyPath := os.Args[2]
caPath := os.Args[3]
metricsData, err := fetchEtcdMetrics(certPath, keyPath, caPath)
if err != nil {
http.Error(w, fmt.Sprintf("发生错误:%v", err), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, metricsData)
}
func main() {
if len(os.Args) < 4 {
fmt.Println("用法: go run your_script.go <cert_path> <key_path> <ca_path>")
os.Exit(1)
}
http.HandleFunc("/fetch_etcd_metrics", fetchEtcdMetricsHandler)
port := 5010
fmt.Printf("服务器正在运行,地址:http://0.0.0.0:%d\n", port)
err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
if err != nil {
fmt.Printf("启动服务器时发生错误:%v\n", err)
}
}
标签:http,nil,err,fmt,etcd,转发,go,return From: https://www.cnblogs.com/Direction-of-efforts/p/18053849