2013-04-10 74 views
2

我要创建HTTP处理程序来处理一个会话:如何取消订阅http处理程序?

func init(){ 
    http.HandleFunc("/sess/215489598", func(w http.ResponseWriter, r *http.Request) { 
     //do something 
    }) 
} 

,然后将其删除会话结束时(到期)。

我该怎么做?

回答

4

这是不能直接:一个HTTP多路复用器(型号ServeMux)不不公开删除操作。

使用HTTP多路复用器进行会话管理是一个糟糕的主意。 HTTP服务的当前实现是kind of inefficient.它扫描每个URL的整个多路复用器表,所以处理得越多,性能就越差。对于一些路径来说这没问题,但是你不能以这种方式管理数百次会话,而不能管理数十万次。

HTTP多路复用器需要某种同步才能用作会话管理工具。想象一下有一个Unhandle方法。如果您不处理路径,您会希望多路复用器不再使用之前的数据处理路径。但是,不同的够程aren't guaranteed to see each other's changes to the same data without some kind of synchronization.因此,HTTP处理程序仍然可以看到多路复用器的旧观点,然后用你以为你注销处理程序响应请求。

那么,HTTP处理程序本身不能为你 - 这样做也不应该,因为你没有任何手段来同步会话的寿命。

"/sess/"创建单个处理程序。该处理程序应该负责委派个人会话。它可以使用一个map[sessionID]sessionHandler有效地做到这一点,可以管过通道的所有会话管理,让单一的goroutine跟踪会话被创建和销毁,或周围使用会话映射读写锁用更传统的方法去。这样,您可以确保在删除它之后不会尝试向会话处理程序发送新请求。

当然,你可以随时得到一个HTTP请求,所以有人可能会在你锁定地图以删除会话之前跳过并连接到一个会话,如果在你有指令后发生了上下文切换决定要锁定地图,但在实际执行之前,请仔细管理锁定和会话策略。这里要做的“正确的事情”主要取决于您的个人应用程序的需求。

+2

如果您使用Gorilla grabit,它不需要为每个请求扫描整个路由表。 – 2013-04-10 16:43:32

2

恐怕golang http包没有实现的方法现在删除或修改HTTP处理程序,请阅读:

src/pkg/net/http/server.go

http://golang.org/src/pkg/net/http/server.go?s=28409:28496#L962

type ServeMux 
func NewServeMux() *ServeMux 
func (mux *ServeMux) Handle(pattern string, handler Handler) 
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) 
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) 

它只是实现的寄存器功能HandleFunc()

你有2种方法来解决:

1修改源代码来实现的注销功能。这是不可取的,因为直接使用ServerMux不是一个好主意。

或者:

2也许你让事情变得更加复杂。你只需要在一般的处理函数解析/sess/215489598,例如:

func Handler(response http.ResponseWriter, request *http.Request) { 
    modules := strings.Split(request.URL.Path, "/") 

    if modules[1] == "sess" { 
    session_id := modules[2] 
    } 
} 

然后,你知道该怎么做下一:)