Senior
There is a large file with a million URLs, how to download them quickly without overloading the system and getting banned by the external server?
sobes.tech AI
Answer from AI
To quickly and safely load a million URLs without overloading the system and risking a ban from the server, you need to:
- Limit the number of concurrent requests — use a worker pool or semaphore to control parallelism.
- Implement rate limiting — restrict the request rate to a single server to not exceed the allowed limit.
- Handle errors and perform retries with exponential backoff.
- Use asynchronous or concurrent mechanisms in Go (goroutines + channels).
Example in Go with parallelism control and delays:
package main
import (
"bufio"
"fmt"
"net/http"
"os"
"sync"
"time"
)
func worker(urls <-chan string, wg *sync.WaitGroup, rateLimiter <-chan time.Time) {
defer wg.Done()
client := &http.Client{Timeout: 10 * time.Second}
for url := range urls {
<-rateLimiter // wait for permission to request
resp, err := client.Get(url)
if err != nil {
fmt.Printf("Error loading %s: %v\n", url, err)
continue
}
resp.Body.Close()
fmt.Printf("Loaded: %s\n", url)
}
}
func main() {
file, err := os.Open("urls.txt")
if err != nil {
panic(err)
}
defer file.Close()
urls := make(chan string, 100)
var wg sync.WaitGroup
// Rate limit: 10 requests per second
rateLimiter := time.Tick(100 * time.Millisecond)
// Launch 20 workers
for i := 0; i < 20; i++ {
wg.Add(1)
go worker(urls, &wg, rateLimiter)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
urls <- scanner.Text()
}
close(urls)
wg.Wait()
}
In this example:
- 20 parallel workers process URLs.
rateLimiterlimits request rate to 10 per second.- HTTP client has a timeout.
This approach allows efficient loading of many URLs without overloading the system or causing server-side blocking.