libfv:基于 C++20 的异步 HTTP 库

2022-04-23 20:52:46 +08:00
 fawdlstty

仓库地址:https://github.com/fawdlstty/libfv

介绍一款船新 HTTP 库。C++的 HTTP 库很多,但基于 C++20 的异步网络 HTTP 库几乎没有。我没找到好用的,因此写了一个。在讲解这个库之前,我先说说为什么我们需要这样的库。

C++ HTTP 库有两种主要的实现方式,第一种是同步 HTTP 网络访问,比如这样的代码:

// 伪代码
Response _r = HttpGet ("https://t.cn");
std::cout << _t.text;

这样的代码写起来很简单,但它存在一个问题:HTTP 网络访问比较耗时,可能需要几百毫秒,这么长时间,这个线程将阻塞在这里,比较消耗线程资源。假如遇到需要同时发起几十、几百个请求,将较大消耗系统资源。很显然,它不是一个较好的设计。

第二种是回调通知,比如这样的代码:

// 伪代码
HttpGet ("https://t.cn", [] (Response _r) {
	std::cout << _t.text;
});

这种方式解决了线程问题,也就是,几十、几百个请求可以同时发起,只需要极少量或者一个线程就行,HTTP 库内部实现了请求的内部管理,在收到请求的回复后,调用回调函数,从而实现请求的高效处理。但这种方式有个问题,假如我们需要根据请求结果内容转给下一个请求,这会带来一个回调地狱问题,比如这样的代码:

// 伪代码
HttpGet ("https://t.cn", [] (Response _r) {
    HttpGet (_t.text, [] (Response _r) {
        HttpGet (_t.text, [] (Response _r) {
            HttpGet (_t.text, [] (Response _r) {
                HttpGet (_t.text, [] (Response _r) {
                    std::cout << _t.text;
                });
            });
        });
    });
});

那么,有没更好的处理方式呢?有,通过 C++20 的 co_await 实现异步等待。下面给出 libfv 的发起请求的代码:

fv::Response _r = co_await fv::Get ("https://t.cn");

一方面它能获得回调方式的好处,也就是少量线程支撑同时大量的请求任务,同时它不会带来回调地狱问题。上面的代码通过 libfv 实现,代码可以这样写:

fv::Response _r = co_await fv::Get ("https://t.cn");
_r = co_await fv::Get (_r.text);
_r = co_await fv::Get (_r.text);
_r = co_await fv::Get (_r.text);
_r = co_await fv::Get (_r.text);
std::cout << _t.text;

这儿特别说明一下。单 CPU 处理效率来说,C++20 的异步性能比回调要低,大概 10%左右,也就是假设理论上跑满网络 IO 带宽情况,回调需要 10%的 CPU ,那么使用 C++20 的异步需要 11%,这是 stackless 需要付出的代价。当然,在我看来这个特性完全可以忽略,毕竟 IO 密集型应用首先需要考虑的是跑满网络带宽,一般不太需要关注 CPU 使用率。

libfv 使用方法见仓库:https://github.com/fawdlstty/libfv

4797 次点击
所在节点    C++
61 条回复
fawdlstty
2022-04-27 10:03:35 +08:00
@hez2010 找到一篇文章 https://zhuanlan.zhihu.com/p/395250667
里面有句话“实际上,Future/Promise 并不适合性能要求很高的生产环境,比如游戏引擎任务框架等”
co_await 也是 Future/Promise 吧。中间数据传递的类型都被擦除了(有状态,但编译器在优化时没法和 continue 方法一一对应),从 awaitable 对象外部看来也只知道返回类型是什么类型。使得这关键字从目前设计看来,没法优化

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/848811

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX