gohelpers/pkg/etcd/register.go
2022-06-28 10:44:39 +08:00

109 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package etcd
import (
"context"
"net"
"strconv"
"time"
clientV3 "go.etcd.io/etcd/client/v3"
)
type Client struct {
v3 *clientV3.Client
lease *clientV3.LeaseGrantResponse
interval int32
serviceName string
}
func NewClient(endpoint []string) (*Client, error) {
client, err := clientV3.New(clientV3.Config{
Endpoints: endpoint,
DialTimeout: 5 * time.Second,
})
if err != nil {
return nil, err
}
return &Client{v3: client, interval: 5}, nil
}
// Close 关闭client
func (e *Client) Close() error {
return e.v3.Close()
}
// Register 注册服务
func (e *Client) Register(serviceName string, serviceAddress string) error {
var err error
ctx := context.Background()
e.lease, err = e.v3.Grant(ctx, int64(e.interval+1))
if err != nil {
return err
}
e.serviceName = serviceName + "/" + strconv.Itoa(int(e.lease.ID))
_, err = e.v3.Put(ctx, e.serviceName, getValue(serviceAddress), clientV3.WithLease(e.lease.ID))
if err != nil {
return err
}
e.keepAlive(serviceName, serviceAddress)
return nil
}
// Deregister 注销服务
func (e *Client) Deregister() error {
_, err := e.v3.Delete(context.Background(), e.serviceName)
if err != nil {
return err
}
return nil
}
// keepAlive 异步续约
func (e *Client) keepAlive(name string, addr string) {
// 永久续约续约成功后etcd客户端和服务器会保持通讯通讯成功会写数据到返回的通道中
// 停止进程后服务器链接不上客户端相应key租约到期会被服务器自动删除
c, err := e.v3.KeepAlive(e.v3.Ctx(), e.lease.ID)
go func() {
if err == nil {
for {
select {
case _, ok := <-c:
if !ok { //续约失败
e.v3.Revoke(e.v3.Ctx(), e.lease.ID)
e.Register(name, addr)
return
}
}
}
defer e.v3.Revoke(e.v3.Ctx(), e.lease.ID)
}
}()
}
// getValue etcd服务发现时底层解析的是一个json串且包含Addr字段
func getValue(addr string) string {
// return "{\"Addr\":\"" + localIP() + addr + "\"}"
return localIP() + addr
}
// localIP 获取当前ip
func localIP() string {
addrList, err := net.InterfaceAddrs()
if err != nil {
return ""
}
for _, address := range addrList {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
return ipnet.IP.String()
}
}
}
return ""
}