dnes vás provází Lukáš Grolig
high performance open source RPC framework
message Person {
string name = 1;
int32 id = 2;
bool has_ponycopter = 3;
}
Data jsou předávána jako message. Položkám říkáme field.
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
Dále máme services. To jsou akce, které můžeme provolat a vrátí nám odpověď.
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
Data je možné streamovat.
proto Type | Notes |
---|---|
double | |
float | |
int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. |
int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. |
uint32 | Uses variable-length encoding. |
uint64 | Uses variable-length encoding. |
sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. |
sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. |
fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 228. |
fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 256. |
sfixed32 | Always four bytes. |
sfixed64 | Always eight bytes. |
bool | |
string | A string must always contain UTF-8 encoded or 7-bit ASCII text, and cannot be longer than 232. |
bytes | May contain any arbitrary sequence of bytes no longer than 232. |
message MyMessage1 {
enum EnumAllowingAlias {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 1;
}
}
Samozřejmě můžeme udělat výčet.
message SearchResponse {
repeated Result results = 1;
}
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
}
Aneb náš starý známy list/vector
message Result {
string url = 1;
string title = 2;
map<int32, string> my_map = 4;
}
slovník
[dependencies]
tonic = "0.4"
prost = "0.7"
futures-core = "0.3"
futures-util = "0.3"
tokio = { version = "1.0", features = ["rt-multi-thread", "macros", "sync", "time"] }
async-stream = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rand = "0.7"
[build-dependencies]
tonic-build = "0.4"
fn main() {
tonic_build::compile_protos("proto/definice.proto")
.unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e));
}
use tonic::{transport::Server, Request, Response, Status};
use hello_world::greeter_server::{Greeter, GreeterServer};
use hello_world::{HelloReply, HelloRequest};
pub mod hello_world {
tonic::include_proto!("helloworld"); // The string specified here must match the proto package name
}
#[derive(Debug, Default)]
pub struct MyGreeter {}
#[tonic::async_trait]
impl Greeter for MyGreeter {
async fn say_hello(
&self,
request: Request<HelloRequest>, // Accept request of type HelloRequest
) -> Result<Response<HelloReply>, Status> { // Return an instance of type HelloReply
println!("Got a request: {:?}", request);
let reply = hello_world::HelloReply {
message: format!("Hello {}!", request.into_inner().name).into(), // We must use .into_inner() as the fields of gRPC requests and responses are private
};
Ok(Response::new(reply)) // Send back our formatted greeting
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "[::1]:50051".parse()?;
let greeter = MyGreeter::default();
Server::builder()
.add_service(GreeterServer::new(greeter))
.serve(addr)
.await?;
Ok(())
}
use hello_world::greeter_client::GreeterClient;
use hello_world::HelloRequest;
pub mod hello_world {
tonic::include_proto!("helloworld");
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = GreeterClient::connect("http://[::1]:50051").await?;
let request = tonic::Request::new(HelloRequest {
name: "Tonic".into(),
});
let response = client.say_hello(request).await?;
println!("RESPONSE={:?}", response);
Ok(())
}