@@ -12,6 +12,7 @@ import (
1212 "github.com/xos/serverstatus/db"
1313 "github.com/xos/serverstatus/model"
1414 "github.com/xos/serverstatus/pkg/mygin"
15+ "github.com/xos/serverstatus/pkg/utils"
1516 "github.com/xos/serverstatus/service/singleton"
1617)
1718
@@ -24,11 +25,26 @@ var (
2425 monitorCacheMu sync.Mutex
2526 monitorCache = map [uint64 ]struct {
2627 ts time.Time
27- data []* model. MonitorHistory
28+ data []byte // pre-encoded JSON payload
2829 dur time.Duration
2930 }{}
31+ // serverList/serverDetails 短时缓存
32+ listCacheMu sync.Mutex
33+ listCache = map [string ]struct {
34+ ts time.Time
35+ data []byte
36+ }{}
3037)
3138
39+ // writeJSONPayload 使用已编码的 JSON 字节并按需 gzip 输出
40+ func writeJSONPayload (c * gin.Context , status int , payload []byte ) {
41+ c .Status (status )
42+ c .Writer .Header ().Set ("Content-Type" , "application/json; charset=utf-8" )
43+ if _ , gz , _ := utils .GzipIfAccepted (c .Writer , c .Request , payload ); ! gz {
44+ _ , _ = c .Writer .Write (payload )
45+ }
46+ }
47+
3248func (v * apiV1 ) serve () {
3349 r := v .r .Group ("" )
3450 // 强制认证的 API
@@ -66,11 +82,33 @@ func (v *apiV1) serve() {
6682// query: tag (服务器分组)
6783func (v * apiV1 ) serverList (c * gin.Context ) {
6884 tag := c .Query ("tag" )
69- if tag != "" {
70- c .JSON (200 , singleton .ServerAPI .GetListByTag (tag ))
85+ cacheKey := "serverList:tag=" + tag
86+ listCacheMu .Lock ()
87+ if ce , ok := listCache [cacheKey ]; ok && time .Since (ce .ts ) <= 500 * time .Millisecond {
88+ payload := ce .data
89+ listCacheMu .Unlock ()
90+ writeJSONPayload (c , 200 , payload )
7191 return
7292 }
73- c .JSON (200 , singleton .ServerAPI .GetAllList ())
93+ listCacheMu .Unlock ()
94+
95+ var res interface {}
96+ if tag != "" {
97+ res = singleton .ServerAPI .GetListByTag (tag )
98+ } else {
99+ res = singleton .ServerAPI .GetAllList ()
100+ }
101+ payload , err := utils .EncodeJSON (res )
102+ if err != nil {
103+ payload , _ = utils .EncodeJSON ([]any {})
104+ }
105+ listCacheMu .Lock ()
106+ listCache [cacheKey ] = struct {
107+ ts time.Time
108+ data []byte
109+ }{ts : time .Now (), data : payload }
110+ listCacheMu .Unlock ()
111+ writeJSONPayload (c , 200 , payload )
74112}
75113
76114// serverDetails 获取服务器信息 不传入Query参数则获取全部
@@ -88,15 +126,35 @@ func (v *apiV1) serverDetails(c *gin.Context) {
88126 }
89127 }
90128 tag := c .Query ("tag" )
91- if tag != "" {
92- c .JSON (200 , singleton .ServerAPI .GetStatusByTag (tag ))
129+ cacheKey := "serverDetails:id=" + c .Query ("id" ) + "&tag=" + tag
130+ listCacheMu .Lock ()
131+ if ce , ok := listCache [cacheKey ]; ok && time .Since (ce .ts ) <= 500 * time .Millisecond {
132+ payload := ce .data
133+ listCacheMu .Unlock ()
134+ writeJSONPayload (c , 200 , payload )
93135 return
94136 }
95- if len (idList ) != 0 {
96- c .JSON (200 , singleton .ServerAPI .GetStatusByIDList (idList ))
97- return
137+ listCacheMu .Unlock ()
138+
139+ var res interface {}
140+ if tag != "" {
141+ res = singleton .ServerAPI .GetStatusByTag (tag )
142+ } else if len (idList ) != 0 {
143+ res = singleton .ServerAPI .GetStatusByIDList (idList )
144+ } else {
145+ res = singleton .ServerAPI .GetAllStatus ()
98146 }
99- c .JSON (200 , singleton .ServerAPI .GetAllStatus ())
147+ payload , err := utils .EncodeJSON (res )
148+ if err != nil {
149+ payload , _ = utils .EncodeJSON ([]any {})
150+ }
151+ listCacheMu .Lock ()
152+ listCache [cacheKey ] = struct {
153+ ts time.Time
154+ data []byte
155+ }{ts : time .Now (), data : payload }
156+ listCacheMu .Unlock ()
157+ writeJSONPayload (c , 200 , payload )
100158}
101159
102160// RegisterServer adds a server and responds with the full ServerRegisterResponse
@@ -107,7 +165,7 @@ func (v *apiV1) RegisterServer(c *gin.Context) {
107165 var rs singleton.RegisterServer
108166 // Attempt to bind JSON to RegisterServer struct
109167 if err := c .ShouldBindJSON (& rs ); err != nil {
110- c . JSON ( 400 , singleton.ServerRegisterResponse {
168+ WriteJSON ( c , 400 , singleton.ServerRegisterResponse {
111169 CommonResponse : singleton.CommonResponse {
112170 Code : 400 ,
113171 Message : "Parse JSON failed" ,
@@ -131,9 +189,9 @@ func (v *apiV1) RegisterServer(c *gin.Context) {
131189 response := singleton .ServerAPI .Register (& rs )
132190 // Respond with Secret only if in simple mode, otherwise full response
133191 if simple {
134- c . JSON ( response .Code , response .Secret )
192+ WriteJSON ( c , response .Code , response .Secret )
135193 } else {
136- c . JSON ( response .Code , response )
194+ WriteJSON ( c , response .Code , response )
137195 }
138196}
139197
@@ -180,13 +238,17 @@ func (v *apiV1) monitorHistoriesById(c *gin.Context) {
180238 endTime := time .Now ()
181239 startTime := endTime .Add (- duration )
182240
183- // 命中短时缓存则直接返回
241+ // 命中短时缓存则直接返回(预编码 JSON)
184242 monitorCacheMu .Lock ()
185243 if ce , ok := monitorCache [server .ID ]; ok {
186244 if time .Since (ce .ts ) <= 500 * time .Millisecond && ce .dur == duration {
187- data := ce .data
245+ payload := ce .data
188246 monitorCacheMu .Unlock ()
189- c .JSON (200 , data )
247+ c .Status (200 )
248+ c .Writer .Header ().Set ("Content-Type" , "application/json; charset=utf-8" )
249+ if _ , gz , _ := utils .GzipIfAccepted (c .Writer , c .Request , payload ); ! gz {
250+ _ , _ = c .Writer .Write (payload )
251+ }
190252 return
191253 }
192254 }
@@ -262,19 +324,35 @@ func (v *apiV1) monitorHistoriesById(c *gin.Context) {
262324 networkHistories = sampled
263325 }
264326
327+ // 预编码 JSON,减少后续重复编码
328+ payload , err := utils .EncodeJSON (networkHistories )
329+ if err != nil {
330+ // 回退到空数组
331+ payload , _ = utils .EncodeJSON ([]any {})
332+ }
333+
265334 // 写入短时缓存
266335 monitorCacheMu .Lock ()
267336 monitorCache [server .ID ] = struct {
268337 ts time.Time
269- data []* model. MonitorHistory
338+ data []byte
270339 dur time.Duration
271- }{ts : time .Now (), data : networkHistories , dur : duration }
340+ }{ts : time .Now (), data : payload , dur : duration }
272341 monitorCacheMu .Unlock ()
273342
274343 log .Printf ("API /monitor/%d 返回 %d 条记录(范围: %v,所有监控器)" , server .ID , len (networkHistories ), duration )
275- c .JSON (200 , networkHistories )
344+ c .Status (200 )
345+ c .Writer .Header ().Set ("Content-Type" , "application/json; charset=utf-8" )
346+ if _ , gz , _ := utils .GzipIfAccepted (c .Writer , c .Request , payload ); ! gz {
347+ _ , _ = c .Writer .Write (payload )
348+ }
276349 } else {
277- c .JSON (200 , []any {})
350+ payload , _ := utils .EncodeJSON ([]any {})
351+ c .Status (200 )
352+ c .Writer .Header ().Set ("Content-Type" , "application/json; charset=utf-8" )
353+ if _ , gz , _ := utils .GzipIfAccepted (c .Writer , c .Request , payload ); ! gz {
354+ _ , _ = c .Writer .Write (payload )
355+ }
278356 }
279357 } else {
280358 // SQLite 模式下恢复原始查询逻辑
@@ -289,13 +367,25 @@ func (v *apiV1) monitorHistoriesById(c *gin.Context) {
289367 Order ("created_at DESC" ).
290368 Find (& networkHistories ).Error
291369
370+ var payload []byte
292371 if err != nil {
293- c . JSON ( 200 , []any {})
372+ payload , _ = utils . EncodeJSON ( []any {})
294373 } else {
295- c .JSON (200 , networkHistories )
374+ // 与 Badger 分支一致:预编码 + gzip 按需
375+ payload , _ = utils .EncodeJSON (networkHistories )
376+ }
377+ c .Status (200 )
378+ c .Writer .Header ().Set ("Content-Type" , "application/json; charset=utf-8" )
379+ if _ , gz , _ := utils .GzipIfAccepted (c .Writer , c .Request , payload ); ! gz {
380+ _ , _ = c .Writer .Write (payload )
296381 }
297382 } else {
298- c .JSON (200 , []any {})
383+ payload , _ := utils .EncodeJSON ([]any {})
384+ c .Status (200 )
385+ c .Writer .Header ().Set ("Content-Type" , "application/json; charset=utf-8" )
386+ if _ , gz , _ := utils .GzipIfAccepted (c .Writer , c .Request , payload ); ! gz {
387+ _ , _ = c .Writer .Write (payload )
388+ }
299389 }
300390 }
301391}
@@ -304,8 +394,8 @@ func (v *apiV1) monitorConfigs(c *gin.Context) {
304394 // 获取监控配置列表
305395 if singleton .ServiceSentinelShared != nil {
306396 monitors := singleton .ServiceSentinelShared .Monitors ()
307- c . JSON ( 200 , monitors )
397+ WriteJSON ( c , 200 , monitors )
308398 } else {
309- c . JSON ( 200 , []interface {}{})
399+ WriteJSON ( c , 200 , []interface {}{})
310400 }
311401}
0 commit comments