J'essaie de faire n obtenir des demandes de n, mais mon code fonctionne pour 8 URL, mais 10 Toujours pile sans problème.
Je suis nouveau à parcourir, je ne peux pas comprendre le problème. P> J'essaie d'écrire une application pour battre l'application .NET avec la même tâche. P>
Pourriez-vous suggérer ce qui ne va pas? P>
package main import ( "fmt" "io/ioutil" "log" "net/http" "os" //"bufio" "time" ) type HttpResponse struct { url string response *http.Response err error } func main() { fmt.Println("Hello, world3.") var urls []string = []string{ "www.webmagnat.ro", "nickelfreesolutions.com", "scheepvaarttelefoongids.nl", "tursan.net", "plannersanonymous.com", "saltstack.com", "deconsquad.com", "migom.com", "tjprc.org", "worklife.dk", "food-hub.org"} start := time.Now() results := asyncHttpGets(urls) f, err := os.Create("test.txt") if err != nil { fmt.Println(err) return } for _, result := range results { fmt.Printf("%s status: %s\n", result.url, result.response.Status) l, err := f.WriteString(result.url+"\n") if err != nil { fmt.Println(err) f.Close() return } _ = l } t := time.Now() elapsed := t.Sub(start) fmt.Printf("Ellipsed: %s\n", elapsed) err = f.Close() if err != nil { fmt.Println(err) return } fmt.Println("Buy, world2.") } func asyncHttpGets(urls []string) []*HttpResponse { ch := make(chan *HttpResponse, len(urls)) // buffered responses := []*HttpResponse{} for _, url := range urls { go func(url string) { fmt.Printf("Fetching %s \n", url) resp, err := http.Get("http://" + url) if err != nil { fmt.Printf("Failed to fetch %s\n", err) return } defer resp.Body.Close() if resp.StatusCode == http.StatusOK { fmt.Printf("HTTP Response Status : %v", resp.StatusCode) bodyBytes, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) } bodyString := string(bodyBytes) fmt.Printf("HTTP Response Content Length : %v\n", len(bodyString)) } ch <- &HttpResponse{url, resp, err} }(url) } for { select { case r := <-ch: fmt.Printf("%s was fetched\n", r.url) responses = append(responses, r) if len(responses) == len(urls) { return responses } case <-time.After(50 * time.Millisecond): fmt.Printf(".") } } return responses }
4 Réponses :
Vous devez ajouter la construction de groupe d'attente, car lorsque deux threads exécutent, le fil principal se termine. Voir: https://yourbasic.org/golang/wait-for-goroutines-waitgroup /
Cela ne fonctionne pas, il a coincé à un endroit. Vous ne pouvez pas voir où utilisez-vous wg.done
@Mediator Il n'y a aucun moyen de faire le travail pour vous. J'ai souligné des problèmes avec la raison et j'ai fourni un lien avec un exemple de WG
Vous pouvez utiliser la bibliothèque suivante:
https://github.com/alessiosavi/request P> C'est développé pour résoudre le L'idée est d'allouer une liste de demande, que de les envoyer avec un facteur "parallèle" configurable qui permettent de Exécuter uniquement la demande "n" à l'heure. p> initialiser les demandes (vous avez déjà un ensemble d'URL) p> à ce stade, nous avons une liste contenant les demandes qui doivent être envoyé.
Envoyons-les en parallèle! P> Vous pouvez trouver un exemple d'utilisation dans exemple dossier du référentiel. p> spoiler EM> P> P> P> < BlockQuote Classe = "Spoiler">
je suis l'auteur de cette petite bibliothèque em> p>
blockQuote> p> à de nombreux fichiers ouverts code> traiter avec des demandes parallèles. p>
Le premier problème ici est que vous ne retournez pas de réponse dans le cas d'une erreur, le Démarrer en ajoutant un alors vous pouvez aller sur les réponses jusqu'à ce que tout Les goroutines exceptionnelles sont effectuées p> Vous devez alors décider de la manière de gérer les réponses, allez-vous les lire dans l'appel concomitant ou renvoyer leur corps non lié. Puisque vous voudrez toujours em> tenter de consommer les corps si vous souhaitez réutiliser la connexion et que vous avez différé le corps enfin que vous voudrez enfin avoir une sorte de délai d'attente pour le client (probablement à l'aide d'un contexte code> code>) et placez une limite sur le nombre des demandes concurrentes étant faites. p> p> len (réponses) == len (URL) code> est susceptible de ne jamais correspondre, forçant votre boucle pour continuer pour toujours.
sync.waitgroup code> pour les demandes concurrentes p>
.frose () code>, ceci actuellement doit arriver dans le même appel de la fonction. Vous pouvez soit modifier le type
httpreesponse code> pour rendre cela possible, ou remplacer le
respect.body code> avec un tampon contenant la réponse. P>
Ça marche. Merci. Mais ne fonctionne toujours pas avec N> 1000.
@Mediator, c'est pourquoi j'ai dit que vous devez limiter la concurrence et que vous assurer des demandes peut trop
Oui, j'ai trouvé une solution Github.com/remeh/sizedwaitgroup mais ne fonctionne toujours pas pour 1000 demande et 8 la taille de la limite de la piscine ne peut pas fonctionner aussi. Maintenant, j'ai un problème étrange '2020/02/11 10:44:19 EOF inattendu'
@Mediator: Ce n'est pas vraiment lié aux problèmes de concurrence que vous avez montrés ici. Une connexion inopinément fermée pour une raison quelconque, mais ce n'est pas quelque chose que nous pouvons diagnostiquer de cet exemple.
Le problème est que vous retournez en cas d'erreur sans écrire sur le canal. Voir votre si err! = Nil {retour} code> instruction. Parce que vous n'écrivez pas à la chaîne, le
len (réponses) == len (URL) code> L'instruction ne peut jamais être vraie.
go func(url string) {
fmt.Printf("Fetching %s \n", url)
resp, err := http.Get("http://" + url)
if err != nil {
fmt.Printf("Failed to fetch %s\n", err)
return
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
fmt.Printf("HTTP Response Status : %v", resp.StatusCode)
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
bodyString := string(bodyBytes)
fmt.Printf("HTTP Response Content Length : %v\n", len(bodyString))
}
ch <- &HttpResponse{url, resp, err}
}(url)