brpc-rs: Apache BRPC library for Rust
Apache BRPC is an industrial-grade
RPC framework for building reliable and high-performance services. brpc-rs
enables BRPC clients and servers implemented in the Rust programming language.
brpc-rs
is part of the MesaLock Linux
Project.
Status
This project is currently a prototype under active development. Many APIs are missing; the provided APIs are not guaranteed to be stable until 1.0.
Repository structure
- Project root
- src
- brpc-rs crate, Rust APIs for
brpc-rs
- brpc-rs crate, Rust APIs for
- brpc-build
- brpc-build crate, build-time code generator
- brpc-protoc-plugin
- brpc-protoc-plugin crate, plugin for Google Protobuf compiler
- brpc-sys
- brpc-sys crate, FFI bindings to Apache BRPC
- examples
- examples
- src
This graph illustrates how the crates work together:
Quickstart
Prerequisites
First build and install Apache BRPC. Instructions can be found in getting_started.md.
Alternatively, you may use the prebuilt deb packages of Apache BRPC 0.9.6 for Ubuntu 16.04/18.04. These are NOT official packages.
Make sure these dependencies are already installed:
$ sudo apt-get install libprotobuf-dev libprotoc-dev protobuf-compiler
$ sudo apt-get install libssl-dev libgflags-dev libleveldb-dev
Install brpc-protoc-plugin
from crates.io.
$ cargo install brpc-protoc-plugin
Now we are ready to start a brpc-rs
project.
Cargo.toml
Let's create a small crate, echo_service
, that includes an echo_client
and
an echo_server
.
$ cargo new echo_service && cd echo_service
In Cargo.toml
, add brpc-rs
, prost
and bytes
to the [dependencies]
section; add brpc-build
to the [build-dependencies]
section. For example,
[build-dependencies]
brpc-build = "0.1.0"
[dependencies]
brpc-rs = "0.1.0"
prost = "0.5.0"
bytes = "0.4.12"
Define two binaries: echo_client
and echo_server
in Cargo.toml
[[bin]]
name = "echo_client"
path = "src/client.rs"
[[bin]]
name = "echo_server"
path = "src/server.rs"
build.rs
Put a protobuf file echo.proto
in src
. This file defines EchoRequest
,
EchoResponse
and EchoService
.
syntax="proto2";
package example;
message EchoRequest {
required string message = 1;
};
message EchoResponse {
required string message = 1;
};
service EchoService {
rpc echo(EchoRequest) returns (EchoResponse);
};
Add a line build = "build.rs"
in the [package]
section in Cargo.toml
.
Then, create a file called build.rs
to generate bindings from
src/echo.proto
.
fn main() {
brpc_build::compile_protos(&["src/echo.proto"],
&["src"]).unwrap();
}
Note the package
name in echo.proto
is example
. So build.rs
would generate two files named example.rs
and example.brpc.rs
.
src/server.rs
Next let's implement the echo server. Create src/server.rs
as follows:
use brpc_rs::{Server, ServerOptions, ServiceOwnership};
pub mod echo {
include!(concat!(env!("OUT_DIR"), "/example.rs"));
include!(concat!(env!("OUT_DIR"), "/example.brpc.rs"));
}
fn main() {
let mut service = echo::EchoService::new();
service.set_echo_handler(&mut move |request, mut response| {
response.message = request.message.clone();
Ok(())
});
let mut server = Server::new();
let mut options = ServerOptions::new();
options.set_idle_timeout_ms(1000);
server
.add_service(&service, ServiceOwnership::ServerDoesntOwnService)
.expect("Failed to add service");
server.start(50000, &options).expect("Failed to start service");
server.run(); // Run until CTRL-C
}
Because EchoService
defines a function called echo()
in echo.proto
, the
brpc-protoc-plugin
generates the Rust definition of set_echo_handler()
for
EchoService
. set_echo_handler()
accepts a closure which handles
EchoRequest
sent from clients and returns an EchoResponse
with the same
message. The remaining lines create a server that listens at 0.0.0.0:50000
.
src/client.rs
use brpc_rs::{Channel, ChannelOptions};
pub mod echo {
include!(concat!(env!("OUT_DIR"), "/example.rs"));
include!(concat!(env!("OUT_DIR"), "/example.brpc.rs"));
}
fn main() {
let mut options = ChannelOptions::new();
options.set_timeout_ms(100);
let addr = "127.0.0.1:50000".parse().expect("Invalid socket address");
let ch = Channel::with_options(&addr, &options);
let client = echo::EchoServiceStub::with_channel(&ch);
let request = echo::EchoRequest {
message: "hello".to_owned(),
};
match client.echo(&request) {
Ok(r) => println!("Response: {:?}", r),
Err(e) => eprintln!("Error: {:?}", e),
}
}
The client first creates a Channel
and initializes a service_stub
with that
channel. The client then calls service_stub.echo()
to send a request..
Running the client and server
$ cargo run --bin echo_server &
$ cargo run --bin echo_client
Response: EchoResponse { message: "hello" }
Maintainer
- Yiming Jing
<[email protected]>
@kevinis
License
brpc-rs
is provided under Apache License, Version 2.0. For a copy, see the
LICENSE file.