Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
470c6a8b0e | ||
|
|
efc2810d1d | ||
|
|
de2374577f | ||
|
|
2a1f949c13 | ||
|
|
959e274063 | ||
|
|
b6a2bd37b1 | ||
|
|
3e60c9913a | ||
|
|
fd7f3f4029 | ||
|
|
2705a5d444 | ||
|
|
556055cfcb | ||
|
|
67a0d06944 | ||
|
|
a16d8f1afa | ||
|
|
1bab7bfcba | ||
|
|
5928875623 | ||
|
|
734cf81ff0 |
@@ -54,10 +54,11 @@ function build() {
|
||||
cp -R "$ROOT"/www "$DIST"/
|
||||
cp -R "$ROOT"/pages "$DIST"/
|
||||
|
||||
# we support TOA on linux/amd64 only
|
||||
if [ "$OS" == "linux" ] && [ "$ARCH" == "amd64" ]
|
||||
# we support TOA on linux only
|
||||
if [ "$OS" == "linux" ] && [ -f "${ROOT}/edge-toa/edge-toa-${ARCH}" ]
|
||||
then
|
||||
cp -R "$ROOT"/edge-toa "$DIST"
|
||||
mkdir "$DIST/edge-toa"
|
||||
cp "${ROOT}/edge-toa/edge-toa-${ARCH}" "$DIST/edge-toa/edge-toa"
|
||||
fi
|
||||
|
||||
echo "building ..."
|
||||
|
||||
Binary file not shown.
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/apps"
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/nodes"
|
||||
fsutils "github.com/TeaOSLab/EdgeNode/internal/utils/fs"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
@@ -365,6 +366,29 @@ func main() {
|
||||
}
|
||||
fmt.Println(string(statsJSON))
|
||||
})
|
||||
app.On("disk", func() {
|
||||
var args = os.Args[2:]
|
||||
if len(args) > 0 {
|
||||
switch args[0] {
|
||||
case "speed":
|
||||
speedMB, isFast, err := fsutils.CheckDiskIsFast()
|
||||
if err != nil {
|
||||
fmt.Println("[ERROR]" + err.Error())
|
||||
} else {
|
||||
fmt.Printf("Speed: %.2fMB/s\n", speedMB)
|
||||
if isFast {
|
||||
fmt.Println("IsFast: true")
|
||||
} else {
|
||||
fmt.Println("IsFast: false")
|
||||
}
|
||||
}
|
||||
default:
|
||||
fmt.Println("Usage: edge-node disk [speed]")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("Usage: edge-node disk [speed]")
|
||||
}
|
||||
})
|
||||
app.Run(func() {
|
||||
var node = nodes.NewNode()
|
||||
node.Start()
|
||||
|
||||
@@ -198,6 +198,9 @@ func (this *FileStorage) UpdatePolicy(newPolicy *serverconfigs.HTTPCachePolicy)
|
||||
if newPolicy.PersistenceAutoPurgeInterval != this.policy.PersistenceAutoPurgeInterval {
|
||||
this.initPurgeTicker()
|
||||
}
|
||||
|
||||
// reset ignored keys
|
||||
this.ignoreKeys.Reset()
|
||||
}
|
||||
|
||||
// Init 初始化
|
||||
@@ -410,14 +413,14 @@ func (this *FileStorage) openWriter(key string, expiredAt int64, status int, hea
|
||||
}
|
||||
|
||||
// 是否已忽略
|
||||
if this.ignoreKeys.Has(key) {
|
||||
if maxSize > 0 && this.ignoreKeys.Has(types.String(maxSize)+"$"+key) {
|
||||
return nil, ErrEntityTooLarge
|
||||
}
|
||||
|
||||
// 先尝试内存缓存
|
||||
// 我们限定仅小文件优先存在内存中
|
||||
var maxMemorySize = FileToMemoryMaxSize
|
||||
if maxSize > maxMemorySize {
|
||||
if maxSize > 0 && maxSize < maxMemorySize {
|
||||
maxMemorySize = maxSize
|
||||
}
|
||||
var memoryStorage = this.memoryStorage
|
||||
@@ -642,7 +645,7 @@ func (this *FileStorage) openWriter(key string, expiredAt int64, status int, hea
|
||||
sharedWritingFileKeyLocker.Unlock()
|
||||
}), nil
|
||||
} else {
|
||||
return NewFileWriter(this, writer, key, expiredAt, metaHeaderSize, metaBodySize, -1, func() {
|
||||
return NewFileWriter(this, writer, key, expiredAt, metaHeaderSize, metaBodySize, maxSize, func() {
|
||||
sharedWritingFileKeyLocker.Lock()
|
||||
delete(sharedWritingFileKeyMap, key)
|
||||
if len(sharedWritingFileKeyMap) == 0 {
|
||||
@@ -914,8 +917,8 @@ func (this *FileStorage) TotalMemorySize() int64 {
|
||||
}
|
||||
|
||||
// IgnoreKey 忽略某个Key,即不缓存某个Key
|
||||
func (this *FileStorage) IgnoreKey(key string) {
|
||||
this.ignoreKeys.Push(key)
|
||||
func (this *FileStorage) IgnoreKey(key string, maxSize int64) {
|
||||
this.ignoreKeys.Push(types.String(maxSize) + "$" + key)
|
||||
}
|
||||
|
||||
// CanSendfile 是否支持Sendfile
|
||||
|
||||
@@ -42,7 +42,9 @@ func TestFileStorage_Init(t *testing.T) {
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
storage.purgeLoop()
|
||||
t.Log(storage.list.(*FileList).total, "entries left")
|
||||
t.Log(storage.list.(*FileList).Stat(func(hash string) bool {
|
||||
return true
|
||||
}))
|
||||
}
|
||||
|
||||
func TestFileStorage_OpenWriter(t *testing.T) {
|
||||
|
||||
@@ -54,7 +54,7 @@ type StorageInterface interface {
|
||||
AddToList(item *Item)
|
||||
|
||||
// IgnoreKey 忽略某个Key,即不缓存某个Key
|
||||
IgnoreKey(key string)
|
||||
IgnoreKey(key string, maxSize int64)
|
||||
|
||||
// CanSendfile 是否支持Sendfile
|
||||
CanSendfile() bool
|
||||
|
||||
@@ -158,7 +158,7 @@ func (this *MemoryStorage) OpenReader(key string, useStale bool, isPartial bool)
|
||||
|
||||
// OpenWriter 打开缓存写入器等待写入
|
||||
func (this *MemoryStorage) OpenWriter(key string, expiredAt int64, status int, headerSize int, bodySize int64, maxSize int64, isPartial bool) (Writer, error) {
|
||||
if this.ignoreKeys.Has(key) {
|
||||
if maxSize > 0 && this.ignoreKeys.Has(types.String(maxSize)+"$"+key) {
|
||||
return nil, ErrEntityTooLarge
|
||||
}
|
||||
|
||||
@@ -362,6 +362,9 @@ func (this *MemoryStorage) UpdatePolicy(newPolicy *serverconfigs.HTTPCachePolicy
|
||||
if newPolicy.CapacityBytes() == 0 {
|
||||
_ = this.CleanAll()
|
||||
}
|
||||
|
||||
// reset ignored keys
|
||||
this.ignoreKeys.Reset()
|
||||
}
|
||||
|
||||
// CanUpdatePolicy 检查策略是否可以更新
|
||||
@@ -392,8 +395,8 @@ func (this *MemoryStorage) TotalMemorySize() int64 {
|
||||
}
|
||||
|
||||
// IgnoreKey 忽略某个Key,即不缓存某个Key
|
||||
func (this *MemoryStorage) IgnoreKey(key string) {
|
||||
this.ignoreKeys.Push(key)
|
||||
func (this *MemoryStorage) IgnoreKey(key string, maxSize int64) {
|
||||
this.ignoreKeys.Push(types.String(maxSize) + "$" + key)
|
||||
}
|
||||
|
||||
// CanSendfile 是否支持Sendfile
|
||||
|
||||
@@ -79,7 +79,7 @@ func (this *FileWriter) Write(data []byte) (n int, err error) {
|
||||
err = ErrEntityTooLarge
|
||||
|
||||
if this.storage != nil {
|
||||
this.storage.IgnoreKey(this.key)
|
||||
this.storage.IgnoreKey(this.key, this.maxSize)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ func (this *MemoryWriter) Write(data []byte) (n int, err error) {
|
||||
// 检查尺寸
|
||||
if this.maxSize > 0 && this.bodySize > this.maxSize {
|
||||
err = ErrEntityTooLarge
|
||||
this.storage.IgnoreKey(this.key)
|
||||
this.storage.IgnoreKey(this.key, this.maxSize)
|
||||
return len(data), err
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package teaconst
|
||||
|
||||
const (
|
||||
Version = "1.2.1"
|
||||
Version = "1.2.5"
|
||||
|
||||
ProductName = "Edge Node"
|
||||
ProcessName = "edge-node"
|
||||
|
||||
@@ -129,9 +129,8 @@ func (this *ClientConn) Read(b []byte) (n int, err error) {
|
||||
// 检测是否为超时错误
|
||||
var isTimeout = err != nil && os.IsTimeout(err)
|
||||
var isHandshakeError = isTimeout && !this.hasRead
|
||||
if isTimeout {
|
||||
_ = this.SetLinger(0)
|
||||
} else {
|
||||
|
||||
if err != nil {
|
||||
_ = this.SetLinger(nodeconfigs.DefaultTCPLinger)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||
"github.com/pires/go-proxyproto"
|
||||
"golang.org/x/net/http2"
|
||||
"net"
|
||||
@@ -132,14 +131,8 @@ func (this *HTTPClientPool) Client(req *HTTPRequest,
|
||||
var transport = &HTTPClientTransport{
|
||||
Transport: &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
// 支持TOA的连接
|
||||
conn, err := this.handleTOA(req, ctx, network, originAddr, connectionTimeout)
|
||||
if conn != nil || err != nil {
|
||||
return conn, err
|
||||
}
|
||||
|
||||
// 普通的连接
|
||||
conn, err = (&net.Dialer{
|
||||
conn, err := (&net.Dialer{
|
||||
Timeout: connectionTimeout,
|
||||
KeepAlive: 1 * time.Minute,
|
||||
}).DialContext(ctx, network, originAddr)
|
||||
@@ -215,38 +208,6 @@ func (this *HTTPClientPool) cleanClients() {
|
||||
}
|
||||
}
|
||||
|
||||
// 支持TOA
|
||||
func (this *HTTPClientPool) handleTOA(req *HTTPRequest, ctx context.Context, network string, originAddr string, connectionTimeout time.Duration) (net.Conn, error) {
|
||||
// TODO 每个服务读取自身所属集群的TOA设置
|
||||
var toaConfig = sharedTOAManager.Config()
|
||||
if toaConfig != nil && toaConfig.IsOn {
|
||||
var retries = 3
|
||||
for i := 1; i <= retries; i++ {
|
||||
var port = int(toaConfig.RandLocalPort())
|
||||
// TODO 思考是否支持X-Real-IP/X-Forwarded-IP
|
||||
err := sharedTOAManager.SendMsg("add:" + strconv.Itoa(port) + ":" + req.requestRemoteAddr(true))
|
||||
if err != nil {
|
||||
remotelogs.Error("TOA", "add failed: "+err.Error())
|
||||
} else {
|
||||
dialer := net.Dialer{
|
||||
Timeout: connectionTimeout,
|
||||
KeepAlive: 1 * time.Minute,
|
||||
LocalAddr: &net.TCPAddr{
|
||||
Port: port,
|
||||
},
|
||||
}
|
||||
conn, err := dialer.DialContext(ctx, network, originAddr)
|
||||
// TODO 需要在合适的时机删除TOA记录
|
||||
if err == nil || i == retries {
|
||||
return conn, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// 支持PROXY Protocol
|
||||
func (this *HTTPClientPool) handlePROXYProtocol(conn net.Conn, req *HTTPRequest, proxyProtocol *serverconfigs.ProxyProtocolConfig) error {
|
||||
if proxyProtocol != nil && proxyProtocol.IsOn && (proxyProtocol.Version == serverconfigs.ProxyProtocolVersion1 || proxyProtocol.Version == serverconfigs.ProxyProtocolVersion2) {
|
||||
|
||||
@@ -38,8 +38,13 @@ func (this *HTTPRequest) doCacheRead(useStale bool) (shouldStop bool) {
|
||||
|
||||
// 添加 X-Cache Header
|
||||
var addStatusHeader = this.web.Cache.AddStatusHeader
|
||||
var cacheBypassDescription = ""
|
||||
if addStatusHeader {
|
||||
defer func() {
|
||||
if len(cacheBypassDescription) > 0 {
|
||||
this.writer.Header().Set("X-Cache", cacheBypassDescription)
|
||||
return
|
||||
}
|
||||
var cacheStatus = this.varMapping["cache.status"]
|
||||
if cacheStatus != "HIT" {
|
||||
this.writer.Header().Set("X-Cache", cacheStatus)
|
||||
@@ -94,6 +99,7 @@ func (this *HTTPRequest) doCacheRead(useStale bool) (shouldStop bool) {
|
||||
// 校验请求
|
||||
if !this.cacheRef.MatchRequest(this.RawReq) {
|
||||
this.cacheRef = nil
|
||||
cacheBypassDescription = "BYPASS, not match"
|
||||
return
|
||||
}
|
||||
|
||||
@@ -106,6 +112,7 @@ func (this *HTTPRequest) doCacheRead(useStale bool) (shouldStop bool) {
|
||||
if this.cacheRef.EnableRequestCachePragma {
|
||||
if this.RawReq.Header.Get("Cache-Control") == "no-cache" || this.RawReq.Header.Get("Pragma") == "no-cache" {
|
||||
this.cacheRef = nil
|
||||
cacheBypassDescription = "BYPASS, Cache-Control or Pragma"
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -119,6 +126,7 @@ func (this *HTTPRequest) doCacheRead(useStale bool) (shouldStop bool) {
|
||||
var key = this.Format(this.cacheRef.Key)
|
||||
if len(key) == 0 {
|
||||
this.cacheRef = nil
|
||||
cacheBypassDescription = "BYPASS, empty key"
|
||||
return
|
||||
}
|
||||
var method = this.Method()
|
||||
@@ -134,6 +142,7 @@ func (this *HTTPRequest) doCacheRead(useStale bool) (shouldStop bool) {
|
||||
var storage = caches.SharedManager.FindStorageWithPolicy(cachePolicy.Id)
|
||||
if storage == nil {
|
||||
this.cacheRef = nil
|
||||
cacheBypassDescription = "BYPASS, no policy found"
|
||||
return
|
||||
}
|
||||
this.writer.cacheStorage = storage
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func (this *HTTPRequest) doCheckUserAgent() (shouldStop bool) {
|
||||
if this.web.UserAgent == nil {
|
||||
if this.web.UserAgent == nil || !this.web.UserAgent.IsOn {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -324,11 +324,11 @@ func (this *HTTPWriter) PrepareCache(resp *http.Response, size int64) {
|
||||
|
||||
// 待写入尺寸
|
||||
var totalSize = size
|
||||
if totalSize < 0 && this.isPartial {
|
||||
if this.isPartial {
|
||||
var contentRange = resp.Header.Get("Content-Range")
|
||||
if len(contentRange) > 0 {
|
||||
_, partialTotalSize := httpRequestParseContentRangeHeader(contentRange)
|
||||
if partialTotalSize > 0 {
|
||||
if partialTotalSize > 0 && partialTotalSize > totalSize {
|
||||
totalSize = partialTotalSize
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
|
||||
iplib "github.com/TeaOSLab/EdgeCommon/pkg/iplibrary"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
@@ -26,6 +27,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||
_ "github.com/TeaOSLab/EdgeNode/internal/utils/agents" // 引入Agent管理器
|
||||
_ "github.com/TeaOSLab/EdgeNode/internal/utils/clock" // 触发时钟更新
|
||||
fsutils "github.com/TeaOSLab/EdgeNode/internal/utils/fs"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/utils/jsonutils"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/waf"
|
||||
"github.com/andybalholm/brotli"
|
||||
@@ -141,7 +143,7 @@ func (this *Node) Start() {
|
||||
// 调整系统参数
|
||||
this.checkSystem()
|
||||
|
||||
// 检查硬盘类型
|
||||
// 检查硬盘
|
||||
this.checkDisk()
|
||||
|
||||
// 启动事件
|
||||
@@ -1109,23 +1111,16 @@ func (this *Node) checkSystem() {
|
||||
|
||||
// 检查硬盘
|
||||
func (this *Node) checkDisk() {
|
||||
if runtime.GOOS != "linux" {
|
||||
speedMB, isFast, err := fsutils.CheckDiskIsFast()
|
||||
if err != nil {
|
||||
remotelogs.Error("NODE", "check disk speed failed: "+err.Error())
|
||||
return
|
||||
}
|
||||
for n := 'a'; n <= 'z'; n++ {
|
||||
for _, path := range []string{
|
||||
"/sys/block/vd" + string(n) + "/queue/rotational",
|
||||
"/sys/block/sd" + string(n) + "/queue/rotational",
|
||||
} {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if string(data) == "0" {
|
||||
teaconst.DiskIsFast = true
|
||||
}
|
||||
return
|
||||
}
|
||||
teaconst.DiskIsFast = isFast
|
||||
if isFast {
|
||||
remotelogs.Println("NODE", "disk is fast, writing test speed: "+fmt.Sprintf("%.2fMB/s", speedMB))
|
||||
} else {
|
||||
remotelogs.Println("NODE", "disk is slow, writing test speed: "+fmt.Sprintf("%.2fMB/s", speedMB))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,3 +15,7 @@ func (this *Node) reloadIPLibrary() {
|
||||
func (this *Node) notifyPlusChange() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *Node) execTOAChangedTask() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -90,6 +90,8 @@ func (this *Node) execTask(rpcClient *rpc.RPCClient, task *pb.NodeTask) error {
|
||||
err = this.execUpdatingServersTask(rpcClient)
|
||||
case "plusChanged":
|
||||
err = this.notifyPlusChange()
|
||||
case "toaChanged":
|
||||
err = this.execTOAChangedTask()
|
||||
default:
|
||||
remotelogs.Error("NODE", "task '"+types.String(task.Id)+"', type '"+task.Type+"' has not been handled")
|
||||
}
|
||||
|
||||
@@ -1,117 +1,31 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
//go:build !plus
|
||||
|
||||
package nodes
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/events"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
|
||||
executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
import "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
|
||||
var sharedTOAManager = NewTOAManager()
|
||||
|
||||
func init() {
|
||||
if !teaconst.IsMain {
|
||||
return
|
||||
}
|
||||
|
||||
events.On(events.EventReload, func() {
|
||||
err := sharedTOAManager.Run(sharedNodeConfig.TOA)
|
||||
if err != nil {
|
||||
remotelogs.Error("TOA", err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type TOAManager struct {
|
||||
config *nodeconfigs.TOAConfig
|
||||
pid int
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
func NewTOAManager() *TOAManager {
|
||||
return &TOAManager{}
|
||||
}
|
||||
|
||||
func (this *TOAManager) Run(config *nodeconfigs.TOAConfig) error {
|
||||
this.config = config
|
||||
|
||||
if this.pid > 0 {
|
||||
remotelogs.Println("TOA", "stopping ...")
|
||||
err := this.Quit()
|
||||
if err != nil {
|
||||
remotelogs.Error("TOA", "quit error: "+err.Error())
|
||||
}
|
||||
if this.conn != nil {
|
||||
_ = this.conn.Close()
|
||||
}
|
||||
this.conn = nil
|
||||
this.pid = 0
|
||||
}
|
||||
|
||||
if !config.IsOn {
|
||||
return nil
|
||||
}
|
||||
|
||||
binPath := Tea.Root + "/edge-toa/edge-toa" // TODO 可以做成配置
|
||||
_, err := os.Stat(binPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
remotelogs.Println("TOA", "starting ...")
|
||||
remotelogs.Println("TOA", "args: "+strings.Join(config.AsArgs(), " "))
|
||||
cmd := executils.NewCmd(binPath, config.AsArgs()...)
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var process = cmd.Process()
|
||||
if process == nil {
|
||||
return errors.New("start failed")
|
||||
}
|
||||
this.pid = process.Pid
|
||||
|
||||
goman.New(func() {
|
||||
_ = cmd.Wait()
|
||||
})
|
||||
|
||||
func (this *TOAManager) Apply(config *nodeconfigs.TOAConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *TOAManager) Config() *nodeconfigs.TOAConfig {
|
||||
return this.config
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *TOAManager) Quit() error {
|
||||
return this.SendMsg("quit:0")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *TOAManager) SendMsg(msg string) error {
|
||||
if this.config == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if this.conn != nil {
|
||||
_, err := this.conn.Write([]byte(msg + "\n"))
|
||||
if err != nil {
|
||||
_ = this.conn.Close()
|
||||
this.conn = nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
conn, err := net.DialTimeout("unix", this.config.SockFile(), 1*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
this.conn = conn
|
||||
_, err = this.conn.Write([]byte(msg + "\n"))
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package nodes
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTOAManager_Run(t *testing.T) {
|
||||
manager := NewTOAManager()
|
||||
err := manager.Run(&nodeconfigs.TOAConfig{
|
||||
IsOn: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
@@ -74,6 +74,20 @@ func TestCounter_GC2(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCounterMemory(t *testing.T) {
|
||||
var stat = &runtime.MemStats{}
|
||||
runtime.ReadMemStats(stat)
|
||||
|
||||
var counter = counters.NewCounter()
|
||||
for i := 0; i < 1e5; i++ {
|
||||
counter.Increase(uint64(i), rands.Int(10, 300))
|
||||
}
|
||||
|
||||
var stat1 = &runtime.MemStats{}
|
||||
runtime.ReadMemStats(stat1)
|
||||
t.Log((stat1.TotalAlloc-stat.TotalAlloc)/(1<<20), "MB")
|
||||
}
|
||||
|
||||
func BenchmarkCounter_Increase(b *testing.B) {
|
||||
runtime.GOMAXPROCS(4)
|
||||
|
||||
|
||||
69
internal/utils/fs/disk.go
Normal file
69
internal/utils/fs/disk.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package fsutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CheckDiskWritingSpeed test disk writing speed
|
||||
func CheckDiskWritingSpeed() (speedMB float64, err error) {
|
||||
var tempDir = os.TempDir()
|
||||
if len(tempDir) == 0 {
|
||||
tempDir = "/tmp"
|
||||
}
|
||||
|
||||
const filename = "edge-disk-writing-test.data"
|
||||
var path = tempDir + "/" + filename
|
||||
_ = os.Remove(path) // always try to delete the file
|
||||
|
||||
fp, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var isClosed bool
|
||||
defer func() {
|
||||
if !isClosed {
|
||||
_ = fp.Close()
|
||||
}
|
||||
|
||||
_ = os.Remove(path)
|
||||
}()
|
||||
|
||||
var data = bytes.Repeat([]byte{'A'}, 16<<20)
|
||||
var before = time.Now()
|
||||
_, err = fp.Write(data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = fp.Sync()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = fp.Close()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var costSeconds = time.Since(before).Seconds()
|
||||
speedMB = float64(len(data)) / (1 << 20) / costSeconds
|
||||
|
||||
isClosed = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CheckDiskIsFast check disk is 'fast' disk to write
|
||||
func CheckDiskIsFast() (speedMB float64, isFast bool, err error) {
|
||||
speedMB, err = CheckDiskWritingSpeed()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
isFast = speedMB > 120
|
||||
return
|
||||
}
|
||||
16
internal/utils/fs/disk_test_test.go
Normal file
16
internal/utils/fs/disk_test_test.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||
|
||||
package fsutils_test
|
||||
|
||||
import (
|
||||
fsutils "github.com/TeaOSLab/EdgeNode/internal/utils/fs"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCheckDiskWritingSpeed(t *testing.T) {
|
||||
t.Log(fsutils.CheckDiskWritingSpeed())
|
||||
}
|
||||
|
||||
func TestCheckDiskIsFast(t *testing.T) {
|
||||
t.Log(fsutils.CheckDiskIsFast())
|
||||
}
|
||||
@@ -25,7 +25,7 @@ func (this *TeeReaderCloser) Read(p []byte) (n int, err error) {
|
||||
n, err = this.r.Read(p)
|
||||
if n > 0 {
|
||||
_, wErr := this.w.Write(p[:n])
|
||||
if err == nil && wErr != nil {
|
||||
if (err == nil || err == io.EOF) && wErr != nil {
|
||||
err = wErr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ type FixedSet struct {
|
||||
maxSize int
|
||||
locker sync.RWMutex
|
||||
|
||||
m map[interface{}]zero.Zero
|
||||
keys []interface{}
|
||||
m map[any]zero.Zero
|
||||
keys []any
|
||||
}
|
||||
|
||||
func NewFixedSet(maxSize int) *FixedSet {
|
||||
@@ -23,11 +23,11 @@ func NewFixedSet(maxSize int) *FixedSet {
|
||||
}
|
||||
return &FixedSet{
|
||||
maxSize: maxSize,
|
||||
m: map[interface{}]zero.Zero{},
|
||||
m: map[any]zero.Zero{},
|
||||
}
|
||||
}
|
||||
|
||||
func (this *FixedSet) Push(item interface{}) {
|
||||
func (this *FixedSet) Push(item any) {
|
||||
this.locker.Lock()
|
||||
_, ok := this.m[item]
|
||||
if !ok {
|
||||
@@ -44,7 +44,7 @@ func (this *FixedSet) Push(item interface{}) {
|
||||
this.locker.Unlock()
|
||||
}
|
||||
|
||||
func (this *FixedSet) Has(item interface{}) bool {
|
||||
func (this *FixedSet) Has(item any) bool {
|
||||
this.locker.RLock()
|
||||
defer this.locker.RUnlock()
|
||||
|
||||
@@ -60,7 +60,7 @@ func (this *FixedSet) Size() int {
|
||||
|
||||
func (this *FixedSet) Reset() {
|
||||
this.locker.Lock()
|
||||
this.m = map[interface{}]zero.Zero{}
|
||||
this.m = map[any]zero.Zero{}
|
||||
this.keys = nil
|
||||
this.locker.Unlock()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user