实现基础的智能调度

This commit is contained in:
GoEdgeLab
2023-05-17 18:42:21 +08:00
parent 667628aff3
commit 3fd2925780
33 changed files with 507 additions and 127 deletions

View File

@@ -12,4 +12,5 @@ dbs:
fields:
bool: [ "uamIsOn", "followPort", "requestHostExcludingPort", "autoRemoteStart", "autoInstallNftables" ]
bool: [ "uamIsOn", "followPort", "requestHostExcludingPort", "autoRemoteStart", "autoInstallNftables", "enableIPLists", "detectAgents", "checkingPorts", "enableRecordHealthCheck", "offlineIsNotified" ]

View File

@@ -12,7 +12,8 @@ import (
type DNSTaskType = string
const (
DNSTaskTypeClusterChange DNSTaskType = "clusterChange"
DNSTaskTypeClusterChange DNSTaskType = "clusterChange" // 集群节点、服务发生变化
DNSTaskTypeClusterNodesChange DNSTaskType = "clusterNodesChange" // 集群中节点发生变化
DNSTaskTypeClusterRemoveDomain DNSTaskType = "clusterRemoveDomain" // 从集群中移除域名
DNSTaskTypeNodeChange DNSTaskType = "nodeChange"
DNSTaskTypeServerChange DNSTaskType = "serverChange"

View File

@@ -52,7 +52,9 @@ const (
MessageTypeReportNodeInactive MessageType = "ReportNodeInactive" // 区域监控节点节点不活跃
MessageTypeReportNodeActive MessageType = "ReportNodeActive" // 区域监控节点活跃
MessageTypeConnectivity MessageType = "Connectivity"
MessageTypeConnectivity MessageType = "Connectivity" // 连通性
MessageTypeNodeSchedule MessageType = "NodeSchedule" // 节点调度信息
MessageTypeNodeOfflineDay MessageType = "NodeOfflineDay" // 节点到下线日期
)
type MessageDAO dbs.DAO

View File

@@ -0,0 +1,63 @@
package models
import (
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
)
const (
NodeActionStateEnabled = 1 // 已启用
NodeActionStateDisabled = 0 // 已禁用
)
type NodeActionDAO dbs.DAO
func NewNodeActionDAO() *NodeActionDAO {
return dbs.NewDAO(&NodeActionDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeNodeActions",
Model: new(NodeAction),
PkName: "id",
},
}).(*NodeActionDAO)
}
var SharedNodeActionDAO *NodeActionDAO
func init() {
dbs.OnReady(func() {
SharedNodeActionDAO = NewNodeActionDAO()
})
}
// EnableNodeAction 启用条目
func (this *NodeActionDAO) EnableNodeAction(tx *dbs.Tx, id uint64) error {
_, err := this.Query(tx).
Pk(id).
Set("state", NodeActionStateEnabled).
Update()
return err
}
// DisableNodeAction 禁用条目
func (this *NodeActionDAO) DisableNodeAction(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Pk(id).
Set("state", NodeActionStateDisabled).
Update()
return err
}
// FindEnabledNodeAction 查找启用中的条目
func (this *NodeActionDAO) FindEnabledNodeAction(tx *dbs.Tx, id int64) (*NodeAction, error) {
result, err := this.Query(tx).
Pk(id).
State(NodeActionStateEnabled).
Find()
if result == nil {
return nil, err
}
return result.(*NodeAction), err
}

View File

@@ -0,0 +1,6 @@
package models_test
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,32 @@
package models
import "github.com/iwind/TeaGo/dbs"
// NodeAction 节点智能调度设置
type NodeAction struct {
Id uint64 `field:"id"` // ID
NodeId uint64 `field:"nodeId"` // 节点ID
Role string `field:"role"` // 角色
IsOn bool `field:"isOn"` // 是否启用
Conds dbs.JSON `field:"conds"` // 条件
Action dbs.JSON `field:"action"` // 动作
Duration dbs.JSON `field:"duration"` // 持续时间
Order uint32 `field:"order"` // 排序
State uint8 `field:"state"` // 状态
}
type NodeActionOperator struct {
Id any // ID
NodeId any // 节点ID
Role any // 角色
IsOn any // 是否启用
Conds any // 条件
Action any // 动作
Duration any // 持续时间
Order any // 排序
State any // 状态
}
func NewNodeActionOperator() *NodeActionOperator {
return &NodeActionOperator{}
}

View File

@@ -0,0 +1 @@
package models

View File

@@ -1550,7 +1550,7 @@ func (this *NodeDAO) FindAllEnabledNodesDNSWithClusterId(tx *dbs.Tx, clusterId i
Attr("isOn", true).
Attr("isUp", true).
Attr("isInstalled", isInstalled).
Result("id", "name", "dnsRoutes", "isOn").
Result("id", "name", "dnsRoutes", "isOn", "offlineDay", "actionStatus", "isBackupForCluster", "isBackupForGroup", "backupIPs", "clusterId", "groupId").
DescPk().
Slice(&result).
FindAll()
@@ -1575,7 +1575,7 @@ func (this *NodeDAO) FindEnabledNodeDNS(tx *dbs.Tx, nodeId int64) (*Node, error)
one, err := this.Query(tx).
State(NodeStateEnabled).
Pk(nodeId).
Result("id", "name", "dnsRoutes", "clusterId", "isOn").
Result("id", "name", "dnsRoutes", "clusterId", "isOn", "offlineDay", "isBackupForCluster", "isBackupForGroup", "actionStatus").
Find()
if one == nil {
return nil, err

View File

@@ -18,3 +18,8 @@ func (this *NodeDAO) loadServersFromCluster(tx *dbs.Tx, clusterId int64, serverI
func (this *NodeDAO) composeExtConfig(tx *dbs.Tx, config *nodeconfigs.NodeConfig, clusterIds []int64, cacheMap *utils.CacheMap) error {
return nil
}
// CheckNodeIPAddresses 检查节点IP地址
func (this *NodeDAO) CheckNodeIPAddresses(tx *dbs.Tx, node *Node) (shouldSkip bool, shouldOverwrite bool, ipAddressStrings []string, err error) {
return
}

View File

@@ -43,6 +43,12 @@ type Node struct {
DnsResolver dbs.JSON `field:"dnsResolver"` // DNS解析器
EnableIPLists bool `field:"enableIPLists"` // 启用IP名单
ApiNodeAddrs dbs.JSON `field:"apiNodeAddrs"` // API节点地址
OfflineDay string `field:"offlineDay"` // 下线日期YYYYMMDD
OfflineIsNotified bool `field:"offlineIsNotified"` // 下线是否已通知
IsBackupForCluster bool `field:"isBackupForCluster"` // 是否为集群备用节点
IsBackupForGroup bool `field:"isBackupForGroup"` // 是否为分组备用节点
BackupIPs dbs.JSON `field:"backupIPs"` // 备用IP
ActionStatus dbs.JSON `field:"actionStatus"` // 当前动作配置
}
type NodeOperator struct {
@@ -85,6 +91,12 @@ type NodeOperator struct {
DnsResolver any // DNS解析器
EnableIPLists any // 启用IP名单
ApiNodeAddrs any // API节点地址
OfflineDay any // 下线日期YYYYMMDD
OfflineIsNotified any // 下线是否已通知
IsBackupForCluster any // 是否为集群备用节点
IsBackupForGroup any // 是否为分组备用节点
BackupIPs any // 备用IP
ActionStatus any // 当前动作配置
}
func NewNodeOperator() *NodeOperator {

View File

@@ -7,6 +7,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
timeutil "github.com/iwind/TeaGo/utils/time"
"sort"
"time"
)
@@ -16,7 +17,7 @@ func (this *Node) DecodeInstallStatus() (*NodeInstallStatus, error) {
if len(this.InstallStatus) == 0 {
return NewNodeInstallStatus(), nil
}
status := &NodeInstallStatus{}
var status = &NodeInstallStatus{}
err := json.Unmarshal(this.InstallStatus, status)
if err != nil {
return NewNodeInstallStatus(), err
@@ -37,7 +38,7 @@ func (this *Node) DecodeStatus() (*nodeconfigs.NodeStatus, error) {
if len(this.Status) == 0 {
return nil, nil
}
status := &nodeconfigs.NodeStatus{}
var status = &nodeconfigs.NodeStatus{}
err := json.Unmarshal(this.Status, status)
if err != nil {
return nil, err
@@ -47,7 +48,7 @@ func (this *Node) DecodeStatus() (*nodeconfigs.NodeStatus, error) {
// DNSRouteCodes 所有的DNS线路
func (this *Node) DNSRouteCodes() map[int64][]string {
routes := map[int64][]string{} // domainId => routes
var routes = map[int64][]string{} // domainId => routes
if len(this.DnsRoutes) == 0 {
return routes
}
@@ -61,7 +62,7 @@ func (this *Node) DNSRouteCodes() map[int64][]string {
// DNSRouteCodesForDomainId DNS线路
func (this *Node) DNSRouteCodesForDomainId(dnsDomainId int64) ([]string, error) {
routes := map[int64][]string{} // domainId => routes
var routes = map[int64][]string{} // domainId => routes
if len(this.DnsRoutes) == 0 {
return nil, nil
}
@@ -80,7 +81,7 @@ func (this *Node) DNSRouteCodesForDomainId(dnsDomainId int64) ([]string, error)
// DecodeConnectedAPINodeIds 连接的API
func (this *Node) DecodeConnectedAPINodeIds() ([]int64, error) {
apiNodeIds := []int64{}
var apiNodeIds = []int64{}
if IsNotNull(this.ConnectedAPINodes) {
err := json.Unmarshal(this.ConnectedAPINodes, &apiNodeIds)
if err != nil {
@@ -214,3 +215,8 @@ func (this *Node) DecodeAPINodeAddrs() []*serverconfigs.NetworkAddressConfig {
}
return result
}
// CheckIsOffline 检查是否已经离线
func (this *Node) CheckIsOffline() bool {
return len(this.OfflineDay) > 0 && this.OfflineDay < timeutil.Format("Ymd")
}

View File

@@ -0,0 +1,9 @@
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package models
// HasScheduleSettings 检查是否设置了调度
func (this *Node) HasScheduleSettings() bool {
return false
}

View File

@@ -1,4 +1,4 @@
package stats
package models
import (
"github.com/TeaOSLab/EdgeAPI/internal/errors"
@@ -84,7 +84,9 @@ func (this *NodeTrafficDailyStatDAO) IncreaseDailyStat(tx *dbs.Tx, clusterId int
if err != nil {
return err
}
return nil
// 触发钩子
return this.increaseDailyStatHook(tx, role, nodeId)
}
// FindDailyStats 获取日期之间统计

View File

@@ -0,0 +1,14 @@
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package models
import (
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/iwind/TeaGo/dbs"
)
// 增加日统计Hook
func (this *NodeTrafficDailyStatDAO) increaseDailyStatHook(tx *dbs.Tx, role nodeconfigs.NodeRole, nodeId int64) error {
return nil
}

View File

@@ -1,4 +1,4 @@
package stats
package models
import (
_ "github.com/go-sql-driver/mysql"

View File

@@ -1,4 +1,4 @@
package stats
package models
// NodeTrafficDailyStat 总的流量统计(按天)
type NodeTrafficDailyStat struct {

View File

@@ -0,0 +1 @@
package models

View File

@@ -37,11 +37,15 @@ func init() {
// CreateValue 创建值
func (this *NodeValueDAO) CreateValue(tx *dbs.Tx, clusterId int64, role nodeconfigs.NodeRole, nodeId int64, item string, valueJSON []byte, createdAt int64) error {
if len(valueJSON) == 0 {
return errors.New("'valueJSON' should not be nil")
}
var day = timeutil.FormatTime("Ymd", createdAt)
var hour = timeutil.FormatTime("YmdH", createdAt)
var minute = timeutil.FormatTime("YmdHi", createdAt)
return this.Query(tx).
err := this.Query(tx).
InsertOrUpdateQuickly(maps.Map{
"clusterId": clusterId,
"role": role,
@@ -55,6 +59,17 @@ func (this *NodeValueDAO) CreateValue(tx *dbs.Tx, clusterId int64, role nodeconf
}, maps.Map{
"value": valueJSON,
})
if err != nil {
return err
}
// 触发钩子
err = this.nodeValueHook(tx, role, nodeId, item, valueJSON)
if err != nil {
return err
}
return nil
}
// Clean 清除数据
@@ -324,7 +339,7 @@ func (this *NodeValueDAO) SumNodeClusterValues(tx *dbs.Tx, role string, clusterI
// FindLatestNodeValue 获取最近一条数据
func (this *NodeValueDAO) FindLatestNodeValue(tx *dbs.Tx, role string, nodeId int64, item string) (*NodeValue, error) {
fromMinute := timeutil.FormatTime("YmdHi", time.Now().Unix()-int64(60))
var fromMinute = timeutil.FormatTime("YmdHi", time.Now().Unix()-int64(60))
one, err := this.Query(tx).
Attr("role", role).

View File

@@ -0,0 +1,14 @@
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package models
import (
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/iwind/TeaGo/dbs"
)
// 节点值变更Hook
func (this *NodeValueDAO) nodeValueHook(tx *dbs.Tx, role nodeconfigs.NodeRole, nodeId int64, item nodeconfigs.NodeValueItem, valueJSON []byte) error {
return nil
}

View File

@@ -1 +0,0 @@
package stats

View File

@@ -1,10 +1,11 @@
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build !plus
// +build !plus
package dnsclients
import "github.com/iwind/TeaGo/maps"
import (
"github.com/iwind/TeaGo/maps"
)
// FindProvider 查找服务商实例
func FindProvider(providerType ProviderType, providerId int64) ProviderInterface {

View File

@@ -472,13 +472,14 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
var nodeKeys = []string{}
var addingNodeRecordKeysMap = map[string]bool{} // clusterDnsName_type_ip_route
for _, node := range nodes {
ipAddresses, err := models.SharedNodeIPAddressDAO.FindNodeAccessAndUpIPAddresses(tx, int64(node.Id), nodeconfigs.NodeRoleNode)
shouldSkip, shouldOverwrite, ipAddressesStrings, err := models.SharedNodeDAO.CheckNodeIPAddresses(tx, node)
if err != nil {
return nil, nil, nil, 0, 0, false, false, err
}
if len(ipAddresses) == 0 {
if shouldSkip {
continue
}
routeCodes, err := node.DNSRouteCodesForDomainId(int64(cluster.DnsDomainId))
if err != nil {
return nil, nil, nil, 0, 0, false, false, err
@@ -491,7 +492,16 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
continue
}
}
for _, route := range routeCodes {
if !shouldOverwrite {
ipAddresses, err := models.SharedNodeIPAddressDAO.FindNodeAccessAndUpIPAddresses(tx, int64(node.Id), nodeconfigs.NodeRoleNode)
if err != nil {
return nil, nil, nil, 0, 0, false, false, err
}
if len(ipAddresses) == 0 {
continue
}
for _, ipAddress := range ipAddresses {
// 检查专属节点
if !ipAddress.IsValidInCluster(clusterId) {
@@ -505,6 +515,16 @@ func (this *DNSDomainService) findClusterDNSChanges(cluster *models.NodeCluster,
if net.ParseIP(ip) == nil {
continue
}
ipAddressesStrings = append(ipAddressesStrings, ip)
}
}
if len(ipAddressesStrings) == 0 {
continue
}
for _, route := range routeCodes {
for _, ip := range ipAddressesStrings {
var key = ip + "_" + route
nodeKeys = append(nodeKeys, key)
record, ok := nodeRecordMapping[key]

View File

@@ -62,7 +62,7 @@ func (this *DNSTaskService) FindAllDoingDNSTasks(ctx context.Context, req *pb.Fi
}
switch task.Type {
case dns.DNSTaskTypeClusterChange, dns.DNSTaskTypeClusterRemoveDomain:
case dns.DNSTaskTypeClusterChange, dns.DNSTaskTypeClusterNodesChange, dns.DNSTaskTypeClusterRemoveDomain:
clusterName, err := models.SharedNodeClusterDAO.FindNodeClusterName(tx, int64(task.ClusterId))
if err != nil {
return nil, err

View File

@@ -384,6 +384,9 @@ func (this *NodeService) ListEnabledNodesMatch(ctx context.Context, req *pb.List
NodeRegion: pbRegion,
DnsRoutes: pbRoutes,
Level: int32(node.Level),
OfflineDay: node.OfflineDay,
IsBackupForCluster: node.IsBackupForCluster,
IsBackupForGroup: node.IsBackupForGroup,
})
}
@@ -683,6 +686,9 @@ func (this *NodeService) FindEnabledNode(ctx context.Context, req *pb.FindEnable
DnsRoutes: pbRoutes,
EnableIPLists: node.EnableIPLists,
ApiNodeAddrsJSON: node.ApiNodeAddrs,
OfflineDay: node.OfflineDay,
IsBackupForCluster: node.IsBackupForCluster,
IsBackupForGroup: node.IsBackupForGroup,
}}, nil
}
@@ -1397,12 +1403,15 @@ func (this *NodeService) FindAllEnabledNodesDNSWithNodeClusterId(ctx context.Con
continue
}
result = append(result, &pb.NodeDNSInfo{
Id: int64(node.Id),
Name: node.Name,
IpAddr: ip,
NodeIPAddressId: int64(ipAddress.Id),
Routes: pbRoutes,
NodeClusterId: req.NodeClusterId,
Id: int64(node.Id),
Name: node.Name,
IpAddr: ip,
NodeIPAddressId: int64(ipAddress.Id),
Routes: pbRoutes,
NodeClusterId: req.NodeClusterId,
IsBackupForCluster: node.IsBackupForCluster,
IsBackupForGroup: node.IsBackupForGroup,
IsOffline: node.CheckIsOffline(),
})
}
}
@@ -1497,6 +1506,9 @@ func (this *NodeService) FindEnabledNodeDNS(ctx context.Context, req *pb.FindEna
NodeClusterDNSName: clusterDNS.DnsName,
DnsDomainId: dnsDomainId,
DnsDomainName: dnsDomainName,
IsBackupForCluster: node.IsBackupForCluster,
IsBackupForGroup: node.IsBackupForGroup,
IsOffline: node.CheckIsOffline(),
},
}, nil
}
@@ -2097,6 +2109,9 @@ func (this *NodeService) FindEnabledNodeConfigInfo(ctx context.Context, req *pb.
// ddos protection
result.HasDDoSProtection = node.HasDDoSProtection()
// schedule
result.HasScheduleSettings = node.HasScheduleSettings()
return result, nil
}

View File

@@ -0,0 +1,21 @@
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package services
import (
"context"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
func (this *NodeService) FindNodeScheduleInfo(ctx context.Context, req *pb.FindNodeScheduleInfoRequest) (*pb.FindNodeScheduleInfoResponse, error) {
return nil, this.NotImplementedYet()
}
func (this *NodeService) UpdateNodeScheduleInfo(ctx context.Context, req *pb.UpdateNodeScheduleInfoRequest) (*pb.RPCSuccess, error) {
return nil, this.NotImplementedYet()
}
func (this *NodeService) ResetNodeActionStatus(ctx context.Context, req *pb.ResetNodeActionStatusRequest) (*pb.RPCSuccess, error) {
return nil, this.NotImplementedYet()
}

View File

@@ -68,7 +68,7 @@ func (this *ServerDailyStatService) UploadServerDailyStats(ctx context.Context,
// 节点流量
if nodeId > 0 {
err = stats.SharedNodeTrafficDailyStatDAO.IncreaseDailyStat(tx, clusterId, role, nodeId, timeutil.FormatTime("Ymd", stat.CreatedAt), stat.Bytes, stat.CachedBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests, stat.AttackBytes)
err = models.SharedNodeTrafficDailyStatDAO.IncreaseDailyStat(tx, clusterId, role, nodeId, timeutil.FormatTime("Ymd", stat.CreatedAt), stat.Bytes, stat.CachedBytes, stat.CountRequests, stat.CountCachedRequests, stat.CountAttackRequests, stat.AttackBytes)
if err != nil {
return nil, err
}

View File

@@ -325,7 +325,7 @@ func (this *ServerStatBoardService) ComposeServerStatNodeBoard(ctx context.Conte
}
// 当月总流量
monthlyTrafficStat, err := stats.SharedNodeTrafficDailyStatDAO.SumDailyStat(tx, nodeconfigs.NodeRoleNode, req.NodeId, timeutil.Format("Ym01"), timeutil.Format("Ym31"))
monthlyTrafficStat, err := models.SharedNodeTrafficDailyStatDAO.SumDailyStat(tx, nodeconfigs.NodeRoleNode, req.NodeId, timeutil.Format("Ym01"), timeutil.Format("Ym31"))
if err != nil {
return nil, err
}
@@ -335,7 +335,7 @@ func (this *ServerStatBoardService) ComposeServerStatNodeBoard(ctx context.Conte
// 按日流量统计
var dayFrom = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -14))
dailyTrafficStats, err := stats.SharedNodeTrafficDailyStatDAO.FindDailyStats(tx, "node", req.NodeId, dayFrom, timeutil.Format("Ymd"))
dailyTrafficStats, err := models.SharedNodeTrafficDailyStatDAO.FindDailyStats(tx, "node", req.NodeId, dayFrom, timeutil.Format("Ymd"))
if err != nil {
return nil, err
}

View File

@@ -67267,7 +67267,7 @@
"name": "edgeNSDomains",
"engine": "InnoDB",
"charset": "utf8mb4_general_ci",
"definition": "CREATE TABLE `edgeNSDomains` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '集群ID',\n `userId` int(11) unsigned DEFAULT '0' COMMENT '用户ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `name` varchar(255) DEFAULT NULL COMMENT '域名',\n `groupIds` json DEFAULT NULL COMMENT '分组ID',\n `tsig` json DEFAULT NULL COMMENT 'TSIG配置',\n `verifyTXT` varchar(64) DEFAULT NULL COMMENT '验证用的TXT',\n `verifyExpiresAt` bigint(11) unsigned DEFAULT '0' COMMENT '验证TXT过期时间',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `version` bigint(20) unsigned DEFAULT '0' COMMENT '版本号',\n `status` varchar(64) DEFAULT 'none' COMMENT '状态none|verified',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `userId` (`userId`),\n KEY `name` (`name`),\n KEY `version` (`version`) USING BTREE,\n KEY `status` (`status`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DNS域名'",
"definition": "CREATE TABLE `edgeNSDomains` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '集群ID',\n `userId` int(11) unsigned DEFAULT '0' COMMENT '用户ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `name` varchar(255) DEFAULT NULL COMMENT '域名',\n `groupIds` json DEFAULT NULL COMMENT '分组ID',\n `tsig` json DEFAULT NULL COMMENT 'TSIG配置',\n `verifyTXT` varchar(64) DEFAULT NULL COMMENT '验证用的TXT',\n `verifyExpiresAt` bigint(11) unsigned DEFAULT '0' COMMENT '验证TXT过期时间',\n `recordsHealthCheck` json DEFAULT NULL COMMENT '记录健康检查设置',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `version` bigint(20) unsigned DEFAULT '0' COMMENT '版本号',\n `status` varchar(64) DEFAULT 'none' COMMENT '状态none|verified',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `userId` (`userId`),\n KEY `name` (`name`),\n KEY `version` (`version`) USING BTREE,\n KEY `status` (`status`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DNS域名'",
"fields": [
{
"name": "id",
@@ -67305,6 +67305,10 @@
"name": "verifyExpiresAt",
"definition": "bigint(11) unsigned DEFAULT '0' COMMENT '验证TXT过期时间'"
},
{
"name": "recordsHealthCheck",
"definition": "json COMMENT '记录健康检查设置'"
},
{
"name": "createdAt",
"definition": "bigint(11) unsigned DEFAULT '0' COMMENT '创建时间'"
@@ -67653,7 +67657,7 @@
"name": "edgeNSRecords",
"engine": "InnoDB",
"charset": "utf8mb4_general_ci",
"definition": "CREATE TABLE `edgeNSRecords` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `domainId` int(11) unsigned DEFAULT '0' COMMENT '域名ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `description` varchar(512) DEFAULT NULL COMMENT '备注',\n `name` varchar(255) DEFAULT NULL COMMENT '记录名',\n `type` varchar(32) DEFAULT NULL COMMENT '类型',\n `value` varchar(4096) DEFAULT NULL COMMENT '值',\n `mxPriority` int(11) unsigned DEFAULT '0' COMMENT 'MX优先级',\n `srvPriority` int(11) unsigned DEFAULT '0' COMMENT 'SRV优先级',\n `srvWeight` int(11) unsigned DEFAULT '0' COMMENT 'SRV权重',\n `srvPort` int(11) unsigned DEFAULT '0' COMMENT 'SRV端口',\n `caaFlag` tinyint(1) unsigned DEFAULT '0' COMMENT 'CAA Flag',\n `caaTag` varchar(32) DEFAULT NULL COMMENT 'CAA TAG',\n `ttl` int(11) unsigned DEFAULT '0' COMMENT 'TTL',\n `weight` int(11) unsigned DEFAULT '0' COMMENT '权重',\n `routeIds` json DEFAULT NULL COMMENT '线路',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `version` bigint(20) unsigned DEFAULT '0' COMMENT '版本号',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `domainId` (`domainId`),\n KEY `version` (`version`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DNS记录'",
"definition": "CREATE TABLE `edgeNSRecords` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `domainId` int(11) unsigned DEFAULT '0' COMMENT '域名ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `description` varchar(512) DEFAULT NULL COMMENT '备注',\n `name` varchar(255) DEFAULT NULL COMMENT '记录名',\n `type` varchar(32) DEFAULT NULL COMMENT '类型',\n `value` varchar(4096) DEFAULT NULL COMMENT '值',\n `mxPriority` int(11) unsigned DEFAULT '0' COMMENT 'MX优先级',\n `srvPriority` int(11) unsigned DEFAULT '0' COMMENT 'SRV优先级',\n `srvWeight` int(11) unsigned DEFAULT '0' COMMENT 'SRV权重',\n `srvPort` int(11) unsigned DEFAULT '0' COMMENT 'SRV端口',\n `caaFlag` tinyint(1) unsigned DEFAULT '0' COMMENT 'CAA Flag',\n `caaTag` varchar(32) DEFAULT NULL COMMENT 'CAA TAG',\n `ttl` int(11) unsigned DEFAULT '0' COMMENT 'TTL',\n `weight` int(11) unsigned DEFAULT '0' COMMENT '权重',\n `routeIds` json DEFAULT NULL COMMENT '线路',\n `healthCheck` json DEFAULT NULL COMMENT '健康检查配置',\n `countUp` int(11) unsigned DEFAULT '0' COMMENT '连续上线次数',\n `countDown` int(11) unsigned DEFAULT '0' COMMENT '连续离线次数',\n `isUp` tinyint(1) unsigned DEFAULT '1' COMMENT '是否在线',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `version` bigint(20) unsigned DEFAULT '0' COMMENT '版本号',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `domainId` (`domainId`),\n KEY `version` (`version`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DNS记录'",
"fields": [
{
"name": "id",
@@ -67719,6 +67723,22 @@
"name": "routeIds",
"definition": "json COMMENT '线路'"
},
{
"name": "healthCheck",
"definition": "json COMMENT '健康检查配置'"
},
{
"name": "countUp",
"definition": "int(11) unsigned DEFAULT '0' COMMENT '连续上线次数'"
},
{
"name": "countDown",
"definition": "int(11) unsigned DEFAULT '0' COMMENT '连续离线次数'"
},
{
"name": "isUp",
"definition": "tinyint(1) unsigned DEFAULT '1' COMMENT '是否在线'"
},
{
"name": "createdAt",
"definition": "bigint(11) unsigned DEFAULT '0' COMMENT '创建时间'"
@@ -67992,6 +68012,61 @@
],
"records": []
},
{
"name": "edgeNodeActions",
"engine": "InnoDB",
"charset": "utf8mb4_general_ci",
"definition": "CREATE TABLE `edgeNodeActions` (\n `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `nodeId` bigint(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `role` varchar(16) DEFAULT NULL COMMENT '角色',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `conds` json DEFAULT NULL COMMENT '条件',\n `action` json DEFAULT NULL COMMENT '动作',\n `duration` json DEFAULT NULL COMMENT '持续时间',\n `order` int(11) unsigned DEFAULT '0' COMMENT '排序',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `nodeId` (`nodeId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='节点智能调度设置'",
"fields": [
{
"name": "id",
"definition": "bigint(11) unsigned auto_increment COMMENT 'ID'"
},
{
"name": "nodeId",
"definition": "bigint(11) unsigned DEFAULT '0' COMMENT '节点ID'"
},
{
"name": "role",
"definition": "varchar(16) COMMENT '角色'"
},
{
"name": "isOn",
"definition": "tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用'"
},
{
"name": "conds",
"definition": "json COMMENT '条件'"
},
{
"name": "action",
"definition": "json COMMENT '动作'"
},
{
"name": "duration",
"definition": "json COMMENT '持续时间'"
},
{
"name": "order",
"definition": "int(11) unsigned DEFAULT '0' COMMENT '排序'"
},
{
"name": "state",
"definition": "tinyint(1) unsigned DEFAULT '1' COMMENT '状态'"
}
],
"indexes": [
{
"name": "PRIMARY",
"definition": "UNIQUE KEY `PRIMARY` (`id`) USING BTREE"
},
{
"name": "nodeId",
"definition": "KEY `nodeId` (`nodeId`) USING BTREE"
}
],
"records": []
},
{
"name": "edgeNodeClusterFirewallActions",
"engine": "InnoDB",
@@ -69041,7 +69116,7 @@
"name": "edgeNodeThresholds",
"engine": "InnoDB",
"charset": "utf8mb4_general_ci",
"definition": "CREATE TABLE `edgeNodeThresholds` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `role` varchar(32) DEFAULT NULL COMMENT '节点角色',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '集群ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `item` varchar(255) DEFAULT NULL COMMENT '监控项',\n `param` varchar(255) DEFAULT NULL COMMENT '参数',\n `operator` varchar(255) DEFAULT NULL COMMENT '操作符',\n `value` json DEFAULT NULL COMMENT '对比值',\n `message` varchar(512) DEFAULT NULL COMMENT '消息内容',\n `notifyDuration` int(11) unsigned DEFAULT '0' COMMENT '通知间隔(单位分钟)',\n `notifiedAt` int(11) unsigned DEFAULT '0' COMMENT '上次通知时间',\n `duration` int(11) unsigned DEFAULT '0' COMMENT '时间段',\n `durationUnit` varchar(16) DEFAULT NULL COMMENT '时间段单位',\n `sumMethod` varchar(32) DEFAULT NULL COMMENT '聚合方法',\n `order` int(11) unsigned DEFAULT '0' COMMENT '排序',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `nodeId` (`nodeId`),\n KEY `clusterId` (`clusterId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='集群阈值设置'",
"definition": "CREATE TABLE `edgeNodeThresholds` (\n `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `role` varchar(32) DEFAULT NULL COMMENT '节点角色',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '集群ID',\n `nodeId` int(11) unsigned DEFAULT '0' COMMENT '节点ID',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `item` varchar(255) DEFAULT NULL COMMENT '监控项',\n `param` varchar(255) DEFAULT NULL COMMENT '参数',\n `operator` varchar(255) DEFAULT NULL COMMENT '操作符',\n `value` json DEFAULT NULL COMMENT '对比值',\n `message` varchar(512) DEFAULT NULL COMMENT '消息内容',\n `notifyDuration` int(11) unsigned DEFAULT '0' COMMENT '通知间隔(单位分钟)',\n `notifiedAt` int(11) unsigned DEFAULT '0' COMMENT '上次通知时间',\n `duration` int(11) unsigned DEFAULT '0' COMMENT '时间段',\n `durationUnit` varchar(16) DEFAULT NULL COMMENT '时间段单位',\n `sumMethod` varchar(32) DEFAULT NULL COMMENT '聚合方法',\n `order` int(11) unsigned DEFAULT '0' COMMENT '排序',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n PRIMARY KEY (`id`),\n KEY `nodeId` (`nodeId`),\n KEY `clusterId` (`clusterId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='节点监控阈值设置'",
"fields": [
{
"name": "id",
@@ -69345,7 +69420,7 @@
"name": "edgeNodes",
"engine": "InnoDB",
"charset": "utf8mb4_general_ci",
"definition": "CREATE TABLE `edgeNodes` (\n `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `adminId` int(11) unsigned DEFAULT '0' COMMENT '管理员ID',\n `userId` int(11) unsigned DEFAULT '0' COMMENT '用户ID',\n `level` tinyint(1) unsigned DEFAULT '1' COMMENT '级别',\n `lnAddrs` json DEFAULT NULL COMMENT 'Ln级别访问地址',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `isUp` tinyint(1) unsigned DEFAULT '1' COMMENT '是否在线',\n `countUp` int(11) unsigned DEFAULT '0' COMMENT '连续在线次数',\n `countDown` int(11) unsigned DEFAULT '0' COMMENT '连续下线次数',\n `isActive` tinyint(1) unsigned DEFAULT '1' COMMENT '是否活跃',\n `inactiveNotifiedAt` bigint(11) unsigned DEFAULT '0' COMMENT '离线通知时间',\n `uniqueId` varchar(32) DEFAULT NULL COMMENT '节点ID',\n `secret` varchar(32) DEFAULT NULL COMMENT '密钥',\n `name` varchar(255) DEFAULT NULL COMMENT '节点名',\n `code` varchar(255) DEFAULT NULL COMMENT '代号',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '主集群ID',\n `secondaryClusterIds` json DEFAULT NULL COMMENT '从集群ID',\n `regionId` int(11) unsigned DEFAULT '0' COMMENT '区域ID',\n `groupId` int(11) unsigned DEFAULT '0' COMMENT '分组ID',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `status` json DEFAULT NULL COMMENT '最新的状态',\n `version` int(11) unsigned DEFAULT '0' COMMENT '当前版本号',\n `latestVersion` int(11) unsigned DEFAULT '0' COMMENT '最后版本号',\n `installDir` varchar(512) DEFAULT NULL COMMENT '安装目录',\n `isInstalled` tinyint(1) unsigned DEFAULT '0' COMMENT '是否已安装',\n `installStatus` json DEFAULT NULL COMMENT '安装状态',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n `connectedAPINodes` json DEFAULT NULL COMMENT '当前连接的API节点',\n `maxCPU` int(4) unsigned DEFAULT '0' COMMENT '可以使用的最多CPU',\n `maxThreads` int(11) unsigned DEFAULT '0' COMMENT '最大线程数',\n `ddosProtection` json DEFAULT NULL COMMENT 'DDOS配置',\n `dnsRoutes` json DEFAULT NULL COMMENT 'DNS线路设置',\n `maxCacheDiskCapacity` json DEFAULT NULL COMMENT '硬盘缓存容量',\n `maxCacheMemoryCapacity` json DEFAULT NULL COMMENT '内存缓存容量',\n `cacheDiskDir` varchar(255) DEFAULT NULL COMMENT '主缓存目录',\n `cacheDiskSubDirs` json DEFAULT NULL COMMENT '其他缓存目录',\n `dnsResolver` json DEFAULT NULL COMMENT 'DNS解析器',\n `enableIPLists` tinyint(1) unsigned DEFAULT '1' COMMENT '启用IP名单',\n `apiNodeAddrs` json DEFAULT NULL COMMENT 'API节点地址',\n PRIMARY KEY (`id`),\n KEY `uniqueId` (`uniqueId`),\n KEY `clusterId` (`clusterId`),\n KEY `groupId` (`groupId`),\n KEY `regionId` (`regionId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='节点'",
"definition": "CREATE TABLE `edgeNodes` (\n `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',\n `adminId` int(11) unsigned DEFAULT '0' COMMENT '管理员ID',\n `userId` int(11) unsigned DEFAULT '0' COMMENT '用户ID',\n `level` tinyint(1) unsigned DEFAULT '1' COMMENT '级别',\n `lnAddrs` json DEFAULT NULL COMMENT 'Ln级别访问地址',\n `isOn` tinyint(1) unsigned DEFAULT '1' COMMENT '是否启用',\n `isUp` tinyint(1) unsigned DEFAULT '1' COMMENT '是否在线',\n `countUp` int(11) unsigned DEFAULT '0' COMMENT '连续在线次数',\n `countDown` int(11) unsigned DEFAULT '0' COMMENT '连续下线次数',\n `isActive` tinyint(1) unsigned DEFAULT '1' COMMENT '是否活跃',\n `inactiveNotifiedAt` bigint(11) unsigned DEFAULT '0' COMMENT '离线通知时间',\n `uniqueId` varchar(32) DEFAULT NULL COMMENT '节点ID',\n `secret` varchar(32) DEFAULT NULL COMMENT '密钥',\n `name` varchar(255) DEFAULT NULL COMMENT '节点名',\n `code` varchar(255) DEFAULT NULL COMMENT '代号',\n `clusterId` int(11) unsigned DEFAULT '0' COMMENT '主集群ID',\n `secondaryClusterIds` json DEFAULT NULL COMMENT '从集群ID',\n `regionId` int(11) unsigned DEFAULT '0' COMMENT '区域ID',\n `groupId` int(11) unsigned DEFAULT '0' COMMENT '分组ID',\n `createdAt` bigint(11) unsigned DEFAULT '0' COMMENT '创建时间',\n `status` json DEFAULT NULL COMMENT '最新的状态',\n `version` int(11) unsigned DEFAULT '0' COMMENT '当前版本号',\n `latestVersion` int(11) unsigned DEFAULT '0' COMMENT '最后版本号',\n `installDir` varchar(512) DEFAULT NULL COMMENT '安装目录',\n `isInstalled` tinyint(1) unsigned DEFAULT '0' COMMENT '是否已安装',\n `installStatus` json DEFAULT NULL COMMENT '安装状态',\n `state` tinyint(1) unsigned DEFAULT '1' COMMENT '状态',\n `connectedAPINodes` json DEFAULT NULL COMMENT '当前连接的API节点',\n `maxCPU` int(4) unsigned DEFAULT '0' COMMENT '可以使用的最多CPU',\n `maxThreads` int(11) unsigned DEFAULT '0' COMMENT '最大线程数',\n `ddosProtection` json DEFAULT NULL COMMENT 'DDOS配置',\n `dnsRoutes` json DEFAULT NULL COMMENT 'DNS线路设置',\n `maxCacheDiskCapacity` json DEFAULT NULL COMMENT '硬盘缓存容量',\n `maxCacheMemoryCapacity` json DEFAULT NULL COMMENT '内存缓存容量',\n `cacheDiskDir` varchar(255) DEFAULT NULL COMMENT '主缓存目录',\n `cacheDiskSubDirs` json DEFAULT NULL COMMENT '其他缓存目录',\n `dnsResolver` json DEFAULT NULL COMMENT 'DNS解析器',\n `enableIPLists` tinyint(1) unsigned DEFAULT '1' COMMENT '启用IP名单',\n `apiNodeAddrs` json DEFAULT NULL COMMENT 'API节点地址',\n `offlineDay` varchar(8) DEFAULT NULL COMMENT '下线日期YYYYMMDD',\n `offlineIsNotified` tinyint(1) unsigned DEFAULT '0' COMMENT '下线是否已通知',\n `isBackupForCluster` tinyint(1) unsigned DEFAULT '0' COMMENT '是否为集群备用节点',\n `isBackupForGroup` tinyint(1) unsigned DEFAULT '0' COMMENT '是否为分组备用节点',\n `backupIPs` json DEFAULT NULL COMMENT '备用IP',\n `actionStatus` json DEFAULT NULL COMMENT '当前动作配置',\n PRIMARY KEY (`id`),\n KEY `uniqueId` (`uniqueId`),\n KEY `clusterId` (`clusterId`),\n KEY `groupId` (`groupId`),\n KEY `regionId` (`regionId`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='节点'",
"fields": [
{
"name": "id",
@@ -69502,6 +69577,30 @@
{
"name": "apiNodeAddrs",
"definition": "json COMMENT 'API节点地址'"
},
{
"name": "offlineDay",
"definition": "varchar(8) COMMENT '下线日期YYYYMMDD'"
},
{
"name": "offlineIsNotified",
"definition": "tinyint(1) unsigned DEFAULT '0' COMMENT '下线是否已通知'"
},
{
"name": "isBackupForCluster",
"definition": "tinyint(1) unsigned DEFAULT '0' COMMENT '是否为集群备用节点'"
},
{
"name": "isBackupForGroup",
"definition": "tinyint(1) unsigned DEFAULT '0' COMMENT '是否为分组备用节点'"
},
{
"name": "backupIPs",
"definition": "json COMMENT '备用IP'"
},
{
"name": "actionStatus",
"definition": "json COMMENT '当前动作配置'"
}
],
"indexes": [

View File

@@ -87,8 +87,8 @@ func (this *DNSTaskExecutor) loop() error {
return err
}
}
case dnsmodels.DNSTaskTypeClusterChange:
err = this.doCluster(taskId, taskVersion, int64(task.ClusterId))
case dnsmodels.DNSTaskTypeClusterChange, dnsmodels.DNSTaskTypeClusterNodesChange:
err = this.doCluster(taskId, taskVersion, int64(task.ClusterId), task.Type == dnsmodels.DNSTaskTypeClusterNodesChange)
if err != nil {
err = dnsmodels.SharedDNSTaskDAO.UpdateDNSTaskError(nil, taskId, err.Error())
if err != nil {
@@ -300,7 +300,7 @@ func (this *DNSTaskExecutor) doNode(taskId int64, taskVersion int64, nodeCluster
// 转交给cluster统一处理
if nodeClusterId > 0 {
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, nodeClusterId, dnsmodels.DNSTaskTypeClusterChange)
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, nodeClusterId, dnsmodels.DNSTaskTypeClusterNodesChange)
if err != nil {
return err
}
@@ -310,7 +310,7 @@ func (this *DNSTaskExecutor) doNode(taskId int64, taskVersion int64, nodeCluster
return err
}
for _, clusterId := range clusterIds {
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dnsmodels.DNSTaskTypeClusterChange)
err = dnsmodels.SharedDNSTaskDAO.CreateClusterTask(tx, clusterId, dnsmodels.DNSTaskTypeClusterNodesChange)
if err != nil {
return err
}
@@ -323,8 +323,8 @@ func (this *DNSTaskExecutor) doNode(taskId int64, taskVersion int64, nodeCluster
}
// 修改集群相关记录
func (this *DNSTaskExecutor) doCluster(taskId int64, taskVersion int64, clusterId int64) error {
isOk := false
func (this *DNSTaskExecutor) doCluster(taskId int64, taskVersion int64, clusterId int64, nodesOnly bool) error {
var isOk = false
defer func() {
if isOk {
err := dnsmodels.SharedDNSTaskDAO.UpdateDNSTaskDone(nil, taskId, taskVersion)
@@ -378,6 +378,14 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, taskVersion int64, clusterI
var isChanged = false
var addingNodeRecordKeysMap = map[string]bool{} // clusterDnsName_type_ip_route
for _, node := range nodes {
shouldSkip, shouldOverwrite, ipAddressesStrings, err := models.SharedNodeDAO.CheckNodeIPAddresses(tx, node)
if err != nil {
return err
}
if shouldSkip {
continue
}
routes, err := node.DNSRouteCodesForDomainId(domainId)
if err != nil {
return err
@@ -387,26 +395,36 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, taskVersion int64, clusterI
}
// 所有的IP记录
ipAddresses, err := models.SharedNodeIPAddressDAO.FindAllEnabledAddressesWithNode(tx, int64(node.Id), nodeconfigs.NodeRoleNode)
if err != nil {
return err
if !shouldOverwrite {
ipAddresses, err := models.SharedNodeIPAddressDAO.FindAllEnabledAddressesWithNode(tx, int64(node.Id), nodeconfigs.NodeRoleNode)
if err != nil {
return err
}
if len(ipAddresses) == 0 {
continue
}
for _, ipAddress := range ipAddresses {
// 检查专属节点
if !ipAddress.IsValidInCluster(clusterId) {
continue
}
var ip = ipAddress.DNSIP()
if len(ip) == 0 || !ipAddress.CanAccess || !ipAddress.IsUp || !ipAddress.IsOn {
continue
}
if net.ParseIP(ip) == nil {
continue
}
ipAddressesStrings = append(ipAddressesStrings, ip)
}
}
if len(ipAddresses) == 0 {
if len(ipAddressesStrings) == 0 {
continue
}
for _, ipAddress := range ipAddresses {
// 检查专属节点
if !ipAddress.IsValidInCluster(clusterId) {
continue
}
var ip = ipAddress.DNSIP()
if len(ip) == 0 || !ipAddress.CanAccess || !ipAddress.IsUp || !ipAddress.IsOn {
continue
}
if net.ParseIP(ip) == nil {
continue
}
for _, ip := range ipAddressesStrings {
for _, route := range routes {
var key = route + "@" + ip
_, ok := oldRecordsMap[key]
@@ -456,80 +474,82 @@ func (this *DNSTaskExecutor) doCluster(taskId int64, taskVersion int64, clusterI
}
// 服务域名
servers, err := models.SharedServerDAO.FindAllServersDNSWithClusterId(tx, clusterId)
if err != nil {
return err
}
serverRecords := []*dnstypes.Record{} // 之所以用数组再存一遍是因为dnsName可能会重复
serverRecordsMap := map[string]*dnstypes.Record{} // dnsName => *Record
for _, record := range records {
if record.Type == dnstypes.RecordTypeCNAME && record.Value == clusterDomain+"." {
serverRecords = append(serverRecords, record)
serverRecordsMap[record.Name] = record
if !nodesOnly {
servers, err := models.SharedServerDAO.FindAllServersDNSWithClusterId(tx, clusterId)
if err != nil {
return err
}
}
// 新增的域名
var serverDNSNames = []string{}
for _, server := range servers {
var dnsName = server.DnsName
if len(dnsName) == 0 {
continue
}
serverDNSNames = append(serverDNSNames, dnsName)
_, ok := serverRecordsMap[dnsName]
if !ok {
isChanged = true
err = manager.AddRecord(domain, &dnstypes.Record{
Id: "",
Name: dnsName,
Type: dnstypes.RecordTypeCNAME,
Value: clusterDomain + ".",
Route: "", // 注意这里为空,需要在执行过程中获取默认值
TTL: ttl,
})
if err != nil {
return err
serverRecords := []*dnstypes.Record{} // 之所以用数组再存一遍是因为dnsName可能会重复
serverRecordsMap := map[string]*dnstypes.Record{} // dnsName => *Record
for _, record := range records {
if record.Type == dnstypes.RecordTypeCNAME && record.Value == clusterDomain+"." {
serverRecords = append(serverRecords, record)
serverRecordsMap[record.Name] = record
}
}
}
// 自动设置的CNAME
var cnameRecords = []string{}
if dnsConfig != nil {
cnameRecords = dnsConfig.CNAMERecords
}
for _, cnameRecord := range cnameRecords {
// 如果记录已存在,则跳过
if lists.ContainsString(serverDNSNames, cnameRecord) {
continue
}
serverDNSNames = append(serverDNSNames, cnameRecord)
_, ok := serverRecordsMap[cnameRecord]
if !ok {
isChanged = true
err = manager.AddRecord(domain, &dnstypes.Record{
Id: "",
Name: cnameRecord,
Type: dnstypes.RecordTypeCNAME,
Value: clusterDomain + ".",
Route: "", // 注意这里为空,需要在执行过程中获取默认值
TTL: ttl,
})
if err != nil {
return err
// 新增的域名
var serverDNSNames = []string{}
for _, server := range servers {
var dnsName = server.DnsName
if len(dnsName) == 0 {
continue
}
serverDNSNames = append(serverDNSNames, dnsName)
_, ok := serverRecordsMap[dnsName]
if !ok {
isChanged = true
err = manager.AddRecord(domain, &dnstypes.Record{
Id: "",
Name: dnsName,
Type: dnstypes.RecordTypeCNAME,
Value: clusterDomain + ".",
Route: "", // 注意这里为空,需要在执行过程中获取默认值
TTL: ttl,
})
if err != nil {
return err
}
}
}
}
// 多余的域名
for _, record := range serverRecords {
if !lists.ContainsString(serverDNSNames, record.Name) {
isChanged = true
err = manager.DeleteRecord(domain, record)
if err != nil {
return err
// 自动设置的CNAME
var cnameRecords = []string{}
if dnsConfig != nil {
cnameRecords = dnsConfig.CNAMERecords
}
for _, cnameRecord := range cnameRecords {
// 如果记录已存在,则跳过
if lists.ContainsString(serverDNSNames, cnameRecord) {
continue
}
serverDNSNames = append(serverDNSNames, cnameRecord)
_, ok := serverRecordsMap[cnameRecord]
if !ok {
isChanged = true
err = manager.AddRecord(domain, &dnstypes.Record{
Id: "",
Name: cnameRecord,
Type: dnstypes.RecordTypeCNAME,
Value: clusterDomain + ".",
Route: "", // 注意这里为空,需要在执行过程中获取默认值
TTL: ttl,
})
if err != nil {
return err
}
}
}
// 多余的域名
for _, record := range serverRecords {
if !lists.ContainsString(serverDNSNames, record.Name) {
isChanged = true
err = manager.DeleteRecord(domain, record)
if err != nil {
return err
}
}
}
}

View File

@@ -1,3 +1,5 @@
//go:build !plus
package tasks_test
import (

View File

@@ -127,7 +127,7 @@ func (this *HealthCheckClusterTask) Loop() error {
if err != nil {
return err
}
var message = "有" + numberutils.FormatInt(len(failedResults)) + "个节点在健康检查中出现问题"
var message = "有" + numberutils.FormatInt(len(failedResults)) + "个节点IP在健康检查中出现问题"
err = models.NewMessageDAO().CreateClusterMessage(nil, nodeconfigs.NodeRoleNode, this.clusterId, models.MessageTypeHealthCheckFailed, models.MessageLevelError, message, message, failedResultsJSON)
if err != nil {
return err

View File

@@ -16,6 +16,7 @@ import (
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
timeutil "github.com/iwind/TeaGo/utils/time"
"net"
"net/http"
"strconv"
@@ -66,7 +67,7 @@ func (this *HealthCheckExecutor) Run() ([]*HealthCheckResult, error) {
var tx *dbs.Tx
for _, node := range nodes {
if !node.IsOn {
if !node.IsOn || node.IsBackupForCluster || node.IsBackupForGroup || (len(node.OfflineDay) > 0 && node.OfflineDay < timeutil.Format("Ymd")) {
continue
}
@@ -194,6 +195,15 @@ func (this *HealthCheckExecutor) runNode(healthCheckConfig *serverconfigs.Health
this.logErr("HealthCheckExecutor", err.Error())
return
}
// 触发节点动作
if !result.IsOk {
err := this.fireNodeActions(int64(result.Node.Id))
if err != nil {
this.logErr("HealthCheckExecutor", err.Error())
}
return
}
}
// 触发阈值

View File

@@ -0,0 +1,9 @@
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
//go:build !plus
package tasks
// 触发节点动作
func (this *HealthCheckExecutor) fireNodeActions(nodeId int64) error {
return nil
}