共计 3838 个字符,预计需要花费 10 分钟才能阅读完成。
gRPC 系列(一) 装置和入门
gRPC 是由谷歌公司开发的一款 rpc 框架,反对多种语言,包含 C ++、Java、Golang、python 等等。这个系列将会次要记录 gRPC 的学习过程,本文次要包含装置和简略的应用,语言为 C ++。
装置
我的操作系统是 ubuntu20.04。
-
装置依赖
sudo apt-get install pkg-config sudo apt-get install autoconf automake libtool make g++ unzip sudo apt-get install libgfalgs-dev libgtest-dev sudo apt-get install clang libc++-dev
-
下载 gRPC
git clone https://github.com/grpc/grpc.git cd grpc git submodule update --init // 更新第三方源码
-
装置 protobuf 源码
cd third_party/protobuf/ git submodule update --init --recursive ./autogen.sh // 生成配置脚本 ./configure // 生成 Makefile 文件,为下一步的编译做筹备,能够加上装置门路:--prefix=path make make check sudo make install sudo ldconfig // 更新共享库缓存 which protoc // 查看软件是否装置胜利 protoc --version // 查看是否装置胜利
-
装置 gRPC
cd ../.. make sudo make install
简略应用
应用 grpc 包含几个步骤:定义服务、生成代码、编写服务端代码、编写客户端代码、运行。
定义服务
服务定义文件是 proto 文件,中文文档能够参考 Protobuf 语法指南
这里先写一个简略的 proto 文件
syntax="proto3";
// 语法类型
package Simple;
// 这是生成代码应用的 namespace,所有生成的代码都会在这个 namespace 中。// 指定服务的名称,生成的代码外面的二级 namespace
service Server {rpc Echo(EchoRequest) returns (EchoReponse){}}
message EchoRequest {string msg = 1; //}
message EchoResponse {string msg = 1;}
下面的接口中,必须有参数和返回值,如果不须要参数或者返回值,也必须定义一个空的(没有成员)message,否则无奈通过编译。
生成代码
装置好 grpc 之后,能够应用 grpc 的相干的命令行程序,来应用 proto 文件生成 C ++ 代码,这里须要分两步走,一个是生成 protobuf 序列化和反序列化代码,二是生成根本服务框架代码。
> protoc -I ./ --cpp_out=. simple.proto
> protoc -I ./ --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` simple.proto
> ls
simple.grpc.pb.cc simple.grpc.pb.h simple.pb.cc simple.pb.h simple.proto
编写服务端代码
服务端咱们须要继承生成文件 simple.grpc.pb.h 中的 Simple::Server::Service,实现上述定义的 rpc 接口,咱们能够看一下 simple.grpc.pb.h 文件中的内容。
简略的服务端代码如下:
#include <iostream>
#include <grpcpp/grpcpp.h>
#include <grpcpp/security/credentials.h>
#include "../protos/simple/simple.grpc.pb.h"
// 增加本人的门路
using grpc::Status;
using grpc::ServerContext;
class SimpleServiceImpl final : public Simple::Server::Service{
public:
Status Echo(ServerContext* context,
const Simple::EchoRequest* req,
Simple::EchoResponse* resp)override
{resp->set_msg(req->msg());
return Status::OK;
}
};
int main()
{
// 服务器构建器
grpc::ServerBuilder builder;
// 增加监听的地址和端口,抉择不认证
builder.AddListeningPort("localhost:12345",grpc::InsecureServerCredentials());
// 注册服务
ServiceImpl service;
builder.RegisterService(&service);
// 构建服务器
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
std::cout << "Server running" << std::endl;
// 进入服务器解决循环
server->Wait();
return 0;
}
而后运行咱们的程序(不要遗记链接 grpc 库和源文件 simple.grpc.pb.cc、simple.pb.cc)。
我是用 CMake 构建编译链的,在我的项目目录的 CMakeLists.txt 中查找库并增加到门路中。
set(protobuf_MODULE_COMPATIBLE True)
find_package(Protobuf REQUIRED)
set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
# set grpc
find_package(gRPC REQUIRED)
set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure)
include_directories(${_PROTOBUF_INCLUDE_DIR}
${PROJECT_SOURCE_DIR}/grpc/protos
)
在 simple.cpp 所在门路增加依赖
add_executable(SimpleClient simple_client.cpp)
target_link_libraries(SimpleClient
${_GRPC_GRPCPP_UNSECURE}
${_PROTOBUF_LIBPROTOBUF}
simple.grpc.pb.cc
simple.pb.cc
)
add_executable(SimpleServer simple_server.cpp)
target_link_libraries(SimpleServer
${_GRPC_GRPCPP_UNSECURE}
${_PROTOBUF_LIBPROTOBUF}
simple.grpc.pb.cc
simple.pb.cc
)
install(TARGETS
SimpleServer
SimpleClient
DESTINATION bin/
)
而后编译过程如下:
// 进入我的项目根目录下,> mkdir -p build
> cd build
> cmake ../ CMAKE_INSTALL_PREFIX="your_install_path"
> cd your_install_path/bin
> ./SimpleServer
> Server running
编写客户端代码
#include <iostream>
#include <string>
#include <grpcpp/grpcpp.h>
#include <grpcpp/channel.h>
#include <grpcpp/create_channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/security/credentials.h>
#include "../protos/simple/simple.grpc.pb.h"
using grpc::Status;
using grpc::Channel;
using grpc::ClientContext;
int main()
{
// 创立一个 channel,保护的是和服务器的连贯
std::shared_ptr<Channel> chan = grpc::CreateChannel("localhost:12345",grpc::InsecureChannelCredentials());
// 创立一个 stub
std::unique_ptr<Simple::Server::Stub> stub = Simple::Server::NewStub(chan);
Simple::EchoRequest req;
req.set_msg("Hello World");
Simple::EchoResponse resp;
ClientContext context;
Status st = stub->Echo(&context,req,&resp);
if(st.ok()){std::cout << resp.msg() <<std::endl;
}
return 0;
}
编译和下面服务器编译办法统一:
> SimpleClient
Hello World
>
正文完