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 (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeAPI/internal/goman"
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/goman"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
 | 
						"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
				
			||||||
@@ -29,8 +30,9 @@ var httpAccessLogDAOMapping = map[int64]*HTTPAccessLogDAOWrapper{} // dbNodeId =
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// HTTPAccessLogDAOWrapper HTTP访问日志DAO
 | 
					// HTTPAccessLogDAOWrapper HTTP访问日志DAO
 | 
				
			||||||
type HTTPAccessLogDAOWrapper struct {
 | 
					type HTTPAccessLogDAOWrapper struct {
 | 
				
			||||||
	DAO    *HTTPAccessLogDAO
 | 
						DAO     *HTTPAccessLogDAO
 | 
				
			||||||
	NodeId int64
 | 
						NodeId  int64
 | 
				
			||||||
 | 
						IsLocal bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
@@ -195,7 +197,7 @@ func (this *DBNodeInitializer) loop() error {
 | 
				
			|||||||
					continue
 | 
										continue
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				daoObject := dbs.DAOObject{
 | 
									var daoObject = dbs.DAOObject{
 | 
				
			||||||
					Instance: db,
 | 
										Instance: db,
 | 
				
			||||||
					DB:       node.Name + "(id:" + strconv.Itoa(int(node.Id)) + ")",
 | 
										DB:       node.Name + "(id:" + strconv.Itoa(int(node.Id)) + ")",
 | 
				
			||||||
					Table:    tableDef.Name,
 | 
										Table:    tableDef.Name,
 | 
				
			||||||
@@ -210,12 +212,13 @@ func (this *DBNodeInitializer) loop() error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
				accessLogLocker.Lock()
 | 
									accessLogLocker.Lock()
 | 
				
			||||||
				accessLogDBMapping[nodeId] = db
 | 
									accessLogDBMapping[nodeId] = db
 | 
				
			||||||
				dao := &HTTPAccessLogDAO{
 | 
									var dao = &HTTPAccessLogDAO{
 | 
				
			||||||
					DAOObject: daoObject,
 | 
										DAOObject: daoObject,
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				httpAccessLogDAOMapping[nodeId] = &HTTPAccessLogDAOWrapper{
 | 
									httpAccessLogDAOMapping[nodeId] = &HTTPAccessLogDAOWrapper{
 | 
				
			||||||
					DAO:    dao,
 | 
										DAO:     dao,
 | 
				
			||||||
					NodeId: nodeId,
 | 
										NodeId:  nodeId,
 | 
				
			||||||
 | 
										IsLocal: dbutils.IsLocalAddr(node.Host),
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				accessLogLocker.Unlock()
 | 
									accessLogLocker.Unlock()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -161,16 +161,27 @@ func (this *HTTPAccessLogDAO) DumpAccessLogsFromQueue(size int) (hasMore bool, e
 | 
				
			|||||||
		size = 100
 | 
							size = 100
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(oldAccessLogQueue) == 0 && len(accessLogQueue) == 0 {
 | 
				
			||||||
 | 
							return false, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var dao = randomHTTPAccessLogDAO()
 | 
						var dao = randomHTTPAccessLogDAO()
 | 
				
			||||||
	if dao == nil {
 | 
						if dao == nil {
 | 
				
			||||||
		dao = &HTTPAccessLogDAOWrapper{
 | 
							dao = &HTTPAccessLogDAOWrapper{
 | 
				
			||||||
			DAO:    SharedHTTPAccessLogDAO,
 | 
								DAO:    SharedHTTPAccessLogDAO,
 | 
				
			||||||
			NodeId: 0,
 | 
								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 (
 | 
					import (
 | 
				
			||||||
	"github.com/iwind/TeaGo/dbs"
 | 
						"github.com/iwind/TeaGo/dbs"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -69,3 +70,26 @@ func SetGlobalVarMax(db *dbs.DB, variableName string, maxValue int) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						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 (
 | 
					import (
 | 
				
			||||||
	dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
 | 
						dbutils "github.com/TeaOSLab/EdgeAPI/internal/db/utils"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/assert"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12,3 +13,13 @@ func TestQuoteLike(t *testing.T) {
 | 
				
			|||||||
		t.Log(s + " => " + dbutils.QuoteLike(s))
 | 
							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