最近在努力同步维护SegmentFault的文章积累~方便后续持续更新~
原文是2019年7月底开源时po的,这里对近况进行了调整和补充。
希望自己和项目都可以持续进步 (๑╹ヮ╹๑)ノ 欢迎多多交流!
我们的项目C++ Workflow于两天前开源啦~~~
https://github.com/sogou/workflow
目前文档、开源管理及其他方面都在摸索推进中,我也按捺不住想要以开发者之一的名义,写一系列个人博客,让大家可以从方方面面了解到workflow的全部信息~最官方的更新还是要以github为准,欢迎大家关注我们的项目,尝试使用并提出宝贵意见。
项目主页的README里已经有非常详细的介绍了,这里我来补充一些基本信息。本系列其他文章链接也会持续更新到这里。
一、 使用情况
Workflow是搜狗的C++服务器引擎,支撑搜狗和腾讯的海量线上请求,包括搜狗几乎所有后端C++在线服务,如搜索服务,云输入法,在线广告等,每日处理超百亿请求。这是一个设计轻盈优雅的企业级程序引擎,是由首席架构师带领我们小几人的虚拟团队经历一年多打磨出来并开源的,可以满足大多数C++后端开发需求,目前开源一年多了也在持续迭代中,开发者社区也在用心维护。
除了公司内,很多中小型公司使用,有的是用作计算server,有的是用作异步MySQL客户端,更多的是更加复杂的高吞吐低延迟异步流程复杂系统,用以重构基本基本性能提升好几倍,轻松把cpu吃满,开源一路以来能够被认可真的是一件非常振奋人心的事情。然而开源对我们来说只是刚刚开始,这是一条充满挑战的道路。非常期待亮相于github的workflow未来可以拥有更多的可能性。
感慨完毕,说回正题~在公司内部和github中容易被用户接纳和使用,我认为得益于以下几个优点:
1.1 极其优异的性能
我们这里说的性能,不是单指如何跑满cpu、如何单独地让网络请求极速响应、或者说如何异步操作文件或其他设备,而是所有这些资源都可以被其具体的调度器管理,尽可能地全部都调度起来。
由于workflow是个框架,除非是具体业务场景的前后对比否则很难给出benchmark,因此性能优化因业务而已。但当作webserver这一场景的话,和业内比较通用的nginx和brpc在吞吐和长尾方面做了一些benchmark,可供大家参考:workflow benchmark。
值得一提的是,workflow用做proxy的时候,压测最大QPS是echo server的结果的1/2,是workflow中异步调度无损耗的最好证明。
性能比nginx要好是很自然的,可以参考我先前的一篇用以改造异步调度QAT加速卡的小伙伴的测试,还没细优化,随便看看:OpenSSL异步模式与Intel QAT加速卡(四) 新一代异步调度框架workflow
我老大、也就是项目主作者的习惯是喜欢把东西做到最简洁、把性能做到最极致,因此项目对性能的每一个细节都不会马虎,本人受益匪浅。但是我们团队接触开源比较少,因此我个人非常希望能在性能优化方面学习到更多优秀的做法。
1.2 比其他C++框架更友好的用户体验
我们给开发者用户接触到的是task(任务)和series(任务流):
- task由工厂创建、自行销毁;
- series可以手动从工厂创建或者自动创建,也是自行销毁。
用户再也接触不到连接池、线程池、包括想要做aio时的文件fd与各种异步通知机制。
从语言的发展来看,go的出现与被喜爱是必然的,原因之一就是天下苦C++久矣,而go的封装很高级很简约。虽然C++后续也推出了各种新用法,但不是所有用户都会升到更高的标准,目前workflow的标准是C++11。
而任务和任务流的概念在理解和易用性上简直甩开事件机制和用循环来做多次进入的开发模式十条街(后面这种模式真的太难了,我感觉自己也并没有理解透彻,但发现OpenSSL的异步和grpc的异步server都是这样做的)。但是,我们一开始学习编程的时候,就知道要封装函数,而不是学习怎么做事件通知,学习的是最简单的for循环里执行相同的代码段,而不是用循环做多次重入实现不一样的阶段控制。而任务和任务流的封装,就是函数和循环的封装,是很贴近最基本的编程理念的。
关于OpenSSL中异步和aio的异步机制,以前写过一篇是做mac的aio模块时对aio各种异步通知机制的拙见,感兴趣的小伙伴可以看看,并且欢迎给我指出错误:异步I/O -- posix aio 从入门到放弃的吐血实践。
1.3 通信计算资源融为一体的解决方案
我们特别适用于重计算,而搜索的绝大部分使用场景都是重计算的server,而网络和计算都可以用workflow一并解决。
workflow认为一切资源都是可以异步调度的,因此对于目前支持对接的资源,我鶸鶸地归纳对比了如下表格:
计算这里详细说一下,原先检索模块开发小伙伴常常面临选择高吞吐网络框架的同时,自己需要面对不同计算资源比例而划分不同大小的线程池。
然而每种计算具体资源需求比例是动态变化的,重要性也不一样,后端响应时长也是动态变动,如果我们在初始化的时候创建若干个特定大小的线程池,线程资源难以共用。
Go内部的go routine调度就是用来解决这种事情的。那么C++来说,现在workflow可以和go一样解决全局计算资源共享和按需调度的需求了,并且打通网络、磁盘等等其他资源。
1.4 代码架构层次良好,易于拼装,实现二次开发
workflow的世界里有三个原则:
- 串行是由任务组成的
- 并行是由串行组成的
- 并行是一种任务
于是乎,workflow是一套完备的、可以收敛一切循环和控制的任务流模型。
以下是我的一些个人解读:
- 由于可以串行,我们就可以动态建流图,并且无限执行下去;
- 由于可以并行,并行的是各个串行流,我们可以对多个并发执行的流在完成时做收敛;
- 并行本身是一种任务,因此可以加到串行流图里,即每个任务都可以是一个复合任务组装而成,组装后提供给其他使用者使用,而使用者不需要关心复合任务内部细节,进一步组装。
当然workflow的其他优点很多,这些是公司内部使用情况的一些总结,其他的会陆续给大家介绍~今天其他点也不太写得完了,这里列个大概,后续会更新哦~