【问题标题】:How can I unsubscribe http handler?如何取消订阅 http 处理程序?
【发布时间】:2013-04-01 17:23:22
【问题描述】:

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

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

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

我该怎么做?

【问题讨论】:

    标签: http session go handler unsubscribe


    【解决方案1】:

    恐怕 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()

    您有两种解决方法:

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

    那你就知道下一步该怎么做了:)

    【讨论】:

      【解决方案2】:

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

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

      HTTP 多路复用器需要某种同步才能用作会话管理工具。想象有一个 Unhandle 方法。如果您取消处理路径,您会期望多路复用器不再使用其先前的数据处理您的路径。但是,不同的 goroutines 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 请求,因此如果在您决定后在指令中发生上下文切换,那么在您锁定地图以删除会话之前的那一刻,有人可能会跳入并连接到会话您想在实际操作之前锁定地图,因此请仔细管理您的锁定和会话策略。这里要做的“正确的事情”主要取决于您的个人应用程序的需求。

      【讨论】:

      • 如果你使用Gorilla takeit,它不需要为每个请求扫描整个路由表。
      猜你喜欢
      • 2012-06-15
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      • 2019-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多