gRPC应用C++

1.  gRPC简述

RPC,远程方法调用,就是像调用本地方法一样调用远程方法。

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# 支持。

基本原理:在服务端提供方法,并运行服务器监听客户端请求;客户端调用RPC方法,gRPC客户端向服务端发送请求,并将结果返回给客户端调用函数。

 

gRPC 默认使用 protocol buffers,这是 Google 开源的一套成熟的结构数据序列化机制(当然也可以使用其他数据格式如 JSON)。推荐使用protobuf v3。

github:https://github.com/grpc/grpc

RPC框架要做到的最基本的三件事:

1)服务端如何确定客户端要调用的函数;

在远程调用中,客户端和服务端分别维护一个【ID->函数】的对应表, ID在所有进程中都是唯一确定的。客户端在做远程过程调用时,附上这个ID,服务端通过查表,来确定客户端需要调用的函数,然后执行相应函数的代码。

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更加合适。

2.  安装

1$ git clone https://github.com/grpc/grpc.git 2$ cd grpc 3$ git submodule update --init 4$make 5$sudo make install

注:执行submodule时时间较长

1[INSTALL] Installing public C headers 2[MAKE] Generating cache.mk 3[STRIP] Stripping libaddress_sorting.a 4[STRIP] Stripping libgpr.a 5[STRIP] Stripping libgrpc.a 6[STRIP] Stripping libgrpc_cronet.a 7[STRIP] Stripping libgrpc_unsecure.a 8[INSTALL] Installing C pkg-config files 9[INSTALL] Installing libaddress_sorting.a 10[INSTALL] Installing libgpr.a 11[INSTALL] Installing libgrpc.a 12[INSTALL] Installing libgrpc_cronet.a 13[INSTALL] Installing libgrpc_unsecure.a 14[STRIP] Stripping libaddress_sorting.so.7.0.0 15[STRIP] Stripping libgpr.so.7.0.0 16[STRIP] Stripping libgrpc.so.7.0.0 17[STRIP] Stripping libgrpc_cronet.so.7.0.0 18[STRIP] Stripping libgrpc_unsecure.so.7.0.0 19[INSTALL] Installing libaddress_sorting.so.7.0.0 20[INSTALL] Installing libgpr.so.7.0.0 21[INSTALL] Installing libgrpc.so.7.0.0 22[INSTALL] Installing libgrpc_cronet.so.7.0.0 23[INSTALL] Installing libgrpc_unsecure.so.7.0.0 24[INSTALL] Installing public C++ headers 25[AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc_plugin_support.a 26[HOSTCXX] Compiling src/compiler/cpp_plugin.cc 27[HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_cpp_plugin 28[HOSTCXX] Compiling src/compiler/csharp_plugin.cc 29[HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_csharp_plugin 30[HOSTCXX] Compiling src/compiler/node_plugin.cc 31[HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_node_plugin 32[HOSTCXX] Compiling src/compiler/objective_c_plugin.cc 33[HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_objective_c_plugin 34[HOSTCXX] Compiling src/compiler/php_plugin.cc 35[HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_php_plugin 36[HOSTCXX] Compiling src/compiler/python_plugin.cc 37[HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_python_plugin 38[HOSTCXX] Compiling src/compiler/ruby_plugin.cc 39[HOSTLD] Linking /home/wang/repo/grpc/bins/opt/grpc_ruby_plugin 40[PROTOC] Generating protobuf CC file from src/proto/grpc/channelz/channelz.proto 41[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/channelz/channelz.proto 42[PROTOC] Generating protobuf CC file from src/proto/grpc/health/v1/health.proto 43[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/health/v1/health.proto 44[PROTOC] Generating protobuf CC file from src/proto/grpc/testing/echo_messages.proto 45[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/echo_messages.proto 46[PROTOC] Generating protobuf CC file from src/proto/grpc/testing/simple_messages.proto 47[PROTOC] Generating protobuf CC file from src/proto/grpc/testing/echo.proto 48[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/simple_messages.proto 49[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/echo.proto 50[PROTOC] Generating protobuf CC file from src/proto/grpc/testing/duplicate/echo_duplicate.proto 51[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/duplicate/echo_duplicate.proto 52[PROTOC] Generating protobuf CC file from src/proto/grpc/core/stats.proto 53[CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/core/stats.pb.cc 54[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/core/stats.proto 55[CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/core/stats.grpc.pb.cc 56[CXX] Compiling src/cpp/util/core_stats.cc 57[AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++_core_stats.a 58[PROTOC] Generating protobuf CC file from src/proto/grpc/testing/payloads.proto 59[PROTOC] Generating protobuf CC file from src/proto/grpc/testing/stats.proto 60[PROTOC] Generating protobuf CC file from src/proto/grpc/testing/control.proto 61[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/payloads.proto 62[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/stats.proto 63[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/control.proto 64[PROTOC] Generating protobuf CC file from src/proto/grpc/testing/messages.proto 65[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/messages.proto 66[PROTOC] Generating protobuf CC file from src/proto/grpc/testing/benchmark_service.proto 67[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/benchmark_service.proto 68[PROTOC] Generating protobuf CC file from src/proto/grpc/testing/report_qps_scenario_service.proto 69[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/report_qps_scenario_service.proto 70[PROTOC] Generating protobuf CC file from src/proto/grpc/testing/worker_service.proto 71[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/testing/worker_service.proto 72[CXX] Compiling src/cpp/codegen/codegen_init.cc 73[AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++.a 74[AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++_cronet.a 75[PROTOC] Generating protobuf CC file from src/proto/grpc/status/status.proto 76[CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/status/status.pb.cc 77[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/status/status.proto 78[CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/status/status.grpc.pb.cc 79[CXX] Compiling src/cpp/util/error_details.cc 80[AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++_error_details.a 81[PROTOC] Generating protobuf CC file from src/proto/grpc/reflection/v1alpha/reflection.proto 82[GRPC] Generating gRPC's protobuf service CC file from src/proto/grpc/reflection/v1alpha/reflection.proto 83[CXX] Compiling src/cpp/ext/proto_server_reflection.cc 84[CXX] Compiling src/cpp/ext/proto_server_reflection_plugin.cc 85[CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/reflection/v1alpha/reflection.pb.cc 86[CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc 87[AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++_reflection.a 88[AR] Creating /home/wang/repo/grpc/libs/opt/libgrpc++_unsecure.a 89[CXX] Compiling src/cpp/server/channelz/channelz_service.cc 90[CXX] Compiling src/cpp/server/channelz/channelz_service_plugin.cc 91[CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/channelz/channelz.pb.cc 92[CXX] Compiling /home/wang/repo/grpc/gens/src/proto/grpc/channelz/channelz.grpc.pb.cc 93[AR] Creating /home/wang/repo/grpc/libs/opt/libgrpcpp_channelz.a 94[STRIP] Stripping libgrpc++.a 95[STRIP] Stripping libgrpc++_cronet.a 96[STRIP] Stripping libgrpc++_error_details.a 97[STRIP] Stripping libgrpc++_reflection.a 98[STRIP] Stripping libgrpc++_unsecure.a 99[STRIP] Stripping libgrpcpp_channelz.a 100[INSTALL] Installing C++ pkg-config files 101[INSTALL] Installing libgrpc++.a 102[INSTALL] Installing libgrpc++_cronet.a 103[INSTALL] Installing libgrpc++_error_details.a 104[INSTALL] Installing libgrpc++_reflection.a 105[INSTALL] Installing libgrpc++_unsecure.a 106[INSTALL] Installing libgrpcpp_channelz.a 107[LD] Linking /home/wang/repo/grpc/libs/opt/libgrpc++.so.1.20.0 108[LD] Linking /home/wang/repo/grpc/libs/opt/libgrpc++_cronet.so.1.20.0 109[LD] Linking /home/wang/repo/grpc/libs/opt/libgrpc++_error_details.so.1.20.0 110[LD] Linking /home/wang/repo/grpc/libs/opt/libgrpc++_reflection.so.1.20.0 111[LD] Linking /home/wang/repo/grpc/libs/opt/libgrpc++_unsecure.so.1.20.0 112[LD] Linking /home/wang/repo/grpc/libs/opt/libgrpcpp_channelz.so.1.20.0 113[STRIP] Stripping libgrpc++.so.1.20.0 114[STRIP] Stripping libgrpc++_cronet.so.1.20.0 115[STRIP] Stripping libgrpc++_error_details.so.1.20.0 116[STRIP] Stripping libgrpc++_reflection.so.1.20.0 117[STRIP] Stripping libgrpc++_unsecure.so.1.20.0 118[STRIP] Stripping libgrpcpp_channelz.so.1.20.0 119[INSTALL] Installing libgrpc++.so.1.20.0 120[INSTALL] Installing libgrpc++_cronet.so.1.20.0 121[INSTALL] Installing libgrpc++_error_details.so.1.20.0 122[INSTALL] Installing libgrpc++_reflection.so.1.20.0 123[INSTALL] Installing libgrpc++_unsecure.so.1.20.0 124[INSTALL] Installing libgrpcpp_channelz.so.1.20.0 125[INSTALL] Installing grpc protoc plugins 126[INSTALL] Installing root certificates

install log

安装的文件包含:bin,include,lib,share(根证书)。

3.  应用

examples下有各语言版本的示例,examples/protoc是protoc示例文件。

如下演示的是helloworld示例,examples中不仅支持同步调用,还支持异步调用。

1. proto文件定义RPC方法及参数

helloworld.proto

1syntax = "proto3"; 2 3option java_package = "io.grpc.examples"; 4 5package helloworld; 6 7// The greeter service definition. 8service Greeter { 9 // Sends a greeting 10 rpc SayHello (HelloRequest) returns (HelloReply) {} 11} 12 13// The request message containing the user's name. 14message HelloRequest { 15 string name = 1; 16} 17 18// The response message containing the greetings 19message HelloReply { 20 string message = 1; 21}

编译生成c++源文件(grpc和应用)

1protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto 2protoc --cpp_out=. helloworld.proto

2. server端代码

1#include <iostream> 2#include <memory> 3#include <string> 4 5#include <grpcpp/grpcpp.h> 6 7#ifdef BAZEL_BUILD 8#include "examples/protos/helloworld.grpc.pb.h" 9#else 10#include "helloworld.grpc.pb.h" 11#endif 12 13using grpc::Server; 14using grpc::ServerBuilder; 15using grpc::ServerContext; 16using grpc::Status; 17using helloworld::HelloRequest; 18using helloworld::HelloReply; 19using helloworld::Greeter; 20 21// Logic and data behind the server's behavior. 22class GreeterServiceImpl final : public Greeter::Service { 23 Status SayHello(ServerContext* context, const HelloRequest* request, 24 HelloReply* reply) override { 25 std::string prefix("Hello "); 26 reply->set_message(prefix + request->name()); 27 return Status::OK; 28 } 29}; 30 31void RunServer() { 32 std::string server_address("0.0.0.0:50051"); 33 GreeterServiceImpl service; 34 35 ServerBuilder builder; 36 // Listen on the given address without any authentication mechanism. 37 builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); 38 // Register "service" as the instance through which we'll communicate with 39 // clients. In this case it corresponds to an *synchronous* service. 40 builder.RegisterService(&service); 41 // Finally assemble the server. 42 std::unique_ptr<Server> server(builder.BuildAndStart()); 43 std::cout << "Server listening on " << server_address << std::endl; 44 45 // Wait for the server to shutdown. Note that some other thread must be 46 // responsible for shutting down the server for this call to ever return. 47 server->Wait(); 48} 49 50int main(int argc, char** argv) { 51 RunServer(); 52 53 return 0; 54}

编译执行:

1g++ -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 2$ ./server 3Server listening on 0.0.0.0:50051

3**.** client****端代码

1#include <iostream> 2#include <memory> 3#include <string> 4 5#include <grpcpp/grpcpp.h> 6 7#ifdef BAZEL_BUILD 8#include "examples/protos/helloworld.grpc.pb.h" 9#else 10#include "helloworld.grpc.pb.h" 11#endif 12 13using grpc::Channel; 14using grpc::ClientContext; 15using grpc::Status; 16using helloworld::HelloRequest; 17using helloworld::HelloReply; 18using helloworld::Greeter; 19 20class GreeterClient { 21 public: 22 GreeterClient(std::shared_ptr<Channel> channel) 23 : stub_(Greeter::NewStub(channel)) {} 24 25 // Assembles the client's payload, sends it and presents the response back 26 // from the server. 27 std::string SayHello(const std::string& user) { 28 // Data we are sending to the server. 29 HelloRequest request; 30 request.set_name(user); 31 32 // Container for the data we expect from the server. 33 HelloReply reply; 34 35 // Context for the client. It could be used to convey extra information to 36 // the server and/or tweak certain RPC behaviors. 37 ClientContext context; 38 39 // The actual RPC. 40 Status status = stub_->SayHello(&context, request, &reply); 41 42 // Act upon its status. 43 if (status.ok()) { 44 return reply.message(); 45 } else { 46 std::cout << status.error_code() << ": " << status.error_message() 47 << std::endl; 48 return "RPC failed"; 49 } 50 } 51 52 private: 53 std::unique_ptr<Greeter::Stub> stub_; 54}; 55 56int main(int argc, char** argv) { 57 // Instantiate the client. It requires a channel, out of which the actual RPCs 58 // are created. This channel models a connection to an endpoint (in this case, 59 // localhost at port 50051). We indicate that the channel isn't authenticated 60 // (use of InsecureChannelCredentials()). 61 GreeterClient greeter(grpc::CreateChannel( 62 "127.0.0.1:50051", grpc::InsecureChannelCredentials())); 63 std::string user("world"); 64 std::string reply = greeter.SayHello(user); 65 std::cout << "Greeter received: " << reply << std::endl; 66 67 return 0; 68}

编译执行:

1g++ -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 2$ ./client 3Greeter received: Hello world

参考:

1. https://www.grpc.io/docs/ 官网

2. http://doc.oschina.net/grpc 中文官网

3. 花了一个星期,我终于把RPC框架整明白了!

4. Grpc+Grpc Gateway实践一 介绍与环境安装

5. grpc 的安装和使用

6. 面试问题:REST与RPC区别?

7.  实现一个 RESTful API 服务器 RSET和RPC比较

8. gRPC(HTTP / 2)比使用HTTP / 2的REST更快吗?  默认情况下,gRPC不比HTTP / REST更快,但它为您提供了更快的工具。有些事情对于REST来说很难或不可能做到。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )