gitee.com/h79/goutils@v1.22.10/discovery/etcd/service.go (about)

     1  package etcd
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"gitee.com/h79/goutils/common/logger"
     7  	"gitee.com/h79/goutils/common/system"
     8  	"gitee.com/h79/goutils/discovery/config"
     9  	"gitee.com/h79/goutils/discovery/registry"
    10  	"gitee.com/h79/goutils/discovery/service"
    11  	clientV3 "go.etcd.io/etcd/client/v3"
    12  	"time"
    13  )
    14  
    15  var _ service.Service = (*edService)(nil)
    16  
    17  type edService struct {
    18  	Base
    19  	lease         clientV3.Lease
    20  	leaseId       clientV3.LeaseID
    21  	cancelFunc    func()
    22  	keepAliveChan <-chan *clientV3.LeaseKeepAliveResponse
    23  	cfg           config.Config
    24  }
    25  
    26  // NewService
    27  // 注册一个服务
    28  func NewService(cfg config.Config, points config.EndPoints, registry registry.Registry) (service.Service, error) {
    29  
    30  	cli, err := NewClient3(&points, 30)
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  
    35  	logger.Info("etcd.service: register service")
    36  
    37  	return NewServiceWith(cli, cfg)
    38  }
    39  
    40  func NewServiceWith(cli *clientV3.Client, cfg config.Config) (service.Service, error) {
    41  
    42  	// 创建租约
    43  	lease := clientV3.NewLease(cli)
    44  
    45  	// 设置租约时间
    46  	leaseResp, err := lease.Grant(context.TODO(), cfg.Check.Interval.Microseconds())
    47  	if err != nil {
    48  		_ = cli.Close()
    49  		return nil, err
    50  	}
    51  
    52  	// 设置续租
    53  	ctx, cancelFunc := context.WithCancel(context.TODO())
    54  	keepaliveChan, err := lease.KeepAlive(ctx, leaseResp.ID)
    55  
    56  	if err != nil {
    57  		_ = cli.Close()
    58  		cancelFunc()
    59  		return nil, err
    60  	}
    61  
    62  	ser := &edService{
    63  		Base: Base{
    64  			client:  cli,
    65  			watcher: nil,
    66  		},
    67  		lease:         lease,
    68  		leaseId:       leaseResp.ID,
    69  		cancelFunc:    cancelFunc,
    70  		keepAliveChan: keepaliveChan,
    71  		cfg:           cfg,
    72  	}
    73  
    74  	if err = ser.create(); err != nil {
    75  		ser.Stop()
    76  		logger.Error("etcd.service: register service failure,%+v", err)
    77  		return nil, err
    78  	}
    79  
    80  	return ser, nil
    81  }
    82  
    83  // Start
    84  /**
    85  * Service interface
    86  * 使用 goroutine  go Start
    87   */
    88  func (s *edService) Start() error {
    89  
    90  	system.ChildRunning(s.keepAlive)
    91  
    92  	return nil
    93  }
    94  
    95  // Stop interface
    96  func (s *edService) Stop() {
    97  	s.revoke()
    98  	s.cancelFunc()
    99  }
   100  
   101  func (s *edService) keepAlive() {
   102  	if !s.cfg.Check.Ttl {
   103  		return
   104  	}
   105  	for {
   106  		select {
   107  		case c := <-s.keepAliveChan:
   108  			if c == nil {
   109  				logger.Error("etcd.service: 已经关闭续租功能")
   110  				return
   111  			} else {
   112  				logger.NDebug("etcd.service: 续租成功")
   113  			}
   114  		case <-system.Closed():
   115  			return
   116  		}
   117  	}
   118  }
   119  
   120  func (s *edService) create() error {
   121  	key := s.cfg.Node.NameWith("")
   122  	data, err := json.Marshal(&s.cfg.Server)
   123  	if err != nil {
   124  		return err
   125  	}
   126  	kv := clientV3.NewKV(s.client)
   127  	_, err = kv.Put(context.TODO(), key, string(data), clientV3.WithLease(s.leaseId))
   128  	return err
   129  }
   130  
   131  func (s *edService) revoke() {
   132  	time.Sleep(2 * time.Second)
   133  	if s.lease != nil {
   134  		_, _ = s.lease.Revoke(context.TODO(), s.leaseId)
   135  		s.lease = nil
   136  	}
   137  	if s.client != nil {
   138  		_ = s.client.Close()
   139  		s.client = nil
   140  	}
   141  }