github.com/TeaOSLab/EdgeNode@v1.3.8/internal/utils/fs/status.go (about)

     1  // Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
     2  
     3  package fsutils
     4  
     5  import (
     6  	"encoding/json"
     7  	teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
     8  	"github.com/TeaOSLab/EdgeNode/internal/goman"
     9  	"github.com/iwind/TeaGo/Tea"
    10  	"github.com/shirou/gopsutil/v3/load"
    11  	"os"
    12  	"time"
    13  )
    14  
    15  type Speed int
    16  
    17  func (this Speed) String() string {
    18  	switch this {
    19  	case SpeedExtremelyFast:
    20  		return "extremely fast"
    21  	case SpeedFast:
    22  		return "fast"
    23  	case SpeedLow:
    24  		return "low"
    25  	case SpeedExtremelySlow:
    26  		return "extremely slow"
    27  	}
    28  	return "unknown"
    29  }
    30  
    31  const (
    32  	SpeedExtremelyFast Speed = 1
    33  	SpeedFast          Speed = 2
    34  	SpeedLow           Speed = 3
    35  	SpeedExtremelySlow Speed = 4
    36  )
    37  
    38  var (
    39  	DiskSpeed   = SpeedLow
    40  	DiskSpeedMB float64
    41  )
    42  
    43  var IsInHighLoad = false
    44  var IsInExtremelyHighLoad = false
    45  
    46  const (
    47  	highLoad1Threshold          = 20
    48  	extremelyHighLoad1Threshold = 40
    49  )
    50  
    51  func init() {
    52  	if !teaconst.IsMain {
    53  		return
    54  	}
    55  
    56  	// test disk
    57  	goman.New(func() {
    58  		// load last result from local disk
    59  		cacheData, cacheErr := os.ReadFile(Tea.Root + "/data/" + diskSpeedDataFile)
    60  		if cacheErr == nil {
    61  			var cache = &DiskSpeedCache{}
    62  			err := json.Unmarshal(cacheData, cache)
    63  			if err == nil && cache.SpeedMB > 0 {
    64  				DiskSpeedMB = cache.SpeedMB
    65  				DiskSpeed = cache.Speed
    66  			}
    67  		}
    68  
    69  		// initial check
    70  		_, _, _ = CheckDiskIsFast()
    71  
    72  		// check every one hour
    73  		var ticker = time.NewTicker(1 * time.Hour)
    74  		var count = 0
    75  		for range ticker.C {
    76  			_, _, err := CheckDiskIsFast()
    77  			if err == nil {
    78  				count++
    79  				if count > 24 {
    80  					return
    81  				}
    82  			}
    83  		}
    84  	})
    85  
    86  	// check high load
    87  	goman.New(func() {
    88  		var ticker = time.NewTicker(5 * time.Second)
    89  		for range ticker.C {
    90  			stat, _ := load.Avg()
    91  			IsInExtremelyHighLoad = stat != nil && stat.Load1 > extremelyHighLoad1Threshold
    92  			IsInHighLoad = stat != nil && stat.Load1 > highLoad1Threshold && !DiskIsFast()
    93  		}
    94  	})
    95  }
    96  
    97  func DiskIsFast() bool {
    98  	return DiskSpeed == SpeedExtremelyFast || DiskSpeed == SpeedFast
    99  }
   100  
   101  func DiskIsExtremelyFast() bool {
   102  	// 在开发环境下返回false,以便于测试
   103  	if Tea.IsTesting() {
   104  		return false
   105  	}
   106  	return DiskSpeed == SpeedExtremelyFast
   107  }
   108  
   109  // WaitLoad wait system load to downgrade
   110  func WaitLoad(maxLoad float64, maxLoops int, delay time.Duration) {
   111  	for i := 0; i < maxLoops; i++ {
   112  		stat, err := load.Avg()
   113  		if err == nil {
   114  			if stat.Load1 > maxLoad {
   115  				time.Sleep(delay)
   116  			} else {
   117  				return
   118  			}
   119  		}
   120  	}
   121  }