想要远程停止http服务器

发布于 2024-11-24 02:11:37 字数 909 浏览 1 评论 0原文

我想远程停止http服务器(我可以做到),但我也想在停止后收到一条指示它已停止的消息。这给我带来了一些问题。我能找到的唯一解决方案如下所示,我认为这并不理想。 谁能提供更好的解决方案。问题是发送到客户端的最终消息无法通过,除非我使用“go func() {”末尾所示的 goroutine。

代码如下:


//*************
func stopServer(ohtWriter http.ResponseWriter, phtRequest *http.Request) {// Stop The Server
//*************

    var iBytesSent  int
    var oOsError    os.Error
    var sErmes  string

    println("Stopping Server")

    iBytesSent,oOsError = ohtWriter.Write([]byte("Message from server - server now stopped."))

    if oOsError != nil {
        sErmes = ". Error = " +oOsError.String()
    } else {
        sErmes = ". No error on write"
    }

    println("stopServer: Bytes sent = " +strconv.Itoa(iBytesSent) +sErmes)

    ohtFlusher, tCanFlush := ohtWriter.(http.Flusher)
    if tCanFlush {
        ohtFlusher.Flush()
    }

    go func() {
        time.Sleep(3e9)
        os.Exit(0)
    }()
}

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:


//*************
func stopServer(ohtWriter http.ResponseWriter, phtRequest *http.Request) {// Stop The Server
//*************

    var iBytesSent  int
    var oOsError    os.Error
    var sErmes  string

    println("Stopping Server")

    iBytesSent,oOsError = ohtWriter.Write([]byte("Message from server - server now stopped."))

    if oOsError != nil {
        sErmes = ". Error = " +oOsError.String()
    } else {
        sErmes = ". No error on write"
    }

    println("stopServer: Bytes sent = " +strconv.Itoa(iBytesSent) +sErmes)

    ohtFlusher, tCanFlush := ohtWriter.(http.Flusher)
    if tCanFlush {
        ohtFlusher.Flush()
    }

    go func() {
        time.Sleep(3e9)
        os.Exit(0)
    }()
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半﹌身腐败 2024-12-01 02:11:37

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

编辑:我想如果您控制应用程序中的所有 http.Handler,您可以保留进行中请求的计数(使用适当的线程同步),并将下面的代码修改为 a) 拒绝一旦调用“关闭”,就会建立新的连接 b) 在关闭之前等待所有正在进行的请求完成...

package main

import (
    "http"
    "os"
    "io"
    "log"
    "strconv"
)

func main() {
    http.HandleFunc("/", ServeHTTP)
    http.ListenAndServe(":8081", nil)
}

const responseString = "Shutting down\n"

func ServeHTTP(w http.ResponseWriter, req *http.Request) {
    w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    w.Header().Set("Content-Length", strconv.Itoa(len(responseString)))
    io.WriteString(w, responseString)

    f, canFlush := w.(http.Flusher)
    if canFlush {
        f.Flush()
    }

    conn, _, err := w.(http.Hijacker).Hijack()
    if err != nil {
        log.Fatalf("error while shutting down: %v", err)
    }

    conn.Close()

    log.Println("Shutting down")
    os.Exit(0)
}   

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...

package main

import (
    "http"
    "os"
    "io"
    "log"
    "strconv"
)

func main() {
    http.HandleFunc("/", ServeHTTP)
    http.ListenAndServe(":8081", nil)
}

const responseString = "Shutting down\n"

func ServeHTTP(w http.ResponseWriter, req *http.Request) {
    w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    w.Header().Set("Content-Length", strconv.Itoa(len(responseString)))
    io.WriteString(w, responseString)

    f, canFlush := w.(http.Flusher)
    if canFlush {
        f.Flush()
    }

    conn, _, err := w.(http.Hijacker).Hijack()
    if err != nil {
        log.Fatalf("error while shutting down: %v", err)
    }

    conn.Close()

    log.Println("Shutting down")
    os.Exit(0)
}   
妥活 2024-12-01 02:11:37

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

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

苯莒 2024-12-01 02:11:37

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

http://www.sergiotapia.me/how-to-停止你的http服务器/


package main

import (  
    "net/http"
    "os"

    "github.com/bmizerany/pat"
)

var mux = pat.New()

func main() {  
    mux.Get("/kill", http.HandlerFunc(kill))
    http.Handle("/", mux)
    http.ListenAndServe(":8080", nil)
}

func kill(w http.ResponseWriter, r *http.Request) {  
    os.Exit(0)
}

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

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


package main

import (  
    "net/http"
    "os"

    "github.com/bmizerany/pat"
)

var mux = pat.New()

func main() {  
    mux.Get("/kill", http.HandlerFunc(kill))
    http.Handle("/", mux)
    http.ListenAndServe(":8080", nil)
}

func kill(w http.ResponseWriter, r *http.Request) {  
    os.Exit(0)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文