袁曉晨,張衛(wèi)山,高紹姝,時(shí) 斌,趙永俊,王 冶,安云云
1(中國(guó)石油大學(xué)(華東)計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院,青島 266580)
2(青島海爾空調(diào)電子有限公司 電控模塊開(kāi)發(fā)部,青島 266101)
3(解放軍9144 部隊(duì),青島 266102)
4(國(guó)網(wǎng)山東省電力公司 青島市黃島區(qū)供電公司,青島 266500)
計(jì)算機(jī)視覺(jué)圖像識(shí)別是人工智能的重要應(yīng)用,廣泛應(yīng)用在工業(yè)、醫(yī)學(xué)、軍事、教育、商業(yè)、體育、安防檢測(cè)等行業(yè)與領(lǐng)域中.機(jī)器學(xué)習(xí),尤其是深度學(xué)習(xí)展現(xiàn)出了針對(duì)圖像識(shí)別領(lǐng)域優(yōu)秀的識(shí)別性能.而機(jī)器學(xué)習(xí)本身需要建立在大量的帶有指導(dǎo)意義的既有數(shù)據(jù)集基礎(chǔ)之上.在進(jìn)行深度學(xué)習(xí)模型訓(xùn)練流程中,往往需要針對(duì)海量圖片進(jìn)行人工數(shù)據(jù)標(biāo)注,繁重的圖像標(biāo)注任務(wù)增添了大量時(shí)間成本.
傳統(tǒng)的圖像標(biāo)注工具,如表1所示,大多以單機(jī)運(yùn)行的傳統(tǒng)單體式系統(tǒng)架構(gòu)為主,運(yùn)行在單機(jī)之上,同一時(shí)間同一系統(tǒng)運(yùn)行實(shí)例上只允許一個(gè)用戶(hù)對(duì)本地資源進(jìn)行圖像標(biāo)定.當(dāng)使用傳統(tǒng)圖像標(biāo)注工具進(jìn)行協(xié)作標(biāo)定時(shí),需要用戶(hù)手動(dòng)進(jìn)行圖像集的分組并拷貝至協(xié)作組員的工作站.協(xié)作組員各自完成任務(wù)后仍需要用戶(hù)自行合并制作數(shù)據(jù)集.由于缺少集中化的圖像與工作流,導(dǎo)致傳統(tǒng)單機(jī)標(biāo)注工具在協(xié)作場(chǎng)景下存在大量的文件與數(shù)據(jù)傳輸,在海量圖像文件的壓縮、打包與傳輸過(guò)程中產(chǎn)生了大量的時(shí)間與人工成本.
表1 傳統(tǒng)圖像標(biāo)注工具對(duì)比
為了解決機(jī)器學(xué)習(xí)圖像識(shí)別訓(xùn)練的各種前置準(zhǔn)備工作費(fèi)時(shí)費(fèi)力的問(wèn)題,本文提出并設(shè)計(jì)實(shí)現(xiàn)了一種基于Spring Cloud、面向機(jī)器學(xué)習(xí)模型訓(xùn)練的協(xié)作式圖像數(shù)據(jù)管理與標(biāo)注平臺(tái),通過(guò)眾包任務(wù)的方式,優(yōu)化圖像標(biāo)注流程,設(shè)計(jì)實(shí)現(xiàn)了面向海量圖像的存儲(chǔ)、標(biāo)定集管理、圖像標(biāo)定任務(wù)管理等功能模塊.系統(tǒng)采用微服務(wù)架構(gòu),將系統(tǒng)各個(gè)部分進(jìn)行解耦[1],實(shí)現(xiàn)服務(wù)注冊(cè)與發(fā)現(xiàn)、負(fù)載均衡、容錯(cuò)處理,提升了系統(tǒng)的高可用性、可維護(hù)性與可擴(kuò)展性.基于GitLab-CICD 實(shí)現(xiàn)了微服務(wù)的增量更新、持續(xù)部署與灰度更新.通過(guò)將海量圖像標(biāo)定數(shù)據(jù)進(jìn)行分組劃分,簡(jiǎn)化數(shù)據(jù)標(biāo)注過(guò)程中的操作,降低了數(shù)據(jù)標(biāo)注人員的時(shí)間成本,提升了數(shù)據(jù)標(biāo)注工作效率.
眾包任務(wù)模式指的是將本應(yīng)當(dāng)由單一機(jī)構(gòu)或個(gè)人執(zhí)行的工作內(nèi)容在公開(kāi)或非公開(kāi)網(wǎng)絡(luò)上以公開(kāi)的方式外包給特定或非特定用戶(hù)[2].通過(guò)采用眾包任務(wù)的模式,將龐大的圖像標(biāo)注任務(wù)切分為小的任務(wù),能夠有效提升標(biāo)定的速度與質(zhì)量,從而加速深度學(xué)習(xí)模型訓(xùn)練流程.
微服務(wù)[3]是一系列功能簡(jiǎn)單、互相之間采用輕量級(jí)通信協(xié)議協(xié)同工作的功能區(qū)塊.每個(gè)小的功能區(qū)塊具有高內(nèi)聚、低耦合的特點(diǎn),能夠獨(dú)立自主地運(yùn)行.
微服務(wù)架構(gòu)是一種架構(gòu)模式,它是SOA 架構(gòu)(Service Of Application)的進(jìn)一步發(fā)揚(yáng),通過(guò)將龐大的系統(tǒng)根據(jù)業(yè)務(wù)邊界細(xì)粒度地拆分為小的服務(wù)模塊.每個(gè)小的服務(wù)模塊具有高內(nèi)聚、低耦合的特點(diǎn),均能夠獨(dú)立地運(yùn)行.每個(gè)模塊可以由不同的團(tuán)隊(duì)進(jìn)行開(kāi)發(fā)[4].
微服務(wù)架構(gòu)擁有著許多傳統(tǒng)單體式應(yīng)用所不具備的優(yōu)勢(shì)[5]:
① 復(fù)雜度可控:通過(guò)將復(fù)雜的系統(tǒng)細(xì)粒度地拆分為小體積、業(yè)務(wù)簡(jiǎn)單的模塊,降低了每個(gè)模塊的開(kāi)發(fā)難度與復(fù)雜度.各個(gè)模塊間互相解耦[6],當(dāng)需求變更時(shí),只需要修改對(duì)應(yīng)的模塊即可實(shí)現(xiàn)系統(tǒng)整體功能上的變更,無(wú)需考慮其他模塊可能因?yàn)榻涌趯?shí)現(xiàn)的變更而無(wú)法正常工作的問(wèn)題.
② 團(tuán)隊(duì)協(xié)作效率高:當(dāng)確定系統(tǒng)各個(gè)微服務(wù)接口定義后即可分組并行開(kāi)發(fā)不同的微服務(wù)模塊,從而提升了整體開(kāi)發(fā)效率.同時(shí)不同微服務(wù)模塊無(wú)需集成為一個(gè)整體,只需要能夠互相調(diào)用即可保證系統(tǒng)的正常運(yùn)行,避免了單體式應(yīng)用集成過(guò)程中出現(xiàn)的組件源碼不兼容,降低了集成成本.
③ 獨(dú)立部署:每個(gè)小模塊都能夠獨(dú)立地運(yùn)行,不會(huì)因?yàn)槠渌?wù)故障而受到影響.通過(guò)微服務(wù)調(diào)度系統(tǒng)的支持,能夠?qū)崿F(xiàn)快速部署在單機(jī)或集群上,從而充分利用計(jì)算性能.
④ 維護(hù)難度低:配合持續(xù)集成與持續(xù)部署(CI/CD),即可實(shí)現(xiàn)灰度發(fā)布與服務(wù)熱更新,無(wú)需系統(tǒng)全部停機(jī)或重啟即可完成功能更新.
⑤ 多種技術(shù)允許共存:微服務(wù)獨(dú)立部署使得微服務(wù)間只需要約定技術(shù)、語(yǔ)言無(wú)關(guān)的RPC 協(xié)議即可實(shí)現(xiàn)不同技術(shù)、語(yǔ)言實(shí)現(xiàn)的微服務(wù)共存并配合工作[7].
⑥ 系統(tǒng)穩(wěn)定性高:微服務(wù)架構(gòu)的系統(tǒng)擁有熔斷機(jī)制,當(dāng)系統(tǒng)部分組件失效時(shí)能夠及時(shí)阻止故障船體,從而避免系統(tǒng)發(fā)生雪崩式功能失效,提升了系統(tǒng)的穩(wěn)定性.
基于對(duì)象的云存儲(chǔ)即對(duì)象存儲(chǔ)(object storage)是近幾年逐漸流行的一個(gè)新興且切實(shí)可行的大規(guī)模存儲(chǔ)方案[8],使用較為簡(jiǎn)便的方法實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ),即充分利用已有的存儲(chǔ)組件、網(wǎng)絡(luò)技術(shù)和處理技術(shù),使系統(tǒng)擁有較好的可擴(kuò)展性以及高吞吐量[9].對(duì)象存儲(chǔ)思想的核心為對(duì)象,每個(gè)對(duì)象都有唯一的標(biāo)識(shí)[10].對(duì)象存儲(chǔ)將文件劃分為一個(gè)個(gè)對(duì)象,為用戶(hù)提供了統(tǒng)一的存儲(chǔ)空間,從而能更好的對(duì)文件進(jìn)行訪問(wèn)控制和存儲(chǔ)管理[11].這些對(duì)象被分布在整個(gè)集群之中,為保障數(shù)據(jù)安全、防止數(shù)據(jù)丟失將每一個(gè)對(duì)象多重備份復(fù)制到多個(gè)設(shè)備上.對(duì)象存儲(chǔ)系統(tǒng)將數(shù)據(jù)塊列表映射為對(duì)象列表,將各類(lèi)數(shù)據(jù)塊簡(jiǎn)化成為一個(gè)個(gè)對(duì)象來(lái)進(jìn)行管理[12],極大改善了系統(tǒng)的可伸縮性,可以輕易實(shí)現(xiàn)海量數(shù)據(jù)的管理.
傳統(tǒng)的數(shù)據(jù)集標(biāo)注往往在單終端中進(jìn)行,大量的圖像需要由一個(gè)部門(mén)或者個(gè)人完成.使用傳統(tǒng)的標(biāo)注工具進(jìn)行多人協(xié)作式圖像標(biāo)注時(shí),在圖像整理上浪費(fèi)了大量時(shí)間.協(xié)作前需要人工將大量圖像打包分組,協(xié)作后需要將圖像與標(biāo)定數(shù)據(jù)回收合并為同一個(gè)數(shù)據(jù)集合.常見(jiàn)的文件系統(tǒng)針對(duì)海量小文件的處理性能往往不及少量大文件,導(dǎo)致人工打包也是一項(xiàng)耗時(shí)的工作.針對(duì)以上痛點(diǎn),圖像標(biāo)注系統(tǒng)主要有以下需求:
① 圖像數(shù)據(jù)托管:為避免文件系統(tǒng)直接頻繁操作大量小文件,從而節(jié)省任務(wù)分配數(shù)據(jù)打包的時(shí)間,圖像數(shù)據(jù)應(yīng)當(dāng)由專(zhuān)門(mén)的機(jī)制進(jìn)行托管,必要時(shí)以圖像為基本單位提供圖像及其元數(shù)據(jù)檢索服務(wù).
② 任務(wù)劃分與管理:為實(shí)現(xiàn)眾包模式的圖像標(biāo)注,需要將包含大量圖像的任務(wù)拆分為小任務(wù),交由不同的個(gè)人進(jìn)行標(biāo)注.
③ 支持多種標(biāo)注模式:系統(tǒng)應(yīng)當(dāng)支持機(jī)器視覺(jué)訓(xùn)練常用的關(guān)鍵點(diǎn)、矩形、多邊形標(biāo)注模式.
④ 支持多種導(dǎo)出格式:針對(duì)主流深度學(xué)習(xí)源碼所接受的格式,系統(tǒng)應(yīng)當(dāng)具備良好的擴(kuò)展性以支持更多的深度學(xué)習(xí)框架.
⑤ 數(shù)據(jù)統(tǒng)計(jì):任務(wù)發(fā)起者應(yīng)當(dāng)能夠看到子任務(wù)的標(biāo)注進(jìn)度、標(biāo)簽數(shù)量等統(tǒng)計(jì)信息,從而有針對(duì)性地決定是否需要增加或者調(diào)整圖像組成.
⑥ 支撐模塊需求:除此之外,系統(tǒng)應(yīng)當(dāng)具有基本的用戶(hù)與權(quán)限控制功能.
① 系統(tǒng)微服務(wù)劃分
根據(jù)系統(tǒng)需求分析結(jié)果,將系統(tǒng)劃分為4 個(gè)功能性微服務(wù)和3 個(gè)架構(gòu)支撐服務(wù):圖像對(duì)象存儲(chǔ)服務(wù)、圖像集合管理服務(wù)、標(biāo)定集合管理服務(wù)、數(shù)據(jù)輸入輸出服務(wù)、用戶(hù)及授權(quán)管理和服務(wù)網(wǎng)關(guān).
圖像對(duì)象存儲(chǔ)服務(wù)用于面向海量圖片的對(duì)象存儲(chǔ),將圖片統(tǒng)一以相同規(guī)則生成的不重復(fù)定位符作為索引,避免圖片重復(fù)存儲(chǔ)與圖片文件名重復(fù)沖突的問(wèn)題.
圖像集合管理服務(wù)用于將離散的圖片在邏輯上組成一個(gè)集合,作為系統(tǒng)中圖片操作的基本單位.
標(biāo)定集合管理服務(wù)用于管理和存儲(chǔ)圖像集對(duì)應(yīng)的標(biāo)定數(shù)據(jù),同時(shí)提供標(biāo)定任務(wù)的劃分與分配.
數(shù)據(jù)導(dǎo)入導(dǎo)出服務(wù)主要用于圖像、標(biāo)簽數(shù)據(jù)的解包導(dǎo)入與打包導(dǎo)出.提供常見(jiàn)的壓縮與視頻格式的解析與常見(jiàn)數(shù)據(jù)集格式的導(dǎo)出等功能.
② 系統(tǒng)架構(gòu)設(shè)計(jì)
系統(tǒng)整體采用分層式結(jié)構(gòu),如圖1所示.為了開(kāi)發(fā)過(guò)程中能夠更明確的分工,其中服務(wù)層按照微服務(wù)的思想進(jìn)行拆分.各層主要包含內(nèi)容如下:
持久化層:為了方便使用微服務(wù)編排框架進(jìn)行部署,所有有狀態(tài)的服務(wù)均從整體架構(gòu)中分離整合在持久化層中.其中包括用于對(duì)象數(shù)據(jù)存儲(chǔ)的NoSQL 數(shù)據(jù)庫(kù);用于關(guān)系型信息數(shù)據(jù)存儲(chǔ)的SQL 數(shù)據(jù)庫(kù);用于全局?jǐn)?shù)據(jù)緩存的內(nèi)存NoSQL 數(shù)據(jù)庫(kù);用于全局消息同步的消息隊(duì)列中間件.
微服務(wù)層:包含了業(yè)務(wù)邏輯微服務(wù)群和架構(gòu)支撐服務(wù)群兩部分.架構(gòu)支撐服務(wù)群中包含了微服務(wù)架構(gòu)必需的注冊(cè)發(fā)現(xiàn)中心、日志監(jiān)控、配置中心等基礎(chǔ)微服務(wù).業(yè)務(wù)邏輯微服務(wù)群提供了實(shí)現(xiàn)業(yè)務(wù)邏輯的相關(guān)微服務(wù),包括圖像對(duì)象存儲(chǔ)微服務(wù)、圖像集管理微服務(wù)、標(biāo)定管理微服務(wù)和數(shù)據(jù)導(dǎo)入導(dǎo)出微服務(wù).
網(wǎng)關(guān)層:網(wǎng)關(guān)層包含了由Spring Gateway 實(shí)現(xiàn)的API 網(wǎng)關(guān)微服務(wù)、前端站點(diǎn)微服務(wù)和Nginx 總代理微服務(wù),提供了系統(tǒng)接入入口.
CI/CD 支撐部分:系統(tǒng)源代碼采用了Gitlab 私服進(jìn)行托管,Gitlab 也提供了對(duì)持續(xù)集成的支持,故直接采用Gitlab-CICD 實(shí)現(xiàn)系統(tǒng)開(kāi)發(fā)過(guò)程中的持續(xù)集成與部署.
系統(tǒng)采用現(xiàn)有完整的微服務(wù)方案,使用服務(wù)發(fā)現(xiàn)實(shí)現(xiàn)松散的服務(wù)間耦合,采用聲明式RPC 客戶(hù)端實(shí)現(xiàn)微服務(wù)間的互相調(diào)用,使用統(tǒng)一網(wǎng)關(guān)代理微服務(wù)作為系統(tǒng)入口,添加負(fù)載均衡機(jī)制以擴(kuò)展系統(tǒng)負(fù)載容量,使用OAuth2 開(kāi)放認(rèn)證協(xié)議作為認(rèn)證機(jī)制.
圖1 圖像標(biāo)注系統(tǒng)架構(gòu)
在微服務(wù)架構(gòu)的系統(tǒng)中,為了實(shí)現(xiàn)微服務(wù)間既有松散的耦合度,又能夠互相訪問(wèn),微服務(wù)注冊(cè)與發(fā)現(xiàn)機(jī)制是一種常用方法[13].通過(guò)由微服務(wù)自行將自身的信息主動(dòng)注冊(cè)至注冊(cè)中心的方式,使得其他微服務(wù)可以通過(guò)查詢(xún)注冊(cè)中心注冊(cè)記錄的方式間接地發(fā)現(xiàn)其存在并獲得訪問(wèn)相關(guān)參數(shù).注冊(cè)中心是注冊(cè)與發(fā)現(xiàn)中最重要的一部分,在Spring Cloud 微服務(wù)套件中,提供了注冊(cè)中心的一種原生實(shí)現(xiàn)和兩種接入實(shí)現(xiàn):
① Eureka Server:由Netflix 開(kāi)發(fā)的基于原生Java的開(kāi)源注冊(cè)中心實(shí)現(xiàn),Spring Cloud 套件給出了基于Spring Boot 快速構(gòu)建注冊(cè)中心的方案.
② Spring Cloud Consul:Consul是由HashiCorp 公司開(kāi)發(fā)的一種服務(wù)網(wǎng)格解決方案,提供具有服務(wù)發(fā)現(xiàn),配置和分段功能的全功能控制平面[14].通過(guò)添加org.springframework.cloud.spring-cloud-starter-consul-all 依賴(lài),同樣可以實(shí)現(xiàn)類(lèi)似的注冊(cè)發(fā)現(xiàn)功能.
Spring Cloud Zookeeper:Apache ZooKeeper是一項(xiàng)集中式服務(wù),用于維護(hù)配置信息,命名,提供分布式同步和提供組服務(wù)[15].基于Spring Cloud的微服務(wù)可以通過(guò)添加org.springframework.cloud.spring-cloudstarter-zookeeper-all 依賴(lài)實(shí)現(xiàn)基于ZooKeeper的注冊(cè)發(fā)現(xiàn).
由于后兩種注冊(cè)發(fā)現(xiàn)的方案需要單獨(dú)部署第三方的應(yīng)用實(shí)例來(lái)支撐微服務(wù)注冊(cè)與發(fā)現(xiàn)的功能,故選擇可自行構(gòu)建的Eureka Server 方案.
Eureka的注冊(cè)與發(fā)現(xiàn)方案整體流程如圖2所示,主要分為兩部分.
圖2 基于Eureka的注冊(cè)發(fā)現(xiàn)實(shí)現(xiàn)流程
第一部分為Eureka 注冊(cè)中心.Spring 提供了一套項(xiàng)目生成工具Spring Initializer[16],允許開(kāi)發(fā)人員直接通過(guò)可視化配置直接生成Spring Boot 項(xiàng)目,這里借用Spring Initializer 可以直接生成Eureka Server的項(xiàng)目.
如圖3所示,在Spring Initializer 中輸入項(xiàng)目信息并選中Eureka Server 依賴(lài),點(diǎn)擊Generate 即可得到初始項(xiàng)目模板.在Spring Boot 啟動(dòng)類(lèi)上添加@EnableEurekaServer參數(shù)即可開(kāi)啟項(xiàng)目依賴(lài)中的Eureka Server.
圖3 使用Spring Initializer 生成Eureka Server 實(shí)例
第二部分即業(yè)務(wù)微服務(wù)中的Discovery Client.在需要通過(guò)服務(wù)發(fā)現(xiàn)感知其他服務(wù)實(shí)例的微服務(wù)中,增加org.springframework.cloud.spring-cloud-starter-netflixeureka-client 依賴(lài),并在項(xiàng)目引導(dǎo)類(lèi)上添加@Enable-DiscoveryClient 注解,即可為Feign 客戶(hù)端添加服務(wù)發(fā)現(xiàn)的功能.
完成其他業(yè)務(wù)微服務(wù)開(kāi)發(fā)后,同時(shí)啟動(dòng)各個(gè)微服務(wù),可通過(guò)登錄Eureka 監(jiān)控頁(yè)面看到各個(gè)微服務(wù)的注冊(cè)情況,如圖4所示.
圖4 通過(guò)Eureka Server 查看服務(wù)發(fā)現(xiàn)注冊(cè)狀態(tài)
相較于傳統(tǒng)的單體式應(yīng)用,微服務(wù)架構(gòu)的應(yīng)用更接近于單體式應(yīng)用站群.微服務(wù)架構(gòu)應(yīng)用為了實(shí)現(xiàn)從外部表現(xiàn)為與單體式應(yīng)用類(lèi)似的形式,需要一個(gè)微服務(wù)作為接口網(wǎng)關(guān),同時(shí)需要提供負(fù)載均衡的特性.
對(duì)于API 網(wǎng)關(guān),Spring Cloud 提供了兩套方案:
① Zuul:Zuul 來(lái)源于Netflix 開(kāi)源的微服務(wù)架構(gòu)套件.Zuul 底層采用了Tomcat Embeded 版本作為HTTP支撐層.
② Spring Cloud Gateway:Spring Cloud Gateway是由Spring 項(xiàng)目組基于其自研Web 框架WebFlux 實(shí)現(xiàn)的API 網(wǎng)關(guān).Spring Cloud Gateway是Spring Cloud去Netflix 進(jìn)程中非常重要的一個(gè)項(xiàng)目,旨在替代Zuul成為未來(lái)的Spring Cloud 框架下的API 網(wǎng)關(guān)組件.
WebFlux 底層為直接使用Netty 等高性能非阻塞服務(wù)器,相較于采用Servlet 架構(gòu)的Tomcat(Embeded)性能上略勝一籌[17].考慮到未來(lái)Spring 項(xiàng)目組開(kāi)發(fā)的方向與性能預(yù)期,采用Spring Cloud Gateway 作為系統(tǒng)API 網(wǎng)關(guān).
Spring Cloud Gateway 同樣可以使用Spring Initializer進(jìn)行項(xiàng)目初始化,初始化完成后可以通過(guò)在application.yml 中的spring.cloud.gateway.route 字段中配置接口路徑與微服務(wù)的映射.
代碼1.Spring Cloud Gateway 路由配置spring:application:name:application-gateway cloud:gateway:routes:# 用戶(hù)服務(wù)-id:user-service uri:lb://user-service predicates:->Path=/oauth/**,/user/**,/role/**# 其他服務(wù)#…
對(duì)于負(fù)載均衡,Spring Cloud 框架提供了Ribbon組件.Ribbon是一款客戶(hù)端側(cè)負(fù)載均衡器,它可以自動(dòng)從Discovery Client 中獲取微服務(wù)實(shí)力列表,應(yīng)用常見(jiàn)的負(fù)載均衡算法實(shí)現(xiàn)在同一服務(wù)的多個(gè)冗余實(shí)例上的負(fù)載均衡[18].通過(guò)添加org.springframework.cloud.spring-cloud-starter-netflix-ribbon 依賴(lài)即可在服務(wù)調(diào)用側(cè)引入負(fù)載均衡組件.
微服務(wù)之間往往避免不了互相調(diào)用對(duì)方的服務(wù).當(dāng)進(jìn)行同步接口調(diào)用時(shí),被調(diào)用方宕機(jī)、接口調(diào)用超時(shí)往往會(huì)引起調(diào)用方的異常.為了避免因微服務(wù)之間的依賴(lài)關(guān)系而出現(xiàn)大面積故障,調(diào)用方服務(wù)應(yīng)當(dāng)感知被調(diào)用方的異常并作出防御性動(dòng)作,防止故障繼續(xù)的蔓延.
在Spring Cloud 框架中,提供了Hystrix 組件.Hystrix 能夠在被調(diào)用微服務(wù)出現(xiàn)異常時(shí)及時(shí)熔斷,觸發(fā)調(diào)用方的異常處理流程,防止調(diào)用方產(chǎn)生異常.Hystrix組件可以通過(guò)在微服務(wù)中添加org.springframework.cloud.spring-cloud-starter-netflix-hystrix 依賴(lài)來(lái)添加至微服務(wù)中.在微服務(wù)啟動(dòng)類(lèi)上添加@EnableHystrix 注解即可啟用熔斷器.
在深度學(xué)習(xí)圖像識(shí)別模型訓(xùn)練過(guò)程中往往需要準(zhǔn)備大量圖像,而實(shí)現(xiàn)存儲(chǔ)并快速索引圖像數(shù)據(jù)就是標(biāo)注系統(tǒng)性能提升的關(guān)鍵點(diǎn).
SSDB是一個(gè)高性能的支持豐富數(shù)據(jù)結(jié)構(gòu)的NoSQL數(shù)據(jù)庫(kù),其底層實(shí)現(xiàn)為Google的高性能鍵值對(duì)數(shù)據(jù)庫(kù)LevelDB.
首先是一個(gè)高性能SSDB 集群,SSDB 采用的是與Redis 相同的網(wǎng)絡(luò)通信實(shí)現(xiàn),故可以采用Redis 集群常用的TwemProxy 代理實(shí)現(xiàn)如圖5所示的對(duì)象存儲(chǔ)架構(gòu).
圖5 SSDB 集群架構(gòu)
圖5上部分是圖像對(duì)象存儲(chǔ)微服務(wù).圖像存儲(chǔ)微服務(wù)使用圖像原始數(shù)據(jù)經(jīng)哈希運(yùn)算得到的索引號(hào)作為圖像在對(duì)象系統(tǒng)中的唯一索引.每一張圖像采用一個(gè)哈希表進(jìn)行存儲(chǔ),在哈希表中額外增加有關(guān)圖像內(nèi)容相關(guān)的元信息,對(duì)于重復(fù)上傳的內(nèi)容采取增加元信息中記錄的索引數(shù)量而不重復(fù)存儲(chǔ).
在傳統(tǒng)的單體式應(yīng)用中,只需要編譯一次即可得到可運(yùn)行的產(chǎn)物,而在微服務(wù)架構(gòu)應(yīng)用中,因?yàn)閯澐譃榱硕鄠€(gè)實(shí)例,這種類(lèi)似于“站群”的系統(tǒng)往往需要編譯多個(gè)“單體式應(yīng)用”并封裝為Docker 鏡像進(jìn)行部署.為了減少編譯部署階段的工作量,使用Gitlab-CICD 實(shí)現(xiàn)全自動(dòng)化的編譯、測(cè)試與部署.
首先是準(zhǔn)備一個(gè)Gitlab 實(shí)例,可以使用Gitlab 官方站點(diǎn)或者建立開(kāi)源的Gitlab-CE 實(shí)例,本文不再贅述有關(guān)Gitlab 實(shí)例搭建的內(nèi)容.
系統(tǒng)采用了Docker Swarm 作為微服務(wù)編排框架,使用Harbor 作為Docker Swarm 集群的私有鏡像源.
Gitlab-CICD 中另一個(gè)重要組成部分便是Gitlab-Runner.Gitlab-Runner是實(shí)際執(zhí)行持續(xù)集成任務(wù)的主體.Gitlab-Runner 支持多種部署方式,本項(xiàng)目選擇了基于裸機(jī)系統(tǒng)的編譯環(huán)境,方便做一些特殊的環(huán)境配置.
Gitlab-CICD 執(zhí)行流程如圖6所示,主要環(huán)節(jié)包括:
① 代碼提交:在各個(gè)微服務(wù)中建立Git 倉(cāng)庫(kù),并將倉(cāng)庫(kù)托管至Gitlab.當(dāng)微服務(wù)代碼得到更新并推送提交至Gitlab 時(shí),Gitlab 會(huì)自動(dòng)檢查倉(cāng)庫(kù)目標(biāo)分支中的.gitlab-ci.yml 文件中的配置,并在流水線(pipeline)中添加持續(xù)集成的任務(wù).
② CICD 任務(wù)的執(zhí)行:Gitlab-Runner 定時(shí)向Gitlab的流水線隊(duì)列請(qǐng)求任務(wù),當(dāng)Gitlab-Runner 得到任務(wù)后在其宿主機(jī)上執(zhí)行配置文件中定義的腳本.腳本中定義的動(dòng)作完成微服務(wù)的編譯、測(cè)試、鏡像打包與提交、灰度更新.
圖6 Gitlab-CICD 執(zhí)行流程
以圖像管理服務(wù)為例,編寫(xiě)了如代碼2 所示的gitlab-CICD.yml 配置文件.
代碼2.Gitlab 持續(xù)集成與持續(xù)部署配置stages:-測(cè)試-構(gòu)建-部署測(cè)試:stage:測(cè)試only:-master tags:-dlp script:-mvn test構(gòu)建:
stage:構(gòu)建only:-master tags:-dlp script:-mvn package-Dmaven.test.skip=true-docker build-t ${DOCKER_REGISTRY}/dlp/${SERVICE_NAME}:latest.-docker push ${DOCKER_REGISTRY}/dlp/${SERVICE_NAME}:latest部署:stage:部署only:-master tags:-dlp script:-docker-H ${DOCKER_SWARM} service update--image ${DOCKER_REGISTRY}/dlp/${SERVICE_NAME}:latest${DOCKER_SWARM_ STACK_NAME}_${SERVICE_NAME}
如代碼2 所示,CICD 一次任務(wù)將分為3 個(gè)階段:構(gòu)建、測(cè)試與部署.其中測(cè)試階段由Maven 進(jìn)行編譯并執(zhí)行系統(tǒng)中的單元測(cè)試;構(gòu)建階段直接使用Maven進(jìn)行服務(wù)器端編譯,隨后使用Gitlab-Runner 宿主機(jī)上的docker 構(gòu)建鏡像并推送至Harbor;部署階段通過(guò)暴露Docker Swarm 中的Manager 節(jié)點(diǎn)上dockerd的2375端口,實(shí)現(xiàn)從Gitlab-Runner 宿主機(jī)直接控制集群并觸發(fā)微服務(wù)鏡像更新.運(yùn)行效果如圖7所示.
通過(guò)在各個(gè)微服務(wù)實(shí)例中分別修改相同邏輯后分別以手動(dòng)部署與持續(xù)集成在多節(jié)點(diǎn)集群上部署并統(tǒng)計(jì)用時(shí),得到邏輯更新至生產(chǎn)環(huán)境的耗時(shí)如表2所示.
圖7 Gitlab-CICD 執(zhí)行效果
表2 手動(dòng)部署與CICD 部署效率對(duì)比
由表2可知,CICD 有效減少了系統(tǒng)集成過(guò)程中的集成與部署時(shí)間成本,提升了系統(tǒng)邏輯變更同步至生產(chǎn)環(huán)境的效率.
項(xiàng)目采用了微服務(wù)系統(tǒng)常見(jiàn)的前后端分離結(jié)構(gòu),前端在接口確定后采用樁服務(wù)器(mock-server)與后端并行開(kāi)發(fā).后端系統(tǒng)測(cè)試過(guò)程中使用了postman 進(jìn)行接口的測(cè)試,如圖8所示.
Postman[19]是一個(gè)用于API 接口開(kāi)發(fā)的協(xié)作平臺(tái).它提供了一套API 接口開(kāi)發(fā)工具,包括API 客戶(hù)端、文檔生成、自動(dòng)化測(cè)試、API 接口監(jiān)控、API 設(shè)計(jì)與樁服務(wù)器與接口文檔協(xié)作.
Postman 內(nèi)嵌了OAuth2的認(rèn)證模型,通過(guò)配置即可實(shí)現(xiàn)一系列共用同認(rèn)證服務(wù)的API 同時(shí)獲得登錄認(rèn)證的功能.
圖8 使用postman 對(duì)后端接口進(jìn)行測(cè)試
以深度學(xué)習(xí)圖像數(shù)據(jù)制備流程為例,對(duì)系統(tǒng)中圖像導(dǎo)入、任務(wù)分配與標(biāo)定、數(shù)據(jù)導(dǎo)出流程進(jìn)行功能測(cè)試.
首先是圖像導(dǎo)入.圖像標(biāo)注系統(tǒng)支持圖像、視頻、PDF、OpenDocument 等格式混合打包上傳,上傳界面如圖9所示.上傳完成數(shù)據(jù)傳輸后轉(zhuǎn)入異步解壓處理流程,異步解壓完成后前端顯示實(shí)際圖像集大小.
在圖像集中創(chuàng)建出標(biāo)定集后即可向系統(tǒng)中其他用戶(hù)分配標(biāo)定任務(wù)進(jìn)行圖像標(biāo)定的團(tuán)隊(duì)協(xié)作.分配任務(wù)過(guò)程如圖10 所示.
切換至任務(wù)執(zhí)行用戶(hù),可以在“我的任務(wù)”頁(yè)面中看到由任務(wù)發(fā)起用戶(hù)分配的任務(wù),點(diǎn)擊“開(kāi)始”按順序?qū)D像進(jìn)行標(biāo)定.進(jìn)入標(biāo)定流程后,如圖11 所示,通過(guò)在圖像上拖拽創(chuàng)建圖像區(qū)域,完成對(duì)圖像內(nèi)容的標(biāo)記.
圖9 創(chuàng)建圖像集
圖10 分配標(biāo)定任務(wù)
標(biāo)注過(guò)程中發(fā)起任務(wù)的用戶(hù)能夠看到各個(gè)任務(wù)執(zhí)行用戶(hù)的標(biāo)定進(jìn)度與當(dāng)前已標(biāo)定圖像的標(biāo)簽統(tǒng)計(jì)信息.當(dāng)圖像集標(biāo)定完成后,任務(wù)發(fā)起者可以對(duì)圖像進(jìn)行最終修正并導(dǎo)出圖像集合與標(biāo)定集合開(kāi)展深度學(xué)習(xí)模型訓(xùn)練.以導(dǎo)出的VOC XML 格式為例,最終導(dǎo)出的標(biāo)簽集如圖12 所示.
圖11 圖像標(biāo)注過(guò)程
圖12 標(biāo)簽集合導(dǎo)出
本文采用開(kāi)源Apache Benchmark 對(duì)系統(tǒng)中圖像對(duì)象存儲(chǔ)系統(tǒng)進(jìn)行多并發(fā)場(chǎng)景下的性能測(cè)試,測(cè)試環(huán)境如表3所示.
如表4所示為模擬多用戶(hù)進(jìn)行每個(gè)終端進(jìn)行10次訪問(wèn)(總計(jì)訪問(wèn)次數(shù)=并發(fā)數(shù)量×10)的資源響應(yīng)速度的測(cè)試的測(cè)試結(jié)果.
由表4可知,采用微服務(wù)架構(gòu)有效提升了系統(tǒng)容量,允許更多的用戶(hù)參與到眾包圖像標(biāo)定工作中.
表3 性能測(cè)試節(jié)點(diǎn)環(huán)境配置
表4 圖像存儲(chǔ)服務(wù)性能測(cè)試結(jié)果(單位:ms)
本文設(shè)計(jì)實(shí)現(xiàn)了面向深度學(xué)習(xí)的圖像標(biāo)注系統(tǒng),與傳統(tǒng)的本地標(biāo)注工具不同,本系統(tǒng)引入了眾包協(xié)作的思想與多種圖像格式存儲(chǔ)支持,將繁重的數(shù)據(jù)標(biāo)注任務(wù)進(jìn)行合作完成,并提供了多種導(dǎo)出格式,避免了傳統(tǒng)工具協(xié)作標(biāo)注工作流中大量圖像數(shù)據(jù)的分包與標(biāo)簽數(shù)據(jù)合并操作,簡(jiǎn)化了協(xié)作標(biāo)定流程,有效提升了數(shù)據(jù)準(zhǔn)備階段的工作效率.同時(shí),系統(tǒng)架構(gòu)層面采用了微服務(wù)架構(gòu),開(kāi)發(fā)階段引入基于Gitlab-CICD的持續(xù)集成與持續(xù)部署,加速了系統(tǒng)開(kāi)發(fā)到部署的更新迭代.