2018-05-17 ProcessClass 管理

目的

梳理 fdb 有哪些 ProcessClass,是怎么啟動(dòng)這些 ProcessClass 的命雀,以及主要的 ProcessClass 的作用。

思路

在 fdb 的實(shí)現(xiàn)中斩箫,在 WorkerInterfacer.h 文件中有一個(gè) startRole 的函數(shù)吏砂,在 fdb 啟動(dòng)某個(gè) ProcessClass 的時(shí)候都會(huì)調(diào)用該函數(shù)來(lái)進(jìn)行注冊(cè)。所以我們可以通過(guò)該函數(shù)來(lái)幫助我們梳理fdb的實(shí)現(xiàn)乘客。

void startRole(UID roleId, UID workerId, std::string as, std::map<std::string, std::string> details = std::map<std::string, std::string>(), std::string origination = "Recruited");

角色列表

通過(guò)直接搜索 startRole狐血,可以得到完整的 ProcessClass 列表有:

  1. LogRouter
  2. Resolver
  3. MasterProxyServer
  4. StorageServer
  5. SharedTLog
  6. MasterServer
  7. Worker
  8. TLog
  9. Tester
  10. ClusterController

ACTOR Future<Void> workerServer( Reference<ClusterConnectionFile> connFile, Reference<AsyncVar<Optional<ClusterControllerFullInterface>>> ccInterface, LocalityData localities, Reference<AsyncVar<ClusterControllerPriorityInfo>> asyncPriorityInfo, ProcessClass initialClass, std::string folder, int64_t memoryLimit, std::string metricsConnFile, std::string metricsPrefix ) 函數(shù)中,先根據(jù) getDiskStores 來(lái)啟動(dòng) StorageServer/TLog, 并注冊(cè)一個(gè) Worker 的角色易核。之后通過(guò)事件循環(huán)監(jiān)聽(tīng) interf 來(lái)決定啟動(dòng)其它角色匈织。例如其中的 MasterServer

loop choose {

when( RecruitMasterRequest req = waitNext(interf.master.getFuture()) ) {
                MasterInterface recruited;
                recruited.locality = locality;
                recruited.initEndpoints();

                startRole( recruited.id(), interf.id(), "MasterServer" );

                DUMPTOKEN( recruited.waitFailure );
                DUMPTOKEN( recruited.getRateInfo );
                DUMPTOKEN( recruited.tlogRejoin );
                DUMPTOKEN( recruited.changeCoordinators );
                DUMPTOKEN( recruited.getCommitVersion );

                //printf("Recruited as masterServer\n");
                Future<Void> masterProcess = masterServer( recruited, dbInfo, ServerCoordinators( connFile ), req.lifetime );
                errorForwarders.add( zombie(recruited, forwardError( errors, "MasterServer", recruited.id(), masterProcess )) );
                req.reply.send(recruited);
            }
}

流程上:

  1. ClusterConnectionFile 里面有 coordinator 的地址
  2. fdbd 方法嘗試從 coordiantor 中選擇一個(gè)選舉為 clusterControler,同時(shí)
  3. 會(huì)調(diào)用 workerServer 方法牡直,這兒 workerServer 會(huì)和上一步的 clusterControler 方法共用一個(gè) ClusterControllerFullInterface 變量(之后 clusterControler 會(huì)通過(guò)其來(lái)發(fā)送控制消息缀匕?)。
  4. clusterControler 會(huì)啟動(dòng) Master碰逸,見(jiàn)方法 clusterWatchDatabase

角色個(gè)數(shù)

fdb 期望來(lái)自動(dòng)決策“啟動(dòng)哪些角色以及啟動(dòng)多少”乡小,默認(rèn)的配置在 fdbclient/Knobs.cpp 下。如下

        // Configuration
    init( DEFAULT_AUTO_PROXIES,                      3 );
    init( DEFAULT_AUTO_RESOLVERS,                    1 );
    init( DEFAULT_AUTO_LOGS,                         3 );

ClusterControllerData 類中的一些方法饵史,例如 getStorageWorker 根據(jù)請(qǐng)求的條件劲件,分配出合適的 worker。在分析機(jī)制约急,有一個(gè) Fitness 的概念來(lái)選擇最合適的 worker 負(fù)責(zé)相應(yīng)的角色零远。 findWorkersForConfiguration 函數(shù)負(fù)責(zé)從配置中規(guī)劃整個(gè)集群。

    vector<std::pair<WorkerInterface, ProcessClass>> getWorkersForRoleInDatacenter(Optional<Standalone<StringRef>> const& dcId, ProcessClass::ClusterRole role, int amount, DatabaseConfiguration const& conf, std::map< Optional<Standalone<StringRef>>, int>& id_used, Optional<WorkerFitnessInfo> minWorker = Optional<WorkerFitnessInfo>(), bool checkStable = false ) {
        std::map<std::pair<ProcessClass::Fitness,int>, vector<std::pair<WorkerInterface, ProcessClass>>> fitness_workers;
        vector<std::pair<WorkerInterface, ProcessClass>> results;
        if (amount <= 0)
            return results;

        for( auto& it : id_worker ) {
            auto fitness = it.second.processClass.machineClassFitness( role );
            if( workerAvailable(it.second, checkStable) && !conf.isExcludedServer(it.second.interf.address()) && it.second.interf.locality.dcId() == dcId &&
              ( !minWorker.present() || ( it.second.interf.id() != minWorker.get().worker.first.id() && ( fitness < minWorker.get().fitness || (fitness == minWorker.get().fitness && id_used[it.first] <= minWorker.get().used ) ) ) ) ) {
                fitness_workers[ std::make_pair(fitness, id_used[it.first]) ].push_back(std::make_pair(it.second.interf, it.second.processClass));
            }
        }

        for( auto& it : fitness_workers ) {
            auto& w = it.second;
            g_random->randomShuffle(w);
            for( int i=0; i < w.size(); i++ ) {
                results.push_back(w[i]);
                id_used[w[i].first.locality.processId()]++;
                if( results.size() == amount )
                    return results;
            }
        }

        return results;
    }

ProcessClass::Fitness ProcessClass::machineClassFitness( ClusterRole role ) const {
    switch( role ) {
    case ProcessClass::Storage:
        switch( _class ) {
        case ProcessClass::StorageClass:
            return ProcessClass::BestFit;
        case ProcessClass::UnsetClass:
            return ProcessClass::UnsetFit;
        case ProcessClass::TransactionClass:
            return ProcessClass::WorstFit;
        case ProcessClass::LogClass:
            return ProcessClass::WorstFit;
        case ProcessClass::TesterClass:
            return ProcessClass::NeverAssign;
        default:
            return ProcessClass::NeverAssign;
        }
    case ProcessClass::TLog:
        switch( _class ) {
        case ProcessClass::LogClass:
            return ProcessClass::BestFit;
        case ProcessClass::TransactionClass:
            return ProcessClass::GoodFit;
        case ProcessClass::UnsetClass:
            return ProcessClass::UnsetFit;
        case ProcessClass::StorageClass:
            return ProcessClass::WorstFit;
        case ProcessClass::TesterClass:
            return ProcessClass::NeverAssign;
        default:
            return ProcessClass::NeverAssign;
        }
    case ProcessClass::Proxy:
        switch( _class ) {
        case ProcessClass::ProxyClass:
            return ProcessClass::BestFit;
        case ProcessClass::StatelessClass:
            return ProcessClass::GoodFit;
        case ProcessClass::ResolutionClass:
            return ProcessClass::BestOtherFit;
        case ProcessClass::TransactionClass:
            return ProcessClass::BestOtherFit;
        case ProcessClass::UnsetClass:
            return ProcessClass::UnsetFit;
        case ProcessClass::TesterClass:
            return ProcessClass::NeverAssign;
        default:
            return ProcessClass::WorstFit;
        }
    case ProcessClass::Master:
        switch( _class ) {
        case ProcessClass::MasterClass:
            return ProcessClass::BestFit;
        case ProcessClass::StatelessClass:
            return ProcessClass::GoodFit;
        case ProcessClass::ResolutionClass:
            return ProcessClass::BestOtherFit;
        case ProcessClass::TransactionClass:
            return ProcessClass::BestOtherFit;
        case ProcessClass::UnsetClass:
            return ProcessClass::UnsetFit;
        case ProcessClass::TesterClass:
            return ProcessClass::NeverAssign;
        default:
            return ProcessClass::WorstFit;
        }
    case ProcessClass::Resolver:
        switch( _class ) {
        case ProcessClass::ResolutionClass:
            return ProcessClass::BestFit;
        case ProcessClass::StatelessClass:
            return ProcessClass::GoodFit;
        case ProcessClass::TransactionClass:
            return ProcessClass::BestOtherFit;
        case ProcessClass::UnsetClass:
            return ProcessClass::UnsetFit;
        case ProcessClass::TesterClass:
            return ProcessClass::NeverAssign;
        default:
            return ProcessClass::WorstFit;
        }
    case ProcessClass::LogRouter:
        switch( _class ) {
        case ProcessClass::LogRouterClass:
            return ProcessClass::BestFit;
        case ProcessClass::StatelessClass:
            return ProcessClass::GoodFit;
        case ProcessClass::ResolutionClass:
            return ProcessClass::BestOtherFit;
        case ProcessClass::TransactionClass:
            return ProcessClass::BestOtherFit;
        case ProcessClass::UnsetClass:
            return ProcessClass::UnsetFit;
        case ProcessClass::TesterClass:
            return ProcessClass::NeverAssign;
        default:
            return ProcessClass::WorstFit;
        }
    case ProcessClass::ClusterController:
        switch( _class ) {
        case ProcessClass::ClusterControllerClass:
            return ProcessClass::BestFit;   
        case ProcessClass::StatelessClass:
            return ProcessClass::GoodFit;
        case ProcessClass::MasterClass:
            return ProcessClass::BestOtherFit;
        case ProcessClass::ResolutionClass:
            return ProcessClass::BestOtherFit;
        case ProcessClass::ProxyClass:
            return ProcessClass::BestOtherFit;
        case ProcessClass::UnsetClass:
            return ProcessClass::UnsetFit;
        case ProcessClass::TesterClass:
            return ProcessClass::NeverAssign;
        default:
            return ProcessClass::WorstFit;
        }
    default:
        return ProcessClass::NeverAssign;
    }
}
    std::pair<WorkerInterface, ProcessClass> getStorageWorker( RecruitStorageRequest const& req ) {
        std::set<Optional<Standalone<StringRef>>> excludedMachines( req.excludeMachines.begin(), req.excludeMachines.end() );
        std::set<Optional<Standalone<StringRef>>> includeDCs( req.includeDCs.begin(), req.includeDCs.end() );
        std::set<AddressExclusion> excludedAddresses( req.excludeAddresses.begin(), req.excludeAddresses.end() );

        for( auto& it : id_worker )
            if( workerAvailable( it.second, false ) &&
                    !excludedMachines.count(it.second.interf.locality.zoneId()) &&
                    ( includeDCs.size() == 0 || includeDCs.count(it.second.interf.locality.dcId()) ) &&
                    !addressExcluded(excludedAddresses, it.second.interf.address()) &&
                    it.second.processClass.machineClassFitness( ProcessClass::Storage ) <= ProcessClass::UnsetFit ) {
                return std::make_pair(it.second.interf, it.second.processClass);
            }

        if( req.criticalRecruitment ) {
            ProcessClass::Fitness bestFit = ProcessClass::NeverAssign;
            Optional<std::pair<WorkerInterface, ProcessClass>> bestInfo;
            for( auto& it : id_worker ) {
                ProcessClass::Fitness fit = it.second.processClass.machineClassFitness( ProcessClass::Storage );
                if( workerAvailable( it.second, false ) &&
                        !excludedMachines.count(it.second.interf.locality.zoneId()) &&
                        ( includeDCs.size() == 0 || includeDCs.count(it.second.interf.locality.dcId()) ) &&
                        !addressExcluded(excludedAddresses, it.second.interf.address()) &&
                        fit < bestFit ) {
                    bestFit = fit;
                    bestInfo = std::make_pair(it.second.interf, it.second.processClass);
                }
            }

            if( bestInfo.present() ) {
                return bestInfo.get();
            }
        }

        throw no_more_servers();
    }

WorkerInterface

WorkerInterface 包含ClientWorkerInterface

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末厌蔽,一起剝皮案震驚了整個(gè)濱河市牵辣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奴饮,老刑警劉巖纬向,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件择浊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡逾条,警方通過(guò)查閱死者的電腦和手機(jī)琢岩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)师脂,“玉大人担孔,你說(shuō)我怎么就攤上這事〕跃” “怎么了糕篇?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)酌心。 經(jīng)常有香客問(wèn)我拌消,道長(zhǎng),這世上最難降的妖魔是什么安券? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任墩崩,我火速辦了婚禮,結(jié)果婚禮上侯勉,老公的妹妹穿的比我還像新娘鹦筹。我一直安慰自己,他們只是感情好壳鹤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布盛龄。 她就那樣靜靜地躺著,像睡著了一般芳誓。 火紅的嫁衣襯著肌膚如雪余舶。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天锹淌,我揣著相機(jī)與錄音匿值,去河邊找鬼。 笑死赂摆,一個(gè)胖子當(dāng)著我的面吹牛挟憔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播烟号,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼绊谭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了汪拥?” 一聲冷哼從身側(cè)響起达传,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后宪赶,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體宗弯,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年搂妻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蒙保。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡欲主,死狀恐怖邓厕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情岛蚤,我是刑警寧澤邑狸,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布懈糯,位于F島的核電站涤妒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏赚哗。R本人自食惡果不足惜她紫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望屿储。 院中可真熱鬧贿讹,春花似錦、人聲如沸够掠。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)疯潭。三九已至赊堪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間竖哩,已是汗流浹背哭廉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留相叁,地道東北人遵绰。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像增淹,于是被迫代替她去往敵國(guó)和親椿访。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理虑润,服務(wù)發(fā)現(xiàn)成玫,斷路器,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • 接著上節(jié) condition_varible ,本節(jié)主要介紹future的內(nèi)容梁剔,練習(xí)代碼地址虽画。本文參考http:/...
    jorion閱讀 14,793評(píng)論 1 5
  • Lua 5.1 參考手冊(cè) by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,797評(píng)論 0 38
  • 接著上節(jié) atomic,本節(jié)主要介紹condition_varible的內(nèi)容荣病,練習(xí)代碼地址码撰。本文參考http://...
    jorion閱讀 8,491評(píng)論 0 7
  • 1:12點(diǎn)半,老板娘打電話給我个盆,讓我把車開(kāi)到公司脖岛。開(kāi)過(guò)來(lái)以后,把公司有一部小白車上面的菜轉(zhuǎn)移到我的這個(gè)車子上面颊亮,然...
    賢旺閱讀 114評(píng)論 0 0