#rpc #fibers

fibers_rpc

RPC library built on top of fibers crate

35 releases

0.3.4 Sep 7, 2020
0.3.3 Sep 11, 2019
0.3.2 Aug 18, 2019
0.3.1 Mar 31, 2019
0.1.10 Mar 23, 2018

#681 in Network programming

Download history 11/week @ 2021-10-05 43/week @ 2021-10-12 19/week @ 2021-10-19 7/week @ 2021-10-26 81/week @ 2021-11-02 13/week @ 2021-11-09 15/week @ 2021-11-16 15/week @ 2021-11-23 48/week @ 2021-11-30 67/week @ 2021-12-07 16/week @ 2021-12-14 1/week @ 2021-12-21 5/week @ 2021-12-28 12/week @ 2022-01-04 22/week @ 2022-01-11 21/week @ 2022-01-18

60 downloads per month
Used in less than 8 crates

MIT license

120KB
3K SLoC

fibers_rpc

fibers_rpc Documentation Build Status Code Coverage License: MIT

Rust RPC library built on top of fibers crate.

Documentation

Features

  • Asynchronous RPC server/client using fibers crate
  • Support two type of RPC:
    • Request/response model
    • Notification model
  • Strongly typed RPC using bytecodec crate
    • You can treat arbitrarily Rust structures that support serde as RPC messages
    • It is possible to handle huge structures as RPC messages without compromising efficiency and real-time property by implementing your own encoder/decoder
  • Multiplexing multiple RPC messages in a single TCP stream
  • Prioritization between messages
  • Expose Prometheus metrics

Technical Details

See doc/.

Examples

Simple echo RPC server:

use bytecodec::bytes::{BytesEncoder, RemainingBytesDecoder};
use fibers_rpc::{Call, ProcedureId};
use fibers_rpc::client::ClientServiceBuilder;
use fibers_rpc::server::{HandleCall, Reply, ServerBuilder};
use futures::Future;

// RPC definition
struct EchoRpc;
impl Call for EchoRpc {
    const ID: ProcedureId = ProcedureId(0);
    const NAME: &'static str = "echo";

    type Req = Vec<u8>;
    type ReqEncoder = BytesEncoder<Vec<u8>>;
    type ReqDecoder = RemainingBytesDecoder;

    type Res = Vec<u8>;
    type ResEncoder = BytesEncoder<Vec<u8>>;
    type ResDecoder = RemainingBytesDecoder;
}

// RPC server
struct EchoHandler;
impl HandleCall<EchoRpc> for EchoHandler {
    fn handle_call(&self, request: <EchoRpc as Call>::Req) -> Reply<EchoRpc> {
        Reply::done(request)
    }
}
let server_addr = "127.0.0.1:1919".parse().unwrap();
let mut builder = ServerBuilder::new(server_addr);
builder.add_call_handler(EchoHandler);
let server = builder.finish(fibers_global::handle());
fibers_global::spawn(server.map_err(|e| panic!("{}", e)));

// RPC client
let service = ClientServiceBuilder::new().finish(fibers_global::handle());
let service_handle = service.handle();
fibers_global::spawn(service.map_err(|e| panic!("{}", e)));

let request = Vec::from(&b"hello"[..]);
let response = EchoRpc::client(&service_handle).call(server_addr, request.clone());
let response = fibers_global::execute(response)?;
assert_eq!(response, request);

Informal benchmark result (v0.2.1):

$ uname -a
Linux DESKTOP 4.4.0-43-Microsoft #1-Microsoft Wed Dec 31 14:42:53 PST 2014 x86_64 x86_64 x86_64 GNU/Linux

$ lscpu | grep 'Model name:'
Model name:            Intel(R) Core(TM) i7-7660U CPU @ 2.50GHz

// Runs the example echo server in a shell.
$ cargo run --example echo --release -- server

// Executes a benchmark command in another shell.
$ echo "hello" | cargo run --example echo --release -- bench -c 1024 -n 1000000
# ELAPSED: 8.111424
# RPS: 123282.91555218912

Dependencies

~1.7–2.3MB
~49K SLoC