grpc-rust icon indicating copy to clipboard operation
grpc-rust copied to clipboard

Start Http2Server manually

Open overvenus opened this issue 7 years ago • 3 comments

Hello @stepancheg

I saw Http2Server::new() creates a Http2Server and start it immediately.

impl Http2Server {
    pub fn new<S>(port: u16, service: S) -> Http2Server
        where S : HttpService
    {
        let listen_addr = ("::", port).to_socket_addrs().unwrap().next().unwrap();

        let (get_from_loop_tx, get_from_loop_rx) = mpsc::channel();

        let state: Arc<Mutex<HttpServerState>> = Default::default();

        let state_copy = state.clone();

        let join_handle = thread::spawn(move || { // Http2Server starts at here.
            run_server_event_loop(listen_addr, state_copy, service, get_from_loop_tx);
        });

        let loop_to_server = get_from_loop_rx.recv().unwrap();

        Http2Server {
            state: state,
            loop_to_server: loop_to_server,
            thread_join_handle: Some(join_handle),
        }
    }
    // ...
}

Could you separate run_server_event_loop from new? Then the following code could be less confusing I think.

Confuse me :confused::

fn main() {
    let _server = LongTestsAsyncServer::new(23432, LongTestsServerImpl {});
    // Why does the server magically started?
    loop {
        thread::park();
    }
}

Much clear :grinning::

fn main() {
    let server = LongTestsAsyncServer::new(23432, LongTestsServerImpl {});
    server.run()
}

Thanks!

overvenus avatar Jan 04 '17 04:01 overvenus

I'm not sure it is better. API you propose have some drawbacks.

For example: does run function ever exit? If run exists, am I allowed to call it again? How should I shutdown my server?

What if I need to start several servers? Now I can write:

fn main() {
    let server1 = Server1::new(..);
    let server2 = Server2::new(..)

    wait_for_shutdown_signal(); // for SIGTERM or from control socket

    // And that's it: both servers shut down.
}

It is harder to use when server is executed in run function.

stepancheg avatar Jan 10 '17 03:01 stepancheg

I think creating the server first and then running it makes more sense. We can see that mio, tokio-proto, hyper all create first then run.

What if I need to start several servers?

I don't think it is common to start multi servers in production. Listening one address for one server is enough, and we only need to register multi handlers for the server.

siddontang avatar Jan 10 '17 06:01 siddontang

does run function ever exit?

It never exits.

If run exists, am I allowed to call it again?

No, if it exists, something must have gone wrong. In fact, I want it panic immediately, you know, fail fast.

What if I need to start several servers?

A simple solution would look like:

fn main() {
    let server1 = Server1::new(..);
    let server2 = Server2::new(..);

    thread::spawn(move || {
        server1.run();
    });

    thread::spawn(move || {
        server2.run();
    });

    // ...

    // So how do we shutdown servers?
}

In order to shutdown servers, they need a channel.

pub struct Http2Server {
    listen_addr: Mutex<SocketAddr>,
    shutdown_tx: mpsc::Sender<()>,
    shutdown_rx: Mutex<Option<mpsc::Receiver<()>>>,
    state: Arc<Mutex<HttpServerState>>,
}

impl Http2Server {
    pub fn run(&self) {
        let shutdown_rx = {
            let mut shutdown_rx = self.shutdown_rx.lock().unwrap();
            shutdown_rx.take().expect("server is already running or stopped")
        };

        // listen and serve ...
    }

    pub fn shutdown_tx(&self) -> mpsc::Sender<()> {
        self.shutdown_tx.clone()
    }
}

fn main() {
    let server1 = Server1::new(..);
    let shutdown = server1.shutdown_tx();

    let h = thread::spawn(move || {
        server1.run();
    });

    // ...

    shutdown.send(());
    h.join().unwrap();
}

I know shutdown_tx() seems weird, if you have any suggestions or comments, please let me know!

BTW I have already implement it in my branch, I'd like to send a PR if this API looks good to you. :grinning:

overvenus avatar Jan 10 '17 07:01 overvenus