The Service trait is a simplified interface making it easy to write
network applications in a modular and reusable way, decoupled from the
underlying protocol. It is one of Tokio's fundamental abstractions.

A Service is a function of a Request. It immediately returns a
Future representing the eventual completion of processing the
request. The actual request processing may happen at any time in the
future, on any thread or executor. The processing may depend on calling
other services. At some point in the future, the processing will complete,
and the Future will resolve to a response or error.

At a high level, the Service::call represents an RPC request. The
Service value can be a server or a client.

An RPC server implements the Service trait. Requests received by the
server over the network are deserialized then passed as an argument to the
server value. The returned response is sent back over the network.

A client consumes a service by using a Service value. The client may
issue requests by invoking call and passing the request as an argument.
It then receives the response by waiting for the returned future.

As an example, here is how a Redis request would be issued:

letclient=redis::Client::new()
.connect("127.0.0.1:6379".parse().unwrap())
.unwrap();
letresp=client.call(Cmd::set("foo", "this is the value of foo"));
// Wait for the future to resolveprintln!("Redis response: {:?}", await(resp));

More often than not, all the pieces needed for writing robust, scalable
network applications are the same no matter the underlying protocol. By
unifying the API for both clients and servers in a protocol agnostic way,
it is possible to write middleware that provide these pieces in a
reusable way.

The above timeout implementation is decoupled from the underlying protocol
and is also decoupled from client or server concerns. In other words, the
same timeout middleware could be used in either a client or a server.