亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

簡單的 Go 網絡服務器,在客戶端看不到響應

簡單的 Go 網絡服務器,在客戶端看不到響應

Go
慕田峪7331174 2021-11-15 16:13:28
我正在學習 Go,并且正在編寫一個簡單的 Web 服務器,它使用一個通道來限制并發請求的數量。服務器在控制臺打印日志條目,顯示它正在接收請求并處理它們,但是客戶端瀏覽器不顯示任何輸出。我試過添加響應編寫器的沖洗,但沒有幫助。作為菜鳥,我錯過了什么?感謝您提供任何提示/指示。這是代碼:package mainimport (    "fmt"    "html"    "net/http"    "time")// define a type to be used with our request channeltype clientRequest struct {    r *http.Request    w http.ResponseWriter}const (    MaxRequests int = 10)// the request channel, to limit the number of simultaneous requests being processedvar reqChannel chan *clientRequestfunc init() {    reqChannel = make(chan *clientRequest, MaxRequests)}func main() {    // create the server's handler    var ServeMux = http.NewServeMux()    ServeMux.HandleFunc("/", serveHandler)    // start pool of request handlers, all reading from the same channel    for i := 0; i < MaxRequests; i++ {        go processRequest(i)    }    // create the server object    s := &http.Server{        Addr:           ":8080",        Handler:        ServeMux,         // handler to invoke, http.DefaultServeMux if nil        ReadTimeout:    10 * time.Second, // maximum duration before timing out read of the request        WriteTimeout:   10 * time.Second, // maximum duration before timing out write of the response        MaxHeaderBytes: 1 << 20,          // maximum size of request headers, 1048576 bytes    }    // start the server    err := s.ListenAndServe()    if err != nil {        fmt.Println("Server failed to start: ", err)    }}func serveHandler(w http.ResponseWriter, r *http.Request) {    var newRequest = new(clientRequest)    newRequest.r = r    newRequest.w = w    reqChannel <- newRequest // send the new request to the request channel    fmt.Printf("Sent request to reqChannel for URL: %q\n", html.EscapeString(r.URL.Path))}
查看完整描述

2 回答

?
ibeautiful

TA貢獻1993條經驗 獲得超6個贊

服務器在serveHandler返回時關閉響應。


一種解決方法是阻塞serveHandler直到請求被處理。在以下代碼中,worker 關閉done以表示請求已完成。處理程序等待done關閉。


type clientRequest struct {

    r *http.Request

    w http.ResponseWriter

    done chan struct{}  // <-- add this line

}


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

   var newRequest = new(clientRequest)

   newRequest.r = r

   newRequest.w = w

   newRequest.done = make(chan struct{})


   reqChannel <- newRequest // send the new request to the request channel

   fmt.Printf("Sent request to reqChannel for URL: %q\n", html.EscapeString(r.URL.Path))

   <-newRequest.done  // wait for worker goroutine to complete

}


func processRequest(instanceNbr int) {

   fmt.Printf("processRequest started for instance #%d\n", instanceNbr)

   for theRequest := range reqChannel { // receive requests from the channel until it is closed

       fmt.Printf("Got request from reqChannel for URL: %q\n", html.EscapeString(theRequest.r.URL.Path))


       fmt.Fprintf(theRequest.w, "processRequest instance #%d: URL is %q", instanceNbr, html.EscapeString(theRequest.r.URL.Path))

       if f, ok := theRequest.w.(http.Flusher); ok {

           f.Flush()

       }

       close(theRequest.done)  // signal handler that request is complete

   }

}

如果目標是限制活動處理程序的數量,那么您可以使用通道作為計數信號量來限制活動處理程序 goroutine 的數量:


var reqChannel = make(chan struct{}, MaxRequests)


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

    reqChannel <- struct{}{} 

    // handle the request

    <-reqChannel

}

請注意,服務器在每個連接的 goroutine 中運行處理程序。


更簡單的是只編寫一個處理程序。大多數服務器不需要限制請求處理程序的并發性。


查看完整回答
反對 回復 2021-11-15
?
慕的地6264312

TA貢獻1817條經驗 獲得超6個贊

您的答案在net/http 代碼的這一部分:


    // HTTP cannot have multiple simultaneous active requests.[*]

    // Until the server replies to this request, it can't read another,

    // so we might as well run the handler in this goroutine.

    // [*] Not strictly true: HTTP pipelining.  We could let them all process

    // in parallel even if their responses need to be serialized.

    serverHandler{c.server}.ServeHTTP(w, w.req)

    if c.hijacked() {

        return

    }

    w.finishRequest()

后ServeHTTP返回時,請求完成。


所以你有幾個解決方案:

放棄你的工人模式并完成工作 serveHandler


在完成之前等待請求被完全處理serveHandler,如下所示:


(在我的本地測試)


type clientRequest struct {

    r *http.Request

    w http.ResponseWriter

    done chan struct{}

}


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

    var newRequest = new(clientRequest)

    newRequest.r = r

    newRequest.w = w

    newRequest.done = make(chan struct{})


    reqChannel <- newRequest // send the new request to the request channel

    fmt.Printf("Sent request to reqChannel for URL: %q\n", html.EscapeString(r.URL.Path))

    <-newRequest.done // wait for the worker to finish

}


func processRequest(instanceNbr int) {

    fmt.Printf("processRequest started for instance #%d\n", instanceNbr)

    for theRequest := range reqChannel { // receive requests from the channel until it is closed

        fmt.Printf("Got request from reqChannel for URL: %q\n", html.EscapeString(theRequest.r.URL.Path))


        // xxx this isn't working:

        fmt.Fprintf(theRequest.w, "processRequest instance #%d: URL is %q", instanceNbr, html.EscapeString(theRequest.r.URL.Path))

        if f, ok := theRequest.w.(http.Flusher); ok {

            f.Flush()

        }

        theRequest.done <- struct{}{}

    }

}


查看完整回答
反對 回復 2021-11-15
  • 2 回答
  • 0 關注
  • 277 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號