写文章之前。我们一般会想要採用何种方式,是“开门见山”,还是”疑问式开头“。写代码也有些类似。在编码之前我们须要考虑系统总体方案,这也就是各种设计文档的作用。在设计新系统之初,我基本的目的是:保证高效率;保证高扩展性。
效率评价以”任务数/秒“做单位。
因为我的系统仅仅是client,不应该占用太多内存以及CPU。所以内存占用率,CPU使用率也被作为一个硬性指标。那么这里就存在疑问的地方:client有必要採用Boost Asio来做吗?我个人认为这取决于client的规模。假设client须要做到高并发。那么应该採用异步IO方式来做;反之则不必。
进一步。我们是怎样做到高效率?我们的设计大体流程例如以下:
注意:这里的任务都是同一份实例。
stream_server:负责接收任务。它实际上包含两部分:stream_server和stream_client。stream_server负责accept新连接。当连接到来时,它创建出stream_client。
这个被创建出的stream_client负责详细的任务解析。任务接收。
stream_client并不保存任务信息,它直接将正确的任务交由task_manager去进一步处理。
stream_server内部保存着各个client实例。这是为了方便以后对并发数的限制。
task_manager实际上包含分发和检測任务超时两个功能。不管是何种功能,task_manager都不保存任务信息。分发时,task_manager将任务分配到相应的runner中去执行;检測超时。则调用各个runner提供的检測超时接口。
runner是唯一真正持有任务实例的地方。从上面我们对stream_server和task_manager的描写叙述,这二者都不持有任务。我们希望通过这种设计,最大限度地实现0拷贝。runner的划分依据业务而来。比方:下载某个文件之后解压,那么我们可分创先出download_runner和decompress_runner:download_runner进行下载,decompress_runner进行解压。这样细分的优点是:假设decompress_runner失败了。那么能够再交由task_manager分发到download_runner进行重试。
换言之,runner能够得到重用。
client是实际运行任务的模块。任务可能是完毕一次HTTP请求(长连接或是短连接由client依据任务来决定),也可能是调用一次shell脚本。为了保证任务的成功率以及原子性,client具有超时控制,以及自己主动重试的功能(重试次数由runner指定)。
写到这里已经非常明显了,假设要做到多任务并发,或者採用多个client同一时候并发。或者採用多个runner同一时候执行任务。这里须要注意的是:runner是同步且被动的。
也就是:runner同一时刻仅仅能执行一个任务,且须要由task_manager主动给予任务。