前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >【C++】开源:grpc远程过程调用(RPC)配置与使用

【C++】开源:grpc远程过程调用(RPC)配置与使用

作者头像
DevFrank
发布于 2024-07-24 07:32:22
发布于 2024-07-24 07:32:22
41300
代码可运行
举报
运行总次数:0
代码可运行

😏1. 项目介绍

项目Github地址:https://github.com/grpc/grpc

官网:https://grpc.io/

中文文档:https://doc.oschina.net/grpc?t=57966

gRPC是一个高性能、开源的远程过程调用(RPC)框架,由Google开发并基于Protocol Buffers实现。它可以在客户端和服务器之间进行快速、有效的通信,并支持多种编程语言。gRPC的设计目标是让开发者能够像调用本地函数一样调用远程服务,从而简化分布式系统的开发。

以下是gRPC的主要特点和优势:

1.高效性能:gRPC使用基于HTTP/2的协议进行通信,支持双向流、流式处理和多路复用等特性,从而实现了更高效的数据传输和低延迟的通信。

2.强大的IDL(接口定义语言):gRPC使用Protocol Buffers作为其默认的IDL,它提供了简单、轻量级的数据交换格式,并通过代码生成工具生成符合各种编程语言的代码。这使得开发者可以轻松定义服务接口和数据结构,并自动生成相应的代码。

3.多语言支持:gRPC支持多种编程语言,包括但不限于Java、C++、Python、Go、Node.js等,这使得不同语言的应用程序可以无缝地进行通信和集成。

4.支持多种服务类型:gRPC支持四种服务类型:Unary、Server Streaming、Client Streaming和Bidirectional Streaming。这使得开发者可以根据实际需求选择最适合的服务类型,并实现灵活的数据传输方式。

5.可插拔的认证和流控制:gRPC提供了可插拔的认证机制,可以基于SSL/TLS进行安全通信。此外,还支持流控制、拦截器、错误处理等功能,使得开发者可以更好地控制和管理通信过程。

6.丰富的生态系统:gRPC拥有活跃的社区和广泛的应用场景,许多知名公司和项目都在使用gRPC。这意味着你可以从丰富的资源中获取支持、文档和示例代码,从而更好地学习和使用gRPC。

总结起来,gRPC是一个强大的远程过程调用框架,它具有高效性能、强大的IDL、多语言支持、多种服务类型和丰富的生态系统。通过使用gRPC,开发者可以轻松构建高性能、可扩展的分布式系统,并简化不同语言之间的通信和集成。

😊2. 环境配置

下面进行环境配置,包括apt安装和源码安装:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# apt安装
sudo apt install protobuf-compiler-grpc libgrpc++-dev
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 安装依赖
sudo apt install build-essential autoconf libtool pkg-config
# 源码安装
git clone --recurse-submodules -b v1.56.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc
cd grpc
mkdir -p cmake/build
cd cmake/build
cmake -DgRPC_INSTALL=ON \
      -DgRPC_BUILD_TESTS=OFF \
      -DCMAKE_INSTALL_PREFIX=$MY_INSTALL_DIR \
      ../..
make -j4
sudo make install
sudo ldconfig

测试代码,验证版本:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <grpcpp/grpcpp.h>

int main() {
  std::cout << "gRPC version: " << grpc_version_string() << std::endl;
  return 0;
}

编译运行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
g++ -o main main.cpp -lgrpc++ -lgrpc -lprotobuf -lpthread  && ./main

😆3. 使用说明

源码提供了一些案例,在example,可在此基础上扩充服务信息,即更改proto相关协议,用法跟protobuf类似。

example官方示例:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cd examples/cpp/helloworld
mkdir -p cmake/build
cd cmake/build
cmake -DCMAKE_PREFIX_PATH=$MY_INSTALL_DIR ../..
make -j4
# 运行
./greeter_server
./greeter_client
# 结果
Greeter received: Hello world
服务端和客户端调用示例:

因为grpc也是用protobuf作为数据序列化协议,所以先创建helloworld.proto

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
syntax = "proto3";

package helloworld;

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

使用protobuf-grpc编译器生成c++代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protoc -I=. --cpp_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto

服务端示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#include "helloworld.grpc.pb.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;

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;
    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()
{
    RunServer();
    return 0;
}

客户端示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#include "helloworld.grpc.pb.h"

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;

class GreeterClient
{
public:
    GreeterClient(std::shared_ptr<Channel> channel)
        : stub_(Greeter::NewStub(channel)) {}

    std::string SayHello(const std::string &name)
    {
        HelloRequest request;
        request.set_name(name);

        HelloReply reply;
        ClientContext context;

        Status status = stub_->SayHello(&context, request, &reply);
        if (status.ok())
        {
            return reply.message();
        }
        else
        {
            return "RPC failed";
        }
    }

private:
    std::unique_ptr<Greeter::Stub> stub_;
};

int main()
{
    std::string server_address("localhost:50051");
    GreeterClient greeter(grpc::CreateChannel(
        server_address, grpc::InsecureChannelCredentials()));
    std::string user("World");

    std::string reply = greeter.SayHello(user);
    std::cout << "Server replied: " << reply << std::endl;

    return 0;
}

编译:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
g++ server.cpp helloworld.grpc.pb.cc helloworld.pb.cc -lgrpc++ -lgrpc -lprotobuf -lpthread -o server
g++ client.cpp helloworld.grpc.pb.cc helloworld.pb.cc -lgrpc++ -lgrpc -lprotobuf -lpthread -o client
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-11-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
解读Nginx:深入剖析HTTP启动流程
1、遇到conf文件的http模块。http不是在Nginx的mian函数中启动,而是解析conf文件时遇到http才会去解析并启动。
Lion Long
2025/01/08
1240
解读Nginx:深入剖析HTTP启动流程
十一长假精荐!--nginx http请求PHASE
当客户端的一个request到达服务器的时候,可以想象一下,一个服务器应该怎么处理这个请求呢?nginx又是怎么处理请求的呢?
后端技术探索
2018/08/09
8070
nginx0.1.0之event模块初始化源码分析(2)
本文分析nginx的event在初始化时的第一个步骤,就是执行每个类型为NGX_EVENT_MODULE的模块的create_conf函数。该版本一共有8个这样的模块。下面我们看一下各个模块create_conf函数的代码。 这是ngx_event_core_module模块的create_conf函数。
theanarkh
2019/03/06
4290
nginx0.1.0之http模块初始化源码分析(5)
继续http模块的分析,这次分析的是init_module钩子函数的执行。http模块各子模块的init_module钩子主要做的事情是两个,一个就是注册phases回调,一个就是挂载模块到filter链表。首先看一下注册phases回调的模块 access模块
theanarkh
2019/03/06
4110
nginx0.1.0之http模块初始化源码分析(1)
http模块的初始化类似event模块,初始化的起点在解析到http指令的时候。对应的处理函数是ngx_http_block,因为该函数比较长,所以我们分段解析。第一部分先解析http模块的pre_conf、create_main_conf函数的实现。
theanarkh
2019/03/06
5980
nginx0.1.0之event模块初始化源码分析(4)
event的配置解析相关的代码已经分析完毕。下面分析一下另一个流程中event模块的实现。即在nginx创建进程,并且开始执行进程里的代码的时候。入口函数是ngx_worker_process_cycle。
theanarkh
2019/03/06
3900
【Nginx 源码学习】平滑重启,源码追踪
重启意味着新旧接替,在交接任务的过程中势必会存在新旧server并存的情形,因此,最主要的问题在于如何保证新旧server可以并存,如果重启前后的server端口一致,如何保证两者可以监听同一端口。
看、未来
2022/05/06
8210
【Nginx 源码学习】平滑重启,源码追踪
nginx0.1.0之http模块初始化源码分析(3)
我们继续分析ngx_http_block函数的代码,指令解析完,继续执行各子模块的钩子函数。
theanarkh
2019/03/06
5290
深入理解nginx realip模块
  nginx 的 Real IP 模块用于解决代理服务器转发请求到nginx上时可能出现的 IP 地址问题。因为当 PROXY收到客户端的请求时,它会通过自己的IP与nginx服务器连接并转发请求。这会导致在nginx应用程序中记录的 IP 地址是代理服务器的地址,而不是实际客户端的地址。
码农心语
2024/04/10
1.3K0
深入理解nginx realip模块
nginx日志模块源码分析
请求在处理结束时,会按请求路径的配置上下文记访问日志。 如果在请求处理期间产生了内部跳转(参考另一篇nginx跳转讲述), 请求结束时的路径可能不同于原始的请求路径。
stan1ey
2021/06/07
1.6K0
nginx日志模块源码分析
Nginx(六):配置解析之location解析
nginx成为非常流行的代理服务软件,最根本的原因也许是在于其强悍性能。但还有一些必要的条件,比如功能的完整,配置的易用,能够解决各种各样的实际需求问题,这些是一个好的软件的必备特性。
烂猪皮
2021/01/28
2K0
Nginx(六):配置解析之location解析
nginx0.1.0之http模块初始化源码分析(2)
本文讲解http各个模块create_srv_conf和create_loc_conf钩子,还有指令的解析。 各模块的create_srv_conf和create_loc_conf函数逻辑都类似,不一一列举,执行完后内存视图是。
theanarkh
2019/03/06
3870
nginx0.1.0之event模块初始化源码分析(1)
nginx模块初始化的流程在下面的代码中,核心模块的初始化,各核心模块首先在create_conf中创建保存配置的数据结构,然后在ngx_conf_parse中,通过解析命令,执行对应的命令处理函数,完成赋值和各核心模块的子模块初始化。最后,如果在ngx_conf_parse时,没有设置值,则执行init_conf函数进行默认初始化。
theanarkh
2019/03/06
4910
nginx0.1.0之event模块初始化源码分析(3)
前面已经分析了event初始化的整体流程和第一步create_conf,接下来看一下第二步ngx_conf_parse。这里不分析该函数的代码,该函数主要是遍历配置文件的内容,然后读取命令和参数。最后匹配nginx所有模块的配置,找到处理该指令的函数。我们首先看一下event模块中ngx_event_core_module模块的指令配置。
theanarkh
2019/03/06
5680
nginx0.1.0 access_handler模块源码分析
access模块主要是对连接到nginx中的客户端进行权限管理,nginx会根据access模块注册的命令,在解析命令的时候,遇到对应的命令的时候,会调用access注册的处理函数,access模块的处理函数会解析并记录这些配置,然后在每个连接到来时,判断ip是否在封禁的池子了。nginx只判断deny的规则,即同一个ip命中多条规则的时候,只要有一条是deny则结果就是deny。即deny优先。
theanarkh
2019/04/24
4070
nginx源代码分析–模块分类
比方。对一个普通的訪问本地静态文件的请求处理,从 Nginx 收到请求并開始处理。到处 理结果的响应包体发送到网络上结束,整个过程的两个步骤 – 请求处理和响应处理 – 分别 由 handler 和 filter 处理完毕。
全栈程序员站长
2022/07/07
7230
nginx处理http请求十一个阶段流程源码分析
使用 ngx_http_phase_t 结构存储每个阶段可用的处理函数(handler)。
stan1ey
2021/06/07
1.4K0
nginx处理http请求十一个阶段流程源码分析
nginx1.17.9源码分析之线程池
我们发现事件驱动的软件都得配一个线程池。libuv和nginx都是。因为事件驱动的软件是单线程。但是有些事情总会引起线程阻塞。所以这个事情就不能放到主线程里做。这就是为什么事件驱动都要配一个线程池。把任务交给线程池中的线程。主线程继续执行。任务完成后通知主线程或者执行回调就行。 我们先看一下nginx线程池的架构。然后开始分析。
theanarkh
2020/03/31
5940
nginx1.17.9源码分析之线程池
深入理解nginx的https sni机制
  SNI(Server Name Indication)是一种TLS(Transport Layer Security)协议的扩展,用于在建立加密连接时指定服务器的主机名。在使用单个IP地址和端口提供多个域名的服务时,SNI是非常有用的。  当客户端发起TLS握手时,它会发送一个包含所请求主机名的扩展,这样服务器就可以根据这个主机名选择合适的证书来完成握手。这使得服务器能够在同一IP地址和端口上为多个域名提供加密连接,而不需要为每个域名分配一个独立的IP地址。  对于HTTPS网站来说,SNI是至关重要的,因为它允许服务器在同一IP地址上为多个域名提供加密连接,不需要为每个域名单独部署一台服务器,从而降低了运维成本并提高了灵活性。  在使用SNI时,服务器端必须能够根据客户端发送的SNI信息来选择正确的证书进行握手。通常,服务器端配置会包含多个虚拟主机的证书信息,以便根据收到的SNI信息选择正确的证书来完成握手。  总的来说,SNI允许客户端在TLS握手期间指定所请求的主机名,从而使服务器能够根据主机名选择正确的证书,实现一个IP地址上多个域名的加密连接。
码农心语
2024/04/09
3.1K1
深入理解nginx的https sni机制
nginx proxy_bind支持多ip绑定
proxy_bind隶属于proxy_module,为向后端建立连接时的local ip,在nginx源码中只支持bind一个ip进行回源,若想使用多个ip进行回源时,可以修改源码支持bind ip数组。在实际应用中我就是这样做的。bind ip数据轮询选择ip进行回源与upstream建立连接,以解决单ip回源连接数限制问题。下面proxy_bind部分就是针对proxy_bind进行优化后的代码,支持bind多ip。
stan1ey
2021/06/07
4.4K0
nginx proxy_bind支持多ip绑定
推荐阅读
相关推荐
解读Nginx:深入剖析HTTP启动流程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验