mirror of
				https://github.com/TeaOSLab/EdgeAPI.git
				synced 2025-11-04 16:00:24 +08:00 
			
		
		
		
	自动检测本地数据库磁盘是否已满,如果已满,则不再写入访问日志
This commit is contained in:
		@@ -2,6 +2,7 @@ package models
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAPI/internal/goman"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
			
		||||
@@ -31,6 +32,7 @@ var httpAccessLogDAOMapping = map[int64]*HTTPAccessLogDAOWrapper{} // dbNodeId =
 | 
			
		||||
type HTTPAccessLogDAOWrapper struct {
 | 
			
		||||
	DAO     *HTTPAccessLogDAO
 | 
			
		||||
	NodeId  int64
 | 
			
		||||
	IsLocal bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
@@ -195,7 +197,7 @@ func (this *DBNodeInitializer) loop() error {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				daoObject := dbs.DAOObject{
 | 
			
		||||
				var daoObject = dbs.DAOObject{
 | 
			
		||||
					Instance: db,
 | 
			
		||||
					DB:       node.Name + "(id:" + strconv.Itoa(int(node.Id)) + ")",
 | 
			
		||||
					Table:    tableDef.Name,
 | 
			
		||||
@@ -210,12 +212,13 @@ func (this *DBNodeInitializer) loop() error {
 | 
			
		||||
 | 
			
		||||
				accessLogLocker.Lock()
 | 
			
		||||
				accessLogDBMapping[nodeId] = db
 | 
			
		||||
				dao := &HTTPAccessLogDAO{
 | 
			
		||||
				var dao = &HTTPAccessLogDAO{
 | 
			
		||||
					DAOObject: daoObject,
 | 
			
		||||
				}
 | 
			
		||||
				httpAccessLogDAOMapping[nodeId] = &HTTPAccessLogDAOWrapper{
 | 
			
		||||
					DAO:     dao,
 | 
			
		||||
					NodeId:  nodeId,
 | 
			
		||||
					IsLocal: dbutils.IsLocalAddr(node.Host),
 | 
			
		||||
				}
 | 
			
		||||
				accessLogLocker.Unlock()
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -161,16 +161,27 @@ func (this *HTTPAccessLogDAO) DumpAccessLogsFromQueue(size int) (hasMore bool, e
 | 
			
		||||
		size = 100
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(oldAccessLogQueue) == 0 && len(accessLogQueue) == 0 {
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var dao = randomHTTPAccessLogDAO()
 | 
			
		||||
	if dao == nil {
 | 
			
		||||
		dao = &HTTPAccessLogDAOWrapper{
 | 
			
		||||
			DAO:    SharedHTTPAccessLogDAO,
 | 
			
		||||
			NodeId: 0,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(oldAccessLogQueue) == 0 && len(accessLogQueue) == 0 {
 | 
			
		||||
		return false, nil
 | 
			
		||||
		// 检查本地数据库空间
 | 
			
		||||
		if dbutils.IsLocalDatabase && !dbutils.HasFreeSpace {
 | 
			
		||||
			return false, errors.New("dump accesslog failed: there is no enough space left for database (" + dbutils.LocalDatabaseDataDir + ")")
 | 
			
		||||
		}
 | 
			
		||||
	} else if dao.IsLocal {
 | 
			
		||||
		// 检查本地数据库空间
 | 
			
		||||
		// 我们假定本地只能安装一个数据库,访问日志中的数据库和当前API连接的数据库一致
 | 
			
		||||
		if !dbutils.HasFreeSpace {
 | 
			
		||||
			return true, errors.New("dump accesslog failed: there is no enough space left for database (" + dbutils.LocalDatabaseDataDir + ")")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 开始事务
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										73
									
								
								internal/db/utils/disk.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								internal/db/utils/disk.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
			
		||||
 | 
			
		||||
package dbutils
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAPI/internal/goman"
 | 
			
		||||
	"github.com/go-sql-driver/mysql"
 | 
			
		||||
	"github.com/iwind/TeaGo/dbs"
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const minFreeSpaceGB = 3
 | 
			
		||||
 | 
			
		||||
var HasFreeSpace = true
 | 
			
		||||
var IsLocalDatabase = false
 | 
			
		||||
var LocalDatabaseDataDir = ""
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	var ticker = time.NewTicker(5 * time.Minute)
 | 
			
		||||
 | 
			
		||||
	dbs.OnReadyDone(func() {
 | 
			
		||||
		goman.New(func() {
 | 
			
		||||
			for range ticker.C {
 | 
			
		||||
				HasFreeSpace = CheckHasFreeSpace()
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CheckHasFreeSpace 检查当前数据库是否有剩余空间
 | 
			
		||||
func CheckHasFreeSpace() bool {
 | 
			
		||||
	db, _ := dbs.Default()
 | 
			
		||||
	if db == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	config, _ := db.Config()
 | 
			
		||||
	if config == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dsnConfig, _ := mysql.ParseDSN(config.Dsn)
 | 
			
		||||
	if dsnConfig == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if IsLocalAddr(dsnConfig.Addr) {
 | 
			
		||||
		IsLocalDatabase = true
 | 
			
		||||
 | 
			
		||||
		// only for local database
 | 
			
		||||
		one, err := db.FindOne("SHOW VARIABLES WHERE variable_name='datadir'")
 | 
			
		||||
		if err != nil || len(one) == 0 {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var dir = one.GetString("Value")
 | 
			
		||||
		if len(dir) == 0 {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		LocalDatabaseDataDir = dir
 | 
			
		||||
 | 
			
		||||
		var stat unix.Statfs_t
 | 
			
		||||
		err = unix.Statfs(dir, &stat)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var availableSpace = (stat.Bavail * uint64(stat.Bsize)) / (1 << 30) // GB
 | 
			
		||||
		return availableSpace > minFreeSpaceGB
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								internal/db/utils/disk_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								internal/db/utils/disk_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
			
		||||
 | 
			
		||||
package dbutils_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
 | 
			
		||||
	_ "github.com/iwind/TeaGo/bootstrap"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestHasFreeSpace(t *testing.T) {
 | 
			
		||||
	t.Log(dbutils.CheckHasFreeSpace())
 | 
			
		||||
	t.Log(dbutils.LocalDatabaseDataDir)
 | 
			
		||||
}
 | 
			
		||||
@@ -2,6 +2,7 @@ package dbutils
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/iwind/TeaGo/dbs"
 | 
			
		||||
	"net"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -69,3 +70,26 @@ func SetGlobalVarMax(db *dbs.DB, variableName string, maxValue int) error {
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsLocalAddr 是否为本地数据库
 | 
			
		||||
func IsLocalAddr(addr string) bool {
 | 
			
		||||
	var host = addr
 | 
			
		||||
	if strings.Contains(addr, ":") {
 | 
			
		||||
		host, _, _ = net.SplitHostPort(addr)
 | 
			
		||||
		if len(host) == 0 {
 | 
			
		||||
			host = addr
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if host == "127.0.0.1" || host == "::1" || host == "localhost" {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	interfaceAddrs, _ := net.InterfaceAddrs()
 | 
			
		||||
	for _, interfaceAddr := range interfaceAddrs {
 | 
			
		||||
		if strings.HasPrefix(interfaceAddr.String(), host+"/") {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ package dbutils_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
 | 
			
		||||
	"github.com/iwind/TeaGo/assert"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -12,3 +13,13 @@ func TestQuoteLike(t *testing.T) {
 | 
			
		||||
		t.Log(s + " => " + dbutils.QuoteLike(s))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestIsLocalAddr(t *testing.T) {
 | 
			
		||||
	var a = assert.NewAssertion(t)
 | 
			
		||||
	a.IsTrue(dbutils.IsLocalAddr("127.0.0.1"))
 | 
			
		||||
	a.IsTrue(dbutils.IsLocalAddr("localhost"))
 | 
			
		||||
	a.IsTrue(dbutils.IsLocalAddr("::1"))
 | 
			
		||||
	a.IsTrue(dbutils.IsLocalAddr("127.0.0.1:3306"))
 | 
			
		||||
	a.IsFalse(dbutils.IsLocalAddr("192.168.2.200"))
 | 
			
		||||
	a.IsFalse(dbutils.IsLocalAddr("192.168.2.200:3306"))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user