github.com/TeaOSLab/EdgeNode@v1.3.8/internal/utils/agents/manager.go (about)

     1  // Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
     2  
     3  package agents
     4  
     5  import (
     6  	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
     7  	teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
     8  	"github.com/TeaOSLab/EdgeNode/internal/events"
     9  	"github.com/TeaOSLab/EdgeNode/internal/goman"
    10  	"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
    11  	"github.com/TeaOSLab/EdgeNode/internal/rpc"
    12  	"github.com/iwind/TeaGo/Tea"
    13  	"os"
    14  	"sync"
    15  	"time"
    16  )
    17  
    18  var SharedManager = NewManager()
    19  
    20  func init() {
    21  	if !teaconst.IsMain {
    22  		return
    23  	}
    24  
    25  	events.On(events.EventLoaded, func() {
    26  		goman.New(func() {
    27  			SharedManager.Start()
    28  		})
    29  	})
    30  }
    31  
    32  // Manager Agent管理器
    33  type Manager struct {
    34  	ipMap  map[string]string // ip => agentCode
    35  	locker sync.RWMutex
    36  
    37  	db DB
    38  
    39  	lastId int64
    40  }
    41  
    42  func NewManager() *Manager {
    43  	return &Manager{
    44  		ipMap: map[string]string{},
    45  	}
    46  }
    47  
    48  func (this *Manager) SetDB(db DB) {
    49  	this.db = db
    50  }
    51  
    52  func (this *Manager) Start() {
    53  	remotelogs.Println("AGENT_MANAGER", "starting ...")
    54  
    55  	err := this.loadDB()
    56  	if err != nil {
    57  		remotelogs.Error("AGENT_MANAGER", "load database failed: "+err.Error())
    58  		return
    59  	}
    60  
    61  	// 从本地数据库中加载
    62  	err = this.Load()
    63  	if err != nil {
    64  		remotelogs.Error("AGENT_MANAGER", "load failed: "+err.Error())
    65  	}
    66  
    67  	// 先从API获取
    68  	err = this.LoopAll()
    69  	if err != nil {
    70  		if rpc.IsConnError(err) {
    71  			remotelogs.Debug("AGENT_MANAGER", "retrieve latest agent ip failed: "+err.Error())
    72  		} else {
    73  			remotelogs.Error("AGENT_MANAGER", "retrieve latest agent ip failed: "+err.Error())
    74  		}
    75  	}
    76  
    77  	// 定时获取
    78  	var duration = 30 * time.Minute
    79  	if Tea.IsTesting() {
    80  		duration = 30 * time.Second
    81  	}
    82  	var ticker = time.NewTicker(duration)
    83  	for range ticker.C {
    84  		err = this.LoopAll()
    85  		if err != nil {
    86  			remotelogs.Error("AGENT_MANAGER", "retrieve latest agent ip failed: "+err.Error())
    87  		}
    88  	}
    89  }
    90  
    91  func (this *Manager) Load() error {
    92  	var offset int64 = 0
    93  	var size int64 = 10000
    94  	for {
    95  		agentIPs, err := this.db.ListAgentIPs(offset, size)
    96  		if err != nil {
    97  			return err
    98  		}
    99  		if len(agentIPs) == 0 {
   100  			break
   101  		}
   102  		for _, agentIP := range agentIPs {
   103  			this.locker.Lock()
   104  			this.ipMap[agentIP.IP] = agentIP.AgentCode
   105  			this.locker.Unlock()
   106  
   107  			if agentIP.Id > this.lastId {
   108  				this.lastId = agentIP.Id
   109  			}
   110  		}
   111  		offset += size
   112  	}
   113  
   114  	return nil
   115  }
   116  
   117  func (this *Manager) LoopAll() error {
   118  	for {
   119  		hasNext, err := this.Loop()
   120  		if err != nil {
   121  			return err
   122  		}
   123  		if !hasNext {
   124  			break
   125  		}
   126  	}
   127  	return nil
   128  }
   129  
   130  // Loop 单次循环获取数据
   131  func (this *Manager) Loop() (hasNext bool, err error) {
   132  	rpcClient, err := rpc.SharedRPC()
   133  	if err != nil {
   134  		return false, err
   135  	}
   136  	ipsResp, err := rpcClient.ClientAgentIPRPC.ListClientAgentIPsAfterId(rpcClient.Context(), &pb.ListClientAgentIPsAfterIdRequest{
   137  		Id:   this.lastId,
   138  		Size: 10000,
   139  	})
   140  	if err != nil {
   141  		return false, err
   142  	}
   143  	if len(ipsResp.ClientAgentIPs) == 0 {
   144  		return false, nil
   145  	}
   146  	for _, agentIP := range ipsResp.ClientAgentIPs {
   147  		if agentIP.ClientAgent == nil {
   148  			// 设置ID
   149  			if agentIP.Id > this.lastId {
   150  				this.lastId = agentIP.Id
   151  			}
   152  
   153  			continue
   154  		}
   155  
   156  		// 写入到数据库
   157  		err = this.db.InsertAgentIP(agentIP.Id, agentIP.Ip, agentIP.ClientAgent.Code)
   158  		if err != nil {
   159  			return false, err
   160  		}
   161  
   162  		// 写入Map
   163  		this.locker.Lock()
   164  		this.ipMap[agentIP.Ip] = agentIP.ClientAgent.Code
   165  		this.locker.Unlock()
   166  
   167  		// 设置ID
   168  		if agentIP.Id > this.lastId {
   169  			this.lastId = agentIP.Id
   170  		}
   171  	}
   172  
   173  	return true, nil
   174  }
   175  
   176  // AddIP 添加记录
   177  func (this *Manager) AddIP(ip string, agentCode string) {
   178  	this.locker.Lock()
   179  	this.ipMap[ip] = agentCode
   180  	this.locker.Unlock()
   181  }
   182  
   183  // LookupIP 查询IP所属Agent
   184  func (this *Manager) LookupIP(ip string) (agentCode string) {
   185  	this.locker.RLock()
   186  	defer this.locker.RUnlock()
   187  	return this.ipMap[ip]
   188  }
   189  
   190  // ContainsIP 检查是否有IP相关数据
   191  func (this *Manager) ContainsIP(ip string) bool {
   192  	this.locker.RLock()
   193  	defer this.locker.RUnlock()
   194  	_, ok := this.ipMap[ip]
   195  	return ok
   196  }
   197  
   198  func (this *Manager) loadDB() error {
   199  	var sqlitePath = Tea.Root + "/data/agents.db"
   200  	_, sqliteErr := os.Stat(sqlitePath)
   201  	var db DB
   202  	if sqliteErr == nil || !teaconst.EnableKVCacheStore {
   203  		db = NewSQLiteDB(sqlitePath)
   204  	} else {
   205  		db = NewKVDB()
   206  	}
   207  	err := db.Init()
   208  	if err != nil {
   209  		return err
   210  	}
   211  	this.db = db
   212  	return nil
   213  }