在前一篇介绍mongos的请求处理逻辑中,提到对于读请求(queryop、getmore)来说,具体和ShardServer交互执行查询任务的是TaskExecutor模块,今天详细介绍下TaskExecutor模块的业务逻辑。
TaskExecutor设计
TaskExecutor模块功能上包括建立并维持mongos到shardserver的长连接,以及执行网络交互请求的network线程池,总体设计如下图所示:

TaskExecutorPool:TaskExecutor整体上以Pool的形态对外体现,启动时初始化多个TaskExecutor,包括一个用于和ConfigServer通信,以及多个用于和ShardServer通信,默认每个CPU核创建一个;
ThreadPoolTaskExecutor:TaskExecutor的具体实现类,主要包含三个队列,主要工作还是交给NetworkInterfaceASIO完成;
_networkInProgressQueue: 表示等待NetworkInterfaceASIO处理返回的任务队列;
_poolInProgressQueue:表示NetworkInterfaceASIO已经完成处理,正在处理查询结果写入查询缓存区;
_unsignaledEvents:等待被唤醒的conn线程队列;
NetworkInterfaceASIO:TaskExecutor的核心模块,每个ThreadPoolTaskExecutor实例对应一个本实例,负责从ConnectionPool获取到对应ShardServer的网络连接,并包含一个Network线程执行和ShardServer的网络交互,采用Boost.ASIO异步网络通信。NetworkInterfaceASIO包含两个队列:
inGetConnection: 表示正在等待从ConnectionPool获取连接的任务队列;
_inProgress:表示已获取到连接,正在和ShardServer交互的任务队列;
ConnectionPool:到ShardServer的连接池,每个NetworkInterfaceASIO实例对应一个连接池实例,连接按照远端ShardServer地址组织,一个SpecificPool管理到一个ShardServer的多个网络连接,连接的数量根据业务压力动态创建,也就是说同一个mongos到同一个ShardServer会同时存在很多个网络连接;
TaskExecutor时序图

对于查询请求(queryop、getmore)来说,mongos使用pipeline的线程模型,由conn线程和network线程配合完成查询请求处理:
conn线程:获取到ShardServer的网络连接,生成查询任务放入任务队列,然后阻塞等待;
network线程:将查询请求发给ShardServer,接收响应,并把查询结果写入到针对每个shardserver的查询结果缓存,然后唤醒conn线程进一步处理。
总结下mongos的conn和network线程使用方式:
conn线程:每个网络连接创建一个conn线程,负责接收客户端请求sourceMessage、处理请求processMessage和回复响应sinkMessage,网络调用为同步阻塞模式;
network线程:默认每个CPU核创建一个network线程,负责和ShardServer交付,使用boost.asio异步网络模式;
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31556448/viewspace-2219248/ ,如需转载,请注明出处,否则将追究法律责任。