自动检测本地数据库磁盘是否已满,如果已满,则不再写入访问日志

This commit is contained in:
刘祥超
2022-10-27 10:27:47 +08:00
parent 4b425e1698
commit 0a6111b2e5
6 changed files with 145 additions and 9 deletions

View File

@@ -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"
@@ -29,8 +30,9 @@ var httpAccessLogDAOMapping = map[int64]*HTTPAccessLogDAOWrapper{} // dbNodeId =
// HTTPAccessLogDAOWrapper HTTP访问日志DAO
type HTTPAccessLogDAOWrapper struct {
DAO *HTTPAccessLogDAO
NodeId int64
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,
DAO: dao,
NodeId: nodeId,
IsLocal: dbutils.IsLocalAddr(node.Host),
}
accessLogLocker.Unlock()
}

View File

@@ -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
View 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
}

View 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)
}

View File

@@ -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
}

View File

@@ -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"))
}