gpt4 book ai didi

go - 多个Http.Get随机挂起

转载 作者:数据小太阳 更新时间:2023-10-29 03:34:20 27 4
gpt4 key购买 nike

我正在尝试学习 Golang 并进行了一个简单的项目来调用所有 craigslist 城市并查询它们以进行特定搜索。在下面的代码中,我删除了 listingmap 中的所有链接,但那里有超过 400 个链接。所以循环相当大。我认为这将是一个很好的测试,可以将我所学的知识付诸应用,但我遇到了一个奇怪的问题。

有些时候,大多数 Http.Get() 都没有从服务器获得响应,而其他时候却毫无问题地获得了所有响应。所以我开始添加打印件来显示有多少错误我们恢复了,有多少成功通过了。此外,在运行时它会随机挂起并且从不响应。该程序没有卡住,但该站点只是坐在那里尝试加载,而终端没有显示任何事件。

我通过在恢复后推迟清理来确保我的响应主体已关闭,但它似乎仍然不起作用。有没有什么东西让任何人跳出来,也许我错过了?

提前谢谢大家!

package main

import (
"fmt"
"net/http"
"html/template"
"io/ioutil"
"encoding/xml"
"sync"
)

var wg sync.WaitGroup

var locationMap = map[string]string {"https://auburn.craigslist.org/": "auburn "...}

var totalRecovers int = 0
var successfulReads int = 0

type Listings struct {
Links []string `xml:"item>link"`
Titles []string `xml:"item>title"`
Descriptions []string `xml:"item>description"`
Dates []string `xml:"item>date"`
}

type Listing struct {
Title string
Description string
Date string
}

type ListAggPage struct {
Title string
Listings map[string]Listing
SearchRequest string
}

func cleanUp(link string) {
defer wg.Done()
if r:= recover(); r!= nil {
totalRecovers++
// recoverMap <- link
}
}

func cityRoutine(c chan Listings, link string) {
defer cleanUp(link)

var i Listings
address := link + "search/sss?format=rss&query=motorhome"
resp, rErr := http.Get(address)
if(rErr != nil) {
fmt.Println("Fatal error has occurs while getting response.")
fmt.Println(rErr);
}

bytes, bErr := ioutil.ReadAll(resp.Body)
if(bErr != nil) {
fmt.Println("Fatal error has occurs while getting bytes.")
fmt.Println(bErr);
}
xml.Unmarshal(bytes, &i)
resp.Body.Close()
c <- i
successfulReads++
}

func listingAggHandler(w http.ResponseWriter, r *http.Request) {
queue := make(chan Listings, 99999)
listing_map := make(map[string]Listing)

for key, _ := range locationMap {
wg.Add(1)
go cityRoutine(queue, key)
}

wg.Wait()
close(queue)

for elem := range queue {
for index, _ := range elem.Links {
listing_map[elem.Links[index]] = Listing{elem.Titles[index * 2], elem.Descriptions[index], elem.Dates[index]}
}
}

p := ListAggPage{Title: "Craigslist Aggregator", Listings: listing_map}
t, _ := template.ParseFiles("basictemplating.html")
fmt.Println(t.Execute(w, p))

fmt.Println("Successfully loaded: ", successfulReads)
fmt.Println("Recovered from: ", totalRecovers)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "<h1>Whoa, Go is neat!</h1>")
}

func main() {
http.HandleFunc("/", indexHandler)
http.HandleFunc("/agg/", listingAggHandler)
http.ListenAndServe(":8000", nil)
}

最佳答案

我很难找到我正在阅读的关于此的 golang 邮件列表讨论,但您通常不想打开数百个请求。这里有一些信息:How Can I Effectively 'Max Out' Concurrent HTTP Requests?

Craigslist 也可能只是限制您的速率。无论哪种方式,我建议将并发请求限制在 20 个左右,这里是对 listingAggHandler 的快速更新。

queue := make(chan Listings, 99999)
listing_map := make(map[string]Listing)

request_queue := make(chan string)
for i := 0; i < 20; i++ {
go func() {
for {
key := <- request_queue
cityRoutine(queue, key)
}
}()
}

for key, _ := range locationMap {
wg.Add(1)
request_queue <- key
}

wg.Wait()
close(request_queue)
close(queue)

应用程序应该仍然非常快。我也同意对你的问题的其他评论。也会尽量避免在全局范围内投入太多。

您还可以通过使用请求池中的 WaitGroup 来稍微修饰我的更改,并让每个 goroutine 自行清理并减少 WaitGroup 。这会限制一些全局范围。

关于go - 多个Http.Get随机挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52668444/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com