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

news/2025/2/24 8:52:10

目录

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

http://www.niftyadmin.cn/n/5864129.html

相关文章

ArcGIS Pro热力图制作指南:从基础到进阶

引言 在地理信息科学领域&#xff0c;热力图作为一种直观的数据可视化手段&#xff0c;广泛应用于展示空间数据的密度和热度分布。ArcGIS Pro&#xff0c;作为一款强大的地理信息系统&#xff08;GIS&#xff09;软件&#xff0c;为我们提供了制作热力图的便捷工具。本文将从基…

Pi币与XBIT:在去中心化交易所的崛起中重塑加密市场

在加密货币市场迅猛发展的背景下&#xff0c;Pi币和XBIT正在成为投资者关注的焦点。Pi币作为一项创新的数字货币&#xff0c;通过独特的挖矿机制和广泛的用户基础&#xff0c;迅速聚集了大量追随者&#xff0c;展示了强大的市场潜力。同时&#xff0c;币应XBIT去中心化交易所的…

鸿蒙开发深入浅出01(基本环境搭建、页面模板与TabBar)

鸿蒙开发深入浅出01&#xff08;基本环境搭建、页面模板与TabBar&#xff09; 1、效果展示2、下载 DevEco Studio3、创建项目4、新建页面模板5、更改应用信息6、新建以下页面7、Index.ets8、真机运行9、图片资源文件 1、效果展示 2、下载 DevEco Studio 访问官网根据自己的版本…

笔记 大学物理B下册

机械振动和电磁振荡 简谐振动 简谐振动表达式 如果物体所受合外力的大小总是与物体离开平衡位置的唯一大小成正比且方向相反&#xff0c;那么该物体的运动就是简谐振动。这种性质的力称为线性回复力。线性回复力 F − k x F -kx F−kx d 2 x d t 2 − ω 2 x \frac{d^2…

rust之Tokio学习1

任务 一个 Tokio 任务是一个异步的绿色线程&#xff0c;它们通过 tokio::spawn 进行创建&#xff0c;该函数会返回一个 JoinHandle 类型的句柄 调用者可以使用该句柄跟创建的任务进行交互 示例 spawn 函数的参数是一个 async 语句块&#xff0c;该语句块甚至可以返回一个值&…

python学opencv|读取图像(七十四)人脸识别:EigenFaces算法

【1】引言 前序学习进程中&#xff0c;做的是检测&#xff0c;只是能检测出来由人脸、猫脸和行人&#xff0c;相关文章链接为&#xff1a; python学opencv|读取图像&#xff08;七十一&#xff09;使用cv2.CascadeClassifier()函数detectMultiScale()函数实现图像中的人脸检测…

基于Python+django+mysql旅游数据爬虫采集可视化分析推荐系统

2024旅游推荐系统爬虫可视化&#xff08;协同过滤算法&#xff09; 基于Pythondjangomysql旅游数据爬虫采集可视化分析推荐系统 有文档说明 部署文档 视频讲解 ✅️基于用户的协同过滤推荐算法 卖价就是标价~ 项目技术栈 Python语言、Django框架、MySQL数据库、requests网络爬虫…

智能控制基础应用-C#Codesys共享内存实现数据高速交互

智能控制基础应用-C#&Codesys共享内存实现数据高速交互 文章目录 智能控制基础应用-C#&Codesys共享内存实现数据高速交互前言一、 Codesys共享内存程序实现二、Python共享内存程序实现2.1 界面说明 三、功能测试注意事项 前言 共享内存是一种高效的进程间通信&#xf…