mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-07 10:40:26 +08:00
优化并发读写限制
This commit is contained in:
@@ -314,8 +314,9 @@ func (this *FileReader) ReadBodyRange(buf []byte, start int64, end int64, callba
|
|||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
var n int
|
||||||
fsutils.ReaderLimiter.Ack()
|
fsutils.ReaderLimiter.Ack()
|
||||||
n, err := this.fp.Read(buf)
|
n, err = this.fp.Read(buf)
|
||||||
fsutils.ReaderLimiter.Release()
|
fsutils.ReaderLimiter.Release()
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
var n2 = int(end-offset) + 1
|
var n2 = int(end-offset) + 1
|
||||||
|
|||||||
@@ -380,6 +380,7 @@ func (this *FileStorage) openReader(key string, allowMemory bool, useStale bool,
|
|||||||
|
|
||||||
// 检查文件记录是否已过期
|
// 检查文件记录是否已过期
|
||||||
var estimatedSize int64
|
var estimatedSize int64
|
||||||
|
var existInList bool
|
||||||
if !useStale {
|
if !useStale {
|
||||||
exists, filesize, err := this.list.Exist(hash)
|
exists, filesize, err := this.list.Exist(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -389,6 +390,7 @@ func (this *FileStorage) openReader(key string, allowMemory bool, useStale bool,
|
|||||||
return nil, ErrNotFound
|
return nil, ErrNotFound
|
||||||
}
|
}
|
||||||
estimatedSize = filesize
|
estimatedSize = filesize
|
||||||
|
existInList = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试通过MMAP读取
|
// 尝试通过MMAP读取
|
||||||
@@ -412,7 +414,13 @@ func (this *FileStorage) openReader(key string, allowMemory bool, useStale bool,
|
|||||||
|
|
||||||
var err error
|
var err error
|
||||||
if openFile == nil {
|
if openFile == nil {
|
||||||
|
if existInList {
|
||||||
|
fsutils.ReaderLimiter.Ack()
|
||||||
|
}
|
||||||
fp, err = os.OpenFile(path, os.O_RDONLY, 0444)
|
fp, err = os.OpenFile(path, os.O_RDONLY, 0444)
|
||||||
|
if existInList {
|
||||||
|
fsutils.ReaderLimiter.Release()
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -583,7 +591,7 @@ func (this *FileStorage) openWriter(key string, expiredAt int64, status int, hea
|
|||||||
// 数据库中是否存在
|
// 数据库中是否存在
|
||||||
existsCacheItem, _, _ := this.list.Exist(hash)
|
existsCacheItem, _, _ := this.list.Exist(hash)
|
||||||
if existsCacheItem {
|
if existsCacheItem {
|
||||||
readerFp, err := os.OpenFile(tmpPath, os.O_RDONLY, 0444)
|
readerFp, err := fsutils.OpenFile(tmpPath, os.O_RDONLY, 0444)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
var partialReader = NewPartialFileReader(readerFp)
|
var partialReader = NewPartialFileReader(readerFp)
|
||||||
err = partialReader.Init()
|
err = partialReader.Init()
|
||||||
@@ -616,9 +624,11 @@ func (this *FileStorage) openWriter(key string, expiredAt int64, status int, hea
|
|||||||
if isNewCreated && existsFile {
|
if isNewCreated && existsFile {
|
||||||
flags |= os.O_TRUNC
|
flags |= os.O_TRUNC
|
||||||
}
|
}
|
||||||
if !isFlushing && !fsutils.WriterLimiter.TryAck() {
|
if !isFlushing {
|
||||||
|
if !fsutils.WriterLimiter.TryAck() {
|
||||||
return nil, ErrServerIsBusy
|
return nil, ErrServerIsBusy
|
||||||
}
|
}
|
||||||
|
}
|
||||||
writer, err := os.OpenFile(tmpPath, flags, 0666)
|
writer, err := os.OpenFile(tmpPath, flags, 0666)
|
||||||
if !isFlushing {
|
if !isFlushing {
|
||||||
fsutils.WriterLimiter.Release()
|
fsutils.WriterLimiter.Release()
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var maxThreads = runtime.NumCPU()
|
var maxThreads = runtime.NumCPU()
|
||||||
var WriterLimiter = NewLimiter(max(maxThreads, 4))
|
var WriterLimiter = NewLimiter(max(maxThreads, 8))
|
||||||
var ReaderLimiter = NewLimiter(max(maxThreads*2, 8))
|
var ReaderLimiter = NewLimiter(max(maxThreads, 8))
|
||||||
|
|
||||||
type Limiter struct {
|
type Limiter struct {
|
||||||
threads chan struct{}
|
threads chan struct{}
|
||||||
@@ -60,7 +60,7 @@ func (this *Limiter) Ack() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *Limiter) TryAck() bool {
|
func (this *Limiter) TryAck() bool {
|
||||||
const timeoutDuration = 1 * time.Second
|
const timeoutDuration = 500 * time.Millisecond
|
||||||
|
|
||||||
var timeout *time.Timer
|
var timeout *time.Timer
|
||||||
select {
|
select {
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
package fsutils
|
package fsutils
|
||||||
|
|
||||||
import "os"
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
func Remove(filename string) (err error) {
|
func Remove(filename string) (err error) {
|
||||||
WriterLimiter.Ack()
|
WriterLimiter.Ack()
|
||||||
@@ -31,3 +33,24 @@ func WriteFile(filename string, data []byte, perm os.FileMode) (err error) {
|
|||||||
WriterLimiter.Release()
|
WriterLimiter.Release()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OpenFile(name string, flag int, perm os.FileMode) (f *os.File, err error) {
|
||||||
|
if flag&os.O_RDONLY == os.O_RDONLY {
|
||||||
|
ReaderLimiter.Ack()
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err = os.OpenFile(name, flag, perm)
|
||||||
|
|
||||||
|
if flag&os.O_RDONLY == os.O_RDONLY {
|
||||||
|
ReaderLimiter.Release()
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Open(name string) (f *os.File, err error) {
|
||||||
|
ReaderLimiter.Ack()
|
||||||
|
f, err = os.Open(name)
|
||||||
|
ReaderLimiter.Release()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
17
internal/utils/fs/os_test.go
Normal file
17
internal/utils/fs/os_test.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2024 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"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOpenFile(t *testing.T) {
|
||||||
|
f, err := fsutils.OpenFile("./os_test.go", os.O_RDONLY, 0444)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
_ = f.Close()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user