Skip to content

Commit 8b644c1

Browse files
committed
feat(server): add Server::run_threads to run on multiple threads
1 parent eaa22cd commit 8b644c1

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ iovec = "0.1"
2929
language-tags = "0.2"
3030
log = "0.4"
3131
mime = "0.3.2"
32+
net2 = "0.2"
3233
percent-encoding = "1.0"
3334
relay = "0.1"
3435
time = "0.1"

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ extern crate iovec;
2828
extern crate language_tags;
2929
#[macro_use] extern crate log;
3030
pub extern crate mime;
31+
extern crate net2;
3132
#[macro_use] extern crate percent_encoding;
3233
extern crate relay;
3334
extern crate time;

src/server/mod.rs

+87-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ use std::io;
1414
use std::marker::PhantomData;
1515
use std::net::SocketAddr;
1616
use std::rc::{Rc, Weak};
17+
use std::sync::Arc;
18+
use std::thread;
1719
use std::time::Duration;
1820

1921
use futures::task::{self, Task};
2022
use futures::future::{self};
2123
use futures::{Future, Stream, Poll, Async};
24+
use net2;
2225

2326
#[cfg(feature = "compat")]
2427
use http;
@@ -60,7 +63,7 @@ pub struct Http<B = ::Chunk> {
6063
keep_alive: bool,
6164
pipeline: bool,
6265
sleep_on_errors: bool,
63-
_marker: PhantomData<B>,
66+
_marker: PhantomData<fn() -> B>,
6467
}
6568

6669
/// An instance of a server created through `Http::bind`.
@@ -178,7 +181,7 @@ impl<B: AsRef<[u8]> + 'static> Http<B> {
178181
{
179182
let core = try!(Core::new());
180183
let handle = core.handle();
181-
let listener = try!(TcpListener::bind(addr, &handle));
184+
let listener = try!(thread_listener(addr, &handle));
182185

183186
Ok(Server {
184187
new_service: new_service,
@@ -445,6 +448,88 @@ impl<S, B> Server<S, B>
445448
}
446449
}
447450

451+
452+
impl<S, B> Server<S, B>
453+
where S: NewService<Request = Request, Response = Response<B>, Error = ::Error> + Send + Sync + 'static,
454+
B: Stream<Error=::Error> + 'static,
455+
B::Item: AsRef<[u8]>,
456+
{
457+
/// Run the server on multiple threads.
458+
#[cfg(unix)]
459+
pub fn run_threads(self, threads: usize) {
460+
assert!(threads > 0, "threads must be more than 0");
461+
462+
let Server {
463+
protocol,
464+
new_service,
465+
reactor,
466+
listener,
467+
shutdown_timeout,
468+
} = self;
469+
470+
let new_service = Arc::new(new_service);
471+
let addr = listener.local_addr().unwrap();
472+
473+
let threads = (1..threads).map(|i| {
474+
let protocol = protocol.clone();
475+
let new_service = new_service.clone();
476+
thread::Builder::new()
477+
.name(format!("hyper-server-thread-{}", i))
478+
.spawn(move || {
479+
let reactor = Core::new().unwrap();
480+
let listener = thread_listener(&addr, &reactor.handle()).unwrap();
481+
let srv = Server {
482+
protocol,
483+
new_service,
484+
reactor,
485+
listener,
486+
shutdown_timeout,
487+
};
488+
srv.run().unwrap();
489+
})
490+
.unwrap()
491+
}).collect::<Vec<_>>();
492+
493+
let srv = Server {
494+
protocol,
495+
new_service,
496+
reactor,
497+
listener,
498+
shutdown_timeout,
499+
};
500+
srv.run().unwrap();
501+
502+
for thread in threads {
503+
thread.join().unwrap();
504+
}
505+
}
506+
}
507+
508+
fn thread_listener(addr: &SocketAddr, handle: &Handle) -> io::Result<TcpListener> {
509+
let listener = match *addr {
510+
SocketAddr::V4(_) => try!(net2::TcpBuilder::new_v4()),
511+
SocketAddr::V6(_) => try!(net2::TcpBuilder::new_v6()),
512+
};
513+
try!(reuse_port(&listener));
514+
try!(listener.reuse_address(true));
515+
try!(listener.bind(addr));
516+
listener.listen(1024).and_then(|l| {
517+
TcpListener::from_listener(l, addr, handle)
518+
})
519+
}
520+
521+
#[cfg(unix)]
522+
fn reuse_port(tcp: &net2::TcpBuilder) -> io::Result<()> {
523+
use net2::unix::*;
524+
try!(tcp.reuse_port(true));
525+
Ok(())
526+
}
527+
528+
#[cfg(not(unix))]
529+
fn reuse_port(_tcp: &net2::TcpBuilder) -> io::Result<()> {
530+
Ok(())
531+
}
532+
448533
impl<S: fmt::Debug, B: Stream<Error=::Error>> fmt::Debug for Server<S, B>
449534
where B::Item: AsRef<[u8]>
450535
{

0 commit comments

Comments
 (0)