LogicServer初探
构造函数中启动的是一些管理器
template <typename T> LogicServer<T>::LogicServer(pm::common::Context &ctx, MgrEventDelegator *delegator, const pm::ServerRole &role) : ctx_(ctx), event_delegator_(delegator), role_(role) { //比如一个xxxServer与另一个xxxServer连接,内部其实是靠 //xxxServer内部的xxxServiceServer连接的 //这个ServiceManager应该就是xxxServiceServer连接的管理器 pm::common::ServiceManager::set(&sm_); T::manager::set(&tm_); pm::common::RpcCallbackRef::set(&rpc_cb_ref_); pm::db::RedisManager::set(&rm_); pm::common::ServerStatManager::set(&ssm_); }
// 具体的LoginApp,GateApp或者GameApp会调用这个函数 template <typename T> void LogicServer<T>::work() { // start thread pool 启动线程池 thread_pool_.reset(new pm::common::ThreadPool(CFG(loop_threads))); //初始化一个线程池的单例 pm::common::ThreadPool::set(thread_pool_.get()); thread_pool_->start(); thread_pool_->waitForReady(); //初始化http http_manager_.reset(new HttpManager(thread_pool_->chooseBestThreadBase())); // init mgr_client 初始化mgr_client, // 获得与MgrApp连接的线程 auto &mgr_base = thread_pool_->chooseBestThreadBase(); std::promise<std::shared_ptr<pm::common::TcpConnection>> mgr_handler_promise; auto mgr_handler_future = mgr_handler_promise.get_future(); mgr_base.post([&mgr_base, &mgr_handler_promise] { auto tcp_conn = std::make_shared<pm::common::TcpConnection>(mgr_base, -1); mgr_handler_promise.set_value(std::move(tcp_conn)); }); //等待mgr_handler_promise的set_value被调用(会阻塞主线程) //确保创建tcp连接的实例 auto tcp_conn = mgr_handler_future.get(); mgr_client_.reset(new pm::common::MgrHandler( ctx_, std::make_shared<pm::common::RpcChannel>( ctx_, std::static_pointer_cast<pm::common::DiscreteConnection>( std::make_shared<pm::common::TcpDiscreteConnection>(tcp_conn))), event_delegator_)); //初始化redis if (CFG(enable_redis)) { if (CFG(enable_redis_cluster)) { pm::db::RedisManager::inst().initForCluster(ctx_, CFG(redis_cluster_addr)); } else { pm::db::RedisManager::inst().init(ctx_, CFG(redis_ip), CFG(redis_port)); } } // set lua env //---------------- std::string script_dir = CFG(script_dir); std::string lua_loader_file = script_dir + "/framework/loader.lua"; // init lua auto &lua_stack = ctx_.getLuaStack(); lua_stack.setString("script_dir", script_dir) .setString("component", getServerRoleName(role_)) .setInt("server_id", FLAGS_server_id) .setString("server_tag", CFG(tag)) .setData("config", ServerConfig::inst().getCfgReader().getCfg()) .setRegisterUserData(pm::consts::mgr_client_key_name, mgr_client_.get()) .setRegisterUserData(pm::consts::http_manager_key_name, http_manager_.get()); //--------------- if (!lua_stack.dofile(lua_loader_file)) { REPORT_LOG(ERROR) << "execute lua failed: " << lua_loader_file; } else if (!_startLocalServer()) { //具体连接工作(连接mgr)在_startLocalServer()中进行 REPORT_LOG(ERROR) << "start local server failed"; } else if (!_startLater()) { REPORT_LOG(ERROR) << "call startLater failed"; } else { ctx_.getLuaStack().postEvent(LuaEventType::ON_READY); } lua_settop(lua_stack.state(), 0); _loopUntilExit(); }
_loopUntilExit()就进入了主线程的循环当中
template <typename T> void LogicServer<T>::_loopUntilExit() { //从配置文件读取,服务器帧频率的概念,默认是10,也就是一秒执行10次 int hz = CFG(tick_hertz); if (hz > 0) { auto tick_interval = static_cast<int>(1000 * 1.0 / hz); ctx_.getLuaStack().setInt("tick_interval", tick_interval); uint64_t cycles = 0; while (!ctx_.isStopped()) { tick(cycles++, tick_interval); } } else { ctx_.dispatch(); } }
#define PER_SECOND(x) \ if (cycles % (static_cast<int>(static_cast<double>(x) * CFG(tick_hertz))) == 0) template <typename T> void LogicServer<T>::tickBefore(uint64_t cycles) { //这个应该是检查和mgr是否还连接着吧? //心跳检查 PER_SECOND(10) { if (mgr_client_) { pm::mgr::MgrTickMessage req; req.set_server_id(ServerConfig::inst().getLocalInfo().id()); mgr_client_->callMethod(&pm::mgr::MgrService::tick, &req); } } //和lua垃圾回收有关 PER_SECOND(30) { auto gc_count = ctx_.getLuaStack().gcCount(); if (gc_count > CFG(gc_warn_size)) { LOG(WARNING) << "lua vm size: " << gc_count; } } } template <typename T> void LogicServer<T>::tick(uint64_t cycles, int tick_interval) { auto start_time = pm::common::nowtime(); //非阻塞去进行一次event_base_loop,处理堆积的事务 { MICROPROFILE_SCOPEI("_loopUntilExit", "dispatch_once", MP_YELLOW); ctx_.dispatch_once(); } { MICROPROFILE_SCOPEI("_loopUntilExit", "onTick", MP_BROWN); //tickBefore做一些和mgr之间心跳检查以及检查lua虚拟机的gc工作 this->tickBefore(cycles); this->onTick(cycles); } { MICROPROFILE_SCOPEI("_loopUntilExit", "sleep", MP_BLUE); auto end_time = pm::common::nowtime(); auto tick_execution_time = end_time - start_time; int quota_per_tick = CFG(quota_per_tick); if (tick_execution_time > quota_per_tick) { LOG(WARNING) << "execution time of tick more than " << quota_per_tick << ", execution time: " << tick_execution_time; ctx_.getLuaStack().postEvent(pm::LuaEventType::ON_EXCEED_TICK_QUOTA, tick_execution_time); } auto sleep_time = tick_interval - tick_execution_time; double load_smooth_bias = CFG(load_smooth_bias); // clamp double new_ratio = (std::min)((std::max)(1 - static_cast<double>(sleep_time) / tick_interval, 0.0), 1.0); server_load_ = (1 - load_smooth_bias) * server_load_ + load_smooth_bias * new_ratio; SET_STAT(double, app_load, server_load_); beforeSleep(sleep_time); auto real_sleep_time = tick_interval - (pm::common::nowtime() - start_time); if (real_sleep_time > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(real_sleep_time)); } } MicroProfileFlip(nullptr); }
一帧中,主线程先处理堆积的事务(dispatch_once),然后在tickBefore里做一下mgr心跳检查和lua垃圾回收检查相关的事情,然后算一下各种性能指标和剩余睡觉时间,最后
std::this_thread::sleep_for(std::chrono::milliseconds(real_sleep_time))
 
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号