使用goroutines时HTTP GET请求的时间响应

时间:2014-05-10 16:20:09

标签: go goroutine

我有一个简单的代码,可以为文本文件(url_list.txt)中列出的每个URL打印GET响应时间。

当按顺序触发请求时,返回的时间对应于各个URL的预期响应时间。

但是,当同时执行相同的代码时,返回的响应时间通常高于预期。

在调用http.Get(url)之前捕获的 time_start 似乎不是实际发送请求的时间。我想http.Get(url)的执行在某种程度上排队。

使用goroutines时有更好的方法来捕获网址响应时间吗?

这是我的代码:

顺序请求:

package main

import ("fmt"
        "net/http"
        "io/ioutil"
        "time"
        "strings"
)

func get_resp_time(url string) {
        time_start := time.Now()
        resp, err := http.Get(url)
        if err != nil {
            panic(err)
        }
        defer resp.Body.Close()
        fmt.Println(time.Since(time_start), url)
}

func main() {
    content, _ := ioutil.ReadFile("url_list.txt")
    urls := strings.Split(string(content), "\n")

    for _, url := range urls {
        get_resp_time(url)
        //go get_resp_time(url)
    }

    //time.Sleep(20 * time.Second)
}

并发请求:

package main

import ("fmt"
        "net/http"
        "io/ioutil"
        "time"
        "strings"
)

func get_resp_time(url string) {
        time_start := time.Now()
        resp, err := http.Get(url)
        if err != nil {
            panic(err)
        }
        defer resp.Body.Close()
        fmt.Println(time.Since(time_start), url)
}

func main() {
    content, _ := ioutil.ReadFile("url_list.txt")
    urls := strings.Split(string(content), "\n")

    for _, url := range urls {
        //get_resp_time(url)
        go get_resp_time(url)
    }

    time.Sleep(20 * time.Second)
} 

1 个答案:

答案 0 :(得分:5)

您正在立即启动所有请求。如果文件中有1000个url,那么你一次启动1000个go例程。这可能会起作用,但可能会给您带来有关超出套接字或文件句柄的错误。我建议一次启动有限数量的提取,如下面的代码所示。

这也应该有助于时机。

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "strings"
    "sync"
    "time"
)

func get_resp_time(url string) {
    time_start := time.Now()
    resp, err := http.Get(url)
    if err != nil {
        log.Printf("Error fetching: %v", err)
    }
    defer resp.Body.Close()
    fmt.Println(time.Since(time_start), url)
}

func main() {
    content, _ := ioutil.ReadFile("url_list.txt")
    urls := strings.Split(string(content), "\n")

    const workers = 25

    wg := new(sync.WaitGroup)
    in := make(chan string, 2*workers)

    for i := 0; i < workers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for url := range in {
                get_resp_time(url)
            }
        }()
    }

    for _, url := range urls {
        if url != "" {
            in <- url
        }
    }
    close(in)
    wg.Wait()
}