RPC,遠程方法調用,就是像調用本地方法同樣調用遠程方法。php
gRPC是Google實現的一種RPC框架,基於HTTP/2標準設計,帶來諸如雙向流、流控、頭部壓縮、單 TCP 鏈接上的多複用請求等特。這些特性使得其在移動設備上表現更好,更省電和節省空間佔用。目前提供 C、Java 和 Go 語言版本,分別是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持。java
基本原理:在服務端提供方法,並運行服務器監聽客戶端請求;客戶端調用RPC方法,gRPC客戶端向服務端發送請求,並將結果返回給客戶端調用函數。node
gRPC 默認使用 protocol buffers,這是 Google 開源的一套成熟的結構數據序列化機制(固然也可使用其餘數據格式如 JSON)。推薦使用protobuf v3。python
github:https://github.com/grpc/grpcios
RPC框架要作到的最基本的三件事:c++
1)服務端如何肯定客戶端要調用的函數;git
在遠程調用中,客戶端和服務端分別維護一個【ID->函數】的對應表, ID在全部進程中都是惟一肯定的。客戶端在作遠程過程調用時,附上這個ID,服務端經過查表,來肯定客戶端須要調用的函數,而後執行相應函數的代碼。github
2)如何進行序列化和反序列化;面試
客戶端和服務端交互時將參數或結果轉化爲字節流在網絡中傳輸,那麼數據轉化爲字節流的或者將字節流轉換成能讀取的固定格式時就須要進行序列化和反序列化,序列化和反序列化的速度也會影響遠程調用的效率。編程
3)如何進行網絡傳輸(選擇何種網絡協議);
多數RPC框架選擇TCP做爲傳輸協議,也有部分選擇HTTP。如gRPC使用HTTP2。不一樣的協議各有利弊。TCP更加高效,而HTTP在實際應用中更加的靈活。
REST與RPC應用場景
REST和RPC都經常使用於微服務架構中。
1)HTTP相對更規範,更標準,更通用,不管哪一種語言都支持http協議。若是你是對外開放API,例如開放平臺,外部的編程語言多種多樣,你沒法拒絕對每種語言的支持,如今開源中間件,基本最早支持的幾個協議都包含RESTful。
2)RPC 框架做爲架構微服務化的基礎組件,它能大大下降架構微服務化的成本,提升調用方與服務提供方的研發效率,屏蔽跨進程調用函數(服務)的各種複雜細節。讓調用方感受就像調用本地函數同樣調用遠端函數、讓服務提供方感受就像實現一個本地函數同樣來實現服務。
REST調用及測試都很方便,RPC就顯得有點繁瑣,可是RPC的效率是毋庸置疑的,因此建議在多系統之間的內部調用採用RPC。對外提供的服務,Rest更加合適。
$ git clone https://github.com/grpc/grpc.git $ cd grpc $ git submodule update --init $make $sudo make install
注:執行submodule時時間較長
[INSTALL] Installing public C headers [MAKE] Generating cache.mk [STRIP] Stripping libaddress_sorting.a [STRIP] Stripping libgpr.a [STRIP] Stripping libgrpc.a [STRIP] Stripping libgrpc_cronet.a [STRIP] Stripping libgrpc_unsecure.a [INSTALL] Installing C pkg-config files [INSTALL] Installing libaddress_sorting.a [INSTALL] Installing libgpr.a [INSTALL] Installing libgrpc.a [INSTALL] Installing libgrpc_cronet.a [INSTALL] Installing libgrpc_unsecure.a [STRIP] Stripping libaddress_sorting.so.7.0.0 [STRIP] Stripping libgpr.so.7.0.0 [STRIP] Stripping libgrpc.so.7.0.0 [STRIP] Stripping libgrpc_cronet.so.7.0.0 [STRIP] Stripping libgrpc_unsecure.so.7.0.0 [INSTALL] Installing libaddress_sorting.so.7.0.0 [INSTALL] Installing libgpr.so.7.0.0 [INSTALL] Installing libgrpc.so.7.0.0 [INSTALL] Installing libgrpc_cronet.so.7.0.0 [INSTALL] Installing libgrpc_unsecure.so.7.0.0 [INSTALL] Installing public C++ headers [AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc_plugin_support.a [HOSTCXX] Compiling src/compiler/cpp_plugin.cc [HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_cpp_plugin [HOSTCXX] Compiling src/compiler/csharp_plugin.cc [HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_csharp_plugin [HOSTCXX] Compiling src/compiler/node_plugin.cc [HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_node_plugin [HOSTCXX] Compiling src/compiler/objective_c_plugin.cc [HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_objective_c_plugin [HOSTCXX] Compiling src/compiler/php_plugin.cc [HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_php_plugin [HOSTCXX] Compiling src/compiler/python_plugin.cc [HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_python_plugin [HOSTCXX] Compiling src/compiler/ruby_plugin.cc [HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_ruby_plugin [PROTOC] Generating protobuf CC file from src/proto/grpc/channelz/channelz.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/channelz/channelz.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/health/v1/health.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/health/v1/health.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/testing/echo_messages.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/echo_messages.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/testing/simple_messages.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/testing/echo.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/simple_messages.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/echo.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/testing/duplicate/echo_duplicate.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/duplicate/echo_duplicate.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/core/stats.proto [CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/core/stats.pb.cc [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/core/stats.proto [CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/core/stats.grpc.pb.cc [CXX] Compiling src/cpp/util/core_stats.cc [AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++_core_stats.a [PROTOC] Generating protobuf CC file from src/proto/grpc/testing/payloads.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/testing/stats.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/testing/control.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/payloads.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/stats.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/control.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/testing/messages.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/messages.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/testing/benchmark_service.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/benchmark_service.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/testing/report_qps_scenario_service.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/report_qps_scenario_service.proto [PROTOC] Generating protobuf CC file from src/proto/grpc/testing/worker_service.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/worker_service.proto [CXX] Compiling src/cpp/codegen/codegen_init.cc [AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++.a [AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++_cronet.a [PROTOC] Generating protobuf CC file from src/proto/grpc/status/status.proto [CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/status/status.pb.cc [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/status/status.proto [CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/status/status.grpc.pb.cc [CXX] Compiling src/cpp/util/error_details.cc [AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++_error_details.a [PROTOC] Generating protobuf CC file from src/proto/grpc/reflection/v1alpha/reflection.proto [GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/reflection/v1alpha/reflection.proto [CXX] Compiling src/cpp/ext/proto_server_reflection.cc [CXX] Compiling src/cpp/ext/proto_server_reflection_plugin.cc [CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/reflection/v1alpha/reflection.pb.cc [CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc [AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++_reflection.a [AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++_unsecure.a [CXX] Compiling src/cpp/server/channelz/channelz_service.cc [CXX] Compiling src/cpp/server/channelz/channelz_service_plugin.cc [CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/channelz/channelz.pb.cc [CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/channelz/channelz.grpc.pb.cc [AR] Creating /home/wang/repo/grpc/libs/opt/libgrpcpp_channelz.a [STRIP] Stripping libgrpc++.a [STRIP] Stripping libgrpc++_cronet.a [STRIP] Stripping libgrpc++_error_details.a [STRIP] Stripping libgrpc++_reflection.a [STRIP] Stripping libgrpc++_unsecure.a [STRIP] Stripping libgrpcpp_channelz.a [INSTALL] Installing C++ pkg-config files [INSTALL] Installing libgrpc++.a [INSTALL] Installing libgrpc++_cronet.a [INSTALL] Installing libgrpc++_error_details.a [INSTALL] Installing libgrpc++_reflection.a [INSTALL] Installing libgrpc++_unsecure.a [INSTALL] Installing libgrpcpp_channelz.a [LD] Linking /home/wang/repo/grpc/libs/opt/libgrpc++.so.1.20.0 [LD] Linking /home/wang/repo/grpc/libs/opt/libgrpc++_cronet.so.1.20.0 [LD] Linking /home/wang/repo/grpc/libs/opt/libgrpc++_error_details.so.1.20.0 [LD] Linking /home/wang/repo/grpc/libs/opt/libgrpc++_reflection.so.1.20.0 [LD] Linking /home/wang/repo/grpc/libs/opt/libgrpc++_unsecure.so.1.20.0 [LD] Linking /home/wang/repo/grpc/libs/opt/libgrpcpp_channelz.so.1.20.0 [STRIP] Stripping libgrpc++.so.1.20.0 [STRIP] Stripping libgrpc++_cronet.so.1.20.0 [STRIP] Stripping libgrpc++_error_details.so.1.20.0 [STRIP] Stripping libgrpc++_reflection.so.1.20.0 [STRIP] Stripping libgrpc++_unsecure.so.1.20.0 [STRIP] Stripping libgrpcpp_channelz.so.1.20.0 [INSTALL] Installing libgrpc++.so.1.20.0 [INSTALL] Installing libgrpc++_cronet.so.1.20.0 [INSTALL] Installing libgrpc++_error_details.so.1.20.0 [INSTALL] Installing libgrpc++_reflection.so.1.20.0 [INSTALL] Installing libgrpc++_unsecure.so.1.20.0 [INSTALL] Installing libgrpcpp_channelz.so.1.20.0 [INSTALL] Installing grpc protoc plugins [INSTALL] Installing root certificates
安裝的文件包含:bin,include,lib,share(根證書)。
examples下有各語言版本的示例,examples/protoc是protoc示例文件。
以下演示的是helloworld示例,examples中不只支持同步調用,還支持異步調用。
1. proto文件定義RPC方法及參數
helloworld.proto
syntax = "proto3"; option java_package = "io.grpc.examples"; package helloworld; // 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; }
編譯生成c++源文件(grpc和應用)
protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto
protoc --cpp_out=. helloworld.proto
2. server端代碼
#include <iostream> #include <memory> #include <string> #include <grpcpp/grpcpp.h> #ifdef BAZEL_BUILD #include "examples/protos/helloworld.grpc.pb.h" #else #include "helloworld.grpc.pb.h" #endif using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; using helloworld::HelloRequest; using helloworld::HelloReply; using helloworld::Greeter; // Logic and data behind the server's behavior. class GreeterServiceImpl final : public Greeter::Service { Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* reply) override { std::string prefix("Hello "); reply->set_message(prefix + request->name()); return Status::OK; } }; void RunServer() { std::string server_address("0.0.0.0:50051"); GreeterServiceImpl service; 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(); } int main(int argc, char** argv) { RunServer(); return 0; }
編譯執行:
g++ -o server helloworld.pb.cc helloworld.grpc.pb.cc server.cc -L/usr/local/lib `pkg-config --cflags protobuf grpc` -std=c++11 `pkg-config --libs protobuf grpc++ grpc` -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed -ldl $ ./server Server listening on 0.0.0.0:50051
3. client端代碼
#include <iostream> #include <memory> #include <string> #include <grpcpp/grpcpp.h> #ifdef BAZEL_BUILD #include "examples/protos/helloworld.grpc.pb.h" #else #include "helloworld.grpc.pb.h" #endif using grpc::Channel; using grpc::ClientContext; using grpc::Status; using helloworld::HelloRequest; using helloworld::HelloReply; using helloworld::Greeter; class GreeterClient { public: GreeterClient(std::shared_ptr<Channel> channel) : stub_(Greeter::NewStub(channel)) {} // Assembles the client's payload, sends it and presents the response back // from the server. std::string SayHello(const std::string& user) { // Data we are sending to the server. HelloRequest request; request.set_name(user); // Container for the data we expect from the server. HelloReply reply; // Context for the client. It could be used to convey extra information to // the server and/or tweak certain RPC behaviors. ClientContext context; // The actual RPC. Status status = stub_->SayHello(&context, request, &reply); // Act upon its status. if (status.ok()) { return reply.message(); } else { std::cout << status.error_code() << ": " << status.error_message() << std::endl; return "RPC failed"; } } private: std::unique_ptr<Greeter::Stub> stub_; }; int main(int argc, char** argv) { // Instantiate the client. It requires a channel, out of which the actual RPCs // are created. This channel models a connection to an endpoint (in this case, // localhost at port 50051). We indicate that the channel isn't authenticated // (use of InsecureChannelCredentials()). GreeterClient greeter(grpc::CreateChannel( "127.0.0.1:50051", grpc::InsecureChannelCredentials())); std::string user("world"); std::string reply = greeter.SayHello(user); std::cout << "Greeter received: " << reply << std::endl; return 0; }
編譯執行:
g++ -o client helloworld.pb.cc helloworld.grpc.pb.cc client.cc -L/usr/local/lib `pkg-config --cflags protobuf grpc` -std=c++11 `pkg-config --libs protobuf grpc++ grpc` -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed -ldl $ ./client Greeter received: Hello world
參考:
1. https://www.grpc.io/docs/ 官網
2. http://doc.oschina.net/grpc 中文官網
4. Grpc+Grpc Gateway實踐一 介紹與環境安裝
5. grpc 的安裝和使用