当前位置: 首页 > news >正文

微服务即时通信系统---(三)框架学习

目录

brpc

RPC框架

核心概念

工作原理

介绍

安装

头文件包含和编译时指明库 

类与接口介绍

日志输出类与接口

protobuf类与接口

Closure类 

RpcController类

服务端类与接口

ServerOptions类

Server类

ClosureGuard类

HttpHeader类

Controller类

客户端类与接口

 ChannelOptions类

Channel类

使用

同步调用

proto文件

server端

client端

Makefile

异步调用

client端

封装channel

封装思想(结合etcd服务发现模块的回调函数)

ServiceChannel类

ServiceChannelManager类

代码测试

main.proto

reg.cc

dis.cc

Makefile

测试结果

本章主要是学习和使用本项目中所需使用到的一些框架。

brpc

RPC框架

RPC(Remote Procedure Call,远程过程调用)框架,是一种用于实现分布式系统中跨网络调用远程服务的工具。

它允许程序像调用本地函数一样调用远程服务器上的函数,隐藏了底层网络通信的复杂性。

举例:想要实现一个a + b的函数,我们只需写好函数头,然后在函数内部调用远程服务器上的a+b函数,远程服务器计算完成之后返还结果。

核心概念

客户端(Client) 发起远程调用的程序。
服务端(Server) 提供远程服务的程序。
存根(Stub) 客户端代理,负责将调用请求打包并发送给服务端。
骨架(Skeleton)

服务端代理,负责接收请求并调用实际的服务实现。

工作原理

调用 客户端通过存根发起远程调用。
序列化 存根将调用信息序列化为网络传输格式。
传输 序列化后的数据通过网络发送到服务端。
反序列化 服务端的骨架接收并反序列化数据。
执行 骨架调用本地服务实现。
返回 服务端将结果序列化后返回给客户端。
反序列化 客户端存根接收并反序列化结果,返回给调用者。

介绍

brpc是用C++编写的工业级RPC框架,常用于搜索、存储、机器学习、广告、推荐等高性能系统。

特点:

能搭建在一个端口支持多协议的服务,或访问各种服务。
Server能同步或异步处理请求。
Client支持同步、异步、半同步,或使用组合channels简化复杂的分库或并发访问。
通过http界面调试服务,使用cpu、heap、contention profilers。
获得更好的延时和吞吐。
把你组织中使用的协议快速地加入brpc,或定制各类组件,包括命名服务,负载均衡。

安装

先安装依赖:

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

通过github上的brpc源码进行安装。

brpc的github地址:https://github.com/apache/brpc.git

通过命令安装:

# 克隆远端仓库
git clone https://github.com/apache/brpc.git

# 进入工作目录
cd brpc/

# 创建build
mkdir build && cd build

# 使用cmake构建Makefile
cmake .. -DCMAKE_INSTALL_PREFIX=/usr && cmake --build . -j6

# make安装
make && sudo make install

头文件包含和编译时指明库 

#include <brpc/channel.h>
#include <brpc/server.h>
#include <butil/logging.h>
-lbrpc -lssl -lleveldb -lcrypto -lprotobuf -lgflags

类与接口介绍

日志输出类与接口

本项目采用spdlog进行日志输出,这里只是想关闭brpc自带的日志输出系统。

/usr/include/butil/logging.h:

namespace logging {

// TODO(avi): do we want to do a unification of character types here?
#if defined(OS_WIN)
typedef wchar_t LogChar;
#else
typedef char LogChar;
#endif

// Where to record logging output? A flat file and/or system debug log
// via OutputDebugString.
enum LoggingDestination {
    LOG_TO_NONE             = 0,
    LOG_TO_FILE             = 1 << 0,
    LOG_TO_SYSTEM_DEBUG_LOG = 1 << 1,

    LOG_TO_ALL = LOG_TO_FILE | LOG_TO_SYSTEM_DEBUG_LOG,

    // On Windows, use a file next to the exe; on POSIX platforms, where
    // it may not even be possible to locate the executable on disk, use
    // stderr.
#if defined(OS_WIN)
    LOG_DEFAULT = LOG_TO_FILE,
#elif defined(OS_POSIX)
    LOG_DEFAULT = LOG_TO_SYSTEM_DEBUG_LOG,
#endif
};

struct BUTIL_EXPORT LoggingSettings {
    // The defaults values are:
    //
    //  logging_dest: LOG_DEFAULT
    //  log_file:     NULL
    //  lock_log:     LOCK_LOG_FILE
    //  delete_old:   APPEND_TO_OLD_LOG_FILE
    LoggingSettings();

    LoggingDestination logging_dest;

    // The three settings below have an effect only when LOG_TO_FILE is
    // set in |logging_dest|.
    const LogChar* log_file;
    LogLockingState lock_log;
    OldFileDeletionState delete_old;
};

// This function may be called a second time to re-direct logging (e.g after
// loging in to a user partition), however it should never be called more than
// twice.
inline bool InitLogging(const LoggingSettings& settings) {
    return BaseInitLoggingImpl(settings);
}

通过logging::LoggingDestination::LOG_TO_NONE + LoggingSettings::logging_dest + InitLogging来将日志的输出地设为0,即不输出。 

#include <butil/logging.h>

int main(int argc, char *argv[])
{
    logging::LoggingSettings settings;
    settings.logging_dest = logging::LoggingDestination::LOG_TO_NONE;
    logging::InitLogging(settings);
    return 0;
}

protobuf类与接口

Closure类 

/usr/include/google/protobuf/stubs/callback.h:

namespace google {
namespace protobuf {

class PROTOBUF_EXPORT Closure {
 public:
  Closure() {}
  virtual ~Closure();
  virtual void Run() = 0;
};

// See Closure.
inline Closure* NewCallback(void (*function)()) {
  return new internal::FunctionClosure0(function, true);
}

}
}

Closure 类用于定义异步操作完成后的回调逻辑。它是一个抽象类,用户需要继承并实现 Run() 方法,该方法在 RPC 调用完成时被调用。

主要功能:

  • 回调机制Closure 允许用户在 RPC 调用完成后执行自定义逻辑。

  • 资源管理:通过 NewCallback() 函数创建 Closure 对象,自动管理其生命周期。

即:Closure类中的Run方法,是在客户端完成RPC调用之后的回调函数。

RpcController类

 /usr/include/google/protobuf/service.h:

namespace google {
namespace protobuf {
class PROTOBUF_EXPORT RpcController {

  // After a call has finished, returns true if the call failed.  The possible
  // reasons for failure depend on the RPC implementation.  Failed() must not
  // be called before a call has finished.  If Failed() returns true, the
  // contents of the response message are undefined.
  virtual bool Failed() const = 0;

  // If Failed() is true, returns a human-readable description of the error.
  virtual std::string ErrorText() const = 0;
};
}
}

RpcController 类用于控制 RPC 调用的行为和状态,提供对调用过程的控制接口。

主要功能:

  • 调用控制:支持取消、重置等操作。

  • 状态查询:检查调用是否完成、是否失败等。

  • 错误处理:获取错误信息和状态码。

常用方法:

  • Reset():重置控制器状态,用于复用。

  • Failed():检查调用是否失败。

  • ErrorText():获取错误信息。

  • SetFailed():手动标记调用为失败。

  • StartCancel():取消调用。

服务端类与接口

ServerOptions类

/usr/include/brpc/server.h:

namespace brpc{
struct ServerOptions {
    
    // connections without data transmission for so many seconds will be closed
    // Default: -1 (disabled)
    int idle_timeout_sec

    // Number of pthreads that server runs on. Notice that this is just a hint,
    // you can't assume that the server uses exactly so many pthreads because
    // pthread workers are shared by all servers and channels inside a
    // process. And there're no "io-thread" and "worker-thread" anymore,
    // brpc automatically schedules "io" and "worker" code for better
    // parallelism and less context switches.
    // If this option <= 0, number of pthread workers is not changed.
    // Default: #cpu-cores
    int num_threads;

};

// Represent server's ownership of services.
enum ServiceOwnership {
    SERVER_OWNS_SERVICE, // 添加服务失败时, 服务器自动删除服务对象
    SERVER_DOESNT_OWN_SERVICE // 添加服务失败时, 服务器不会删除服务对象
};
}

向 brpc 服务器添加服务,通常是指用户实现一个基于 Protobuf 定义的服务接口,并将其注册到 brpc 服务器中。这个过程确实需要用户重写服务函数,但不仅仅是简单的函数重写,而是需要遵循一定的规范和流程。

以下是向 brpc 服务器添加服务的详细步骤:

  1. 使用 Protobuf 定义服务接口。

  2. 实现服务接口中的虚函数(即重写服务函数)。

  3. 将服务实例注册到 brpc 服务器。

  4. 启动服务器并处理客户端请求。

Server类
namespace brpc{
class Server {
    
    // Start on IP_ANY:port.
    int Start(int port, const ServerOptions* opt);

    // Stop accepting new connections and requests from existing connections.
    // Returns 0 on success, -1 otherwi

相关文章:

  • 基于GWO灰狼优化的WSN网络最优节点部署算法matlab仿真
  • [ComfyUI] 【AI】高级采样器与一般采样器的区别详解
  • 【蓝桥杯单片机】第十三届省赛第二场
  • ArcGIS Pro热力图制作指南:从基础到进阶
  • Python 数据类型转换
  • vllm部署LLM(qwen2.5,llama,deepseek)
  • DeepSeek 助力 Vue 开发:打造丝滑的单选按钮(Radio Button)
  • Hutool - Script:脚本执行封装,以 JavaScript 为例
  • 高性能GPU计算:释放计算潜力的加速利器
  • rkipc取jpeg图片分析
  • C++经典框架案例(三)
  • 2025雅森北京展今天开幕,全景展现新能源汽车时代
  • 算法分享——弗洛伊德算法暴力破解多源最短路问题
  • Java-01-源码篇-04集合-05-ConcurrentHashMap(1)
  • 关于实际工作中如何定位、复现、解决bug的个人心得
  • DeepSeek 部署全指南:常见问题解析与最新技术实践
  • 【Linux网络编程】数据链路层和网络层的几个问题:MTU,校验和,全球网段,路由表
  • C1车证学习笔记
  • Ryu:轻量开源,开启 SDN 新程
  • Ubuntu及其衍生系统安装Python
  • “上报集团文化助力区域高质量发展赋能平台”揭牌
  • 江苏银行一季度净赚近98亿增逾8%,不良贷款率微降
  • 外交部回应涉长江和记出售巴拿马运河港口交易:望有关各方审慎行事,充分沟通
  • 见证上海援藏30年成果,萨迦非遗珍品展来沪
  • 俄外长与美国务卿通电话,讨论俄美关系及乌克兰问题
  • 央行副行长:增强外汇市场韧性,坚决对市场顺周期行为进行纠偏