c++雅兰亭库 (yalantinglibs) 介绍及使用(序列化、json和结构体转换、协程)

雅兰亭库(yalantinglibs)介绍

雅兰亭库,名字很优雅,也很强大。它是阿里开源的一个现代C++基础工具库的集合, 现在包括 struct_pack, struct_json, struct_xml, struct_yaml, struct_pb, easylog, coro_rpc, coro_io, coro_http 和 async_simple等功能, 也一直在持续优化并添加更多的新功能。

yaLanTingLibs 的目标::为C++开发者提供高性能,极度易用的现代C++基础工具库, 帮助用户构建高性能的现代C++应用。

yalantinglibs开源地址:

https://github.com/alibaba/yalantinglibs

更多内容参见官方文档介绍:

雅兰亭库 | A collection of C++20 libraries, include async_simple, coro_rpc and struct_pack.

编译器要求

 如果你的编译器只支持C++17,yalantinglibs 只会编译序列化库(struct_*系列,只能使用struct_*系列的功能如快速序列化,结构体和json的相互转换等)。如果你的编译器低于C++17,那么只围观下可以,用不了。也建议升级使用C++17及以上版本,目前来说C++17已经很常用了。

确保你的编译器版本不低于:

  • clang6++ (libstdc++-8 以上)。
  • g++9 或更高版本。
  • msvc 14.20 或更高版本。

如果你的编译器支持C++20,yalantinglibs会编译全部库。

确保你的编译器版本不低于:

  • clang11++ (libstdc++-8 以上)。
  • g++10 或更高版本。
  • msvc 14.29 或更高版本。

可以手动指定Cmake选项-DENABLE_CPP_20=ON 或 -DENABLE_CPP_20=OFF来控制。

安装&编译

Yalantinglibs 是一个head-only的库,这意味着你可以简单粗暴的直接将./include/ylt拷贝走。但是更推荐的做法还是用Cmake安装。

  • 克隆仓库
git clone https://github.com/alibaba/yalantinglibs.git
  • 构建,测试并安装

  • 建议最好在安装之前编译样例/压测程序并执行测试:

cmake ..
cmake --build . --config debug # 可以在末尾加上`-j 选项, 通过并行编译加速
ctest . # 执行测试

测试/样例/压测的可执行文件存储在路径./build/output/下。

  • 你也可以跳过编译:
# 可以通过这些选项来跳过编译样例/压测/测试程序
cmake .. -DBUILD_EXAMPLES=OFF -DBUILD_BENCHMARK=OFF -DBUILD_UNIT_TESTS=OFF
cmake --build .
  1. 默认情况下会安装到系统默认的include路径,你也可以通过选项来自定义安装路径。
cmake --install . # --prefix ./user_defined_install_path
  1. 开始编程
  • 使用CMAKE:

安装完成后,你可以直接拷贝并打开文件夹src/*/examples,然后执行以下命令:

mkdir build
cd build
cmake ..
cmake --build .
  • 手动编译:
  1. 将 include/加入到头文件包含路径中(如果已安装到系统默认路径,可跳过该步骤)
  2. 将 include/ylt/thirdparty 加入到头文件包含路径中(如果已通过Cmake 选项 -DINSTALL_INDEPENDENT_THIRDPARTY=ON 安装了第三方依赖,可跳过该步骤)
  3. 如果你使用了 coro_ 开头的任何头文件, 在linux系统下需要添加选项 -pthread . 使用g++编译器时需要添加选项 -fcoroutines
  4. 全部搞定. 更多细节请参考 example/cmakelist.txt.
  • 更多细节: 如需查看更多细节, 除了example/cmakelist.txt

cmake中使用

 前提是已经过前面步骤的构建,使用 cmake 在项目中导入 ylt 的示例:

cmake_minimum_required(VERSION 3.15)
project(file_transfer)
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Release")
endif()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(Threads REQUIRED)
link_libraries(Threads::Threads)
find_package(yalantinglibs REQUIRED)
link_libraries(yalantinglibs::yalantinglibs)

add_executable(coro_io_example main.cpp)

struct_pack

struct_pack是一个基于编译期反射,易用且高性能的序列化库,head-only。一行代码即可完成序列化/反序列化。性能远超protobuf等传统序列化库。

// 定义一个C++结构体
struct person {
  int64_t id;
  std::string name;
  int age;
  double salary;
};
// 初始化对象
person person1{.id = 1, .name = "hello struct pack", .age = 20, .salary = 1024.42};

// 一行代码序列化
std::vector<char> buffer = struct_pack::serialize(person1);

// 一行代码反序列化
auto person2 = deserialize<person>(buffer);

struct_pack 性能优异,最快比protobuf 高一个数量级,但是之前struct_pack 是C++20 开发的,只支持C++20 编译器,并且只支持aggregate 类型的序列化反序列化,为了让更多低版本编译器的用户也能使用struct_pack,现在支持了C++17 。

struct_json

基于反射的json库,轻松实现结构体和json之间的映射。

#include "ylt/struct_json/json_reader.h"
#include "ylt/struct_json/json_writer.h"

struct person {
  std::string name;
  int age;
};
REFLECTION(person, name, age);

int main() {
  person p{.name = "tom", .age = 20};
  std::string str;
  struct_json::to_json(p, str); // {"name":"tom","age":20}

  person p1;
  struct_json::from_json(p1, str);
}

json 解析benchmark 

struct_json 不但易用性更好,性能上也比rapidjson更高。

img

struct_json 解析10个文件的速度全面领先rapidjson,其中在解析gsoc-2018.json 文件的时候struct_json 性能是rapidjson 的6.3倍,说明struct_json 不仅仅在易用性和安全性上更好,性能上也不错。

struct_json, struct_xml, struct_yaml 正是为了让我们从繁琐不安全的手写代码中解放出来,通过结构体实现序列化和反序列化的自动化,安全可靠,性能还更好,是时候用它们去替代经典的rapidxxx系列啦。

coro_rpc

coro_rpc是用C++20开发的基于无栈协程和编译期反射的高性能的rpc库,在单机上echo测试qps达到2000万(详情见benchmark部分) ,性能远高于grpc和brpc等rpc库。然而高性能不是它的主要特色,coro_rpc的主要特色是易用性,免安装,包含头文件就可以用,几行代码就可以完成一个rpc服务器和客户端。

coro_rpc的设计理念是:以易用性为核心,回归rpc本质,让用户专注于业务逻辑而不是rpc框架细节,几行代码就可以完成rpc开发。 rpc的本质是什么?rpc的本质就是一个远程函数,除了rpc底层的网络IO之外,其它的就和普通函数一样。用户不需要关注rpc底层的网络IO、路由、序列化等细节,用户只需要专注于rpc函数的业务逻辑即可,这就是coro_rpc的设计理念, 正是基于这一设计理念,coro_rpc提供了非常简单易用的API给用户使用。通过一个例子来看看coro_rpc的易用性如何。

rpc使用

1.定义rpc函数

// rpc_service.hpp
inline std::string echo(std::string str) { return str; }

2.注册rpc函数和启动server

#include "rpc_service.hpp"
#include <ylt/coro_rpc/coro_rpc_server.hpp>

int main() {

  // 初始化服务器
  coro_rpc_server server(/*thread_num =*/10, /*port =*/9000);

  server.register_handler<echo>(); // 注册rpc函数

  server.start(); // 启动server并阻塞等待
}

对于rpc服务端来说,用户只需要定义rpc函数再启动server即可,不需要关注其它细节,5,6行代码就可以提供一个rpc服务了,是不是很简单!再来看看client是怎么调用hello这个rpc服务的。

rpc_client端

  1. 连接服务端
  2. rpc调用
#include "rpc_service.hpp"
#include <ylt/coro_rpc/coro_rpc_client.hpp>

Lazy<void> test_client() {
  coro_rpc_client client;
  co_await client.connect("localhost", /*port =*/"9000");

  auto r = co_await client.call<echo>("hello coro_rpc"); //传参数调用rpc函数
  std::cout << r.result.value() << "\n"; //will print "hello coro_rpc"
}

int main() {
  syncAwait(test_client());
}

client调用rpc函数也同样简单,5,6行代码就可以实现rpc调用了。 就像调用本地函数一样调用远程rpc函数,在call里面输入函数名字和参数就可以实现远程调用了,非常简单。

上面的这个简单的例子已经充分展示了coro_rpc的易用性和特点了,也体现了rpc的本质,即用户可以像调用本地函数那样调用远程函数,用户只需要关注rpc函数的业务逻辑即可。

coro_rpc的接口易用性还体现在rpc函数几乎没有任何限制,rpc函数可以拥有任意多个参数,参数的序列化和反序列化由rpc库自动完成,用户无需关心。

和grpc、brpc比较易用性

rpc易用性比较

RPC 是否需要定义DSL 是否支持协程 hello world例子代码行数 依赖库 是否header only
grpc Yes No 70+ helloworld 16 No
brpc Yes No 40+ helloworld 6 No
coro_rpc No Yes 9 3 Yes

c++未来演化

如果说C++11是C++的一个里程碑,那么C++20就是现代C++的一个里程碑。因为它引入了非常重要的几个特性,而这将改变C++的编程理念和模型,当然也让C++变得更加好用,比如Concepts、Modules、Coroutine、Ranges等。以协程(Coroutine)为例,它可以让我们用同步方式写异步代码,彻底摆脱了回调地狱(Callback Hell),异步回调模型将被协程代替。用C++20新标准,失去的是弯弯绕绕的Callback,得到的是简单直接的协程。协程让异步变得简单,在未来3~5年,C++网络库的协程化将是大势所趋。

Modules让我们不用再引入include头文件了,而是像其他语言一样使用import库就好,同时它还会大大提升编译速度。将async_simple[2] 模块化后,编译速度提升了45%,性能也略有提升。可以说,Modules带来了C++统一包管理的曙光。

C++新标准的演进速度比较快,从C++11开始保持着三年一个版本的迭代速度,后面还有C++23/26/29。而未来C++标准将提供更多好东西,比如Executors、Networking、编译期反射等。虽然新标准推出比较快,但基于新标准的库却跟不上,比如协程库,目前除了async_simple外,能用的无栈协程库几乎没有,这也是C++的遗留问题。

其他资源

json与C++结构体互相转换_c++ 结构体 转 json_xyz347的博客-CSDN博客

高效工具推荐----vcpkg - 知乎

反射实现无侵入式序列化_yalantinglibs_故人帝梦的博客-CSDN博客

Github C++项目积累_xupeng1644的博客-CSDN博客

iguana反射功能 - 知乎

purecpp - a cool open source modern c++ community 

猜你喜欢

转载自blog.csdn.net/qq8864/article/details/132223608