cauto 2 rokov pred
rodič
commit
b3a775ab25

+ 1 - 1
api/v1/hello.go

@@ -8,5 +8,5 @@ type HelloReq struct {
 	g.Meta `path:"/hello" tags:"Hello" method:"get" summary:"You first hello api"`
 }
 type HelloRes struct {
-	g.Meta `mime:"text/html" example:"string"`
+	g.Meta `mime:"application/json" example:"json"`
 }

+ 41 - 6
api/v1/node.go

@@ -2,15 +2,17 @@ package v1
 
 import (
 	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gcron"
 	"nodeMonitor/internal/model/entity"
 )
 
 type NodeReq struct {
-	g.Meta `path:"/add" tags:"add" method:"post" summary:"增加节点"`
-	Name   string `p:"name" v:"required#节点名称不能为空"`
-	Host   string `p:"host" v:"required#节点不能为空"`
-	Port   int    `p:"port" v:"required#节点端口不能为空"`
-	Url    string `p:"url"`
+	g.Meta   `path:"/add" tags:"add" method:"post" summary:"增加节点"`
+	Name     string `p:"name" v:"required#节点名称不能为空"`
+	Host     string `p:"host" v:"required#节点不能为空"`
+	Port     int    `p:"port"`
+	Url      string `p:"url"`
+	PingType int    `p:"pingType"`
 }
 
 type NodeRes struct {
@@ -28,10 +30,43 @@ type NodeDelRes struct {
 }
 
 type NodeAllReq struct {
-	g.Meta `path:"/all" tags:"del" method:"get" summary:"获取全部节点"`
+	g.Meta `path:"/all" tags:"all" method:"get" summary:"获取全部节点"`
 }
 
 type NodeALlRes struct {
 	g.Meta   `mime:"application/json"`
 	NodeList []*entity.Node `json:"nodeList"`
 }
+
+type NodeCronStartReq struct {
+	g.Meta    `path:"/start" tags:"start" method:"post" summary:"开始PING任务"`
+	StartTime int `p:"startTime"`
+}
+
+type NodeCronStartRes struct {
+	g.Meta       `mime:"application/json"`
+	RetEntry     []*gcron.Entry
+	RetCronCount int
+	Status       bool
+}
+
+type NodeCronStopReq struct {
+	g.Meta `path:"/stop" tags:"stop" method:"post" summary:"停止PING任务"`
+	Remove bool `p:"remove"`
+}
+
+type NodeCronStopRes struct {
+	g.Meta       `mime:"application/json"`
+	RetCronCount int
+	Status       bool
+}
+
+type NodeCronStatusReq struct {
+	g.Meta `path:"/task" tags:"task" method:"get" summary:"查看任务状态"`
+}
+
+type NodeCronStatusRes struct {
+	g.Meta       `mime:"application/json"`
+	RetEntry     []*gcron.Entry
+	RetCronCount int
+}

+ 6 - 4
db/nodeMonitor.sql

@@ -11,7 +11,7 @@
  Target Server Version : 50734
  File Encoding         : 65001
 
- Date: 02/11/2022 15:40:06
+ Date: 03/11/2022 16:23:13
 */
 
 SET NAMES utf8mb4;
@@ -22,15 +22,17 @@ SET FOREIGN_KEY_CHECKS = 0;
 -- ----------------------------
 DROP TABLE IF EXISTS `node`;
 CREATE TABLE `node` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID主键自动添加',
   `name` varchar(128) NOT NULL COMMENT '服务器名称',
   `host` varchar(20) NOT NULL COMMENT '服务器IP',
   `port` int(11) NOT NULL COMMENT '服务器端口',
   `url` text NOT NULL COMMENT '服务器切换地址',
   `update_at` datetime DEFAULT NULL COMMENT '更新时间',
   `create_at` datetime DEFAULT NULL COMMENT '创建时间',
+  `ping_type` int(11) NOT NULL DEFAULT '0' COMMENT '服务器延迟类型 0 icmp 1 tcp',
+  `url_status` int(11) DEFAULT NULL COMMENT '用于表示url是否执行完成',
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
 
 -- ----------------------------
 -- Table structure for pinglog
@@ -46,6 +48,6 @@ CREATE TABLE `pinglog` (
   `create_at` datetime DEFAULT NULL COMMENT '创建时间',
   `host` varchar(128) DEFAULT NULL COMMENT '服务器IP',
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4;
+) ENGINE=InnoDB AUTO_INCREMENT=104 DEFAULT CHARSET=utf8mb4;
 
 SET FOREIGN_KEY_CHECKS = 1;

+ 8 - 14
internal/cmd/cmd.go

@@ -2,15 +2,12 @@ package cmd
 
 import (
 	"context"
-	"github.com/gogf/gf/v2/net/goai"
-	"github.com/gogf/gf/v2/os/gcron"
-	"nodeMonitor/internal/consts"
-	"nodeMonitor/internal/router"
-	"nodeMonitor/internal/task"
-
 	"github.com/gogf/gf/v2/frame/g"
 	"github.com/gogf/gf/v2/net/ghttp"
+	"github.com/gogf/gf/v2/net/goai"
 	"github.com/gogf/gf/v2/os/gcmd"
+	"nodeMonitor/internal/consts"
+	"nodeMonitor/internal/router"
 )
 
 var (
@@ -26,15 +23,12 @@ var (
 
 			// Custom enhance API document.
 			enhanceOpenAPIDoc(s)
-			_, err = gcron.Add(ctx, "*/60 * * * * *", func(ctx context.Context) {
-				go task.Ping(ctx)
-			}, "ping_task")
-			if err != nil {
-				return err
-			}
+			//_, err = gcron.AddSingleton(ctx, "*/60 * * * * *", func(ctx context.Context) {
+			//	go task.Ping(ctx)
+			//}, "ping_task")
 
-			defer gcron.Stop("ping_task")
-			defer gcron.Remove("ping_task")
+			//defer gcron.Stop("ping_task")
+			//defer gcron.Remove("ping_task")
 
 			s.Run()
 			return nil

+ 69 - 4
internal/controller/Node.go

@@ -1,12 +1,17 @@
 package controller
 
 import (
+	"fmt"
 	"github.com/gogf/gf/v2/errors/gcode"
 	"github.com/gogf/gf/v2/errors/gerror"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/gcron"
+	"github.com/gogf/gf/v2/os/glog"
 	"golang.org/x/net/context"
 	v1 "nodeMonitor/api/v1"
 	"nodeMonitor/internal/model"
 	"nodeMonitor/internal/service"
+	"nodeMonitor/internal/task"
 )
 
 var Node = sNode{}
@@ -27,10 +32,11 @@ func (c *sNode) Add(ctx context.Context, req *v1.NodeReq) (res *v1.NodeRes, err
 	}
 
 	err = service.Node().Create(ctx, model.NodeCreateInput{
-		Name: req.Name,
-		Host: req.Host,
-		Port: req.Port,
-		Url:  req.Url,
+		Name:     req.Name,
+		Host:     req.Host,
+		Port:     req.Port,
+		Url:      req.Url,
+		PingType: req.PingType,
 	})
 
 	return
@@ -50,3 +56,62 @@ func (c *sNode) All(ctx context.Context, req *v1.NodeAllReq) (res *v1.NodeALlRes
 	res.NodeList, err = service.Node().GetNode(ctx)
 	return
 }
+
+func (c *sNode) Start(ctx context.Context, req *v1.NodeCronStartReq) (res *v1.NodeCronStartRes, err error) {
+	res = new(v1.NodeCronStartRes)
+	StartTime := req.StartTime
+
+	taskName, err := g.Cfg().Get(ctx, "node.taskName")
+	if err != nil {
+		glog.Debug(ctx, err.Error())
+		return
+	}
+	search := gcron.Search(taskName.String())
+	if search != nil {
+		gcron.Stop(taskName.String())
+		gcron.Start(taskName.String())
+		res.RetEntry = gcron.Entries()
+		res.RetCronCount = gcron.Size()
+		res.Status = true
+		glog.Debug(ctx, "task -- ", gcron.Size())
+	} else {
+		s := fmt.Sprintf("*/%d * * * * *", StartTime)
+		_, err = gcron.AddSingleton(ctx, s, func(ctx context.Context) {
+			go task.Ping(ctx)
+		}, taskName.String())
+		res.RetEntry = gcron.Entries()
+		res.RetCronCount = gcron.Size()
+		res.Status = true
+	}
+
+	return
+}
+
+func (c *sNode) Stop(ctx context.Context, req *v1.NodeCronStopReq) (res *v1.NodeCronStopRes, err error) {
+	res = new(v1.NodeCronStopRes)
+	remove := req.Remove
+	taskName, err := g.Cfg().Get(ctx, "node.taskName")
+	if err != nil {
+		glog.Debug(ctx, err.Error())
+		return
+	}
+	gcron.Stop(taskName.String())
+	if remove {
+		gcron.Remove(taskName.String())
+	}
+
+	search := gcron.Search(taskName.String())
+	if search == nil {
+		res.Status = false
+	}
+	res.RetCronCount = gcron.Size()
+
+	return
+}
+
+func (c *sNode) Task(ctx context.Context, req *v1.NodeCronStatusReq) (res *v1.NodeCronStatusRes, err error) {
+	res = new(v1.NodeCronStatusRes)
+	res.RetEntry = gcron.Entries()
+	res.RetCronCount = gcron.Size()
+	return
+}

+ 12 - 3
internal/controller/hello.go

@@ -2,10 +2,9 @@ package controller
 
 import (
 	"context"
-
 	"github.com/gogf/gf/v2/frame/g"
-
 	"nodeMonitor/api/v1"
+	"nodeMonitor/internal/service"
 )
 
 var (
@@ -15,6 +14,16 @@ var (
 type cHello struct{}
 
 func (c *cHello) Hello(ctx context.Context, req *v1.HelloReq) (res *v1.HelloRes, err error) {
-	g.RequestFromCtx(ctx).Response.Writeln("Hello World!")
+
+	//t1 := time.Now()
+
+	//Format("2006-01-02 15:04")
+	//g.RequestFromCtx(ctx).Response.Writeln(timeStartStr.Sub(t1))
+
+	status, err := service.Ping().GetStatus(ctx, "kdvkr-04.xyz")
+	if err != nil {
+		return res, err
+	}
+	g.RequestFromCtx(ctx).Response.Writeln(status)
 	return
 }

+ 27 - 8
internal/logic/node/node.go

@@ -27,10 +27,11 @@ func New() *sNode {
 func (c *sNode) Create(ctx context.Context, input model.NodeCreateInput) error {
 	return dao.Node.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
 		_, err := dao.Node.Ctx(ctx).Data(do.Node{
-			Name: input.Name,
-			Host: input.Host,
-			Port: input.Port,
-			Url:  input.Url,
+			Name:     input.Name,
+			Host:     input.Host,
+			Port:     input.Port,
+			Url:      input.Url,
+			PingType: input.PingType,
 		}).Insert()
 		return err
 	})
@@ -60,10 +61,11 @@ func (c *sNode) UpdateNode(ctx context.Context, input model.NodeCreateInput) err
 	_, err := dao.Node.Ctx(ctx).Where(g.Map{
 		"host": input.Host,
 	}).Update(g.Map{
-		"host": input.Host,
-		"name": input.Name,
-		"port": input.Port,
-		"url":  input.Url,
+		"host":      input.Host,
+		"name":      input.Name,
+		"port":      input.Port,
+		"url":       input.Url,
+		"ping_type": input.PingType,
 	})
 	return err
 }
@@ -74,3 +76,20 @@ func (c *sNode) GetNode(ctx context.Context) ([]*entity.Node, error) {
 	err := dao.Node.Ctx(ctx).Scan(&nodeList)
 	return nodeList, err
 }
+
+// FindNode 获取指定节点数据
+func (c *sNode) FindNode(ctx context.Context, host string) (*entity.Node, error) {
+	var nodeList *entity.Node
+	err := dao.Node.Ctx(ctx).Where("host = ?", host).Scan(&nodeList)
+	return nodeList, err
+}
+
+// UpdateNodeUrlStatus 更新节点url是否执行完成
+func (c *sNode) UpdateNodeUrlStatus(ctx context.Context, input model.NodeCreateInput) error {
+	_, err := dao.Node.Ctx(ctx).Where(g.Map{
+		"host": input.Host,
+	}).Update(g.Map{
+		"url_status": input.UrlStatus,
+	})
+	return err
+}

+ 22 - 3
internal/logic/pinglog/pinglog.go

@@ -2,11 +2,14 @@ package pinglog
 
 import (
 	"github.com/gogf/gf/v2/database/gdb"
+	"github.com/gogf/gf/v2/frame/g"
+	"github.com/gogf/gf/v2/os/glog"
 	"golang.org/x/net/context"
 	"nodeMonitor/internal/dao"
 	"nodeMonitor/internal/model"
 	"nodeMonitor/internal/model/do"
 	"nodeMonitor/internal/service"
+	"time"
 )
 
 type (
@@ -28,7 +31,7 @@ func (c *sPing) Create(ctx context.Context, ping model.PingSt, host string) erro
 			Maxdelay: ping.MaxDelay,
 			Mindelay: ping.MinDelay,
 			Avgdelay: ping.AvgDelay,
-			Losspk:   ping.AvgDelay,
+			Losspk:   ping.LossPk,
 			Host:     host,
 		}).Insert()
 		return err
@@ -36,7 +39,23 @@ func (c *sPing) Create(ctx context.Context, ping model.PingSt, host string) erro
 }
 
 // GetStatus 查询节点状态
-// SELECT *  FROM pinglog WHERE DATE_SUB(create_at,INTERVAL 10 MINUTE) <= NOW() and avgdelay = 0  and losspk >= 0 and maxdelay = 0 and `host` = 'kdvkr-04.xyz'
-func (c *sPing) GetStatus(ctx context.Context) {
+// SELECT *  FROM pinglog WHERE create_at >= DATE_SUB(NOW(),INTERVAL 10 MINUTE) and avgdelay = 0  and losspk >= 0 and maxdelay = 0 and `host` = 'kdvkr-04.xyz'
+func (c *sPing) GetStatus(ctx context.Context, host string) (bool, error) {
 	//查询的数据超过3次就是不ok了
+	startTime, err := g.Cfg().Get(ctx, "node.startTime")
+	if err != nil {
+		glog.Debug(ctx, err.Error())
+		return false, err
+	}
+
+	loos, err := g.Cfg().Get(ctx, "node.loos")
+	if err != nil {
+		glog.Debug(ctx, err.Error())
+		return false, err
+	}
+
+	timeStartStr := time.Unix(time.Now().Unix()-startTime.Int64(), 0)
+	count, err := dao.Pinglog.Ctx(ctx).Where("create_at > ?", timeStartStr).Where("avgdelay = 0").Where("losspk > ?", loos.Int()).Where("maxdelay = 0 ").Where("host = ?", host).Count()
+
+	return count >= 3, err
 }

+ 6 - 4
internal/model/node.go

@@ -1,10 +1,12 @@
 package model
 
 type NodeCreateInput struct {
-	Name string
-	Host string
-	Port int
-	Url  string
+	Name      string
+	Host      string
+	Port      int
+	Url       string
+	PingType  int
+	UrlStatus int
 }
 
 type NodeDelInput struct {

+ 9 - 0
internal/router/router.go

@@ -10,6 +10,7 @@ func BindController(group *ghttp.RouterGroup) {
 		group.Middleware(ghttp.MiddlewareHandlerResponse)
 		//group.Middleware(middleware.Middleware().CORS)
 		NodeRouter(group)
+		DomeRouter(group)
 	})
 
 }
@@ -21,3 +22,11 @@ func NodeRouter(group *ghttp.RouterGroup) {
 		)
 	})
 }
+
+func DomeRouter(group *ghttp.RouterGroup) {
+	group.Group("/hello", func(group *ghttp.RouterGroup) {
+		group.Bind(
+			controller.Hello,
+		)
+	})
+}

+ 58 - 14
internal/task/ping.go

@@ -24,12 +24,14 @@ func Ping(ctx context.Context) {
 	for _, target := range nodeList {
 		wg.Add(1)
 		//glog.Debug(ctx, target)
-		go PingTask(ctx, target.Host, &wg)
+		go PingTask(ctx, target.Host, &wg, target.PingType, target.Port)
 	}
 	wg.Wait()
+
+	go CheckNodeStatus(ctx)
 }
 
-func PingTask(ctx context.Context, t string, wg *sync.WaitGroup) {
+func PingTask(ctx context.Context, t string, wg *sync.WaitGroup, pingType int, hostPort int) {
 	//var ipSlice []string
 	//ipSlice = append(ipSlice, "kdvkr-02.xyz")
 	//ipSlice = append(ipSlice, "kdvkr-04.xyz")
@@ -46,9 +48,16 @@ func PingTask(ctx context.Context, t string, wg *sync.WaitGroup) {
 	if err == nil {
 		for i := 0; i < pingCount.Int(); i++ {
 			starttime := time.Now().UnixNano()
-			//tcpping := nettools.NewTcpPing(addr.String(), 22, time.Second*4)
-			icmping := nettools.NewIcmpPing(addr.String(), time.Second*4)
-			rest := icmping.Ping()
+
+			var rest nettools.IPingResult
+			if pingType == 0 { //icmp
+				icmping := nettools.NewIcmpPing(addr.String(), time.Second*4)
+				rest = icmping.Ping()
+			} else if pingType == 1 {
+				tcpping := nettools.NewTcpPing(addr.String(), hostPort, time.Second*4)
+				rest = tcpping.Ping()
+			}
+
 			if rest.Error() == nil {
 				delay := rest.Result()
 				//seelog.Info("[func:IcmpPing] Finish Addr:", addr, delay, "ms")
@@ -60,16 +69,14 @@ func PingTask(ctx context.Context, t string, wg *sync.WaitGroup) {
 					stat.MinDelay = delay
 				}
 				stat.RevcPk = stat.RevcPk + 1
-
-				stat.SendPk = stat.SendPk + 1
-				stat.LossPk = int((float64(lossPK) / float64(stat.SendPk)) * 100)
-				duringtime := time.Now().UnixNano() - starttime
-				time.Sleep(time.Duration(3000*1000000-duringtime) * time.Nanosecond)
 			} else {
-				//seelog.Debug("[func:StartPing IcmpPing] ID:", i, " IP:", addr, "| err:", rest.Error())
+				glog.Debug(ctx, "[func:StartPing IcmpPing] ID:", i, " IP:", addr, "| err:", rest.Error())
 				lossPK = lossPK + 1
 			}
-
+			stat.SendPk = stat.SendPk + 1
+			stat.LossPk = int((float64(lossPK) / float64(stat.SendPk)) * 100)
+			duringtime := time.Now().UnixNano() - starttime
+			time.Sleep(time.Duration(3000*1000000-duringtime) * time.Nanosecond)
 		}
 		if stat.RevcPk > 0 {
 			stat.AvgDelay = stat.AvgDelay / stat.RevcPk
@@ -88,11 +95,11 @@ func PingTask(ctx context.Context, t string, wg *sync.WaitGroup) {
 	}
 
 	//添加到数据库
-	AddPinglog(ctx, stat, t)
+	AddPingLog(ctx, stat, t)
 	wg.Done()
 }
 
-func AddPinglog(ctx context.Context, pingres model.PingSt, addr string) {
+func AddPingLog(ctx context.Context, pingres model.PingSt, addr string) {
 	err := service.Ping().Create(ctx, pingres, addr)
 	if err != nil {
 		glog.Debug(ctx, err.Error())
@@ -103,4 +110,41 @@ func AddPinglog(ctx context.Context, pingres model.PingSt, addr string) {
 
 func CheckNodeStatus(ctx context.Context) {
 
+	nodeList, err := service.Node().GetNode(ctx)
+	if err != nil {
+		glog.Debug(ctx, err.Error())
+		return
+	}
+	for _, target := range nodeList {
+		glog.Debug(ctx, "start url req .....")
+		//获取不通的IP进程url请求
+		status, err := service.Ping().GetStatus(ctx, target.Host)
+		if err != nil {
+			glog.Error(ctx, err.Error())
+			return
+		}
+		if status {
+
+			if target.UrlStatus == 200 {
+				return
+			}
+
+			r, err := g.Client().Get(ctx, target.Url)
+			if err != nil {
+				glog.Error(ctx, err.Error())
+				return
+			}
+			defer r.Close()
+			glog.Debug(ctx, "req :", target.Url, "status :", r.Status)
+			if r.StatusCode == 200 {
+				err := service.Node().UpdateNodeUrlStatus(ctx, model.NodeCreateInput{Host: target.Host, UrlStatus: r.StatusCode})
+				if err != nil {
+					glog.Debug(ctx, err.Error())
+					return
+				}
+			}
+		}
+
+	}
+
 }

+ 3 - 1
manifest/config/config.yaml

@@ -42,7 +42,9 @@ database:
 node:
   die: 3    #用于判断线路 不通的次数
   pingCount: 20 #用于检测线路的次数
-
+  startTime: 900 #用于查询15分钟内的数据
+  loos: 30 #用于丢包率检测 如果丢包率>当前值就是坏了
+  taskName: "ping_task" #任务名称
 #gfToken:
 #  cacheKey: "gfToken_"
 #  timeOut: 10800