Browse Source

New async hyper + multithreading (#2510)

Alexander Polakov 8 years ago
parent
commit
c8a551c4ae
2 changed files with 73 additions and 18 deletions
  1. 12 3
      frameworks/Rust/hyper/Cargo.toml
  2. 61 15
      frameworks/Rust/hyper/src/main.rs

+ 12 - 3
frameworks/Rust/hyper/Cargo.toml

@@ -1,7 +1,16 @@
 [package]
 name = "hello"
-version = "0.1.0"
-authors = ["Steve Klabnik <[email protected]>"]
+version = "0.2.0"
+authors = ["Steve Klabnik <[email protected]>", "Alexander Polyakov <[email protected]>"]
 
 [dependencies]
-hyper="0.9.6"
+net2 = "0.2"
+futures = "0.1"
+pretty_env_logger = "0.1"
+log = "0.3.6"
+tokio-core = "0.1"
+num_cpus = "1.2"
+
+[dependencies.hyper]
+git = "https://github.com/hyperium/hyper/"
+rev = "39a53fcd3364634125dafcf4d7a1d191241a7ff0"

+ 61 - 15
frameworks/Rust/hyper/src/main.rs

@@ -1,24 +1,70 @@
+extern crate futures;
 extern crate hyper;
+extern crate pretty_env_logger;
+#[macro_use]
+extern crate log;
+extern crate net2;
+extern crate tokio_core;
+extern crate num_cpus;
 
-use hyper::server::{Server, Request, Response};
-use hyper::uri::RequestUri;
-use hyper::header::ContentType;
-use hyper::header;
+use hyper::{Get, StatusCode};
+use hyper::header::{ContentLength, ContentType};
+use hyper::server::{Server, Service, Request, Response};
 
-const HELLO_WORLD: &'static [u8; 13] = b"Hello, World!";
+use net2::TcpBuilder;
+use net2::unix::UnixTcpBuilderExt;
+use tokio_core::net::TcpListener;
 
-fn main() {
-    Server::http("0.0.0.0:8080").unwrap().handle(handler).unwrap();
+static HELLOWORLD: &'static [u8] = b"Hello, world!";
+
+#[derive(Clone, Copy)]
+struct TechEmpower;
+
+impl Service for TechEmpower {
+    type Request = Request;
+    type Response = Response;
+    type Error = hyper::Error;
+    type Future = ::futures::Finished<Response, hyper::Error>;
+
+    fn call(&self, req: Request) -> Self::Future {
+        ::futures::finished(match (req.method(), req.path()) {
+            (&Get, "/plaintext") => {
+                use hyper::mime::{Mime,TopLevel,SubLevel,Attr,Value};
+                Response::new()
+                    .with_header(ContentLength(HELLOWORLD.len() as u64))
+                    .with_header(ContentType(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])))
+                    .with_body(HELLOWORLD)
+	    },
+            _ => {
+                Response::new()
+                    .with_status(StatusCode::NotFound)
+            }
+        })
+    }
 }
 
-fn handler(req: Request, mut res: Response) {
-    match (req.method, req.uri) {
-        (hyper::Get, RequestUri::AbsolutePath(ref path)) if path == "/plaintext" => {
-            res.headers_mut().set(ContentType("text/plain".parse().unwrap()));
-            res.headers_mut().set(header::Server("Hyper".to_owned()));
 
-            res.send(HELLO_WORLD).unwrap();
-        }
-        _ => (),
+fn main() {
+    use std::net::SocketAddr;
+    pretty_env_logger::init().unwrap();
+    let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
+    let mut threads = vec![];
+    for i in 0..num_cpus::get_physical() {
+        use std::thread;
+        let i = i;
+        let handle = thread::spawn(move|| {
+            let (listening, server) = Server::standalone(|tokio| {
+		    let listener = TcpBuilder::new_v4()?.reuse_port(true)?.bind(addr)?.listen(10000)?;
+		    let addr = try!(listener.local_addr());
+		    let listener = try!(TcpListener::from_listener(listener, &addr, tokio));
+		    Server::new(listener.incoming(), addr).handle(|| Ok(TechEmpower), tokio)
+	    }).unwrap();
+            println!("Listening {} on http://{}", i, listening);
+            server.run();
+        });
+        threads.push(handle);
+    }
+    for t in threads {
+        t.join().unwrap();
     }
 }