This commit is contained in:
kzkzzzz
2025-03-22 01:24:57 +08:00
parent 197476e805
commit 7e0bf82418
22 changed files with 2291 additions and 919 deletions

153
myregistry/consul/consul.go Normal file
View File

@@ -0,0 +1,153 @@
package consul
import (
"fmt"
"git.makemake.in/kzkzzzz/mycommon/myconf"
"git.makemake.in/kzkzzzz/mycommon/myregistry"
"github.com/google/uuid"
api "github.com/hashicorp/consul/api"
"log"
"net"
"net/url"
"time"
)
var _ myregistry.IRegister = (*Consul)(nil)
type Consul struct {
client *api.Client
serviceIds map[string][]string
serviceTags []string
}
func (c *Consul) Name() string {
return "consul"
}
func (c *Consul) Register(service *myregistry.ServiceInfo) error {
// 健康检查
serviceId := uuid.New().String()
c.serviceIds[service.ServiceName] = append(c.serviceIds[service.ServiceName], serviceId)
check := &api.AgentServiceCheck{
CheckID: serviceId,
TCP: fmt.Sprintf("%s:%d", service.Ip, service.Port),
Timeout: "5s", // 超时时间
Interval: "20s", // 运行检查的频率
// 指定时间后自动注销不健康的服务节点
// 最小超时时间为1分钟收获不健康服务的进程每30秒运行一次因此触发注销的时间可能略长于配置的超时时间。
DeregisterCriticalServiceAfter: "5m",
Status: "passing",
}
srv := &api.AgentServiceRegistration{
ID: serviceId, // 服务唯一ID
Name: service.ServiceName, // 服务名称
Tags: c.serviceTags, // 为服务打标签
Address: service.Ip,
Port: service.Port,
Check: check,
}
return c.client.Agent().ServiceRegister(srv)
}
func (c *Consul) Deregister(service *myregistry.ServiceInfo) error {
for _, svcId := range c.serviceIds[service.ServiceName] {
err := c.client.Agent().ServiceDeregister(svcId)
if err != nil {
log.Printf("Failed to deregister service %s: %s\n", service, err)
}
}
return nil
}
type Conf struct {
Addr string
Token string
}
func MustNew(conf *myconf.Config) *Consul {
consul, err := New(conf)
if err != nil {
panic(err)
}
return consul
}
func New(conf *myconf.Config) (*Consul, error) {
cfg := api.DefaultConfig()
cfg.Address = conf.GetString("addr")
cfg.Transport.DialContext = (&net.Dialer{
Timeout: 3 * time.Second,
KeepAlive: 20 * time.Second,
DualStack: true,
}).DialContext
cfg.Token = conf.GetString("token")
username := conf.GetString("username")
password := conf.GetString("password")
if username != "" && password != "" {
cfg.HttpAuth = &api.HttpBasicAuth{
Username: username,
Password: password,
}
}
client, err := api.NewClient(cfg)
if err != nil {
return nil, err
}
cl := &Consul{
client: client,
serviceIds: make(map[string][]string),
serviceTags: make([]string, 0),
}
if v := conf.GetStringSlice("serviceTags"); len(v) > 0 {
cl.serviceTags = v
} else {
cl.serviceTags = []string{}
}
return cl, nil
}
func (c *Consul) Client() *api.Client {
return c.client
}
func GrpcUrl(serviceName string, conf *myconf.Config) string {
return GrpcUrlWithTag("", serviceName, conf)
}
func GrpcUrlWithTag(tag string, serviceName string, conf *myconf.Config) string {
u := &url.URL{
Scheme: schemeName,
Host: conf.GetString("addr"),
Path: serviceName,
}
query := u.Query()
query.Set("healthy", "true")
if v := conf.GetString("token"); v != "" {
query.Set("token", v)
}
if tag != "" {
query.Set("tag", tag)
}
username := conf.GetString("username")
password := conf.GetString("password")
if username != "" && password != "" {
u.User = url.UserPassword(username, password)
}
u.RawQuery = query.Encode()
return u.String()
}