0

次のコードがあります

package main

import (
    "bytes"
    "fmt"
    "github.com/gorilla/mux"
    "log"
    "net/http"
    "time"
    "io"
    httprouter "github.com/fasthttp/router"
    "github.com/valyala/fasthttp"
)

func main() {
    router := mux.NewRouter().StrictSlash(true)
    /*router := NewRouter()*/
    router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        _, _ = fmt.Fprintf(w, "Hello!!!")
    })

    router.HandleFunc("/{name}", func(w http.ResponseWriter, r *http.Request) {
        vars := mux.Vars(r)
        prepare(w, r, vars["name"])

    }).Methods("POST")

    log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", 8080), router))

}

//using fast http 
func _() {
    router := httprouter.New()
    router.GET("/", func(w *fasthttp.RequestCtx) {
        _, _ = fmt.Fprintf(w, "Hello!!!")
    })
    router.POST("/:name", func(w *fasthttp.RequestCtx) {
        prepareRequest(w, w.UserValue("name").(string))
    })

    log.Fatal(fasthttp.ListenAndServe(fmt.Sprintf(":%d", 8080), router.Handler))
}

//func prepare(w *fasthttp.RequestCtx, name string)
func prepare(w http.ResponseWriter, r *http.Request, name string) {
    //other part of the code and call to goroutine
    var urls []string
    //lets say all the url loaded, call the go routine func and wait for channel to respond and then proceed with the response of all url
    results := callUrls(urls) //there are 10 urls atleast to call simultaneously for each request everytime
    process(w, results)
}

type Response struct {
    status          int
    url             string
    body            string
}

func callUrls(urls []string) []*Response {
    ch := make(chan *Response, len(urls))
    for _, url := range urls {
        go func(url string) {
            //http post on url,
            //base on status code of url call, add to status code
            //some thing like

            req, err := http.NewRequest("POST", url, bytes.NewBuffer(somePostData))
            req.Header.Set("Content-Type", "application/json")
            req.Close = true

            client := &http.Client{
                Timeout: time.Duration(time.Duration(100) * time.Millisecond),
            }

            response, err := client.Do(req)

            //Using fast http client
            /*req := fasthttp.AcquireRequest()
                req.SetRequestURI(url)
                req.Header.Set("Content-Type", "application/json")
                req.Header.SetMethod("POST")
                req.SetBody(somePostData)

                response := fasthttp.AcquireResponse()
                client := &fasthttp.Client{
                    ReadTimeout: time.Duration(time.Duration(100) * time.Millisecond),
                }
            err := client.Do(req, response)*/

            if err != nil {
                //do other thing with the response received
                _, _ = io.Copy(ioutil.Discard, response.Body)
                _ = response.Body.Close()
            } else {
                //success response
                _, _ = io.Copy(ioutil.Discard, response.Body)
                _ = response.Body.Close()

                body, _:= ioutil.ReadAll(response.Body)
                strBody := string(body)
                strBody = strings.Replace(strBody, "\r", "", -1)
                strBody = strings.Replace(strBody, "\n", "", -1)    
            }

            // return to channel accordingly
            ch <- &Response{200, "url", "response body"}

        }(url)
    }
    var results []*Response
    for {
        select {
        case r := <-ch:
            results = append(results, r)
            if len(results) == len(urls) {
                //Done
                close(ch)
                return results
            }
        }
    }
}

//func process(w *fasthttp.RequestCtx,results []*Response){
func process(w http.ResponseWriter, results []*Response){
    fmt.Println("response", "response body")
}

マルチコア CPU で少数のリクエストを処理した後 (1 秒あたり約 4000 ~ 6000 のリクエストがあります)、あまりにも多くのファイルを開くエラーと応答時間が発生し、CPU が制限を超えます。(いくつかの文字を置き換えるために数回バイトを文字列に変換するため、CPU が高くなる可能性がありますか?何か提案はありますか?)

req/res body を閉じる、および/または sysctl または ulimit をより高い値に設定することに関する他の質問を見ました。それらに従いましたが、常にエラーが発生します。

サーバーで構成します。

/etc/sysctl.conf net.ipv4.tcp_tw_recycle = 1
open files (-n) 65535

ミリ秒単位で応答するコードが必要ですが、CPU が高い場合は最大 50 秒かかります。

net/http と fast http の両方を試しましたが、改善されませんでした。私の Node.js リクエスト npm は、同じサーバー上ですべてを完璧に処理します。これらの接続または改善に必要なコードの変更を処理する最善の方法は何でしょう。

4

1 に答える 1