Google app engine 如何在Google App Engine标准环境下避免Gorilla会话的内存泄漏?
我正在使用Gorilla在Google App Engine上启用会话变量。到目前为止,我只导入了“github.com/gorilla/sessions”,但gorilla的页面显示: 如果您没有使用gorilla/mux,则需要使用 context.ClearHandler为,否则将泄漏内存!一种简单的方法 这样做是为了在调用http.listenandservice时包装顶级mux: http.listendServe(“:8080”, ClearHandler(http.DefaultServeMux)) 我的问题是如何将其应用于App Engine标准环境,据我所知,该环境默认不使用http.ListenAndServe。我的代码如下所示:Google app engine 如何在Google App Engine标准环境下避免Gorilla会话的内存泄漏?,google-app-engine,go,memory-leaks,gorilla,Google App Engine,Go,Memory Leaks,Gorilla,我正在使用Gorilla在Google App Engine上启用会话变量。到目前为止,我只导入了“github.com/gorilla/sessions”,但gorilla的页面显示: 如果您没有使用gorilla/mux,则需要使用 context.ClearHandler为,否则将泄漏内存!一种简单的方法 这样做是为了在调用http.listenandservice时包装顶级mux: http.listendServe(“:8080”, ClearHandler(http.DefaultS
package test
import (
"fmt"
"net/http"
"github.com/gorilla/sessions"
)
func init() {
http.HandleFunc("/", handler)
}
func handler(w http.ResponseWriter, r *http.Request) {
var cookiestore = sessions.NewCookieStore([]byte("somesecret"))
session, _ := cookiestore.Get(r, "session")
session.Values["foo"] = "bar"
fmt.Fprintf(w, "session value is %v", session.Values["foo"])
}
func handler(w http.ResponseWriter, r *http.Request) {
defer context.Clear(r)
var cookiestore = sessions.NewCookieStore([]byte("somesecret"))
session, _ := cookiestore.Get(r, "session")
session.Values["foo"] = "bar"
fmt.Fprintf(w, "session value is %v", session.Values["foo"])
}
这样会导致内存泄漏吗?Gorilla还提供了一个
context.Clear()
选项,您可以根据以下文档将该选项放入请求处理程序:
因此,处理程序func将变成:
func handler(w http.ResponseWriter, r *http.Request) {
var cookiestore = sessions.NewCookieStore([]byte("somesecret"))
session, _ := cookiestore.Get(r, "session")
session.Values["foo"] = "bar"
fmt.Fprintf(w, "session value is %v", session.Values["foo"])
context.Clear(r)
}
您引用的文档告诉您需要做的一切:使用包装处理程序。由于“仅”具有处理程序函数而不是,因此可以使用适配器获取实现http.handler的值:
func init() {
http.Handle("/", context.ClearHandler(http.HandlerFunc(handler)))
}
您需要为您注册的每个处理程序执行此操作。这就是为什么文档提到只包装传递给的根处理程序更容易(这样就不必包装其他非顶级处理程序)。但这不是唯一的方法,只是最简单/最短的方法
如果您自己不调用http.listendServe()(如在App Engine中),或者您没有一个根处理程序,那么您需要手动包装您注册的所有处理程序
请注意,context.ClearHandler()
返回的处理程序没有做任何神奇的事情,它所做的只是在调用您传递的处理程序之后进行调用。因此,您可以同样轻松地在处理程序中调用context.Clear()
,以实现相同的效果
如果这样做,一件重要的事情是使用defer
,就好像出于某种原因无法访问context.Clear()
(例如,遇到前面的return
语句),您将再次泄漏内存。即使您的函数崩溃,也会调用延迟函数。所以应该这样做:
package test
import (
"fmt"
"net/http"
"github.com/gorilla/sessions"
)
func init() {
http.HandleFunc("/", handler)
}
func handler(w http.ResponseWriter, r *http.Request) {
var cookiestore = sessions.NewCookieStore([]byte("somesecret"))
session, _ := cookiestore.Get(r, "session")
session.Values["foo"] = "bar"
fmt.Fprintf(w, "session value is %v", session.Values["foo"])
}
func handler(w http.ResponseWriter, r *http.Request) {
defer context.Clear(r)
var cookiestore = sessions.NewCookieStore([]byte("somesecret"))
session, _ := cookiestore.Get(r, "session")
session.Values["foo"] = "bar"
fmt.Fprintf(w, "session value is %v", session.Values["foo"])
}
还请注意,会话存储创建只应执行一次,因此将其从处理程序移出到全局变量。并检查和处理错误,以节省您的一些头痛。最后建议的代码是:
package test
import (
"fmt"
"net/http"
"log"
"github.com/gorilla/context"
"github.com/gorilla/sessions"
)
func init() {
http.Handle("/", context.ClearHandler(http.HandlerFunc(handler)))
}
var cookiestore = sessions.NewCookieStore([]byte("somesecret"))
func handler(w http.ResponseWriter, r *http.Request) {
session, err := cookiestore.Get(r, "session")
if err != nil {
// Handle error:
log.Printf("Error getting session: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
session.Values["foo"] = "bar"
fmt.Fprintf(w, "session value is %v", session.Values["foo"])
}
抱歉,我在上面的代码中遇到以下错误:无法将handler(type func(http.ResponseWriter,*http.Request))用作“github.com/gorilla/context”参数中的类型http.handler。ClearHandler:func(http.ResponseWriter,*http.Request)未实现http.handler(缺少ServeHTTP方法),谢谢,在我删除旧的会话cookie后,它工作了(之前它说“securecookie:the value is not valid”,可能是因为使用了不同的Previor键)