首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >金刚websocket内存泄漏

金刚websocket内存泄漏
EN

Stack Overflow用户
提问于 2016-09-09 05:48:15
回答 1查看 2.1K关注 0票数 1

我们有一个基于go-socket.io( socket.io golang实现)和大猩猩websocket的websocket服务,但似乎存在内存泄漏问题。HeapAlloc总是增加,即使我使用debug.FreeOSMemroy强制释放内存。

服务很简单。它将使用jwt令牌对传入请求进行身份验证,如果身份验证成功,则将基于大猩猩websocket conn创建一个go-socket.io conn。但是现在看来,net/textproto.(*Reader).ReadMIMEHeader (包含在net/http.readRequest中,位于net/http.(* conn ).serve中)占用了大量的内存,这使我感到困惑,因为当请求劫持websocket conn时,net/.serve goroutine将立即返回。

  1. 堆在用调用图

use.png

  1. 堆分配空间调用图

alloc.png

  1. gc示踪测井
代码语言:javascript
复制
gc 440 @51045.897s 0%: 0.034+4182+0.96 ms clock, 0.13+0/4182/12246+3.8 ms cpu, 4304->4309->4143 MB, 8266 MB goal, 4 P
scvg340: inuse: 4404, idle: 15, sys: 4419, released: 0, consumed: 4419 (MB)
GC forced
gc 441 @51170.096s 0%: 3.7+4355+1.4 ms clock, 14+2.9/4357/12795+5.8 ms cpu, 4317->4323->4158 MB, 8287 MB goal, 4 P
GC forced
gc 442 @51294.460s 0%: 0.034+3987+1.2 ms clock, 0.13+1.5/3987/11701+4.9 ms cpu, 4336->4341->4169 MB, 8316 MB goal, 4 P
scvg341: inuse: 4318, idle: 133, sys: 4451, released: 0, consumed: 4451 (MB)
GC forced
gc 443 @51418.451s 0%: 0.36+3925+0.99 ms clock, 1.4+4.0/3925/11554+3.9 ms cpu, 4350->4356->4182 MB, 8338 MB goal, 4 P
scvg342: inuse: 4363, idle: 103, sys: 4466, released: 0, consumed: 4466 (MB)
GC forced
gc 444 @51542.394s 0%: 0.042+3986+1.6 ms clock, 0.16+0/3981/11757+6.5 ms cpu, 4361->4367->4194 MB, 8365 MB goal, 4 P
scvg343: inuse: 4404, idle: 74, sys: 4478, released: 0, consumed: 4478 (MB)
GC forced
gc 445 @51666.384s 0%: 3.4+3987+1.4 ms clock, 13+2.5/3986/11747+5.7 ms cpu, 4375->4382->4208 MB, 8388 MB goal, 4 P
scvg344: inuse: 4454, idle: 39, sys: 4493, released: 0, consumed: 4493 (MB)
GC forced
gc 446 @51790.379s 0%: 0.055+4147+1.5 ms clock, 0.22+0/4139/12125+6.2 ms cpu, 4396->4402->4220 MB, 8416 MB goal, 4 P
scvg345: inuse: 4509, idle: 5, sys: 4514, released: 0, consumed: 4514 (MB)
GC forced
gc 447 @51914.542s 0%: 0.052+4205+2.1 ms clock, 0.21+1.5/4199/12348+8.5 ms cpu, 4413->4420->4234 MB, 8441 MB goal, 4 P
GC forced
gc 448 @52038.752s 0%: 2.7+4517+1.8 ms clock, 11+2.3/4517/13245+7.2 ms cpu, 4428->4436->4247 MB, 8469 MB goal, 4 P
scvg346: inuse: 4406, idle: 142, sys: 4548, released: 0, consumed: 4548 (MB)
GC forced
gc 449 @52163.276s 0%: 0.033+4206+1.3 ms clock, 0.13+0/4206/12306+5.3 ms cpu, 4442->4449->4259 MB, 8495 MB goal, 4 P
scvg347: inuse: 4452, idle: 109, sys: 4561, released: 0, consumed: 4561 (MB)
GC forced
gc 450 @52287.491s 0%: 0.044+4262+2.0 ms clock, 0.17+0/4261/12565+8.2 ms cpu, 4452->4459->4272 MB, 8519 MB goal, 4 P
scvg348: inuse: 4498, idle: 74, sys: 4572, released: 0, consumed: 4572 (MB)
GC forced
gc 451 @52411.769s 0%: 0.028+4012+2.0 ms clock, 0.11+0.066/3992/11762+8.0 ms cpu, 4471->4477->4285 MB, 8544 MB goal, 4 P
scvg349: inuse: 4550, idle: 40, sys: 4590, released: 0, consumed: 4590 (MB)
  1. 代码示例 initHTTPServer (c *CometServer) initHTTPServer() { jwtMiddleware := jwtmiddleware.New(jwtmiddleware.Options{ SigningMethod: jwt.SigningMethodHS256,ValidationKeyGetter: func (令牌*jwt.Token) )(接口{ },错误){返回[]字节(setting.JwtSecret),nil },// get令牌从报头、查询字符串和cookie Extractor: jwtmiddleware.FromFirst(:=)TokenFromCookie(setting.JwtTokenCookieField),jwtmiddleware.FromAuthHeader,,ErrorHandler: jwtErrorHandler,}) r := mux.NewRouter() //必须在每次请求后按r.KeepContext = true socketHandler := jwtMiddleware.Handler(c.socketio) r.Handle("/socket.io/“)调用cotext.Clear如果r.PathPrefix("/debug/").Handler(http.DefaultServeMux) { r.PathPrefix("/").Handler(http.FileServer(http.Dir("./asset/"))) } // n.UseHandler(r) c.httpServer = &http.Server{ Addr: setting.HTTPListenAddr,Handler: r,} } // .// go-socket.io代码// .(c *CometServer) initSocketIO()错误{服务器,错误:= socketio.NewServer(传输)如果err != nil {返回err } // .server.On("error",func(so socketio.Socket,err error) {记录器:= SocketLogger(so) logger.Error(“套接字连接错误”) }) server.On("connection",func(so socketio.Socket) ){ var ( uid字符串存在bool )记录器:= SocketLogger(so) claims := (context.Get(so.Request(),“user”))。(*jwt.Token).Claims //在获得索赔后,应清除请求上下文context.Clear(so.Request()) var rawUID接口{} if user,ok := claims。(jwt.MapClaims);ok {如果rawUID,ok = usersetting.JwtUserClaimField;!ok {logger.Error(“无效用户声明”)so.Emit(“断开”,“无效用户声明”)}{logger.Errorf(“无效的logger.Errorf索赔%s",索赔)so.Emit(”断开“,”无效用户声明“)}如果exist =rawUID.(字符串);相同用户的存在{ //多个连接将连接到同一个房间so.Join(uid) // root,用于广播所有用户so.Join( the ) c.users.Add(uid ),( 1) logger.Debug(“套接字连接”)如果setting.DEBUG { so.Emit("debug",fmt.Sprintf(“您的uid为%s,sid为%s",uid,so.Id())}{so.Emit(”断开“),}so.On(“调试”,func(数据字符串){log.Debugf(“从客户%s调试数据”,data) }) so.On(“断开”,func(数据字符串){logger.Debugf(“套接字断开连接”) c.users.Add(uid ),) c.socketio =服务器返回值为零 }
EN

回答 1

Stack Overflow用户

发布于 2016-09-22 08:07:13

最后我解决了这个问题。

我使用https://github.com/auth0/go-jwt-middleware来使用JWT。我还将大猩猩mux路由器的KeepContext打开为true,这样可以从goriila上下文中获得请求的jwt令牌。当我得到jwt令牌时,将立即清除请求上下文(通过context.Clear(r))。到目前为止,一切都是正确的。,但是当go-jwt-中间件失败时,没有机会清除请求上下文,因为mux的KeepContext为真。,这是根本原因。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39404625

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档