grpc框架在linux系统下安装与使用
qq_46489304 2024-09-05 13:37:01 阅读 69
一、编译grpc源码
(1)源码下载,这里准备好了源码连接,直接按下面链接源码和依赖库。
链接: https://pan.baidu.com/s/1UcHkDLbMWb8yNsLEQh3Wxw 提取码: grpc 。
(2)安装必要依赖工具
<code>sudo apt-get install autoconf automake libtool
(3)安装cmake和gcc/g++
本文主要用到cmake来进行编译,所以需要安装cmake和gcc/g++,注意需要保证cmake的版本大于3.15,gcc/g++的版本大于7.0吗。
如果已经安装的cmake,版本号低于3.15,先卸载再安装新的cmake。
卸载命令
sudo apt-get autoremove cmake
安装新的cmake
1.压缩包下载
wget https://cmake.org/files/v3.23/cmake-3.23.0-linux-x86_64.tar.gz
2.解压
tar zxf cmake-3.23.0-linux-x86_64.tar.gz
3.创建软连接
sudo ln -sf /opt/cmake-3.23.0/bin/* /usr/bin/
创建软连接到/usr/bin/下的目的是可以在系统的任何目录下直接运行cmake命令。
(4)解压grpc源码
tar -jxf grpc-v1.45.2.tar.bz2
(5)编译和安转
命令如下,首先进入压缩后的grpc文件夹下,执行如下命令。
mkdir build
cd build
cmake ../
make
sudo make install
(6)protobuf安装
这里的protobuf主要用来数据传输的序列化,使用grpc/third_party/protobuf 里面编译安装对应的 protobuf,不要手动下载其他的protbuf,不然版本可能和grcp不匹配。命令如下。
cd third_party/protobuf/
./autogen.sh
./configure --prefix=/usr/local
make
sudo make install
sudo ldconfig # 使得新安装的动态库能被加载
protoc --version
显示3.19.4
(7)测试
1.编译helloword例子
cd grpc/examples/cpp/helloworld/
mkdir build
cd build/
cmake ..
make
2.启动客户端和服务器
# 启动服务端,监听在50051端口
./greeter_server
Server listening on 0.0.0.0:50051
# 启动客户端,服务端返回Hello world
./greeter_client
Greeter received: Hello world
出现上述结果说明编译成功。
二、如何在c++中使用grpc进行通信
(1)编写proto文件,这文件主要是用来定义服务接口函数和一些消息体结构,然后通过protobuf工具用该文件生成对应的grpc.pb.cc文件和消息体结构类。代码如下:
syntax = "proto3";//声明使用protoc3版本
package myserver;//定义命令空间,主要是为了区分不同的proto文件有相同的函数名和消息体名
service Greeter//定义接口服务
{
rpc SayHello(HelloRequest) returns (HelloRepose){}//接口函数,通过该函数来与服务器进行通信
}
message HelloRequest//请求消息体结构
{
bytes message = 1;//成员变量
}
message HelloRepose//响应消息体结构
{
bytes message = 1;
}
上面代码中,定义个叫Greeter的服务类,在这个类中定义一个接口函数,该函数的功能是接受一个单一的消息,服务器返回单一的消息,这里我只定义了一个,大家可以随意定义。下面接受以下grpc的四种接口模式。
1.简单接口模型
即客户端发起一次请求,服务端响应处理后返回一个结果给客户端。在proto文件对应如下。
rpc SayHello(HelloRequest) returns (HelloResponse);
2.服务端数据流模式
即客户端发起一次请求,服务端可以连续返回数据流。比如:客户端向服务端发送了一个查询数据库的请求,服务端持续返回多次结果。(即客户端发送一次请求,服务端查询到数据库有一万条数据,服务端分批返回10次,每次返回1000条数据给客户端)。
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
用到了stream关键字。
3.客户端数据流模式
与服务端数据流模式相反,客户端持续向服务端发送数据流,在发送结束后,由服务端返回一个响应。比如:客户端有一万条数据 ,分批多次请求服务端,服务端接收后把这些数据都存到数据库,然后返回一次结果给客户端。
在 proto 文件中可如下定义:
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
4.双向数据流模式
也称双向流式 RPC,即客户端和服务端都可以向对方多次收发数据。比如:客户端有一万条数据 ,分批多次请求服务端,服务端每次接收后存到数据库后都发送一次结果给客户端。在 proto 文件中可如下定义:
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
(2)使用protobuf工具将上面的proto文件生成对应的c++语法结构的grpc.pb.cc和grpc.pb.h文件
命名如下:
上面--grpc_out是grpc.pb.cc文件的输出目录,--plugin是 grpc_cpp_plugin这个插件的路径。执行上面命令后会在当前项目路径下生成下面两个文件。
(3)使用protobuf工具将上面的proto文件生成对应的c++语法结构消息体结构类
命令如下:
<code>protoc -I=./ server.proto --cpp_out=./
-I表示proto文件所在目录,--cpp_out表示输出文件的输出目录。生成文件如下。
(4) 服务器代码
<code>/*
*
* Copyright 2015 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <iostream> // 包含输入输出流操作所需的头文件
#include <memory> // 包含智能指针(如 std::unique_ptr)的支持
#include <string> // 包含 std::string 类
#include <grpcpp/ext/proto_server_reflection_plugin.h> // 包含 gRPC 服务器反射插件的支持
#include <grpcpp/grpcpp.h> // 包含 gRPC 核心功能的头文件
#include <grpcpp/health_check_service_interface.h> // 包含健康检查服务的接口
#include "server.grpc.pb.h" // 包含由 .proto 文件生成的头文件
using grpc::Server; // 使用 gRPC Server 类
using grpc::ServerBuilder; // 使用 gRPC ServerBuilder 类
using grpc::ServerContext; // 使用 gRPC ServerContext 类
using grpc::Status; // 使用 gRPC Status 类
using myserver::Greeter; // 使用从 .proto 文件生成的 Greeter 服务类
using myserver::HelloRepose; // 使用从 .proto 文件生成的 HelloRepose 消息类
using myserver::HelloRequest; // 使用从 .proto 文件生成的 HelloRequest 消息类
// Greeter 服务的实现类
class GreeterServiceImpl final : public Greeter::Service {
// 实现 SayHello RPC 方法
Status SayHello(ServerContext* context, const HelloRequest* request,
HelloRepose* reply) override {
// 创建问候前缀
std::string prefix("Hello ");
// 将请求中的内容与前缀拼接,并设置为响应内容
reply->set_contents(prefix + request->contents());
// 返回表示成功的状态
return Status::OK;
}
};
// 设置并运行服务器的函数
void RunServer() {
std::string server_address("0.0.0.0:50051"); // 服务器监听的地址和端口
GreeterServiceImpl service; // 创建 Greeter 服务的实现实例
// 启用默认健康检查服务
grpc::EnableDefaultHealthCheckService(true);
// 初始化 gRPC 服务器反射插件以支持反射功能
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
ServerBuilder builder; // 创建 ServerBuilder 对象
// 将监听端口和不安全凭证添加到服务器构建器
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// 在服务器构建器中注册服务实例
builder.RegisterService(&service);
// 构建并启动服务器
std::unique_ptr<Server> server(builder.BuildAndStart());
// 输出服务器的监听地址
std::cout << "Server listening on " << server_address << std::endl;
// 阻塞当前线程,直到服务器关闭
// 服务器会一直运行,直到由其他线程显式关闭
server->Wait();
}
// 程序的入口点
int main(int argc, char** argv) {
// 启动服务器
RunServer();
// 返回成功的状态码
return 0;
}
(5) 客户端代码
#include <string> // 包含 std::string 类,用于字符串操作
#include <iostream> // 包含输入输出流操作所需的头文件
#include <memory> // 包含智能指针(如 std::unique_ptr)的支持
#include <grpcpp/grpcpp.h> // 包含 gRPC 核心功能的头文件
#include "server.grpc.pb.h" // 包含由 .proto 文件生成的头文件
using grpc::ClientContext; // 使用 gRPC ClientContext 类
using grpc::Channel; // 使用 gRPC Channel 类
using grpc::Status; // 使用 gRPC Status 类
using myserver::HelloRepose; // 使用从 .proto 文件生成的 HelloRepose 消息类
using myserver::HelloRequest; // 使用从 .proto 文件生成的 HelloRequest 消息类
using myserver::Greeter; // 使用从 .proto 文件生成的 Greeter 服务类
// FCClient 类,封装了与 gRPC 服务器的通信
class FCClient {
public:
// 构造函数,接受一个共享的 Channel 对象,创建 Greeter 的 Stub
FCClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {
}
// 发送 SayHello 请求到 gRPC 服务器
std::string SayHello(std::string name) {
ClientContext context; // 创建客户端上下文对象
HelloRepose reply; // 用于接收服务器响应的对象
HelloRequest request; // 创建请求对象并设置内容
request.set_contents(name); // 将传入的名字设置到请求中
// 调用 gRPC 服务方法 SayHello 并获取响应
Status status = stub_->SayHello(&context, request, &reply);
if (status.ok()) {
// 如果请求成功,返回响应中的内容
return reply.contents();
} else {
// 如果请求失败,返回错误信息
return "failure " + status.error_message();
}
}
private:
std::unique_ptr<Greeter::Stub> stub_; // 用于调用 gRPC 服务的 Stub
};
// 程序的入口点
int main(int argc, char* argv[]) {
// 创建与 gRPC 服务器的通道,并指定服务器地址和使用的不安全凭证
auto channel = grpc::CreateChannel("127.0.0.1:50051", grpc::InsecureChannelCredentials());
FCClient client(channel); // 创建 FCClient 实例
// 调用 SayHello 方法并阻塞,直到从 RPC 服务器获取结果
std::string result = client.SayHello("hello , llfc.club !");
// 输出结果
printf("get result [%s]\n", result.c_str());
return 0; // 返回成功状态码
}
(6)CmakeLists文件编写
在linux端采用cmake来编译服务器端和客户端的代码。cmakelists文件如下。
cmake_minimum_required(VERSION 3.1)
project(GrpcClient LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#假设已经安装好grpc了
find_package(Threads REQUIRED)
set(protobuf_MODULE_COMPATIBLE TRUE)
find_package(Protobuf CONFIG REQUIRED)
message(STATUS "Using protobuf ${Protobuf_VERSION}")
set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
set(_REFLECTION gRPC::grpc++_reflection)
# Find gRPC installation
# Looks for gRPCConfig.cmake file installed by gRPC's cmake installation.
find_package(gRPC CONFIG REQUIRED)
message(STATUS "Using gRPC ${gRPC_VERSION}")
set(_GRPC_GRPCPP gRPC::grpc++)
# 添加可执行文件和源文件
file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB PBSOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
add_executable(GrpcClient ${SOURCES}
${PBSOURCES})
target_link_libraries(GrpcClient
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF})
将该文件分别放到,服务器端和客户端的项目文件夹下,比如:
在该目录下打开终端。执行如下命令生成可执行文件
<code>mkdir build
cd ./build
cmake ../
make
可执行就会生成在build文件夹下。
服务器启动
客户端启动并收到服务器的回应
总结,以上就是grpc在linux系统下的编译与简单应用,grpc主要用在服务器上各个服务之间的通信,基于http2,支持异步和同步,效率比较高。
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。