Получение нескольких URL-адресов одновременно с Hyper
Я пытаюсь адаптировать пример базового клиента Hyper для одновременного получения нескольких URL.
Вот код, который у меня сейчас есть:
extern crate futures;
extern crate hyper;
extern crate tokio_core;
use std::io::{self, Write};
use std::iter;
use futures::{Future, Stream};
use hyper::Client;
use tokio_core::reactor::Core;
fn get_url() {
let mut core = Core::new().unwrap();
let client = Client::new(&core.handle());
let uris: Vec<_> = iter::repeat("http://httpbin.org/ip".parse().unwrap()).take(50).collect();
for uri in uris {
let work = client.get(uri).and_then(|res| {
println!("Response: {}", res.status());
res.body().for_each(|chunk| {
io::stdout()
.write_all(&chunk)
.map_err(From::from)
})
});
core.run(work).unwrap();
}
}
fn main() {
get_url();
}
Похоже, что он не работает одновременно (это занимает много времени), я неправильно передаю работу ядру?
1 ответ
Решение
я неправильно даю работу ядру?
Да, вы даете один запрос ядру, а затем требует его выполнения перед началом следующего запроса. Вы взяли асинхронный код и заставили его быть последовательным.
Вам нужно дать реактору единое будущее, которое будет выполнять разные виды параллельной работы:
extern crate futures;
extern crate hyper;
extern crate tokio_core;
use std::io::{self, Write};
use std::iter;
use futures::{stream, Future, Stream};
use hyper::Client;
use tokio_core::reactor::Core;
fn get_url() {
let mut core = Core::new().unwrap();
let client = Client::new(&core.handle());
let uri = "http://httpbin.org/ip".parse().unwrap();
let uris = iter::repeat(uri).take(50);
let work = stream::iter_ok(uris)
.map(|uri| client.get(uri))
.buffer_unordered(1)
.and_then(|res| {
println!("Response: {}", res.status());
res.body().concat2().from_err()
})
.for_each(|body| {
io::stdout().write_all(&body).map_err(From::from)
});
core.run(work).unwrap();
}
fn main() {
get_url();
}
С buffer_unordered
установить в 1:
real 0m1.486s
user 0m0.161s
sys 0m0.168s
И установите на 10:
real 0m0.871s
user 0m0.159s
sys 0m0.170s