4

我想创建 http 处理程序来处理一个会话:

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

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

我怎样才能做到这一点 ?

4

2 回答 2

4

这不可能直接实现:HTTP 多路复用器(ServeMux 类型)不公开删除操作。

使用 HTTP 多路复用器进行会话管理被证明是一个坏主意。HTTP服务的当前实现有点低效。它为每个 URL 扫描整个多路复用器表,因此您拥有的处理程序越多,性能就越差。这对于一些路径来说很好,但你甚至无法管理数百个会话,更不用说数十万个了。

HTTP 多路复用器需要某种同步才能用作会话管理工具。想象有一个 Unhandle 方法。如果您取消处理路径,您会期望多路复用器不再使用其先前的数据处理您的路径。但是,不同的 goroutine不能保证在没有某种同步的情况下看到彼此对相同数据的更改。因此,HTTP 处理程序仍然可以看到多路复用器的旧视图,然后使用您认为已取消注册的处理程序响应请求。

因此,HTTP 处理程序本身不能为您执行此操作——也不应该这样做,因为您没有任何方法来同步会话生命周期。

"/sess/". 该处理程序应负责委派给各个会话。它可以使用 amap[sessionID]sessionHandler来有效地执行此操作,并且可以通过管道管道所有会话管理以让单个 goroutine 跟踪正在创建和销毁的会话,或者使用更传统的方法在会话映射周围使用读写器锁。这样,您可以确保在删除新请求后不会尝试将新请求分派给会话处理程序。

当然,您可以随时收到 HTTP 请求,因此如果在您决定要删除会话后在指令中发生上下文切换,那么有人可能会在您锁定地图以删除会话之前的那一刻跳入并连接到会话在实际操作之前锁定地图,因此请谨慎管理您的锁定和会话策略。这里要做的“正确的事情”主要取决于您个人应用程序的需求。

于 2013-04-10T05:03:38.970 回答
3

恐怕golanghttp包目前还没有实现删除或修改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()

您有两种解决方法:

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]
  }
}

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

于 2013-04-10T05:03:32.660 回答