初始版本

This commit is contained in:
2026-05-06 14:53:45 +08:00
commit b759ceb1c6
10 changed files with 814 additions and 0 deletions

122
nacosx/nacosx.go Normal file
View File

@@ -0,0 +1,122 @@
package nacosx
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
type Config struct {
Server string
NamespaceID string
BindIP string
Timeout time.Duration
}
type Client struct {
baseURL string
namespaceID string
bindIP string
client *http.Client
}
func New(cfg Config) *Client {
timeout := cfg.Timeout
if timeout == 0 {
timeout = 15 * time.Second
}
return &Client{
baseURL: strings.TrimRight(cfg.Server, "/"),
namespaceID: cfg.NamespaceID,
bindIP: cfg.BindIP,
client: &http.Client{Timeout: timeout},
}
}
func (c *Client) BaseURL() string {
return c.baseURL
}
func (c *Client) BindIP() string {
return c.bindIP
}
func (c *Client) ConfigJSON(dataID string, dst any) error {
body, err := c.GetConfig(dataID)
if err != nil {
return err
}
return json.Unmarshal(body, dst)
}
func (c *Client) GetConfig(dataID string) ([]byte, error) {
u, _ := url.Parse(c.baseURL + "/nacos/v1/cs/configs")
q := u.Query()
q.Set("dataId", dataID)
q.Set("group", "DEFAULT_GROUP")
q.Set("tenant", c.namespaceID)
u.RawQuery = q.Encode()
resp, err := c.client.Get(u.String())
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
if resp.StatusCode >= http.StatusMultipleChoices {
return nil, fmt.Errorf("nacos config %s status=%d body=%s", dataID, resp.StatusCode, string(body))
}
return body, nil
}
func (c *Client) Register(serviceName string, port int) error {
values := url.Values{}
values.Set("serviceName", serviceName)
values.Set("ip", c.bindIP)
values.Set("port", strconv.Itoa(port))
values.Set("namespaceId", c.namespaceID)
values.Set("ephemeral", "true")
resp, err := c.client.PostForm(c.baseURL+"/nacos/v1/ns/instance", values)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode >= http.StatusMultipleChoices {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("status=%d body=%s", resp.StatusCode, string(body))
}
return nil
}
func (c *Client) Heartbeat(serviceName string, port int) {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for range ticker.C {
beat, _ := json.Marshal(map[string]any{"serviceName": serviceName, "ip": c.bindIP, "port": port, "ephemeral": true})
u, _ := url.Parse(c.baseURL + "/nacos/v1/ns/instance/beat")
q := u.Query()
q.Set("serviceName", serviceName)
q.Set("ip", c.bindIP)
q.Set("port", strconv.Itoa(port))
q.Set("namespaceId", c.namespaceID)
q.Set("beat", string(beat))
u.RawQuery = q.Encode()
req, _ := http.NewRequest(http.MethodPut, u.String(), nil)
resp, err := c.client.Do(req)
if err != nil {
log.Printf("nacos heartbeat failed: %v", err)
continue
}
io.Copy(io.Discard, resp.Body)
resp.Body.Close()
if resp.StatusCode >= http.StatusMultipleChoices {
log.Printf("nacos heartbeat status=%d", resp.StatusCode)
}
}
}