发送异步响应并且不会收到僵尸 pid

我的目标是 curl 客户端向 Go API 发送 http req,而 Go API 确实如此(1. 运行后台 shell,2. 立即向客户端返回响应,但 3. 继续在后台运行第 1 点服务器端命令)。问题是第 2 点没有立即返回给客户端,客户端仅在第 3 点完成后才得到响应


我试过:


import (

    "fmt"

    "io"

    "io/ioutil"

    "net/http"

    "os"

    "os/exec"

    "log"

    "strings"

    "flag"

    "strconv"

    "crypto/tls"

    "crypto/x509"

    "github.com/gorilla/handlers"

    "github.com/gorilla/mux"

    "github.com/go-ldap/ldap"

    "regexp"

    "errors"

    "encoding/base64"

    "time"

)

func insert(w http.ResponseWriter, r *http.Request) (error) {

fullcmd := fmt.Sprintf("/home/ec2-user/spark_home/bin/spark-submit %s", "dgs")

cmd := exec.Command("/bin/sh", "-c", fullcmd)

err4 := cmd.Start()


if err4 != nil {

    e1 := fmt.Sprintf("Error")

    l.Printf(e1)

    http.Error(w, e1, http.StatusInternalServerError)

    return err4

}  else {

    l.Printf("The data is being ingested asynchronously in the background \n")

    fmt.Fprintf(w, "request received. The data is being ingested asynchronously in the background \n")

    w.Header().Set("Content-Type", "text/plain")

    w.Write([]byte(fmt.Sprintf("request received. The data is being ingested asynchronously in the background \n")))

}


//wait for the spark command to finish, need to Wait() otherwise zombie/orphan pid is created

cmd.Wait()


//do bunch of other commands here that take 30+ seconds


l.Printf("success")

    return nil

}


r := mux.NewRouter()

    r.HandleFunc("/test", insert).Methods(http.MethodPost)

    http.Handle("/", r)  


    server := &http.Server{

        Addr:      ":" + strconv.Itoa(*port),

        Handler:    handlers.LoggingHandler(os.Stdout, http.DefaultServeMux),

        TLSConfig: tlsConfig,

    }     

    server.ListenAndServeTLS(TLS_SERVER_CERTFILE, TLS_SERVER_KEYFILE)


繁华开满天机
浏览 110回答 1
1回答

UYOU

当 HTTP 处理程序返回时,响应将完成,因此如果您想启动一个将继续的作业,您必须在单独的 goroutine 中执行此操作。您可以在 shell 进程启动后立即启动 goroutine,使用如下所示:func insert(w http.ResponseWriter, r *http.Request) (error) {...err4 := cmd.Start()if err4 != nil {  ...}  w.Header().Set("Content-Type", "text/plain")fmt.Fprintf(w, "request received. The data is being ingested asynchronously in the background \n")go func() {   cmd.Wait()   // Do other stuff}()return nil}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go