想要远程停止HTTP服务器

huangapple go评论137阅读模式
英文:

Want to stop http server remotely

问题

我想远程停止http服务器(我可以做到),但我也想在停止后收到一条指示已停止的消息。这给我带来了一些问题。我能找到的唯一解决方案如下所示,但我不认为这是理想的。
有人能提供一个更好的解决方案吗?问题是,除非我使用最后的goroutine,否则无法将最终消息发送给客户端。

代码如下:
//*************
func stopServer(ohtWriter http.ResponseWriter, phtRequest http.Request) {// 停止服务器
//
************

  1. var iBytesSent int
  2. var oOsError os.Error
  3. var sErmes string
  4. println("停止服务器")
  5. iBytesSent,oOsError = ohtWriter.Write([]byte("<html>来自服务器的消息 - 服务器已停止。</html>"))
  6. if oOsError != nil {
  7. sErmes = ". 错误 = " +oOsError.String()
  8. } else {
  9. sErmes = ". 写入无错误"
  10. }
  11. println("stopServer: 发送的字节数 = " +strconv.Itoa(iBytesSent) +sErmes)
  12. ohtFlusher, tCanFlush := ohtWriter.(http.Flusher)
  13. if tCanFlush {
  14. ohtFlusher.Flush()
  15. }
  16. go func() {
  17. time.Sleep(3e9)
  18. os.Exit(0)
  19. }()

}

英文:

I want to stop the http server remotely (which I can do), but I also want to receive a message indicating that it has been stopped after it has been stopped. That is causing me some problems. The only solution that I could find is as shown below, which I do not consider ideal.
Can anyone provide a better solution. The problem is that the final message sent to the client is not getting through unless I use the goroutine as shown at the end "go func() {".

Code is as follows:
<pre><code>
//*************
func stopServer(ohtWriter http.ResponseWriter, phtRequest http.Request) {// Stop The Server
//
************

  1. var iBytesSent int
  2. var oOsError os.Error
  3. var sErmes string
  4. println(&quot;Stopping Server&quot;)
  5. iBytesSent,oOsError = ohtWriter.Write([]byte(&quot;&lt;html&gt;Message from server - server now stopped.&lt;/html&gt;&quot;))
  6. if oOsError != nil {
  7. sErmes = &quot;. Error = &quot; +oOsError.String()
  8. } else {
  9. sErmes = &quot;. No error on write&quot;
  10. }
  11. println(&quot;stopServer: Bytes sent = &quot; +strconv.Itoa(iBytesSent) +sErmes)
  12. ohtFlusher, tCanFlush := ohtWriter.(http.Flusher)
  13. if tCanFlush {
  14. ohtFlusher.Flush()
  15. }
  16. go func() {
  17. time.Sleep(3e9)
  18. os.Exit(0)
  19. }()

}
</code></pre>

答案1

得分: 2

是的,我认为如果没有http包的支持,优雅地关闭是不可能的。这可能会稍微好一些,但仍然会在此请求时关闭任何其他并发请求。也许可以尝试在Go问题跟踪器上提交一个功能请求。更好的方法是打开http包,并添加一个优雅关闭的方法,然后提交它

**编辑:**我猜如果您控制应用程序中的所有http.Handlers,您可以使用适当的线程同步来计算正在处理的请求的数量,并修改下面的代码:a)在调用“shutdown”后拒绝新连接,b)在关闭之前等待所有正在处理的请求完成...

  1. package main
  2. import (
  3. "http"
  4. "os"
  5. "io"
  6. "log"
  7. "strconv"
  8. )
  9. func main() {
  10. http.HandleFunc("/", ServeHTTP)
  11. http.ListenAndServe(":8081", nil)
  12. }
  13. const responseString = "Shutting down\n"
  14. func ServeHTTP(w http.ResponseWriter, req *http.Request) {
  15. w.Header().Set("Content-Type", "text/plain; charset=utf-8")
  16. w.Header().Set("Content-Length", strconv.Itoa(len(responseString)))
  17. io.WriteString(w, responseString)
  18. f, canFlush := w.(http.Flusher)
  19. if canFlush {
  20. f.Flush()
  21. }
  22. conn, _, err := w.(http.Hijacker).Hijack()
  23. if err != nil {
  24. log.Fatalf("error while shutting down: %v", err)
  25. }
  26. conn.Close()
  27. log.Println("Shutting down")
  28. os.Exit(0)
  29. }
英文:

Yeah I think without support from the http package, a graceful shutdown is not really possible. This is maybe a little bit less cringe-worthy, but will still slam closed any other concurrent requests in flight at the time of this request. Maybe try filing a feature request on the Go issue tracker. Better yet, open up the http package, and add a graceful shutdown method, and submit it.

Edit: I guess if you control all of the http.Handlers in your app, you could keep a count of in-flight requests (using appropriate thread synchronization), and modify the code below to a) refuse new connections once "shutdown" is called and b) wait for all in-flight requests to complete before shutting down...

  1. package main
  2. import (
  3. &quot;http&quot;
  4. &quot;os&quot;
  5. &quot;io&quot;
  6. &quot;log&quot;
  7. &quot;strconv&quot;
  8. )
  9. func main() {
  10. http.HandleFunc(&quot;/&quot;, ServeHTTP)
  11. http.ListenAndServe(&quot;:8081&quot;, nil)
  12. }
  13. const responseString = &quot;Shutting down\n&quot;
  14. func ServeHTTP(w http.ResponseWriter, req *http.Request) {
  15. w.Header().Set(&quot;Content-Type&quot;, &quot;text/plain; charset=utf-8&quot;)
  16. w.Header().Set(&quot;Content-Length&quot;, strconv.Itoa(len(responseString)))
  17. io.WriteString(w, responseString)
  18. f, canFlush := w.(http.Flusher)
  19. if canFlush {
  20. f.Flush()
  21. }
  22. conn, _, err := w.(http.Hijacker).Hijack()
  23. if err != nil {
  24. log.Fatalf(&quot;error while shutting down: %v&quot;, err)
  25. }
  26. conn.Close()
  27. log.Println(&quot;Shutting down&quot;)
  28. os.Exit(0)
  29. }

答案2

得分: 0

还没有尝试过,但直接使用http.ServerConn可能会起作用。

英文:

Haven't tried it yet, but using http.ServerConn directly might work.

答案3

得分: 0

这是一个足够简单的方法,适用于本地开发。

http://www.sergiotapia.me/how-to-stop-your-go-http-server/


  1. package main
  2. import (
  3. "net/http"
  4. "os"
  5. "github.com/bmizerany/pat"
  6. )
  7. var mux = pat.New()
  8. func main() {
  9. mux.Get("/kill", http.HandlerFunc(kill))
  10. http.Handle("/", mux)
  11. http.ListenAndServe(":8080", nil)
  12. }
  13. func kill(w http.ResponseWriter, r *http.Request) {
  14. os.Exit(0)
  15. }
英文:

Here's a simple way that's good enough for local development.

http://www.sergiotapia.me/how-to-stop-your-go-http-server/


  1. package main
  2. import (
  3. &quot;net/http&quot;
  4. &quot;os&quot;
  5. &quot;github.com/bmizerany/pat&quot;
  6. )
  7. var mux = pat.New()
  8. func main() {
  9. mux.Get(&quot;/kill&quot;, http.HandlerFunc(kill))
  10. http.Handle(&quot;/&quot;, mux)
  11. http.ListenAndServe(&quot;:8080&quot;, nil)
  12. }
  13. func kill(w http.ResponseWriter, r *http.Request) {
  14. os.Exit(0)
  15. }

huangapple
  • 本文由 发表于 2011年7月15日 02:08:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/6697917.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定