C++ 协程的近况、设计与实现中的细节和决策

本文深入探讨了C++协程的现状,从API级到语言级的实现层次,分析了不同实现的优缺点,如libco、libmill和libgo。重点讨论了协程上下文切换、栈管理、调度策略、网络IO Hook以及完整生态系统的重要性。文章还介绍了如何解决协程栈内存、调度问题和线程安全,展示了C++协程在高并发后端开发中的应用和挑战,以及未来可能的发展方向。
摘要由CSDN通过智能技术生成

时至2018年的今天,C++ 在互联网服务端开发方向依然占据着相当大的份额;百度,腾讯,甚至以java为主流开发语言的阿里都在大规模使用C++做互联网服务端开发,而这恰恰是本文想要讨论的范畴。

C++协程实现及原理分析视频讲解:

C/C++ Linux服务器开发高级架构学习视频点击:C/C++Linux服务器开发高级架构/Linux后台架构师-学习视频

协程的实现与原理剖析丨掌握协程的运用丨实例讲解(上)

协程的实现与原理剖析丨掌握协程的运用丨实例讲解(下)

第1章 C++协程近况简介 协程分两种,无栈协程(stackless)和有栈协程(stackful),前者无法解决异步回调模式中上下文保存与恢复的问题,在此不做论述,文中后续提到的协程均指有栈协程。

第1节.旧时代 在2014年以前,C++服务端开发是以异步回调模型为主流,业务流程中每一个需要等待IO处理的节点都需要切断业务处理流程、保存当前处理的上下文、设置回调函数,等IO处理完成后再恢复上下文、接续业务处理流程。

在一个典型的互联网业务处理流程中,这样的行为节点多达十几个甚至数十个(微服务间的rpc请求、与redis之类的高速缓存的交互、与mysql\mongodb之类的DB交互、调用第三方HttpServer的接口等等);被切割的支离破碎的业务处理流程带来了几个常见的难题:

每个流程都要定义一个上下文struct,并手动保存与恢复;

每次回调都会切断栈上变量的生命周期,导致需要延续使用的变量必须申请到堆上或存入上下文结构中;

由于C++是无GC的语言,碎片化的逻辑给内存管理也带来了更多挑战;

回调式的逻辑是“不知何时会被触发”的,用户状态管理也会有更多挑战;

这些具体的难题综合起来,在工程化角度呈现出的效果就是:代码编写复杂,开发周期长,维护困难,BUG多且防不胜防。

第2节.新时代 2014年腾讯的微信团队开源了一个C风格的协程框架libco,并在次年的架构师峰会上做了宣讲,使业内都认识到异步回调模式升级为协程模式的必要性,从此开启了C++互联网服务端开发的协程时代。BAT三家旗下的各个小部门、业内很多与时俱进的互联网公司都纷纷自研协程框架,一时呈百花齐放之态。

笔者所在的公司当时也试用了一段时间libco,修修补补很多次,终究是因为问题太多而放弃,改用了自研的libgo作为协程开发框架。

聊协程就不能不提到主打协程功能和CSP模式的golang语言,google从09年发布golang至今,经过近10个年头的发酵,已成为互联网服务端开发主流开发语言之一,许多项目和开发者从C++、java、php等语言转向golang。笔者自研的libgo也汲取了golang的设计理念和多年的实践经验。

本文后续针对C++协程框架的设计与实现、与golang这种语言级别支持的协程的差距在哪里、怎样尽力弥补这种差距等方面展开讨论。

第2章.协程库的设计与实现 个人认为,C++协程库从实现完善程度上分为以下几个层次

1.API级 实现协程上下文切换api,或添加一些便于使用的封装; 特点:没有协程调度。

代表作:boost.context, boost.coroutine, ucontext(unix), fiber(windows)

这一层次的协程库,仅仅提供了一个底层api,要想拿来做项目,还有非常非常遥远的距离;不过这些协程api可以为我们实现自己的协程库提供一个良好的基础。

2.玩具级 实现了协程调度,无需用户手动处理协程上下文切换;特点:没有HOOK

代表作:libmill

这一层次的协程库,实现了协程调度(类似于操作系统有了进程调度机制);稍好一些的意识到了阻塞网络io与协程的不协调之处,自己实现了一套网络io相关函数;

但是这也意味着涉及网络的第三方库全部不可用了,比如你想用redis?不好意思,hiredis不能用了,要自己轮一个;你想用mysql?不好意思,mysqlclient不能用了,要自己轮一个。放弃整个C/C++生态全部自己轮,这个玩笑开的有点大,所以只能称之为“玩具级”。

3.工业级 以部分正确的方式HOOK了网络io相关的syscall,可以少改甚至不改代码的兼容大多数第三方库;特点:没有完整生态

代表作:libco

这一层次的协程库,但是hook的不够完善,未能完全模拟syscall的行为,只能兼容行为符合预想的同步模型的第三方库,这虽然只能覆盖一部分的第三方库,但是通过严苛的源码审查、付出代价高昂的测试成本,也可以勉强用于实际项目开发了;

但其他机制不够完善:协程间通讯、协程同步、调试等,因此对开发人员的要求很高,深谙底层机制才能写出没有问题的代码;再加上hook不完善带来的隐患,开发过程可谓是步步惊心、如履薄冰。

4.框架级 以100%行为模拟的方式HOOK了网络io相关的syscall,可以完全不改代码兼容大多数第三方库;依照专为协程而生的语言的使用经验,提供了协程开发所必须的完整生态;

代表作:libgo

这一层次的协程库,能够100%模拟被hook的syscall的行为,能够兼容任何网络io行为的同步模型的第三方库;由于协程开发生态的完善,对开发人员的要求变得很低,新手也可以写出高效稳定的代码。但由于C++的灵活性,用户行为是不受限的,所以依然存在几个边边角角的难点需要开发者注意:没有gc(开发者要了解协程的调度时机和生命期),TLS的问题,用户不按套路出牌、把逻辑代码run在协程之外,粗粒度的线程锁等等。

关于C/C++ Linux后端开发网络底层原理知识 点击

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值