V-lang: Как отправлять +2500 HTTP-запросов в секунду?
Я планирую написать свой скребок с V, и мне нужно отправлять примерно ~2500 запросов в секунду, но я не могу понять, что я делаю не так, он должен отправляться одновременно, но сейчас это смертельно медленно. Такое ощущение, что я делаю что-то действительно не так, но не могу этого понять.
import net.http
import sync
import time
fn send_request(mut wg sync.WaitGroup) ?string {
start := time.ticks()
data := http.get('https://google.com')?
finish := time.ticks()
println('Finish getting time ${finish - start} ms')
wg.done()
return data.text
}
fn main() {
mut wg := sync.new_waitgroup()
for i := 0; i < 50; i++ {
wg.add(1)
go send_request(mut wg)
}
wg.wait()
}
Вывод:
...
Finish getting time 2157 ms
Finish getting time 2173 ms
Finish getting time 2174 ms
Finish getting time 2200 ms
Finish getting time 2225 ms
Finish getting time 2380 ms
Finish getting time 2678 ms
Finish getting time 2770 ms
V Версия: 0.1.29
Система: Ubuntu 20.04
3 ответа
Вы не делаете ничего плохого. Я получаю похожие результаты на нескольких языках разными способами. На многих сайтах есть программное обеспечение, ограничивающее скорость, которое предотвращает повторное чтение, подобное этому, вот с чем вы столкнулись.
Вы можете попробовать использовать каналы, когда они есть, но вы все равно столкнетесь с ограничителем скорости.
В последние недели я много работал в параллельных сферах V, и лучший способ, который я нашел, — это использовать процессор пула.
Отрывок из v/examples:
fn worker_fetch(mut p pool.PoolProcessor, cursor int, worker_id int) voidptr {
id := p.get_item[int](cursor)
resp := http.get('https://hacker-news.firebaseio.com/v0/item/${id}.json') or {
println('failed to fetch data from /v0/item/${id}.json')
return pool.no_result
}
story := json.decode(Story, resp.body) or {
println('failed to decode a story')
return pool.no_result
}
println('# ${cursor}) ${story.title} | ${story.url}')
return pool.no_result
}
// Fetches top HN stories in parallel, depending on how many cores you have
fn main() {
resp := http.get('https://hacker-news.firebaseio.com/v0/topstories.json') or {
println('failed to fetch data from /v0/topstories.json')
return
}
ids := json.decode([]int, resp.body) or {
println('failed to decode topstories.json')
return
}#[0..10]
mut fetcher_pool := pool.new_pool_processor(
callback: worker_fetch
)
// Note: if you do not call set_max_jobs, the pool will try to use an optimal
// number of threads, one per each core in your system, which in most
// cases is what you want anyway... You can override the automatic choice
// by setting the VJOBS environment variable too.
// fetcher_pool.set_max_jobs( 4 )
fetcher_pool.work_on_items(ids)
}
источник: https://github.com/vlang/v/blob/master/examples/news_fetcher.v
документы: https://modules.vosca.dev/standard_library/sync/pool.html .
Лучший способ отправить такое количество запросов на получение, он также использует так называемый запрос Head, он полагается на код состояния, а не на ответ, поскольку он не возвращает его. Это то, что ускоряет HTTP-запросы.