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

news2024/12/24 20:54:25

文章目录

  • 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.coloradmin.cn/o/2168699.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

铝壳电阻是什么?

铝壳电阻是常见的电子元件&#xff0c;广泛应用于各种电子设备和电路中。它的主要功能是将电能转化为热能&#xff0c;从而实现对电流的调节和控制。铝壳电阻具有许多优点&#xff0c;如稳定性好、散热性能优越、耐腐蚀等&#xff0c;因此在电子行业中得到了广泛的应用。 铝壳…

ERNIESpeed-128K在线智能聊天机器人项目(附源码)

本项目是基于百度千帆的智能聊天模型ERNIESpeed-128K开发的 一、技术栈 后端&#xff1a;java8springboot2.6.13 数据库&#xff1a;MongoDB 前端&#xff1a;vue2element-uimarked&#xff08;md格式&#xff09; 二、MongoDB与对话存储的设计 使用MongoDB来储存对话&am…

使用Ruby进行视频内容的自动化分析

在数字化时代&#xff0c;视频内容的爆炸性增长为数据分析带来了新的挑战和机遇。视频不仅是一种流行的娱乐形式&#xff0c;也是传递信息和知识的重要媒介。自动化视频内容分析能够为企业提供洞察力&#xff0c;帮助他们优化内容策略、提高用户参与度和增强市场竞争力。本文将…

基于二分查找的动态规划 leetcode 300.最长递增子序列(续)

封面解释&#xff1a;你看那一口口剑&#xff0c;像不像一个个子序列【狗头】 一。前置条件 阅读本文之前&#xff0c;建议先看一下上一篇文章&#xff1a; 基于二分查找的动态规划 leetcode 300.最长递增子序列-CSDN博客 起码把对应的leetcode题目、以及对应的官方题解二&a…

论文不会写怎么办?推荐这5款AI论文工具帮你一键搞定!

在当今的学术研究和写作领域&#xff0c;AI论文工具已经成为不可或缺的助手。这些工具不仅能够提高写作效率&#xff0c;还能帮助研究者生成高质量的论文。本文将推荐五款优秀的AI论文工具&#xff0c;并特别推荐千笔-AIPassPaper&#xff0c;以帮助读者更好地完成学术写作任务…

Go 1.19.4 序列化和反序列化-Day 16

1. 序列化和反序列化 1.1 序列化 1.1.1 什么是序列化 序列化它是一种将程序中的数据结构&#xff08;map、slice、array等&#xff09;或对象状态转换成一系列字节序列的过程&#xff0c;这些字节可以被存储或通过网络发送。 在GO中&#xff0c;序列化通常涉及到将结构体或其…

JavaSE——三代日期类(Date、Calendar、LocalDate、LocalTime、LocalDateTime、Instant)

目录 一、util包.Date类——第一代日期类 二、SimpleDateFormat——日期时间格式化 1.日期时间转换成字符串 2.字符串转换成日期时间 三、Calendar日历类——第二代日期类 1.Calendar类中常用的静态方法 2.设置指定的字段(不常用) 3.calendar.setTime()使用案例——获取…

总结拓展十二:SAP采购定价条件

第一节 采购定价条件 1.条件类型介绍 2.条件类型概念 条件类型&#xff08;Condition Technology&#xff09;是SAP中运用较多的配置技术&#xff0c;了解条件技术如何运作&#xff0c;有助于我们理解系统在不同情况下的行为和反应&#xff0c;条件技术广泛地应用于定价、文…

【论文_2000】REINFORCE 和 actor-critic 等策略梯度方法的局部收敛性证明

部分证明不太理解 SUTTON R S, MCALLESTER D A, SINGH S P, et al. Policy gradient methods for reinforcement learning with function approximation [C] // Advances in neural information processing systems, 2000: 1057-1063. 【PDF 链接】 文章目录 摘要引言1 策略梯…

Arthas jad(字节码文件反编译成源代码 )

文章目录 二、命令列表2.2 class/classloader相关命令2.2.1 jad&#xff08;字节码文件反编译成源代码 &#xff09;举例1&#xff1a;反编译指定的函数 &#xff1a;jad com.hero.lte.ems.sysmanager.cache.SMTaskCache executeTask举例2&#xff1a;反编绎时只显示源代码&…

PCIe扫盲(14)

系列文章目录 PCIe扫盲&#xff08;一&#xff09; PCIe扫盲&#xff08;二&#xff09; PCIe扫盲&#xff08;三&#xff09; PCIe扫盲&#xff08;四&#xff09; PCIe扫盲&#xff08;五&#xff09; PCIe扫盲&#xff08;六&#xff09; PCIe扫盲&#xff08;七&#xff09…

如何查看电脑的虚拟内存信息?

1、按下键盘的 win R 键 &#xff0c; 输入&#xff1a;cmd &#xff0c; 然后按下【回车】 2、在弹出的窗口输入&#xff1a;systeminfo &#xff0c; 然后按下【回车】&#xff0c;等待加载结果出来。 3、如下位置&#xff0c;显示的即是当前电脑的【虚拟内存】信息&…

Fusion Access

1.FA桌面云需要微软三剑客 2.AD&#xff0c;DNS&#xff0c;DHCP合并部署在一台虚机&#xff0c;内存配置8G 3.FA各个组件 3.1终端接入 3.2接入和访问控制层 3.3虚拟桌面管理层-桌面云规划及部署 3.4安装Linux基础架构虚拟机FA01 3.4.1安装Tools 3.4.2安装FusionAccess组件&am…

希捷电脑硬盘好恢复数据吗?探讨可能性、方法以及注意事项

在数字化时代&#xff0c;数据已成为我们生活和工作中不可或缺的一部分。希捷电脑硬盘作为数据存储的重要设备&#xff0c;承载着大量的个人文件、工作资料以及珍贵回忆。然而&#xff0c;面对硬盘故障或误操作导致的数据丢失&#xff0c;许多用户不禁要问&#xff1a;希捷电脑…

找到你的工具!5款免费可视化报表工具对比分析

选择合适的可视化工具对于分析和展示数据至关重要&#xff0c;以下是五款免费的可视化工具&#xff0c;它们各具特色&#xff0c;能够适应各种需求。本文将介绍每款工具的优势与不足&#xff0c;帮助你找到最合适的解决方案。 1. 山海鲸可视化 介绍&#xff1a;山海鲸可视化是…

UniApp组件与微信小程序组件对照学习

UniApp只是一个第三方的开发工具&#xff0c;借鉴各种平台的能力&#xff0c;UniApp的组件也借鉴了微信小程序的组件&#xff0c;我们学习时&#xff0c;可以进行对照学习&#xff0c;我们在用UniApp开发微信小程序时&#xff0c;UniApp也只是将代码转成了微信小程序的代码&…

“电瓶车火灾”频发,如何防范自救

1.概述 近年来&#xff0c;随着电动自行车使用的普及化&#xff0c;由此引发的起火事故频繁发生。作为上海市烧伤急救中心&#xff0c;上海交通大学医学院附属瑞金医院的灼伤整形科收治的此类病人数量也在逐年上升。电动自行车&#xff0c;已经成为一种新型火灾事故的“肇事者…

【Docker】02-数据卷

1. 数据卷 数据卷(volume) 是一个虚拟目录&#xff0c;是容器内目录与宿主机目录之间映射的桥梁。 2. 常见命令 docker volume createdocker volume lsdocker volume rmdocker volume inspect 查看某个数据卷的详情docker volume prune 清除数据卷 **数据卷挂载&#xff1a…

【笔记】数据结构|链表算法总结|快慢指针场景和解决方案|链表归并算法和插入算法|2012 42

受堆积现象直接影响的是&#xff1a;平均查找长度 产生堆积现象&#xff0c;即产生了冲突&#xff0c;它对存储效率、散列函数和装填因子均不会有影响&#xff0c;而平均查找长度会因为堆积现象而增大。 2012 42 参考灰灰考研 假定采用带头结点的单链表保存单词&#xff0c;当…

MySQL_表_进阶(1/2)

我们的进阶篇中&#xff0c;还是借四张表&#xff0c;来学习接下来最后关于表的需求&#xff0c;以此完成对表的基本学习。 照例给出四张表&#xff1a; 学院表&#xff1a;(testdb.dept) 课程表&#xff1a;(testdb.course) 选课表:&#xff08;testdb.sc&#xff09; 学生表…