mongos是mongodb提供的自动分片组件,在提供分片功能的mongodb系统中,几乎所有的请求都将通过mongos转发到mongod中,然后mongos再汇总,最后返回给客户端.本来就来分析分析mongos的初始化,为后面通过mongos的查询,删除,修改,增加记录 mapreduce aggregate以及mongos的自动分片与负载均衡做准备.下面来看代码,其入口为mongo\s\server.cpp中的main,去掉其中处理命令行参数部分,直接从其正式的开始函数runMongosServer入手.
static bool runMongosServer( bool doUpgrade ) {
pool.addHook( new ShardingConnectionHook( false ) );//mongos使用连接池管理连接,这里设置连接池的回调函数,对于ShardingConnectionHook(false)时仅在创建新的连接时做验证工作,验证用户名以及密码
pool.setName( "mongos connectionpool" );
shardConnectionPool.addHook( new ShardingConnectionHook( true ) );//对于这里ShardingConnectionHook参数为true则需要根据连接的类型,若为master(单服务器) set(replset模式)则需要向连接默认发送命令setShardVersion,传递自己的ServerID(一个OID类型,自动生成),后面将会用到这个ServerID,将mongos错误转发的数据转发回mongs中,让其正确的转发到相应的mongod中,这个部分后面专门会用一篇文章谈到.
shardConnectionPool.setName( "mongos shardconnection connectionpool" );
// Mongos shouldn't lazily kill cursors, otherwise we can end up with extras from migration
DBClientConnection::setLazyKillCursor( false );
ReplicaSetMonitor::setConfigChangeHook( boost::bind( &ConfigServer::replicaSetChange , &configServer , _1 ) );
if ( ! configServer.init( configdbs ) ) {//configServer的初始化,设置configserver的地址.
return false;
if ( ! configServer.ok( true ) ) {//连接configserver,确保能够连接configserver
return false;
}
{
class CheckConfigServers : public task::Task {
virtual string name() const { return "CheckConfigServers"; }
virtual void doWork() { configServer.ok(true); }
};
task::repeat(new CheckConfigServers, 60*1000);//这里每过60秒检查一次configserver是否可连接
}
int configError = configServer.checkConfigVersion( doUpgrade );//更新config版本,只能从2版本升级到3版本,动作简单来说是备份原来的数据
if ( configError ) {//然后读取其数据,根据最新的3版本将数据写入到collection中,不再深入分析
return false;
}
configServer.reloadSettings();//读取configserver中的设置,确保部分数据建立了索引.
init();
#if !defined(_WIN32)
CmdLine::launchOk();
#endif
if ( !noHttpInterface )
boost::thread web( boost::bind(&webServerThread, new NoAdminAccess() /* takes ownership */) );
MessageServer::Options opts;
opts.port = cmdLine.port;
opts.ipList = cmdLine.bind_ip;
start(opts);//开始启动服务.
// listen() will return when exit code closes its socket.
dbexit( EXIT_NET_ERROR );
return true;
}
runMongoServer->ConfigServer::init
bool ConfigServer::init( vector<string> configHosts ) {
string hn = getHostName();
set<string> hosts;
for ( size_t i=0; i<configHosts.size(); i++ ) {
string host = configHosts[i];
hosts.insert( getHost( host , false ) );//服务器地址,不带端口
configHosts[i] = getHost( host , true );//服务器地址,带端口
}
for ( set<string>::iterator i=hosts.begin(); i!=hosts.end(); i++ ) {
string host = *i;
bool ok = false;
for ( int x=10; x>0; x-- ) {//通过getnameinfo解析服务器,
if ( ! hostbyname( host.c_str() ).empty() ) {
ok = true;
break;
}
sleepsecs( 10 );
}
if ( ! ok )
return false;
}
_config = configHosts;//保存配置
string fullString;
joinStringDelim( configHosts, &fullString, ',' );//将所有服务器地址连接起来
_primary.setAddress( ConnectionString( fullString , ConnectionString::SYNC ) );//10gen建议生产环境中不要只使用一台configserver,这里多台server按照sync模式工作,就是所有请求处理同时发往这里设置的多台服务器上.
return true;
}