Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

modern C++(C++20), simple, easy to use rpc framework

License

NotificationsYou must be signed in to change notification settings

qicosmos/rest_rpc

Repository files navigation

OS (Compiler Version)Status
Ubuntu 22.04 (clang 14.0.0)win
Ubuntu 22.04 (gcc 11.2.0)win
macOS Monterey 12 (AppleClang 14.0.0.14000029)win
Windows Server 2022 (MSVC 19.33.31630.0)win

c++20, high performance, cross platform, easy to use rpc framework.

It's so easy to love RPC.

Modern C++开发的RPC库就是这么简单好用!

rest_rpc简介

rest_rpc是一个高性能、易用、跨平台、header only的基于c++20 协程的rpc 库,它的目标是让tcp通信变得非常简单易用,即使不懂网络通信的人也可以直接使用它。它依赖header-only的standaloneasio(tag:asio-1-36-0)

可以快速上手,使用者只需要关注自己的业务逻辑即可。

编译器版本

需要完全支持c++20 的编译器:

gcc12+, clang15+, msvc2022

谁在用rest_rpc

  1. 博世汽车

在这里增加用户

rest_rpc的特点

rest_rpc为用户提供了非常简单易用的接口,几行代码就可以实现rpc通信了,来看第一个例子

一个加法的rpc服务

//服务端注册加法rpc服务intadd(rpc_conn conn,int a,int b) {return a + b; }intmain(){  rpc_serverserver("127.0.0.1:9004",std::thread::hardware_concurrency());  server.register_handler<add>();  server.start();}
//客户端调用加法的rpc服务intmain(){auto rpc_call = []() -> asio::awaitable<void> {    rpc_client client;auto ec =co_await client.connect("127.0.0.1:9004");if(ec) {      REST_LOG_ERROR << ec.message();co_return;    }auto r =co_await client.call<add>(1,2);if(r.ec == rpc_errc::ok) {      REST_LOG_INFO <<"call result:" << r.value;assert(r.value ==3);    }  };sync_wait(rpc_call());}

获取一个对象的rpc服务

//1.先定义person对象structperson {int id;  std::string name;int age;};//2.提供rpc服务personget_person(person p) {  p.name ="jack";return p;}intmain(){  rpc_serverserver("127.0.0.1:9004",std::thread::hardware_concurrency());  server.register_handler<get_person>();  server.start();}
//客户端调用获取person对象的rpc服务intmain(){auto rpc_call = []() -> asio::awaitable<void> {    rpc_client client;auto ec =co_await client.connect("127.0.0.1:9004");if(ec) {      REST_LOG_ERROR << ec.message();co_return;    }        person p{1,"tom",20};auto r =co_await client.call<get_person>(p);if(r.ec==rpc_errc::ok) {      REST_LOG_INFO <<"call result:" << r.value.name;assert(r.value.name =="jack");    }  };sync_wait(rpc_call());}

rest_rpc 比较有特色的一个功能是支持订阅发布。

以订阅某个topic为例:

server 端代码:

voidpublish() {  rpc_serverserver("127.0.0.1:9004",4);  server.async_start();    REST_LOG_INFO <<"will pubish, waiting for input";auto pub = [&]() -> asio::awaitable<void> {    std::string str;while (true) {      std::cin >> str;if(str =="quit") {break;      }// 向客户端发布一个string,你也可以发布一个对象,内部会自动序列化co_await server.publish("topic1", str);    }  };sync_wait(pub());}client 端代码:```cppvoidsubscribe() {  REST_LOG_INFO <<"will subscribe, waiting for publish";auto sub = [&]() -> asio::awaitable<void> {    rpc_client client;co_await client.connect("127.0.0.1:9004");while (true) {// 订阅topic1,库会自动将结果反序列化为std::string, 如果publish是一个person对象,则subscribe参数填person,内部会自动反序列化auto [ec, result] =co_await client.subscribe<std::string>("topic1");if (ec != rpc_errc::ok) {        REST_LOG_ERROR <<"subscribe failed:" <<make_error_code(ec).message();break;      }            REST_LOG_INFO << result;    }  };sync_wait(sub());}

rest_rpc是目前最快的rpc库,具体和grpc和brpc做了性能对比测试,rest_rpc性能是最高的,远超grpc。

性能测试代码在这里:

https://github.com/qicosmos/rest_rpc/tree/master/tests/bench.cpp

rest_rpc 也是比较灵活的,允许用户替换默认的序列化库。

rest_rpc 默认使用yalantinglibs的struct_pack 去做系列化/反序列化的,它的性能非常好。

rest_rpc 也支持用户使用自己的序列化库,只需要去实现一个序列化和一个反序列化函数。

namespaceuser_codec {// adl lookup in user_codec namespacetemplate<typename... Args> std::stringserialize(rest_adl_tag, Args &&...args) {   msgpack::sbufferbuffer(2 *1024);ifconstexpr (sizeof...(Args) >1) {msgpack::pack(buffer,std::forward_as_tuple(std::forward<Args>(args)...));   }else {msgpack::pack(buffer, std::forward<Args>(args)...);   }returnstd::string(buffer.data(), buffer.size()); }template<typename T> Tdeserialize(rest_adl_tag, std::string_view data) {try {static msgpack::unpacked msg;msgpack::unpack(msg, data.data(), data.size());return msg.get().as<T>();   }catch (...) {return T{};   } } }// namespace user_codec

实现这两个函数之后rest_rpc 将会使用自定义的序列化/反序列化函数了。

rest_rpc的更多用法

rest_rpc 支持零拷贝发数据,以echo函数为例:

std::string_viewecho(std::string_view str) {return str;}

假如用户希望发送很大的一个数据,可能有数GB,如果按照常规的做法,需要先序列化,这样就存在内存拷贝,rest_rpc 针对这种场景专门做了优化,当client调用rpc函数时传入的是std::string_view 时,rest_rpc 将不会对传入的数据做拷贝,也不会去做序列化,直接通过socket发送到服务端。

rpc函数的返回类型为std::string_view 时,client收到的响应数据也不会做反序列化和内存拷贝,直接返回的是收到的socket 数据。

这样就可以实现rpc的零拷贝数据发送了,能获得最佳的性能。事实上当用户的rpc函数的参数为单参数并且类型为基本类型(字符串和数字类型)时,rest_rpc 不会做序列化,以获得更好的性能,只有多参数或者结构体时才会去序列化。

更多例子可以参考rest_rpc的example:

https://github.com/qicosmos/rest_rpc/tree/master/examples

社区和群

http://purecpp.cn

qq群:546487929

About

modern C++(C++20), simple, easy to use rpc framework

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors9


[8]ページ先頭

©2009-2026 Movatter.jp