Yueying Li 7/13/2021
Within a single program, running in a single process, recall the well-known notion of a procedure call:
Goal: make communication appear like a local procedure call: transparency for procedure calls – way less painful than sockets…
Differences in data representation
Transport:
IO Manager:
syntax = "proto3";
package todoPackage;
service Todo {
rpc createTodo(TodoItem) returns (TodoItem);
rpc readTodos(voidNoParam) returns (TodoItems);
rpc readTodosStream(voidNoParam) returns (stream TodoItem);
}
message voidNoParam {}
message TodoItem {
int32 id = 1;
string text = 2;
}
message TodoItems {
repeated TodoItem items = 1;
}
repeated
means arraysyntax = "proto3";
option java_package = "ex.grpc";
package helloworld;
message Reply {
int32 result = 1;
}
message HelloMessage {
int32 a = 1;
int32 b = 2;
}
service TestServer {
rpc hello_request (HelloMessage) returns (Reply) {}
}
# CPP
cd protos
protoc --cpp_out=. helloworld.proto
protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto
# Python
cd protos
python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto
class GreeterServiceImpl final : public Greeter::Service {
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
// ...
}
Status SayHelloAgain(ServerContext* context, const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello again ");
reply->set_message(prefix + request->name());
return Status::OK;
}
};
stub_
to invoke the methods, parsing context, request
and reply
class GreeterClient {
public:
// ...
std::string SayHello(const std::string& user) {
// ...
}
std::string SayHelloAgain(const std::string& user) {
// Follows the same pattern as SayHello.
HelloRequest request;
request.set_name(user);
HelloReply reply;
ClientContext context;
// Here we can use the stub's newly available method we just added.
Status status = stub_->SayHelloAgain(&context, request, &reply);
if (status.ok()) {
return reply.message();
} else {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RRPC failed";
}
}
private:
std::unique_ptr<Greeter::Stub> stub_;
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
grpc::EnableDefaultHealthCheckService(true);
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait();
}
rpc GetFeature(Point) returns (Feature) {}
rpc ListFeatures(Rectangle) returns (stream Feature) {}
rpc RecordRoute(stream Point) returns (RouteSummary) {}
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
Point lo = 1;
Point hi = 2;
}
// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
// The name of the feature.
string name = 1;
// The point where the feature is detected.
Point location = 2;
}
// A RouteNote is a message sent while at a given point.
message RouteNote {
// The location from which the message is sent.
Point location = 1;
// The message to be sent.
string message = 2;
}
// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
// The number of points received.
int32 point_count = 1;
// The number of known features passed while traversing the route.
int32 feature_count = 2;
// The distance covered in metres.
int32 distance = 3;
// The duration of the traversal in seconds.
int32 elapsed_time = 4;
}
stub
.grpc::CreateCustomChannel() api with any special channel arguments - grpc::ChannelArguments
An example of generated name
method for a service
// name
inline bool has_name() const;
inline void clear_name();
inline const ::std::string& name() const;
inline void set_name(const ::std::string& value);
inline void set_name(const char* value);
inline ::std::string* mutable_name();
PROTOBUF_FINAL
:// implements Message
public:
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
// .mid_tier_service.UtilRequest util_request = 1;
bool has_util_request() const;
private:
bool _internal_has_util_request() const;
public:
void clear_util_request();
const ::mid_tier_service::UtilRequest& util_request() const;
::mid_tier_service::UtilRequest* release_util_request();
::mid_tier_service::UtilRequest* mutable_util_request();
void set_allocated_util_request(::mid_tier_service::UtilRequest* util_request);
private:
const ::mid_tier_service::UtilRequest& _internal_util_request() const;
::mid_tier_service::UtilRequest* _internal_mutable_util_request();
public:
void unsafe_arena_set_allocated_util_request(
::mid_tier_service::UtilRequest* util_request);
::mid_tier_service::UtilRequest* unsafe_arena_release_util_request();
// uint64 resp_time = 3;
void clear_resp_time();
::PROTOBUF_NAMESPACE_ID::uint64 resp_time() const;
void set_resp_time(::PROTOBUF_NAMESPACE_ID::uint64 value);
private:
::PROTOBUF_NAMESPACE_ID::uint64 _internal_resp_time() const;
void _internal_set_resp_time(::PROTOBUF_NAMESPACE_ID::uint64 value);
public:
// bool last_request = 2;
void clear_last_request();
bool last_request() const;
void set_last_request(bool value);
private:
bool _internal_last_request() const;
void _internal_set_last_request(bool value);
public:
// bool kill = 4;
void clear_kill();
bool kill() const;
void set_kill(bool value);
private:
bool _internal_kill() const;
void _internal_set_kill(bool value);
public:
// uint32 load = 6;
void clear_load();
::PROTOBUF_NAMESPACE_ID::uint32 load() const;
void set_load(::PROTOBUF_NAMESPACE_ID::uint32 value);
private:
::PROTOBUF_NAMESPACE_ID::uint32 _internal_load() const;
void _internal_set_load(::PROTOBUF_NAMESPACE_ID::uint32 value);
public:
// uint64 request_id = 5;
void clear_request_id();
::PROTOBUF_NAMESPACE_ID::uint64 request_id() const;
void set_request_id(::PROTOBUF_NAMESPACE_ID::uint64 value);
private:
::PROTOBUF_NAMESPACE_ID::uint64 _internal_request_id() const;
void _internal_set_request_id(::PROTOBUF_NAMESPACE_ID::uint64 value);
RouteGuide::Service/AsyncService
void ListFeatures() {
routeguide::Rectangle rect;
Feature feature;
ClientContext context;
rect.mutable_lo()->set_latitude(400000000);
rect.mutable_lo()->set_longitude(-750000000);
rect.mutable_hi()->set_latitude(420000000);
rect.mutable_hi()->set_longitude(-730000000);
std::cout << "Looking for features between 40, -75 and 42, -73"
<< std::endl;
std::unique_ptr<ClientReader<Feature> > reader(
stub_->ListFeatures(&context, rect));
while (reader->Read(&feature)) {
std::cout << "Found feature called "
<< feature.name() << " at "
<< feature.location().latitude()/kCoordFactor_ << ", "
<< feature.location().longitude()/kCoordFactor_ << std::endl;
}
Status status = reader->Finish();
if (status.ok()) {
std::cout << "ListFeatures rpc succeeded." << std::endl;
} else {
std::cout << "ListFeatures rpc failed." << std::endl;
}
}
Intro https://github.com/sbueringer/kubecon-slides/tree/master/slides/2018-kubecon-eu
CMakeList and building https://github.com/grpc/grpc/blob/master/BUILDING.md https://github.com/grpc/grpc/blob/v1.38.0/examples/cpp/route_guide/CMakeLists.txt
Protobuf https://developers.google.com/protocol-buffers/docs/proto3
GRPC Basic Tutorial: https://grpc.io/docs/languages/cpp/basics/
GRPC Async https://grpc.io/docs/languages/cpp/async/
GRPC C++ Core API https://grpc.github.io/grpc/cpp/
GRPC complletion queue thread model in tensorflow
https://github.com/grpc/grpc/commit/1bf7207852b4138c8a30e5a2f8f2c4bfffbba262