【微服务即时通讯系统】——brpc远程过程调用、百度开源的RPC框架、brpc的介绍、brpc的安装、brpc使用和功能测试

文章目录

  • brpc
    • 1. brpc的介绍
      • 1.1 rpc的介绍
      • 1.2 rpc的原理
      • 1.3 grpc和brpc
    • 2. brpc的安装
    • 3. brpc使用
      • 3.1 brpc接口介绍
    • 4. brpc使用测试
      • 4.1 brpc同步和异步调用

brpc

在这里插入图片描述
  

1. brpc的介绍

1.1 rpc的介绍

  RPC(Remote Procedure Call)远程过程调用,是一种计算机通信协议,它允许程序在不同的计算机之间进行通信和交互,就像本地调用一样。

  RPC可以屏蔽了底层的网络通信细节,使得程序间的远程通信如同本地调用一样简单。RPC机制使得开发者能够构建分布式计算系统,其中不同的组件可以分布在不同的计算机上,但它们之间可以像在同一台机器上一样相互调用。

  

1.2 rpc的原理

  服务提供者实现特定业务逻辑并注册到服务中心。

  服务中心接收注册信息,为服务消费者提供服务发现通知和负载均衡功能。

  服务消费者向服务中心查询服务订阅后,通过 RPC 机制发起对服务提供者的远程调用,接收并处理结果。

  
在这里插入图片描述

  

   rpc一次调用的过程
  
  在 RPC(远程过程调用)机制中,客户端以接口方式调用服务。客户端存根在接收到调用请求后,将方法、入参等信息组装并序列化成可网络传输的消息体(二进制流),然后找到远程服务地址,通过网络(sockets)将消息发送给服务端。

  服务端存根收到消息后进行反序列化操作(将二进制流反序列化为消息对象),接着调用本地服务进行处理。服务端将处理结果返回给服务端存根,服务端存根序列化处理结果(将结果消息对象序列化为二进制流)。

  再通过网络(sockets)发送至客户端。客户端存根接收到消息后进行反序列化解码(将结果二进制流反序列化为消息对象),最终客户端得到结果。

  
在这里插入图片描述

  

1.3 grpc和brpc

  gRPC

  由 Google 开发并开源。

  支持 C++、Java、Python、Go

  使用 Protocol Buffers 作为默认的接口定义语言和数据序列化格式。

  基于 HTTP/2 协议,支持双向流和多路复用,能够有效地提高网络传输效率。

  适用于构建分布式系统、微服务架构等场景。

  

  bRPC

  由 Baidu 开发并开源。

  只支持 C++

  使用 Protocol Buffers 作为默认的接口定义语言和数据序列化格式。

  可以在一个端口上支持多协议服务,如 HTTP/HTTPS、Redis、Thrift 等,具有很高的灵活性。

  提供了一些独特的功能,如通过 HTTP 界面调试服务、使用各种性能分析工具等。

  适用于搜索、存储、机器学习等高性能系统的开发。

  

2. brpc的安装

  在 Linux 系统(ubuntu) 上安装 brpc 的基本步骤:
  
  先安装依赖:

sudo apt-get install -y git g++ make libssl-dev libprotobuf-dev libprotoc-dev protobuf-compiler libleveldb-dev

  安装 brpc:

git clone https://github.com/apache/brpc.git
cd brpc/
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr .. 
cmake --build . -j6
make && sudo make install

  

3. brpc使用

3.1 brpc接口介绍

  日志输出类与接口:

  包含头文件: #include <butil/logging.h>

namespace logging {
enum LoggingDestination {
 LOG_TO_NONE = 0
};
struct BUTIL_EXPORT LoggingSettings {
 LoggingSettings();
 LoggingDestination logging_dest;
};
bool InitLogging(const LoggingSettings& settings);
}

  
  protobuf 类与接口:

namespace google {
namespace protobuf {
 class PROTOBUF_EXPORT Closure {
 public:
 Closure() {}
 virtual ~Closure();
 virtual void Run() = 0;
};
inline Closure* NewCallback(void (*function)());
class PROTOBUF_EXPORT RpcController {
 bool Failed();
 std::string ErrorText() ;
} 
} 
}

  
  服务端类与接口:

namespace brpc {
struct ServerOptions {
 //无数据传输,则指定时间后关闭连接
 int idle_timeout_sec; // Default: -1 (disabled)
 int num_threads; // Default: #cpu-cores
 //....
}
enum ServiceOwnership {
 //添加服务失败时,服务器将负责删除服务对象
 SERVER_OWNS_SERVICE,
 //添加服务失败时,服务器也不会删除服务对象
 SERVER_DOESNT_OWN_SERVICE
};
class Server {
 int AddService(google::protobuf::Service* service,
 ServiceOwnership ownership);
 int Start(int port, const ServerOptions* opt);
 int Stop(int closewait_ms/*not used anymore*/);
 int Join();
 //休眠直到 ctrl+c 按下,或者 stop 和 join 服务器
 void RunUntilAskedToQuit();
} 
class ClosureGuard {
 explicit ClosureGuard(google::protobuf::Closure* done);
 ~ClosureGuard() { if (_done) _done->Run(); }
} 
class HttpHeader {
 void set_content_type(const std::string& type)
 const std::string* GetHeader(const std::string& key)
 void SetHeader(const std::string& key, 
 const std::string& value);
 const URI& uri() const { return _uri; }
 HttpMethod method() const { return _method; }
 void set_method(const HttpMethod method)
 int status_code()
 void set_status_code(int status_code);
 
} 
class Controller : public google::protobuf::RpcController {
 void set_timeout_ms(int64_t timeout_ms);
 void set_max_retry(int max_retry);
 google::protobuf::Message* response();
 HttpHeader& http_response();
 HttpHeader& http_request();
 bool Failed();
 std::string ErrorText();
 
 using AfterRpcRespFnType = std::function<
 void(Controller* cntl,
 const google::protobuf::Message* req,
 const google::protobuf::Message* res)>;
  void set_after_rpc_resp_fn(AfterRpcRespFnType&& fn)
}

  
  客户端类与接口:

namespace brpc {
struct ChannelOptions {
 //请求连接超时时间
 int32_t connect_timeout_ms;// Default: 200 (milliseconds)
 //rpc 请求超时时间
 int32_t timeout_ms;// Default: 500 (milliseconds)
 //最大重试次数
 int max_retry;// Default: 3
 //序列化协议类型 options.protocol = "baidu_std";
 AdaptiveProtocolType protocol;
 //....
} 
class Channel : public ChannelBase {
 //初始化接口,成功返回 0;
 int Init(const char* server_addr_and_port, 
 const ChannelOptions* options);

  

4. brpc使用测试

4.1 brpc同步和异步调用

  server.hpp

#include <brpc/server.h>
#include <butil/logging.h>
#include "main.pb.h"

// 1. 继承于EchoService创建一个子类,并实现rpc调用的业务功能
class EchoServiceImpl : public example::EchoService 
{
    public:
        EchoServiceImpl(){}
        ~EchoServiceImpl(){}

        void Echo(google::protobuf::RpcController* controller,
                       const ::example::EchoRequest* request,
                       ::example::EchoResponse* response,
                       ::google::protobuf::Closure* done) {
            brpc::ClosureGuard rpc_guard(done); // 对象析构时自动调用done->Run()
            std::cout << "收到消息:" << request->message() << std::endl;

            std::string str = request->message() + "--这是响应!!";
            response->set_message(str);
            //done->Run();
        }
};

int main(int argc, char *argv[])
{
    // 关闭brpc的默认日志输出
    logging::LoggingSettings settings;
    settings.logging_dest = logging::LoggingDestination::LOG_TO_NONE;
    logging::InitLogging(settings);

    // 2. 构造服务器对象
    brpc::Server server;

    // 3. 向服务器对象中,新增EchoService服务
    EchoServiceImpl echo_service; // 添加服务失败时,服务器不会删除服务对象
    int ret = server.AddService(&echo_service, brpc::ServiceOwnership::SERVER_DOESNT_OWN_SERVICE);
    if (ret == -1) 
    {
        std::cout << "添加Rpc服务失败!\n";
        return -1;
    }
    
    // 4. 启动服务器
    brpc::ServerOptions options;
    options.idle_timeout_sec = -1; // 连接空闲超时时间-超时后连接被关闭
    options.num_threads = 1; // io线程数量
    ret = server.Start(8080, &options);
    if (ret == -1) 
    {
        std::cout << "启动服务器失败!\n";
        return -1;
    }

    server.RunUntilAskedToQuit(); // 休眠等待运行结束,避免对SIGINT信号进行处理

    return 0;
}

  makefile:

all : server client
server : server.cc main.pb.cc
	g++ -std=c++17 $^ -o $@ -lbrpc -lgflags -lssl -lcrypto -lprotobuf -lleveldb
client : client.cc main.pb.cc
	g++ -std=c++17 $^ -o $@ -lbrpc -lgflags -lssl -lcrypto -lprotobuf -lleveldb

  

  同步调用:同步调用是指客户端会阻塞收到 server 端的响应或发生错误。

#include <brpc/channel.h>
#include <thread>
#include "main.pb.h"

int main(int argc, char *argv[])
{
    // 1. 构造Channel信道,连接服务器
    brpc::ChannelOptions options;
    options.connect_timeout_ms = -1; // 连接等待超时时间,-1表示一直等待
    options.timeout_ms = -1; // rpc请求等待超时时间,-1表示一直等待
    options.max_retry = 3; // 请求重试次数
    options.protocol = "baidu_std"; // 序列化协议,默认使用baidu_std
    brpc::Channel channel;
    int ret = channel.Init("127.0.0.1:8080", &options);
    if (ret == -1) 
    {
        std::cout << "初始化信道失败!\n";
        return -1;
    }
    
    // 2. 构造EchoService_Stub对象,用于进行rpc调用
    example::EchoService_Stub stub(&channel);
    
    // 3. 进行Rpc调用
    example::EchoRequest req;
    req.set_message("你好~brpc~!");

    brpc::Controller cntl;
    example::EchoResponse rsp;
    stub.Echo(&cntl, &req, &rsp, nullptr); // 同步调用
    if (cntl.Failed() == true) {
        std::cout << "Rpc调用失败:" << cntl.ErrorText() << std::endl;
        return -1;
    }
    std::cout << "同步调用结束!\n";
    std::cout << "收到响应: " << rsp.message() << std::endl;
    
    return 0;
}

  
在这里插入图片描述
  
在这里插入图片描述

  

  异步调用:异步调用是指客户端注册一个响应处理回调函数, 当调用一个 RPC 接口时立即返回,不会阻塞等待响应, 当 server 端返回响应时会调用传入的回调函数处理响应。

#include <brpc/channel.h>
#include <thread>
#include "main.pb.h"

// 这个回调函数用于异步调用对象使用
void callback(brpc::Controller* cntl, ::example::EchoResponse* response) 
{
    std::unique_ptr<brpc::Controller> cntl_guard(cntl);
    std::unique_ptr<example::EchoResponse> resp_guard(response);
    if (cntl->Failed() == true) 
    {
        std::cout << "Rpc调用失败:" << cntl->ErrorText() << std::endl;
        return;
    }
    std::cout << "收到响应: " << response->message() << std::endl;
    // delete cntl;
    // delete response;
}

int main(int argc, char *argv[])
{
    // 1. 构造Channel信道,连接服务器
    brpc::ChannelOptions options;
    options.connect_timeout_ms = -1; // 连接等待超时时间,-1表示一直等待
    options.timeout_ms = -1; // rpc请求等待超时时间,-1表示一直等待
    options.max_retry = 3; // 请求重试次数
    options.protocol = "baidu_std"; // 序列化协议,默认使用baidu_std
    brpc::Channel channel;
    int ret = channel.Init("127.0.0.1:8080", &options);
    if (ret == -1) 
    {
        std::cout << "初始化信道失败!\n";
        return -1;
    }
    
    // 2. 构造EchoService_Stub对象,用于进行rpc调用
    example::EchoService_Stub stub(&channel);
    
    // 3. 进行Rpc调用
    example::EchoRequest req;
    req.set_message("你好~brpc~!");

    // 防止异步调用时 cnt rsp 出作用域被销毁,要在堆上创建对象
    brpc::Controller *cntl = new brpc::Controller();
    example::EchoResponse *rsp = new example::EchoResponse();

    auto clusure = google::protobuf::NewCallback(callback, cntl, rsp); // 异步调用对象
    stub.Echo(cntl, &req, rsp, clusure); // 异步调用
    std::cout << "异步调用结束!\n";
    std::this_thread::sleep_for(std::chrono::seconds(3));
    
    return 0;
}

  
在这里插入图片描述
  
在这里插入图片描述

            

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/884795.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在线远程考试|基于springBoot的在线远程考试系统设计与实现(附项目源码+论文+数据库)

私信或留言即免费送开题报告和任务书&#xff08;可指定任意题目&#xff09; 目录 一、摘要 二、相关技术 三、系统设计 四、数据库设计 五、核心代码 六、论文参考 七、源码获取 一、摘要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突…

常用的cmd命令——使用bat命令创建程序的快捷方式

示例使用场景&#xff1a;例如便携版的软件&#xff0c;需要往桌面发快捷方式 如便携的浏览器&#xff0c;给桌面发送快捷方式&#xff0c;同时设置快捷方式的启动参数。 下面以谷歌浏览器为例&#xff1a; 浏览器的App的下级目录为如下内容 知道了所需文件的位置&#xff0c;…

实在智能:创业需找准“切口” 并着力做深做透

如今&#xff0c;随着人工智能产业的爆发&#xff0c;大量专注于这一领域的初创企业不断涌现。尽管这种多元化的创新生态为产业发展注入了新的活力&#xff0c;但也不可避免的为初创企业带来了诸多压力和挑战。 浙江实在智能科技有限公司(以下简称“实在智能”)作为一家成立6年…

近万字深入讲解iOS常见锁及线程安全

什么是锁&#xff1f; 在程序中&#xff0c;当多个任务&#xff08;或线程&#xff09;同时访问同一个资源时&#xff0c;比如多个操作同时修改一份数据&#xff0c;可能会导致数据不一致。这时候&#xff0c;我们需要“锁”来确保同一时间只有一个任务能够操作这个数据&#…

文档翻译软件哪个好用?高效翻译看这里

文档翻译对打工人来说是件很头疼的事情吧&#xff1f;不仅是因为复杂的专业词汇&#xff0c;还因为不同语言之间的表达方式差异&#xff0c;使得翻译工作变得异常繁琐。 不过&#xff0c;幸运的是&#xff0c;现在有许多在线工具可以帮助我们轻松地翻译文档。 这些工具大多数…

【Linux】ubuntu 16.04 搭建jdk 11 环境(亲测可用)

目录 0.环境 1.题外话 2.详细 0.环境 windows11 主机 Virtual Box 7.0 ubuntu 16.04系统 想搭建个 jdk11的环境&#xff0c;用于项目 1.题外话 因为虚拟机与主机传输文件不方便&#xff0c;所以可以尝试用共享文件夹的方式传输&#xff0c;亲测可用&#xff0c;参考以下博…

C# 游戏引擎中的协程

前言 书接上回&#xff0c;我谈到了Unity中的协程的重要性&#xff0c;虽然协程不是游戏开发“必要的”&#xff0c;但是它可以在很多地方发挥优势。 为了在Godot找回熟悉的Unity协程开发手感&#xff0c;不得不自己做一个协程系统&#xff0c;幸运的是&#xff0c;有了Unity的…

探索顶级低代码开发平台,实现创新

文章盘点ZohoCreator、OutSystems等10款顶尖低代码开发平台&#xff0c;各平台以快速开发、集成、数据安全等为主要特点&#xff0c;适用于不同企业需求&#xff0c;助力数字化转型。 一、Zoho Creator Zoho Creator 是一个低代码开发平台&#xff0c;它简化了应用开发中的复杂…

PK过Google、Facebook,YouTube竟然是外贸引流营销的新前景

在如今的外贸行业中&#xff0c;广告投放已经成为商家吸引客户和提高销量的重要工具。众所周知&#xff0c;Facebook和谷歌是广告投放的两大巨头平台。这两者以其强大的用户基数和广告精准性在市场上占据主导地位。然而&#xff0c;随着互联网的发展和消费趋势的改变&#xff0…

MongoDB 工具包安装(mongodb-database-tools)

首先到官网下载工具包&#xff0c;进入下面页面&#xff0c;复制连接地址&#xff0c;使用wget下载 cd /usr/local/mongodb5.0.14/wget https://fastdl.mongodb.org/tools/db/mongodb-database-tools-rhel70-x86_64-100.6.1.tgz 安装 tar -zxvf mongodb-database-tools-rhel70-…

《北方牧业》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《中国动物检疫》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊。 问&#xff1a;《中国动物检疫》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;河北省畜牧局 主办单…

【rust】 基于rust编写wasm,实现markdown转换为html文本

文章目录 背景转换预览核心代码前置依赖rustup换源 cargo本地路径修改&#xff08;可选&#xff09;cargo换源中科大 wasm-pack安装 背景 尝试用rust编写一款markdown转html的插件&#xff0c;通过wasm给html使用&#xff0c;不得不说体积挺小&#xff0c;约200K&#xff0c; …

spring cloud Gateway网关

网关是将所有面向用户的服务接口统一管理的代理服务器&#xff0c;所有内部服务的远程调用都是在局域网内部&#xff0c;而网关是在公网中。 一、依赖 通过访问网关调用项目中的服务&#xff0c;需要使用Eureka&#xff0c;网关服务器需要在Eureka服务注册它自己&#xff0c;本…

Clipboard.js实现复制文本到剪贴板功能

一、Clipboard.js简介 Clipboard.js是一个轻量级的实现复制文本到剪贴板功能的JavaScript插件&#xff0c;该插件可以将输入框&#xff0c;文本域&#xff0c;DOM节点元素中的文本内容复制到剪贴板中。 官网地址&#xff1a;Clipboard.js 浏览器兼容性&#xff1a;兼容Chrome、…

Ubuntu环境切换到服务器某个用户后source等命令和Tab快捷补全都用不了了,提示没找到,但root用户可以

以escs用户为例&#xff1a; 输入以下命令 grep root /etc/passwd grep escs /etc/passwd 对比发现&#xff0c;root用户配的是bash&#xff0c;而escs却是sh&#xff0c; 所以把escs的sh改成和root一样的bash&#xff0c;命令为 usermod -s /bin/bash escs 改好后就可以了。 …

VSCODE驯服日记(三):配置C++环境

1. 下载mingw64&#xff0c;解压后把bin并添加到环境变量 1>编译器介绍 mingw&#xff1a;专为windowsgcc&#xff1a;多平台msvc &#xff1a;windows&#xff0c;且配合vs使用更佳 注意与调试器gdb和lldb的区别 2. 安装vscode插件&#xff1a; 安装C/C插件 安装code ru…

测试管理新增视图与高级搜索功能,测试计划支持一键生成缺陷详情,MeterSphere开源持续测试工具v3.3版本发布

2024年9月29日&#xff0c;MeterSphere开源持续测试工具正式发布v3.3版本。 在这一版本中&#xff0c;接口测试方面&#xff0c;接口导入功能支持导入Postman、JMX、HAR和MeterSphere格式的文件&#xff0c;接口场景的自定义请求步骤支持cURL快捷导入&#xff1b;测试管理方面…

基于趋近律的滑模控制器设计、仿真(S-function)

目录 一、什么是滑模控制?1. 滑模面2. 控制策略3. 抗干扰和鲁棒性4. 滑模控制的应用 二、什么是趋近律&#xff1f;1. 趋近律三大设计目标2. 常见的趋近律形式1. 等速趋近律2. 指数趋近律3. 幂次趋近律 三、滑模控制器设计四、滑模仿真示例1. Simulink仿真框图2. 不同k值下的仿…

MAC如何获取文件数字签名和进程名称

1、安装需要查看数字签名和进程名称的软件包 2、打开终端命令行&#xff08;Terminal&#xff09; 3、查找数字签名 在终端命令行中输入&#xff1a; codesign -dvv 安装的软件路径 2>&1 | grep "Authority" | head -n 1 | cut -d -f2”回显即为进程的数…

kafka发送消费核心参数与设计原理详解

核心参数详解: 发送端参数: 发送方式:默认值一般都是1: 重试参数 : 批量参数: 消费端参数: 自动提交参数: 如果是false,就是说消费完后不提交位移。也就是说比如之前消费的1-5.第N次还是消费到1-5.如果是false。那么第一次消费1-3,第二次消费4-5:默认是true:我们…