Juice-一種基于MesosFramework的任務(wù)云框架

作者:徐佳
文為原創(chuàng)文章,轉(zhuǎn)載請注明作者及出處

在介紹Juice之前涛癌,我想先聊一聊Mesos犯戏,Mesos被稱為2層調(diào)度框架,是因為Master通過內(nèi)部的Allocator完成Master->Framework的第一層調(diào)度拳话,再由Framework通過調(diào)度器完成對于資源->任務(wù)的分配先匪,這個過程稱為第二層調(diào)度。

About MesosFramework

先來看一看Mesos&Framework的整體架構(gòu)圖:


arch.png

Mesos的Framework分為2部分組成弃衍,分別為調(diào)度器和執(zhí)行器呀非。
調(diào)度器被稱為Scheduler,從Mesos1.0版本開始镜盯,官方提供了基于HTTP的RestAPI供外部調(diào)用并進行二次開發(fā)岸裙。
Scheduler用于處理Master端發(fā)起的回調(diào)事件(資源列表并加載任務(wù)、任務(wù)狀態(tài)通知等)形耗,進行相應(yīng)處理哥桥。Agent接收到Master分配的任務(wù)時辙浑,會根據(jù)任務(wù)的container-type進行不同的處理激涤,當(dāng)處理默認(rèn)container-type='Mesos'時,先檢查Framework所對應(yīng)的Executor進程是否啟動判呕,如果沒有啟動則會先啟動Executor進程倦踢,然后再提交任務(wù)到該Executor去執(zhí)行,當(dāng)運行一個container-type='Docker'的任務(wù)時侠草,則啟動Docker Executor進行處理辱挥,程序的運行狀態(tài)完全取決于Docker內(nèi)部的處理及返回值。

MesosFramework交互API

交互分為2部分API边涕,分別為SchedulerAPI(http://mesos.apache.org/documentation/latest/scheduler-http-api/) 與ExecutorAPI(http://mesos.apache.org/documentation/latest/Executor-http-api/)晤碘, 每個API都會以TYPE來區(qū)分,具體的處理流程如下:
1.Scheduler提交一個請求(type='SUBSCRIBE')到Master(http://master-ip:5050/api/v1/scheduler)功蜓, 并需要設(shè)置'subscribe.framework_info.id'园爷,該ID由Scheduler生成,在一個Mesos集群中必須保證唯一式撼,Mesos以此FrameworkID來區(qū)分各個Framework所提交的任務(wù)童社,發(fā)送完畢后,Scheduler端等待Master的'SUBSCRIBE'回調(diào)事件著隆,Master的返回事件被定義在event對象中扰楼,event.type為'SUBSCRIBE'(注意:'SUBSCRIBE'請求發(fā)起后呀癣,Scheduler與Master端會保持會話連接(keep-alive),Master端主動發(fā)起的事件回調(diào)都會通過該連接通知到Scheduler)弦赖。(scheduler-http-api中接口'SUBSCRIBE')
2.Master主動發(fā)起'OFFERS'事件回調(diào)项栏,通知Scheduler目前集群可分配使用資源,事件的event.type為'OFFERS'腾节。(scheduler-http-api中接口'OFFERS')
3.Scheduler調(diào)用resourcesOffer為Offers安排Tasks忘嫉。當(dāng)完成任務(wù)分配后,主動發(fā)起'ACCEPT'事件請求到Master端告知Offers-Tasks列表案腺。(scheduler-http-api中接口'ACCEPT')
4.Master接收到Scheduler的任務(wù)請求后庆冕,將任務(wù)發(fā)送到OfferId對應(yīng)的Agent中去執(zhí)行任務(wù)。
5.Agent接收到任務(wù)劈榨,檢查任務(wù)對應(yīng)的Executor是否啟動访递,如啟動,則調(diào)用該Executor執(zhí)行任務(wù)同辣,如未啟動拷姿,則調(diào)用lauchExecutor()創(chuàng)建Executor對象并執(zhí)行initialize()初始化Executor,Executor初始化過程中會調(diào)用RegisterExecutorMessage在Agent上注冊旱函,之后便接受任務(wù)開始執(zhí)行响巢。(Executor-http-api中接口'LAUNCH')
6.Executor執(zhí)行完畢或錯誤時通知Agent任務(wù)的task_status。(Executor-http-api中接口'UPDATE')
7.Agent再同步task_status給Master棒妨,Master則調(diào)用'UPDATE'事件回調(diào)踪古,通知Scheduler更新任務(wù)狀態(tài)。(scheduler-http-api中接口'UPDATE')
8.Scheduler確認(rèn)后發(fā)送'ACKNOWLEDGE'請求告知Master任務(wù)狀態(tài)已確認(rèn)券腔。(scheduler-http-api中接口'ACKNOWLEDGE')

任務(wù)狀態(tài)標(biāo)示及Agent宕機處理###

對于一個任務(wù)的運行狀態(tài)伏穆,Mesos定義了13種TASK_STATUS來標(biāo)示,常用的有以下幾種:

TASK_STAGING-任務(wù)準(zhǔn)備狀態(tài)纷纫,該任務(wù)已有Master分配給Slave枕扫,但Slave還未運行時的狀態(tài)。
TASK_RUNNING-任務(wù)已在Agent上運行辱魁。
TASK_FINISHED-任務(wù)已運行完畢烟瞧。
TASK_KILLED-任務(wù)被主動終止,調(diào)用scheduler-http-api中'KILL'接口染簇。
TASK_FAILED-任務(wù)執(zhí)行失敗参滴。
TASK_LOST-任務(wù)丟失,通常發(fā)生在Slave宕機剖笙。

當(dāng)Agent宕機導(dǎo)致TASK_LOST時卵洗,Mesos又是怎么來處理的呢?
在Master和Agent之間,一般都是由Master主動向每一個Agent發(fā)送Ping消息过蹂,如果在設(shè)定時間內(nèi)(flag.slave_ping_timeout十绑,默認(rèn)15s)沒有收到Agent的回復(fù),并且達到一定次數(shù)(flag.max_slave_ping_timeouts酷勺,默認(rèn)次數(shù)為5)本橙,那么Master會操作以下幾個步驟:
1.將該Agent從Master中刪除,此時該Agent的資源將不會再分配給Scheduler脆诉。
2.遍歷該Agent上運行的所有任務(wù)甚亭,向?qū)?yīng)的Framework發(fā)送任務(wù)的Task_Lost狀態(tài)更新,同時把這些任務(wù)從Master中刪除击胜。
3.遍歷該Agent上的所有Executor亏狰,并刪除。
4.觸發(fā)Recind Offer偶摔,把這個Agent上已經(jīng)分配給Scheduler的Offer撤銷暇唾。
5.把這個Agent從master的Replicated log中刪除(Mesos Master依賴Replicated log中的部分持久化集群配置信息進行failer over/recovery)。

使用Marathon可以方便的發(fā)布及部署應(yīng)用###

目前有很多基于MesosFramework的開源框架辰斋,例如Marathon策州。我們在生產(chǎn)環(huán)境中已經(jīng)使用了Marathon框架,一般用它來運行l(wèi)ong-run service/application宫仗,依靠marathon來管理應(yīng)用服務(wù)够挂,它支持應(yīng)用服務(wù)自動/手動起停、水平擴展藕夫、健康檢查等孽糖。我們依靠jenkins+docker+marathon完成服務(wù)的自動化發(fā)布及部署。

Why Juice

下面來講下我基于MesosFramework所開發(fā)的一套框架-Juice汁胆。(開源地址:https://github.com/HujiangTechnology/Juice.git)
在開發(fā)Juice之前梭姓,我公司所有的音視頻轉(zhuǎn)碼切片任務(wù)都是基于一個叫TaskCenter的隊列分配框架霜幼,該框架并不具備分布式調(diào)度的功能(資源分配)嫩码,所以集群的資源利用率一直是個問題,所以罪既,我們想開發(fā)一套基于以下三點的新框架來替代老的TaskCenter铸题。

1.一個任務(wù)調(diào)度型的框架赋元,需要對資源(硬件)盡可能的做到最大的利用率涌献。
2.框架必須可運行各種類型的任務(wù)沙峻。
3.平臺必須是穩(wěn)定的赚导。

憑借對Marathon的使用經(jīng)驗段直,以及對于Mesos相關(guān)文檔的查閱逞刷,我們決定基于MesosFramework來開發(fā)一套任務(wù)調(diào)度型的框架恳邀,Mesos與Framework的特性剛才已經(jīng)說過了雳锋,而我們將所需要執(zhí)行的任務(wù)封在Docker中去執(zhí)行,那么對于框架本身來說他就不用關(guān)心任務(wù)的類型了饮六,這樣業(yè)務(wù)的邊界和框架的邊界就變得很清晰其垄,對于Framework來說,運行一個Docker任務(wù)也很方便卤橄,剛才說過Mesos內(nèi)置了DockerExecutor可以完美的啟動Docker任務(wù)绿满,這樣,我們的框架在Agent端所需要的開發(fā)就非常的少窟扑。
Juice框架在這樣的背景下開始了開發(fā)的歷程喇颁,我們對于它的定位是一套分布式任務(wù)云系統(tǒng),這里為什么要稱為任務(wù)云系統(tǒng)呢嚎货?因為對于調(diào)用者來說橘霎,使用Juice,只要做2件事情:把要做的任務(wù)打成Docker鏡像并Push到docker倉庫中殖属,然后向Juice提交一個Docker類型的任務(wù)茎毁。其它的,交給Juice去完成就可以了忱辅,調(diào)用者不用關(guān)心任務(wù)會在哪臺物理機上被執(zhí)行七蜘,只需要關(guān)心任務(wù)本身的執(zhí)行狀況。

Juice架構(gòu)

除此墙懂,Juice有以下一些特點橡卤,Juice框架分為Juice-Rest(Juice交互API層,可以完成外界對于Juice Task的CRUD操作)和Juice-Service(Juice核心層损搬,負(fù)責(zé)與MesosMaster之間的交互碧库,資源分配、任務(wù)提交巧勤、任務(wù)狀態(tài)更新等)嵌灰,在一套基于Juice框架的應(yīng)用系統(tǒng)中,通常部署1-N個Juice-Rest(取決于系統(tǒng)的TPS)颅悉,以及N個Juice-Service(Juice-Service分主從模式沽瞭,為1主多從,by zookeeper)剩瓶,對于同一個Mesos集群來說驹溃,可以部署1-N套Juice框架,以FrameworkID來區(qū)分延曙,需要部署多套的話在Juice-Service的配置文件中設(shè)置mesos.framework.tag為不同的值即可豌鹤。

Juice.png

Juice-Rest參數(shù)設(shè)置

Juice-Rest采用Spring-Boot編寫(Juice-API接口參見:https://github.com/HujiangTechnology/Juice/blob/master/doc/api_document.md), 處理外界發(fā)起的對任務(wù)CURD操作枝缔,當(dāng)提交一個任務(wù)到Juice-Rest時布疙,需要設(shè)置一些參數(shù),比如:

example to run docker:
{
    "callbackUrl":"http://www.XXXXXXXX.com/v5/tasks/callback",
    "taskName":"demo-task"灵临,
    "env":{"name":"environment"拣挪,"value":"dev"},
    "args":["this is a test"]俱诸,
        "container":{
            "docker":{
                "image":"dockerhub.XXXX.com/demo-slice"
        }菠劝,
        "type":"DOCKER"
    }
}

其中Container中的type目前僅支持'Docker',我們沒有加入'Mesos'類型的Container模式是因為目前項目組內(nèi)部的服務(wù)已經(jīng)都基于Docker化睁搭,但是預(yù)留了'Mesos'類型赶诊,在未來可以支持'Mesos'類型的任務(wù)。
commands模式支持運行Linux命令行命令和Shell腳本园骆,比如:

"commands":"/home/app/entrypoint.sh"

這里支持Commands模式的原因有2點
1.有時調(diào)用方可能只是想在某臺制定的Agent上運行一個腳本舔痪。
2.公司內(nèi)部其他有些項目組還在使用Jar包啟動的模式,預(yù)留一個Shell腳本的入口可以對這些項目產(chǎn)生支持锌唾。
env設(shè)置示例锄码,設(shè)置運行的任務(wù)環(huán)境為dev:

"env":{"name":"environment","value":"dev"}

args設(shè)置示例晌涕,設(shè)置文件路徑:

"args":["/tid/res/test.mp4"]

PS:使用Commands模式時不支持args選項滋捶。
此外,Juice-Rest支持用戶自定義資源大小(目前版本僅支持自定義CPU余黎、內(nèi)存)重窟,如需要指定資源,需在請求接口中配置resources對象惧财,否則巡扇,將會使用默認(rèn)的資源大小運行任務(wù)。Juice-Rest支持資源約束(constrains)垮衷,即滿足在特定Host或Rack_id標(biāo)簽的Agent上運行某任務(wù)厅翔,設(shè)置接口中constrains對象字段即可。

Juice所使用的中間件(MQ搀突、DB等)

下面講一下Rest層的處理模型刀闷,當(dāng)外界發(fā)起一個任務(wù)請求時,Juice-Rest接收到任務(wù)后描姚,并不是直接提交到Juice-Service層涩赢,而是做了以下2件事情:
1.將任務(wù)放入MQ中戈次。(目前Juice使用Redis-List來作為默認(rèn)的Queue轩勘,采用LPUSH、RPOP的模式怯邪,先進先出绊寻,為什么選擇使用Redis中的List作為Queue而沒有選擇其他諸如rabbitmq、kafka這些呢,首先澄步,Redis相對來說是一個比較輕量級的中間件冰蘑,而且HA方案比較成熟,同時村缸,在我看來祠肥,隊列中的最佳任務(wù)wait數(shù)量是應(yīng)該<10000的,否則梯皿,任務(wù)的執(zhí)行周期將會被拉得很長仇箱,以我公司的Juice系統(tǒng)來舉例,由于處理的都是耗時的音視頻轉(zhuǎn)碼切片任務(wù)东羹,通常情況下10000個任務(wù)的排隊等候時間會在幾個小時以上剂桥,所以當(dāng)任務(wù)數(shù)量很大時,考慮擴大集群的處理能力而不是把過多的任務(wù)積壓在隊列中属提,基于此权逗,選擇Redis-List相對其他的傳統(tǒng)MQ來說沒有什么劣勢≡┮椋考慮到一些特殊情況斟薇,Juice也允許用戶實現(xiàn)CacheUtils接口使用其他MQ替換Redis-List)。
2.紀(jì)錄Tasks信息到Juice-Tasks表中恕酸,相當(dāng)于數(shù)據(jù)落地奔垦。后續(xù)版本會基于此實現(xiàn)任務(wù)重試機制(目前的1.1.0內(nèi)部開發(fā)版本已實現(xiàn)),或者在failover切換后完成任務(wù)恢復(fù)尸疆,此功能在后續(xù)1.2.0版本中考慮加入椿猎。(目前數(shù)據(jù)庫使用MySql)。
當(dāng)Juice-Rest接受并完成任務(wù)提交后會返回給調(diào)用方一個Long型18位數(shù)字(JuiceID寿弱,全局唯一)作為憑證號犯眠。當(dāng)任務(wù)完成后,Juice-Rest會主動發(fā)起回調(diào)請求症革,通知調(diào)用方該任務(wù)的運行結(jié)果(以此JuiceID作為業(yè)務(wù)憑證)筐咧,前提是調(diào)用方必須設(shè)置callbackUrl。同時噪矛,調(diào)用方可以使用該JuiceID對進行任務(wù)查詢量蕊、終止等操作。
另外艇挨,在Juice-Rest層單獨維護一個線程池來處理由Juice-service端返回的任務(wù)狀態(tài)信息Task_status残炮。

Juice-Service內(nèi)部處理流程

Juice-Service可以看作是一個MesosFramework,與Master之間通訊協(xié)議采用ProtoBuf缩滨,每一種事件請求都通過對應(yīng)類型的Call產(chǎn)生势就,這里Juice-Service啟動時會發(fā)出Subscribe請求泉瞻,由SubscribeCall()方法產(chǎn)生requestBody,采用OKHTTP發(fā)送苞冯,并維持與Master之間的長連接

private void connecting() throws Exception {
        InputStream stream = null;
        Response res = null;

        try {
            Protos.Call call = subscribeCall();
            res = Restty.create(getUrl())
                    .addAccept(protocol.mediaType())
                    .addMediaType(protocol.mediaType())
                    .addKeepAlive()
                    .requestBody(protocol.getSendBytes(call))
                    .post();

            streamId = res.header(STREAM_ID);
            stream = res.body().byteStream();
            log.info("send subscribe, frameworkId : " + frameworkId + " , url " + getUrl() + ", streamId : " + streamId);
            log.debug("subscribe call : " + call);
            if (null == stream) {
                log.warn("stream is null");
                throw new DriverException("stream is null");
            }
            while (true) {
                int size = SendUtils.readChunkSize(stream);
                byte[] event = SendUtils.readChunk(stream, size);

                onEvent(event);
            }
        } catch (Exception e) {
            log.error("service handle error, due to : " + e);
            throw e;
        } finally {
            if (null != stream) {
                stream.close();
            }
            if (null != res) {
                res.close();
            }
            streamId = null;
        }
}

之后便進入while循環(huán)袖牙,當(dāng)Master端的通知事件發(fā)生時,調(diào)用onEvent()方法執(zhí)行舅锄。
Mesos的回調(diào)事件中鞭达,需要特別處理的主要事件由以下幾種:
1.SUBSCRIBED:Juice框架在接收到此事件后將注冊到Master中的FrameworkID紀(jì)錄到數(shù)據(jù)庫juice_framework表中。
2.OFFERS:當(dāng)Juice-Service接收到該類型事件時皇忿,便會進入資源/任務(wù)分配環(huán)節(jié)碉怔,分配任務(wù)資源并提交到MesosMaster。
3.UPDATE:當(dāng)Agent處理完任務(wù)時禁添,任務(wù)會由Executor->Agent->Master->Juice-Service來完成任務(wù)的狀態(tài)通知撮胧。Juice-Service會將結(jié)果塞入result-list中。
4.ERROR:框架產(chǎn)生問題老翘,通常這樣的問題分兩種芹啥,一種是比較嚴(yán)重的,例如Juice-Service使用了一個已經(jīng)被Master端移除的FrameworkID铺峭,則Master會返回"framework has been removed"的錯誤信息墓怀,Juice-Service此時會拋出UnrecoverException錯誤:

throw new UnrecoverException(message, true)

Juice-Service在處理UnrecoverException類的錯誤時會Reset服務(wù)卫键,當(dāng)?shù)诙€參數(shù)為True時傀履,會重新生成一個新的FrameworkID。
而當(dāng)其他類型的錯誤莉炉,比如Master和Juice-Service之間的長鏈接中斷钓账,僅僅Reset服務(wù)。

下面我想詳細(xì)來說說第二步絮宁,我們先來看下'OFFERS'請求處理代碼段:

private void onEvent(byte[] bytes) {
    ....
    switch (event.getType()) {
            ...
            case OFFERS:
                try {
                    event.getOffers().getOffersList().stream()
                            .filter(of -> {
                                if (SchedulerService.filterAndAddAttrSys(of, attrMap)) {
                                    return true;
                                }
                                declines.add(of.getId());
                                return false;
                            })
                            .forEach(
                                    of -> {
                                        List<TaskInfo> tasks = newArrayList();
                                        String offerId = of.getId().getValue();
                                        try {
                                            SchedulerService.handleOffers(killMap, support, of, attrMap.get(offerId), declines, tasks);
                                        } catch (Exception e) {
                                            declines.add(of.getId());
                                            tasks.forEach(
                                                    t -> {
                                                        AuxiliaryService.getTaskErrors()
                                                                .push(new TaskResult(com.hujiang.juice.common.model.Task.splitTaskNameId(t.getTaskId().getValue())
                                                                        , ERROR, "task failed due to exception!"));
                                                    }
                                            );
                                            tasks.clear();
                                        }
                                        if (tasks.size() > 0) {
                                            AuxiliaryService.acceptOffer(protocol, streamId, of.getId(), frameworkId, tasks, getUrl());
                                        }
                                    }
                            );

                    if (declines.size() > 0) {
                        AuxiliaryService.declineOffer(protocol, streamId, frameworkId, SchedulerCalls.decline(frameworkId, declines), getUrl());
                    }
                    long end = System.currentTimeMillis();
                } finally {
                    declines.clear();
                    attrMap.clear();
                }
                break;
            ...     
    }   
}

該段代碼是分配Offer-tasks的核心代碼梆暮,來看幾個方法:
1.SchedulerService.filterAndAddAttrSys(),該方法作用是過濾不符合的OFFER绍昂,我們知道在Mesos的Agent中是可以通過配置Attr來使一些機器跑特殊的任務(wù)啦粹,而這里的過濾正是基于該特性,比如我們設(shè)置了該Juice-Service只使用包含以下Attr屬性的資源時(在配置文件application.properties中)

mesos.framework.attr=lms窘游,qa唠椭,mid|big

經(jīng)過了SchedulerService.filterAndAddAttrSys()方法的過濾,符合以上attr的資源會被選取執(zhí)行任務(wù)忍饰。同時不符合的Offer會加入declines List贪嫂,通過AuxiliaryServic.declineOffer()一次性發(fā)送給Master告知忽略。
Agent的attr設(shè)置通過/etc/mesos-slave/attributes來設(shè)置喘批。這個文件通常為這樣的:

cat /etc/mesos-slave/attributes

bz:xx;
env:xx;
size:xx;
rack_id:xx;
dc:xx

2.SchedulerService.handleOffers()撩荣,該方法實現(xiàn)了原先MesosFramework中的resourceOffer的功能铣揉,對Offer進行Tasks分配饶深,最后產(chǎn)生TaskInfo List餐曹,由AuxiliaryService.acceptOffer()發(fā)送給Master通知處理任務(wù)。
注意:Master在發(fā)送完Offer事件通知后會一直處于wait狀態(tài)敌厘,直到Framework端調(diào)用Accept call(AuxiliaryService.acceptOffer())或Decline call(AuxiliaryServic.declineOffer())來告知Master資源是否使用后才會通知下一個Framework去分配資源台猴。(默認(rèn)Master會一直等待,如果沒有通知俱两,則Mesos集群中的資源利用率將可能達到100%饱狂,可以通過在Master端設(shè)置Timeout來避免這個問題。)
在Juice-Service內(nèi)部宪彩,當(dāng)SchedulerDriver與Master產(chǎn)生交互后休讳,Juice-Service的處理邏輯由SchedulerService以及AuxiliaryService來實現(xiàn)。
SchedulerService處理Juice的主要邏輯尿孔,比如資源分配算法俊柔、任務(wù)優(yōu)先級算法,所有Master回調(diào)事件處理方法都定義在SchedulerService中活合。
AuxiliaryService維護幾組線程池雏婶,完成各自任務(wù),剛才看到的AuxiliaryService.acceptOffer()和AuxiliaryServic.declineOffer()白指,都是通過調(diào)用AuxiliaryServic中的send-pool去完成call的發(fā)送留晚,另外還有一些管理類的任務(wù)(比如實時查詢?nèi)蝿?wù)狀態(tài)、終止正在運行的任務(wù)等等)通過auxiliary-pool去完成告嘲。所以错维,AuxiliaryServic的調(diào)用都是異步的。

flow.png

Juice中各種隊列的功能介紹

剛才介紹了Juice的任務(wù)在JuiceRest提交時是被放入了一個MQ中橄唬,這個MQ在Juice-Service中被稱為juice.task.queue需五。除此之外,還有另外幾個MQ轧坎,分別是juice.task.retry.queue宏邮、juice.task.result.queue、juice.management.queue缸血。下面來分別說說這些Queue的用處蜜氨。
juice.task.retry.queue:Juice-Service在取任務(wù)時是按照每一個Offer輪詢分配的,當(dāng)一個Offer在分配資源時捎泻,假如從MQ中R-POP出來的任務(wù)不滿足該Offer時(比如need-resources大于該Offer的max offer value時飒炎,或者存在constrains,當(dāng)前的offer和指定執(zhí)行任務(wù)的offer不match時)笆豁,這時郎汪,Juice-Service的做法是將當(dāng)前任務(wù)放入juice.task.retry.queue中赤赊,等待下一次Offer分配時,優(yōu)先從juice.task.retry.queue獲取任務(wù)并分配煞赢,這里涉及到Juice內(nèi)部獲取任務(wù)Queue的優(yōu)先級抛计,我用了一個比較簡單的方式,即每次分配一個新的Offer資源時照筑,先從juice.task.retry.queue中取出一定數(shù)目的任務(wù)(CACHE_TRIES = 5)吹截,當(dāng)還有剩余資源時,則從juice.task.queue中取任務(wù)凝危,直到撐滿這個Offer波俄。另外,處于juice.task.retry.queue會有淘汰機制蛾默,目前的任務(wù)淘汰機制遵循2點懦铺,當(dāng)先觸發(fā)以下某一項時,則該任務(wù)會認(rèn)為失敗支鸡,任務(wù)的Task_status被設(shè)置為Task_Failed冬念,放入juice.task.result.queue,任務(wù)的淘汰算法如下:

1.過期時間淘汰制苍匆,任務(wù)處于juice.task.result.queue的時長>TASK_RETRY_EXPIRE_TIME刘急,則淘汰(DEFAULT_TASK_RETRY_EXPIRE_TIME = 86400秒)。
2.大于最大檢索次數(shù)浸踩,任務(wù)被取出檢索但沒有被執(zhí)行達到最大檢索次數(shù)>MAX_RESERVED叔汁,則淘汰(DEFAULT_MAX_RESERVED = 1024)。

juice.task.result.queue:任務(wù)結(jié)果隊列检碗,Juice-Service在得到一個任務(wù)的狀態(tài)后(不一定是最終狀態(tài))据块,將任務(wù)的TaskResult對象放入juice.task.result.queue,Juice-Rest端從該隊列取出TaskResult折剃,如果已經(jīng)是任務(wù)的最終狀態(tài)另假,比如Task_Finished或者Task_Failed,則通過外部在提交任務(wù)時所填寫的callbackUrl回調(diào)調(diào)用方告知任務(wù)狀態(tài)怕犁。
juice.management.queue:管理類隊列边篮,支持放入Reconcile類或Kill類的任務(wù),由AuxiliaryService發(fā)起任務(wù)的查詢同步或Kill一個正在執(zhí)行的任務(wù)奏甫。

通過SDK提交一個任務(wù)###

目前開源的Juice版本戈轿,已經(jīng)提供了完整的SDK來完成對于Juice-Rest之間的交互,以下是提交一個docker任務(wù)的示例:

總結(jié)及未來

目前Juice 1.1.0開源版本已經(jīng)處于測試階段阵子,新版本除修復(fù)一些Bug之外思杯,還增加了2個新功能:

1.增加了任務(wù)插隊功能,可以通過在傳入?yún)?shù)中設(shè)置priority=1來提高一個任務(wù)的執(zhí)行優(yōu)先級挠进,該任務(wù)會被置于處理隊列的最前端色乾。
2.任務(wù)失敗自動重試功能誊册,設(shè)置傳入?yún)?shù)retry=1,任務(wù)失敗會自動重試暖璧,最多重試3次案怯。

面對復(fù)雜的業(yè)務(wù)需求,Juice目前的版本還有一些特性/功能不支持漆撞,對于此殴泰,最好的方式是請大家Fork這個項目的Git于宙,或直接聯(lián)系本人浮驳,大家一起來把Juice做好。

 @Test
    public void submitsDocker() {
        Submits submitsDocker = Submits.create()
                .setDockerImage("dockerhub.XXXX.com/demo-slice")
                .setTaskName("demo-slice")
                .addArgs("/10002/res/L2.mp4")
                .addEnv("environment", "dev")
                .addResources(2.0, 2048.0);

        Long taskId = JuiceClient.create("http://your-juice-rest-host/v1/tasks", "your-system-id-in-string")
                .setOperations(submitsDocker)
                .handle();

        if(null != taskId) {
            System.out.println("submitsDocker, taskId --> " + taskId);
        }
    }

Q&A:

Q.juice與elastic job的差異
A.我本身對于elastic job并不算太熟悉捞魁,就隨便說幾點至会,如果有錯還請各位糾正:
首先juice與elastic-job-cloud都基于mesos,資源-任務(wù)分配這塊elastic-job用了Fenzo(netflix),而juice是自己開發(fā)的調(diào)度算法谱俭。
juice在作業(yè)調(diào)用時不需要作業(yè)注冊奉件,只要上傳任務(wù)的鏡像(Docker)到倉庫及任務(wù)觸發(fā)。而elastic-job需要注冊作業(yè)昆著。
juice在Rest-Api接口上近乎完全和marathon一致,方便一些使用慣marathon部署service的用戶县貌。
juice目前版本并不支持作業(yè)分片。

Q.能詳細(xì)介紹下任務(wù)資源分配這一塊的算法嗎凑懂?
A.之前已經(jīng)簡單介紹過了煤痕,通過接收'OFFERS'事件觸發(fā)相關(guān)任務(wù)-資源分配的代碼塊。
由于得到的Offer對象實際為一個列表接谨,處理邏輯會循環(huán)為每一個Offer分配具體的任務(wù)摆碉,而每個Offer的任務(wù)列表總資源(CPU,Memory等)必需小于Offer resources * RESOURCES_USE_THRESHOLD(資源使用閥值,可通過配置文件resources.use.threshold設(shè)置脓豪,默認(rèn)0.8),每分配完一個Offer的task_infos后巷帝,便生成Accept Call由發(fā)送線程池進行發(fā)送處理,整個過程都是異步非阻塞的。

Q.所有的任務(wù)都存檔在docker里面對于一些臨時的任務(wù)如何處理?
A.臨時的任務(wù)確實會產(chǎn)生一些垃圾的鏡像扫夜,需要定期對Docker倉庫進行清理楞泼,一般設(shè)置清理周期為1個月。

Q.任務(wù)系統(tǒng)是是否有幫助用戶完成docker封裝的操作笤闯?
A.目前沒有堕阔,所以使用者必需會一些Docker的基本操作,至少要會打鏡像望侈,提交鏡像等印蔬。當(dāng)然,像一些Docker的設(shè)置脱衙,比如掛載volume侥猬,網(wǎng)絡(luò)(bridge例驹、host)等可以在提交任務(wù)時通過參數(shù)設(shè)置。

Q.Mesos和kubernetes的優(yōu)劣勢是什么退唠?
A.其實我主要使用Mesos鹃锈,Mesos相對K8S應(yīng)該是一套更重的系統(tǒng),Mesos更像是個分布式操作系統(tǒng)瞧预,而K8S在容器編排方面更有優(yōu)勢(Pod之類)屎债。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市垢油,隨后出現(xiàn)的幾起案子盆驹,更是在濱河造成了極大的恐慌,老刑警劉巖滩愁,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件躯喇,死亡現(xiàn)場離奇詭異,居然都是意外死亡硝枉,警方通過查閱死者的電腦和手機廉丽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妻味,“玉大人正压,你說我怎么就攤上這事≡鹎颍” “怎么了焦履?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長棕诵。 經(jīng)常有香客問我裁良,道長,這世上最難降的妖魔是什么校套? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任价脾,我火速辦了婚禮,結(jié)果婚禮上笛匙,老公的妹妹穿的比我還像新娘侨把。我一直安慰自己,他們只是感情好妹孙,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布秋柄。 她就那樣靜靜地躺著,像睡著了一般蠢正。 火紅的嫁衣襯著肌膚如雪骇笔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音笨触,去河邊找鬼懦傍。 笑死,一個胖子當(dāng)著我的面吹牛芦劣,可吹牛的內(nèi)容都是我干的粗俱。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼虚吟,長吁一口氣:“原來是場噩夢啊……” “哼寸认!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起串慰,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤偏塞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后模庐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體烛愧,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡油宜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年掂碱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慎冤。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡疼燥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蚁堤,到底是詐尸還是另有隱情醉者,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布披诗,位于F島的核電站撬即,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏呈队。R本人自食惡果不足惜剥槐,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宪摧。 院中可真熱鬧粒竖,春花似錦、人聲如沸几于。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沿彭。三九已至朽砰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瞧柔。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工熔掺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人非剃。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓置逻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親备绽。 傳聞我的和親對象是個殘疾皇子券坞,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

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

  • 摘要 為了滿足渲染、基因測序等計算密集型服務(wù)的需求肺素,UCloud 已推出了“計算工廠”產(chǎn)品恨锚,讓用戶可以快速創(chuàng)建大量...
    UCloud云計算閱讀 734評論 0 1
  • 滬江任務(wù)調(diào)度系統(tǒng)的演化http://mp.weixin.qq.com/s?src=3&timestamp=1500...
    葡萄喃喃囈語閱讀 331評論 0 1
  • 21XX年,科學(xué)家們在人體大腦的研究中取得了極大的進步倍靡! 每個人都能開發(fā)出一種異能猴伶,這種玄之又玄的東西沒有人能掌控...
    癮輪子閱讀 375評論 0 1
  • 1.每個人心中都有一個風(fēng)箏,不管那意味著什么塌西,讓我們勇敢地去追他挎。 2.可是人就是這樣,總會活在某個時限內(nèi)捡需,那里的世...
    菱然閱讀 537評論 0 0
  • 期待了很久的正面管教課程办桨,終于發(fā)現(xiàn)四月發(fā)布了網(wǎng)絡(luò)教學(xué)的發(fā)現(xiàn),索性第一時間報名參加站辉。寶寶現(xiàn)在十個月大呢撞,出現(xiàn)的問題并不...
    M唯一_bcfd閱讀 738評論 3 3