doqpm82240 2015-02-03 14:32
浏览 50
已采纳

很多数据竞赛的Web应用程序

I am writing a web application. Incoming requests will pass through middlewares first. At the moment, I've added two middlwares session and security.
After walked through middlwares, it will execute the handler for the request. Session and security middlwares will execute in their own goroutine.

When I am testing I've got a lot of data race, specially in middlware section

WARNING: DATA RACE
Write by goroutine 18:
  runtime.mapassign1()
      c:/go/src/runtime/hashmap.go:383 +0x0
  net/textproto.MIMEHeader.Set()
      c:/go/src/net/textproto/header.go:22 +0xf4
  net/http.Header.Set()
      c:/go/src/net/http/header.go:31 +0x64
  project/middlewares/session.(*ctrl).setHttpHeader()
      D:/gocode/src/project/middlewares/session/ctrl.go:76 +0x9d
  project/middlewares/session.(*ctrl).evaluateJwt()
      D:/gocode/src/project/middlewares/session/ctrl.go:56 +0x31a
  project/middlewares/session.(*ctrl).serveHttp()
      D:/gocode/src/project/middlewares/session/ctrl.go:94 +0x8a
  project/middlewares/session.func┬À006()
      D:/gocode/src/project/middlewares/session/serve_http.go:23 +0x

Previous write by goroutine 17:
  runtime.mapassign1()
      c:/go/src/runtime/hashmap.go:383 +0x0
  net/textproto.MIMEHeader.Add()
      c:/go/src/net/textproto/header.go:15 +0x212
  net/http.Header.Add()
      c:/go/src/net/http/header.go:24 +0x64
  github.com/unrolled/secure.(*Secure).Process()
      D:/gocode/src/github.com/unrolled/secure/secure.go:177 +0xe5b
  project/middlewares/security.func┬À001()
      D:/gocode/src/project/middlewares/security/serve_http.go:33 +0

Goroutine 18 (running) created at:
  project/middlewares/session.ServeHttp()
      D:/gocode/src/project/middlewares/session/serve_http.go:29 +0x
  project/middlewares.New()
      D:/gocode/src/project/middlewares/ctrl.go:12 +0x99
  github.com/codegangsta/negroni.HandlerFunc.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:24 +0x5f
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Static).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/static.go:30 +0xb71
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Logger).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/logger.go:25 +0x249
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Recovery).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/recovery.go:45 +0xd9
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.(*Negroni).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:73 +0x1c7
  net/http/httptest.(*waitGroupHandler).ServeHTTP()
      c:/go/src/net/http/httptest/server.go:200 +0xfe
  net/http.serverHandler.ServeHTTP()
      c:/go/src/net/http/server.go:1703 +0x1fd
  net/http.(*conn).serve()
      c:/go/src/net/http/server.go:1204 +0x108e

Goroutine 17 (finished) created at:
  project/middlewares/security.ServeHttp()
      D:/gocode/src/project/middlewares/security/serve_http.go:37 +0
  project/middlewares.New()
      D:/gocode/src/project/middlewares/ctrl.go:12 +0x64
  github.com/codegangsta/negroni.HandlerFunc.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:24 +0x5f
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Static).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/static.go:30 +0xb71
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Logger).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/logger.go:25 +0x249
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.middleware.ServeHTTP┬Àfm()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x84
  github.com/codegangsta/negroni.(*Recovery).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/recovery.go:45 +0xd9
  github.com/codegangsta/negroni.middleware.ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:33 +0x114
  github.com/codegangsta/negroni.(*Negroni).ServeHTTP()
      D:/gocode/src/github.com/codegangsta/negroni/negroni.go:73 +0x1c7
  net/http/httptest.(*waitGroupHandler).ServeHTTP()
      c:/go/src/net/http/httptest/server.go:200 +0xfe
  net/http.serverHandler.ServeHTTP()
      c:/go/src/net/http/server.go:1703 +0x1fd
  net/http.(*conn).serve()
      c:/go/src/net/http/server.go:1204 +0x108e
==================
2015/02/03 15:05:31 ctrl.go:17: End of process middlewares
2015/02/03 15:05:31 funcs.go:10: Create new user
2015/02/03 15:05:31 validate.go:14: Validate email thompson@example.com
2015/02/03 15:05:31 validate.go:100: Validate password Test!1234
2015/02/03 15:05:31 validate.go:52: Validate name:  ValidName
2015/02/03 15:05:31 create.go:120: Done
[negroni] Completed 0  in 197ms
PASS
ok      project/testing/account_test 0.664s
PS D:\gocode\src\project\testing\account_test> go test -race
2015/02/03 15:08:10 vs.go:50: Connect to neo4j db.
[negroni] Started POST /user
==================
WARNING: DATA RACE
Write by goroutine 18:
  net/http.(*response).Header()
      c:/go/src/net/http/server.go:615 +0x11a
  github.com/codegangsta/negroni.(*responseWriter).Header()
      <autogenerated>:42 +0x78
  project/middlewares/session.(*ctrl).setHttpHeader()
      D:/gocode/src/project/middlewares/session/ctrl.go:76 +0x68
  project/middlewares/session.(*ctrl).evaluateJwt()
      D:/gocode/src/project/middlewares/session/ctrl.go:56 +0x31a
  project/middlewares/session.(*ctrl).serveHttp()
      D:/gocode/src/project/middlewares/session/ctrl.go:94 +0x8a
  project/middlewares/session.func┬À006()
      D:/gocode/src/project/middlewares/session/serve_http.go:23 +0x

Previous write by goroutine 17:
  net/http.(*response).Header()
      c:/go/src/net/http/server.go:615 +0x11a
  github.com/codegangsta/negroni.(*responseWriter).Header()
      <autogenerated>:42 +0x78
  github.com/unrolled/secure.(*Secure).Process()
      D:/gocode/src/github.com/unrolled/secure/secure.go:177 +0xe24
  project/middlewares/security.func┬À001()
      D:/gocode/src/project/middlewares/security/serve_http.go:33 +0

I use negroni to process middlwares works.

The way, how I process middlwares

func New(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) {

    if err := process(security.ServeHttp(res, req), session.ServeHttp(res, req)); err != nil {
        res.WriteHeader(http.StatusInternalServerError)
        return
    }

    log.Println("End of process middlewares")
    next(res, req)

}

// Process all middlewares
func process(chErrs ...<-chan error) error {

    for _, chErr := range chErrs {

        // Will abort the loop, when error occurs
        if err := <-chErr; err != nil {
            return err
        }

    }
    return nil
}

As you can see, every middlware have they own channel. The for statement will loop until the error channel is closed or error send.

The server configuration

func Config() *negroni.Negroni {
    n := negroni.Classic()
    n.Use(negroni.HandlerFunc(middlewares.New))
    n.UseHandler(routes.Set())
    return n

}

My question is, are the middlewares the reason, why I've got the data race?

  • 写回答

1条回答 默认 最新

  • dongtuhe0506 2015-02-03 14:52
    关注

    It's the fact that you're running the middleware within a goroutine that is the problem.

    If you want to run your middleware in parallel you will have to set up a mutex around the memory that is written to by any middleware executed within a goroutine.

    In your particular case you are both writing and reading from the ResponseWriter's Header

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置