Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
二次元的罪恶王冠
beego
提交
b8efb3ef
B
beego
项目概览
二次元的罪恶王冠
/
beego
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
B
beego
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
b8efb3ef
编写于
6月 06, 2020
作者:
M
Ming Deng
提交者:
GitHub
6月 06, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #3984 from jianzhiyao/develop
fix bug:static can not real hit cache & memory leak
上级
ae15b54f
c265f6e4
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
86 addition
and
23 deletion
+86
-23
admin_test.go
admin_test.go
+2
-0
config.go
config.go
+12
-0
config/json.go
config/json.go
+2
-7
config_test.go
config_test.go
+8
-0
staticfile.go
staticfile.go
+35
-15
staticfile_test.go
staticfile_test.go
+27
-1
未找到文件。
admin_test.go
浏览文件 @
b8efb3ef
...
...
@@ -52,6 +52,8 @@ func oldMap() M {
m
[
"BConfig.WebConfig.DirectoryIndex"
]
=
BConfig
.
WebConfig
.
DirectoryIndex
m
[
"BConfig.WebConfig.StaticDir"
]
=
BConfig
.
WebConfig
.
StaticDir
m
[
"BConfig.WebConfig.StaticExtensionsToGzip"
]
=
BConfig
.
WebConfig
.
StaticExtensionsToGzip
m
[
"BConfig.WebConfig.StaticCacheFileSize"
]
=
BConfig
.
WebConfig
.
StaticCacheFileSize
m
[
"BConfig.WebConfig.StaticCacheFileNum"
]
=
BConfig
.
WebConfig
.
StaticCacheFileNum
m
[
"BConfig.WebConfig.TemplateLeft"
]
=
BConfig
.
WebConfig
.
TemplateLeft
m
[
"BConfig.WebConfig.TemplateRight"
]
=
BConfig
.
WebConfig
.
TemplateRight
m
[
"BConfig.WebConfig.ViewsPath"
]
=
BConfig
.
WebConfig
.
ViewsPath
...
...
config.go
浏览文件 @
b8efb3ef
...
...
@@ -81,6 +81,8 @@ type WebConfig struct {
DirectoryIndex
bool
StaticDir
map
[
string
]
string
StaticExtensionsToGzip
[]
string
StaticCacheFileSize
int
StaticCacheFileNum
int
TemplateLeft
string
TemplateRight
string
ViewsPath
string
...
...
@@ -236,6 +238,8 @@ func newBConfig() *Config {
DirectoryIndex
:
false
,
StaticDir
:
map
[
string
]
string
{
"/static"
:
"static"
},
StaticExtensionsToGzip
:
[]
string
{
".css"
,
".js"
},
StaticCacheFileSize
:
1024
*
100
,
StaticCacheFileNum
:
1000
,
TemplateLeft
:
"{{"
,
TemplateRight
:
"}}"
,
ViewsPath
:
"views"
,
...
...
@@ -317,6 +321,14 @@ func assignConfig(ac config.Configer) error {
}
}
if
sfs
,
err
:=
ac
.
Int
(
"StaticCacheFileSize"
);
err
==
nil
{
BConfig
.
WebConfig
.
StaticCacheFileSize
=
sfs
}
if
sfn
,
err
:=
ac
.
Int
(
"StaticCacheFileNum"
);
err
==
nil
{
BConfig
.
WebConfig
.
StaticCacheFileNum
=
sfn
}
if
lo
:=
ac
.
String
(
"LogOutputs"
);
lo
!=
""
{
// if lo is not nil or empty
// means user has set his own LogOutputs
...
...
config/json.go
浏览文件 @
b8efb3ef
...
...
@@ -20,6 +20,7 @@ import (
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"sync"
)
...
...
@@ -91,13 +92,7 @@ func (c *JSONConfigContainer) DefaultBool(key string, defaultval bool) bool {
// Int returns the integer value for a given key.
func
(
c
*
JSONConfigContainer
)
Int
(
key
string
)
(
int
,
error
)
{
val
:=
c
.
getData
(
key
)
if
val
!=
nil
{
if
v
,
ok
:=
val
.
(
float64
);
ok
{
return
int
(
v
),
nil
}
return
0
,
errors
.
New
(
"not int value"
)
}
return
0
,
errors
.
New
(
"not exist key:"
+
key
)
return
strconv
.
Atoi
(
val
.
(
string
))
}
// DefaultInt returns the integer value for a given key.
...
...
config_test.go
浏览文件 @
b8efb3ef
...
...
@@ -115,6 +115,8 @@ func TestAssignConfig_03(t *testing.T) {
ac
.
Set
(
"RunMode"
,
"online"
)
ac
.
Set
(
"StaticDir"
,
"download:down download2:down2"
)
ac
.
Set
(
"StaticExtensionsToGzip"
,
".css,.js,.html,.jpg,.png"
)
ac
.
Set
(
"StaticCacheFileSize"
,
"87456"
)
ac
.
Set
(
"StaticCacheFileNum"
,
"1254"
)
assignConfig
(
ac
)
t
.
Logf
(
"%#v"
,
BConfig
)
...
...
@@ -132,6 +134,12 @@ func TestAssignConfig_03(t *testing.T) {
if
BConfig
.
WebConfig
.
StaticDir
[
"/download2"
]
!=
"down2"
{
t
.
FailNow
()
}
if
BConfig
.
WebConfig
.
StaticCacheFileSize
!=
87456
{
t
.
FailNow
()
}
if
BConfig
.
WebConfig
.
StaticCacheFileNum
!=
1254
{
t
.
FailNow
()
}
if
len
(
BConfig
.
WebConfig
.
StaticExtensionsToGzip
)
!=
5
{
t
.
FailNow
()
}
...
...
staticfile.go
浏览文件 @
b8efb3ef
...
...
@@ -28,6 +28,7 @@ import (
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/logs"
"github.com/hashicorp/golang-lru"
)
var
errNotStaticRequest
=
errors
.
New
(
"request not a static file request"
)
...
...
@@ -93,10 +94,11 @@ func serverStaticRouter(ctx *context.Context) {
}
type
serveContentHolder
struct
{
data
[]
byte
modTime
time
.
Time
size
int64
encoding
string
data
[]
byte
modTime
time
.
Time
size
int64
originSize
int64
//original file size:to judge file changed
encoding
string
}
type
serveContentReader
struct
{
...
...
@@ -104,22 +106,36 @@ type serveContentReader struct {
}
var
(
staticFile
Map
=
make
(
map
[
string
]
*
serveContentHolder
)
mapLock
sync
.
RWMutex
staticFile
LruCache
*
lru
.
Cache
lruLock
sync
.
RWMutex
)
func
openFile
(
filePath
string
,
fi
os
.
FileInfo
,
acceptEncoding
string
)
(
bool
,
string
,
*
serveContentHolder
,
*
serveContentReader
,
error
)
{
if
staticFileLruCache
==
nil
{
//avoid lru cache error
if
BConfig
.
WebConfig
.
StaticCacheFileNum
>=
1
{
staticFileLruCache
,
_
=
lru
.
New
(
BConfig
.
WebConfig
.
StaticCacheFileNum
)
}
else
{
staticFileLruCache
,
_
=
lru
.
New
(
1
)
}
}
mapKey
:=
acceptEncoding
+
":"
+
filePath
mapLock
.
RLock
()
mapFile
:=
staticFileMap
[
mapKey
]
mapLock
.
RUnlock
()
lruLock
.
RLock
()
var
mapFile
*
serveContentHolder
if
cacheItem
,
ok
:=
staticFileLruCache
.
Get
(
mapKey
);
ok
{
mapFile
=
cacheItem
.
(
*
serveContentHolder
)
}
lruLock
.
RUnlock
()
if
isOk
(
mapFile
,
fi
)
{
reader
:=
&
serveContentReader
{
Reader
:
bytes
.
NewReader
(
mapFile
.
data
)}
return
mapFile
.
encoding
!=
""
,
mapFile
.
encoding
,
mapFile
,
reader
,
nil
}
mapLock
.
Lock
()
defer
mapLock
.
Unlock
()
if
mapFile
=
staticFileMap
[
mapKey
];
!
isOk
(
mapFile
,
fi
)
{
lruLock
.
Lock
()
defer
lruLock
.
Unlock
()
if
cacheItem
,
ok
:=
staticFileLruCache
.
Get
(
mapKey
);
ok
{
mapFile
=
cacheItem
.
(
*
serveContentHolder
)
}
if
!
isOk
(
mapFile
,
fi
)
{
file
,
err
:=
os
.
Open
(
filePath
)
if
err
!=
nil
{
return
false
,
""
,
nil
,
nil
,
err
...
...
@@ -130,8 +146,10 @@ func openFile(filePath string, fi os.FileInfo, acceptEncoding string) (bool, str
if
err
!=
nil
{
return
false
,
""
,
nil
,
nil
,
err
}
mapFile
=
&
serveContentHolder
{
data
:
bufferWriter
.
Bytes
(),
modTime
:
fi
.
ModTime
(),
size
:
int64
(
bufferWriter
.
Len
()),
encoding
:
n
}
staticFileMap
[
mapKey
]
=
mapFile
mapFile
=
&
serveContentHolder
{
data
:
bufferWriter
.
Bytes
(),
modTime
:
fi
.
ModTime
(),
size
:
int64
(
bufferWriter
.
Len
()),
originSize
:
fi
.
Size
(),
encoding
:
n
}
if
isOk
(
mapFile
,
fi
)
{
staticFileLruCache
.
Add
(
mapKey
,
mapFile
)
}
}
reader
:=
&
serveContentReader
{
Reader
:
bytes
.
NewReader
(
mapFile
.
data
)}
...
...
@@ -141,8 +159,10 @@ func openFile(filePath string, fi os.FileInfo, acceptEncoding string) (bool, str
func
isOk
(
s
*
serveContentHolder
,
fi
os
.
FileInfo
)
bool
{
if
s
==
nil
{
return
false
}
else
if
s
.
size
>
int64
(
BConfig
.
WebConfig
.
StaticCacheFileSize
)
{
return
false
}
return
s
.
modTime
==
fi
.
ModTime
()
&&
s
.
s
ize
==
fi
.
Size
()
return
s
.
modTime
==
fi
.
ModTime
()
&&
s
.
originS
ize
==
fi
.
Size
()
}
// isStaticCompress detect static files
...
...
staticfile_test.go
浏览文件 @
b8efb3ef
...
...
@@ -4,6 +4,7 @@ import (
"bytes"
"compress/gzip"
"compress/zlib"
"fmt"
"io"
"io/ioutil"
"os"
...
...
@@ -53,6 +54,31 @@ func TestOpenStaticFileDeflate_1(t *testing.T) {
testOpenFile
(
"deflate"
,
content
,
t
)
}
func
TestStaticCacheWork
(
t
*
testing
.
T
)
{
encodings
:=
[]
string
{
""
,
"gzip"
,
"deflate"
}
fi
,
_
:=
os
.
Stat
(
licenseFile
)
for
_
,
encoding
:=
range
encodings
{
_
,
_
,
first
,
_
,
err
:=
openFile
(
licenseFile
,
fi
,
encoding
)
if
err
!=
nil
{
t
.
Error
(
err
)
continue
}
_
,
_
,
second
,
_
,
err
:=
openFile
(
licenseFile
,
fi
,
encoding
)
if
err
!=
nil
{
t
.
Error
(
err
)
continue
}
address1
:=
fmt
.
Sprintf
(
"%p"
,
first
)
address2
:=
fmt
.
Sprintf
(
"%p"
,
second
)
if
address1
!=
address2
{
t
.
Errorf
(
"encoding '%v' can not hit cache"
,
encoding
)
}
}
}
func
assetOpenFileAndContent
(
sch
*
serveContentHolder
,
reader
*
serveContentReader
,
content
[]
byte
,
t
*
testing
.
T
)
{
t
.
Log
(
sch
.
size
,
len
(
content
))
if
sch
.
size
!=
int64
(
len
(
content
))
{
...
...
@@ -66,7 +92,7 @@ func assetOpenFileAndContent(sch *serveContentHolder, reader *serveContentReader
t
.
Fail
()
}
}
if
len
(
staticFileMap
)
==
0
{
if
staticFileLruCache
.
Len
(
)
==
0
{
t
.
Log
(
"men map is empty"
)
t
.
Fail
()
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录