我正在尝试创建一个http客户端程序,它将发出许多http GET请求。我正在使用缓冲通道来限制并发请求的数量。
当我运行程序时,我得到
Get http://198.18.96.213/: dial tcp 198.18.96.213:80: too many open files
这是我的程序:
package main import ( "fmt" "net/http" "time" ) func HttpGets(numRequests int, numConcurrent int, url string) map[int]int { // I want number of requests with each status code responseStatuses := map[int]int { 100: 0, 101 : 0, 102 : 0, 200 : 0, 201 : 0, 202 : 0, 203 : 0, 204 : 0, 205 : 0, 206 : 0, 207 : 0, 208 : 0, 226 : 0, 300 : 0, 301 : 0, 302 : 0, 303 : 0, 304 : 0, 305 : 0, 306 : 0, 307 : 0, 308 : 0, 400 : 0, 401 : 0, 402 : 0, 403 : 0, 404 : 0, 405 : 0, 406 : 0, 407 : 0, 408 : 0, 409 : 0, 410 : 0, 411 : 0, 412 : 0, 413 : 0, 414 : 0, 415 : 0, 416 : 0, 417 : 0, 421 : 0, 422 : 0, 423 : 0, 424 : 0, 425 : 0, 426 : 0, 427 : 0, 428 : 0, 429 : 0, 430 : 0, 431 : 0, 500 : 0, 501 : 0, 502 : 0, 503 : 0, 504 : 0, 505 : 0, 506 : 0, 507 : 0, 508 : 0, 509 : 0, 510 : 0, 511 : 0, } reqsDone := 0 ch := make(chan *http.Response, numConcurrent) for i := 0; i < numRequests; i++ { go func(url string) { client := &http.Client{} req, reqErr := http.NewRequest("GET", url, nil) if reqErr != nil { fmt.Println(reqErr) } // adding connection:close header hoping to get rid // of too many files open error. Found this in http://craigwickesser.com/2015/01/golang-http-to-many-open-files/ req.Header.Add("Connection", "close") resp, err := client.Do(req) if (err !=nil) { fmt.Println(err) } ch <- resp }(url) } for { select { case r := <-ch: reqsDone += 1 // probably needs a lock? status := r.StatusCode if _, ok := responseStatuses[status]; ok { responseStatuses[status] += 1 } else { responseStatuses[status] = 1 } r.Body.Close() // trying to close body hoping to get rid of too many files open error if (reqsDone == numRequests) { return responseStatuses } } } return responseStatuses } func main() { var numRequests, numConcurrent = 500, 10 url := "http://198.18.96.213/" beginTime := time.Now() results := HttpGets(numRequests, numConcurrent, url) endTime := time.Since(beginTime) fmt.Printf("Total time elapsed: %s\n", endTime) for k,v := range results { if v!=0 { fmt.Printf("%d : %d\n", k, v) } } }
如何确保文件/足球已关闭,以便在发出多个请求时不会出现此错误?
基本上,您生成了数百个goroutine,这些goroutine将在块关闭之前开始连接。
这是一个快速(非常丑陋)的代码:
var ( responseStatuses = make(map[int]int, 63) reqsDone = 0 urlCh = make(chan string, numConcurrent) ch = make(chan *http.Response, numConcurrent) ) log.Println(numConcurrent, numRequests, len(responseStatuses)) for i := 0; i < numConcurrent; i++ { go func() { for url := range urlCh { client := &http.Client{} req, reqErr := http.NewRequest("GET", url, nil) if reqErr != nil { fmt.Println(reqErr) } // adding connection:close header hoping to get rid // of too many files open error. Found this in http://craigwickesser.com/2015/01/golang-http-to-many-open-files/ req.Header.Add("Connection", "close") resp, err := client.Do(req) if err != nil { fmt.Println(err) } ch <- resp } }() } go func() { for i := 0; i < numRequests; i++ { urlCh <- url } close(urlCh) }()
playground