全网唯一基于共享内存的C++ RPC框架

首先声明:我不是标题党,我是在找遍全网,没有找到一个基于共享内存实现、开源且跨平台的C++ RPC框架之后,才着手开发的这个框架。

项目地址:https://github.com/winsoft666/veigar


1. Veigar

Veigar一词来源于英雄联盟里面的“邪恶小法师-维迦”。

Veigar是一个跨平台的远程过程调用(RPC)框架,目前支持Windows、Linux平台。

Veigar基于共享内存技术实现,只支持本机进程或线程间的远程过程调用,这是Veigar与其他RPC框架(如Thrift、grpc)的最大不同之处。

2. 优势

与其他RPC框架相比,Veigar的优势在于:

  • 可以将任何函数暴露给调用方(不限语言,只要实现msgpack-rpc即可)。

  • 任何语言编写的程序都可以调用被暴露的函数。

  • 不需要学习IDL语言。

  • 不需要添加额外的代码生成步骤,仅需要C++代码。

  • 没有服务端和客户端的概念,每个Veigar实例间都可以相互调用。

  • 没有网络问题,如端口占用、半关闭状态等。

  • 没有诡异的端口假可用性问题(特别是在Windows系统上)。

3. 编译

虽然Veigar的底层是基于msgpack实现的,但已经将其包含到项目中,不需要额外编译和安装msgpack

虽然在veigar公共头文件引用了msgpack头文件,但这不会污染您的全局msgpack命名空间,因为Veigar中的msgpack命令空间为veigar_msgpack

Veigar仅支持编译为静态库。

可以使用CMake进行编译构建,也可以使用vcpkg进行安装,如:

vcpkg install veigar

4. 快速上手

在使用Veigar时,仅需要在项目中包含include目录,并链接静态库即可。

4.1 同步调用

下面是一个同步调用的示例:

本示例为了使代码更加简洁,没有对函数返回值进行校验,请在实际使用中不要这样做!

#include <iostream>
#include "veigar/veigar.h"

int main(int argc, char** argv) {
    if (argc != 3) {
        return 1;
    }

    std::string channelName = argv[1];
    std::string targetChannelName = argv[2];

    veigar::Veigar vg;

    vg.bind("echo", [](const std::string& msg, int i, double d, std::vector<uint8_t> buf) {
        std::string result;
        // ...
        return result;
    });

    vg.init(channelName);

    std::vector<uint8_t> buf;
    veigar::CallResult ret = vg.syncCall(targetChannelName, 100, "echo", "hello", 12, 3.14, buf);
    if (ret.isSuccess()) {
        std::cout << ret.obj.get().as<std::string>() << std::endl;
    }
    else {
        std::cout << ret.errorMessage << std::endl;
    }

    vg.uninit();

    return 0;
}

每个Veigar实例有一个在本机范围内唯一的通道名称(Channel),在调用init函数时需要为Veigar指定通道名称,Veigar不会检测通道的唯一性,需要由调用者来保证通道名称的唯一性。

在上述示例中,需要通过命令行参数指定当前实例的通道名称和目标实例的通道名称,如:

sample.exe myself other

每个实例都绑定了名为echo的函数,该函数简单的原样返回msg参数字符串。

通过为syncCall函数指定“目标通道名称”、“函数名称”、“函数参数”及“超时毫秒数”就可以同步调用目标函数并得到调用结果。

4.2 拒绝异常

我不喜欢异常,因此Veigar也不会通过异常的形式来抛出错误,Veigar会主动捕获所有C++标准库、msgpack、boost异常,以返回值的形式返回给调用者。当调用失败时(!ret.isSuccess()),errorMessage中存储的错误信息就可能是Veigar捕获的异常信息。

4.3 异步调用

使用asyncCall函数可以实现异步调用。

下面是异步调用示例:

//
// 与同步调用相同
// ...
std::vector<uint8_t> buf;
std::shared_ptr<veigar::AsyncCallResult> acr = vg.asyncCall(targetChannelName, "echo", "hello", 12, 3.14, buf);
if (acr->second.valid()) {
    auto waitResult = acr->second.wait_for(std::chrono::milliseconds(100));
    if (waitResult == std::future_status::timeout) {
        // timeout
    }
    else {
        veigar::CallResult ret = std::move(acr->second.get());
        if(ret.isSuccess()) {
            std::cout << ret.obj.get().as<std::string>() << std::endl;
        }
        else {
            std::cout << ret.errorMessage << std::endl;
        }
    }
}

vg.releaseCall(acr->first);

//
// 与同步调用相同
// ...

与同步调用不同,asyncCall函数返回的是std::shared_ptr<veigar::AsyncCallResult>,而且调用者在获取到CallResult或不再关系调用结果时,需要调用releaseCall函数释放资源。

5. 性能

使用examples\echo程序作为测试用例。

启动A、B、C三个Channel,每个Channel分别使用2个线程向彼此调用100万次,如下图所示:
请添加图片描述

Windows平台测试结果

测试机器CPU配置:

12th Gen Intel(R) Core(TM) i7-12700H   2.30 GHz

测试结果如下:

Target channel names (Split by comma):
A,B,C
Async method(0/1):
0
Thread number for each target:
2
Call times each of thread:
1000000
Read/Write Timeout(ms):
100
[Thread 1, Target A] Calling...
[Thread 0, Target C] Calling...
[Thread 0, Target A] Calling...
[Thread 1, Target B] Calling...
[Thread 0, Target B] Calling...
[Thread 1, Target C] Calling...
[Thread 1, Target B] Total 1000000, Success 1000000, Error 0, Used: 59092341us, Average: 59us/call, 16922call/s.

[Thread 0, Target B] Total 1000000, Success 1000000, Error 0, Used: 59112785us, Average: 59us/call, 16916call/s.

[Thread 1, Target A] Total 1000000, Success 1000000, Error 0, Used: 59111520us, Average: 59us/call, 16917call/s.

[Thread 0, Target C] Total 1000000, Success 1000000, Error 0, Used: 59126879us, Average: 59us/call, 16912call/s.

[Thread 0, Target A] Total 1000000, Success 1000000, Error 0, Used: 59206766us, Average: 59us/call, 16889call/s.

[Thread 1, Target C] Total 1000000, Success 1000000, Error 0, Used: 59299407us, Average: 59us/call, 16863call/s.

平均每次调用花费59微妙,每秒可以调用约16900次。

请添加图片描述

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

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

相关文章

数据库应用:Windows 部署 MySQL 8.0.36

目录 一、实验 1.环境 2.Windows 部署 MySQL 8.0.36 3.Windows配置环境变量 4.Navicat链接MySQL 二、问题 1.安装MySQL 报错 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 主机软件版本IP备注WindowsMySQL8.0.36localhost 2.Windows 部署 MySQL 8.0.…

【项目部署上线】宝塔部署前端Docker部署后端

【项目部署上线】宝塔部署前端&Docker部署后端 文章目录 【项目部署上线】宝塔部署前端&Docker部署后端1.安装依赖1.1 安装mysql1.2 安装Canal1.3 安装redis1.4 安装rabbitmq1.5 安装nacos 2. 部署前端3. 部署后端 1.安装依赖 1.1 安装mysql docker run -d -p 3306:3…

成功解决No module named ‘skimage‘(ModuleNotFoundError)

成功解决No module named ‘skimage’(ModuleNotFoundError) &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程 &#x1f448; 希望得到您…

模型 OIIC(目标、障碍、洞察、挑战)

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_总纲目录。沟通方案工具。 1 OIIC(目标、障碍、洞察、挑战)模型的应用 1.1 OIIC 驱动的汽车配件渠道优化 一家知名的汽车配件制造商&#xff0c;旗下品牌拥有众多产品&#xff0c;其销售渠道广泛&#xff0c;不仅在…

Python算法题集_实现 Trie [前缀树]

Python算法题集_实现 Trie [前缀树] 题208&#xff1a;实现 Trie (前缀树)1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【定义数据类默认字典】2) 改进版一【初始化字典无额外类】3) 改进版二【字典保存结尾信息无额外类】 4. 最优算法5. 相关…

VirtualBox+Vagrant安装linux

一、VirtualBox安装 VirtualBox官网&#xff1a;Oracle VM VirtualBox 这里采用VirtualBox--7.0.0 版本 二、Vagrant安装 Vagrant官网&#xff1a;Vagrant by HashiCorp Vagrant镜像仓库&#xff1a;Discover Vagrant Boxes - Vagrant Cloud 这里采用Vagrant--2.4.1版本 在…

【 buuctf-single dog】

单身&#x1f436;&#xff0c;哭死&#xff01; 废话不多说直接 binwalk&#xff0c;果然有 zip&#xff0c;直接提取一下 得到的 1.txt 里面都是些类似表情的东西&#xff0c;是 AAencode 加密&#xff0c;js 颜文字加密CTF在线工具-在线AAencode编码|AA编码|AAencode解码|AA…

vue基础操作(vue基础)

想到多少写多少把&#xff0c;其他的想起来了在写。也写了一些css的 input框的双向数据绑定 html <input value"123456" type"text" v-model"account" input"accou" class"bottom-line bottom" placeholder"请输入…

微服务知识02

1、九大高并发解决方案 2、系统架构图​​​​​​​ 3、分布式事务 本地事务、分布式事务 操作不同服务器的数据库&#xff08;垂直分库&#xff09; 4、分布式事务解决方案&#xff08;没有seata之前&#xff09; &#xff08;1&#xff09;XA协议&#xff08;强一致性&a…

vmware安装centos 7.9 操作系统

vmware安装centos 7.6 操作系统 1、下载centos 7.9 操作系统镜像文件2、安装centos 7.9 操作系统3、配置centos 7.6 操作系统3.1、配置静态IP地址 和 dns3.2、查看磁盘分区3.3、查看系统版本 1、下载centos 7.9 操作系统镜像文件 本文选择centos 7.9 最小化安装镜像包 这里选…

花店行业如何快速搭建自己的小程序

如今&#xff0c;小程序已经成为了各行各业的必备工具之一。对于花店来说&#xff0c;拥有一个专属的小程序能够更好地展示花卉信息&#xff0c;提供在线购买等功能。然而&#xff0c;对于初学者来说&#xff0c;制作小程序可能会感到困惑。但是&#xff0c;不要担心&#xff0…

Spring Security 认证授权安全框架

Spring Security概述 1.什么是Spring Security? Spring Security是一个Java框架&#xff0c;用于保护应用程序的安全性。它提供了一套全面的安全解决方案&#xff0c;包括身份验证、授权、防止攻击等功能。Spring Security基于过滤器链的概念&#xff0c;可以轻松地集成到任…

【海贼王的数据航海:利用数据结构成为数据海洋的霸主】顺序表

目录 1 -> 线性表 2 -> 顺序表 2.1 -> 概念及结构 2.2 -> 接口声明 2.3 -> 接口实现 2.3.1 -> 初始化 2.3.2 -> 销毁 2.3.3 -> 检查 2.3.4 -> 打印 2.3.5 -> 尾插 2.3.6 -> 头插 2.3.7 -> 尾删 2.3.8 -> 头删 2.3.9 ->…

【牛客】【刷题节】美团2024届秋招笔试第二场编程真题

1.小美的加法【简单题】 题意理解&#xff1a; 给定一个数组做连加操作&#xff0c;其中只能将一个加号变成乘号 将哪个加号变成乘号&#xff0c;使式子最后的结果最大 解题思路&#xff1a; 只有将两个相邻且乘机最大的数之间变成乘号后&#xff0c;才能保证整个式子结果最大 …

Spring之AOP源码解析(下)

前言 在上一遍文章中,我们主要讲解了ProxyFactory在Spring完成AOP动态代理的过程中发挥的作用。这一篇我们主要讲解这些注解都是如何注入Advisors,然后分析这些Advisors生效的条件 注解都是如何注入Advisor并匹配的 EnableTransactionManagement注解 我们在之前提到EnableT…

乡村研学|乡村研学小程序|基于微信小程序的乡村研学平台设计与实现(源码+数据库+文档)

乡村研学小程序目录 目录 基于微信小程序的乡村研学平台设计与实现 一、前言 二、系统功能设计 三、系统实现 1、微信小程序前台 2、管理员后台 &#xff08;1&#xff09;乡村研学管理 &#xff08;2&#xff09;商品信息管理 &#xff08;3&#xff09;商品类型管理 …

计算机网络:思科实验【2-MAC地址、IP地址、ARP协议及总线型以太网的特性】

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;Cisco Packet Tracer实验 本文对应的实验报告源文件请关注微信公众号程序员刘同学&#xff0c;回复思科获取下载链接。 实验目的实验环境实验内容MAC地址、IP地址、ARP协议总线型以太网的…

【DAY04 软考中级备考笔记】数据结构基本结构和算法

数据结构基本结构和算法 2月25日 – 天气&#xff1a;晴 周六玩了一天&#xff0c;周天学习。 1. 什么是数据结构 数据结构研究的内容是一下两点&#xff1a; 如何使用程序代码把现实世界的问题信息化如何用计算机高效地处理这些信息从创造价值 2. 什么是数据 数据是信息的…

零基础C++开发上位机--基于QT5.15的串口助手(一)

嵌入式开发的过程中&#xff0c;大部分我们的代码是无法一次成功的。这时候我们大部分的工程师可能最熟练的调试方法是printf函数&#xff0c;打印随意一个数据&#xff0c;来观察当前运行的函数是否执行正确。我们连接的工具有各个大神做的串口助手。另外&#xff0c;在做一般…

从0开始python学习-53.python中flask创建简单接口

目录 1. 创建一个简单的请求,没有写方法时默认为get 2. 创建一个get请求 3. 创建一个post请求&#xff0c;默认可以使用params和表单传参 4. 带有参数的post请求 1. 创建一个简单的请求,没有写方法时默认为get from flask import Flask, request# 初始化一个flask的对象 ap…