王 信,劉曉燕,張開琦,王 星,嚴(yán) 馨
(昆明理工大學(xué)信息工程與自動(dòng)化學(xué)院,云南 昆明 650050)
微服務(wù)作為一種將應(yīng)用程序組織為松耦合服務(wù)的軟件開發(fā)技術(shù),使得軟件系統(tǒng)變得模塊化,易于擴(kuò)展,也有利于對(duì)每個(gè)模塊進(jìn)行單獨(dú)的開發(fā)和部署。眾多互聯(lián)網(wǎng)企業(yè)如Google,Amazon和Twitter等都開始采用微服務(wù)架構(gòu)。然而在實(shí)際應(yīng)用場(chǎng)景中,不僅需要單個(gè)服務(wù),更多的是需要編排多個(gè)服務(wù)的組合,即服務(wù)之間的協(xié)同工作。微服務(wù)架構(gòu)出現(xiàn)之前,研究人員已經(jīng)提出了幾種用于編排Web服務(wù)組合的解決方案,如:用于編排Web服務(wù)組合的業(yè)務(wù)過程執(zhí)行語言BPEL(Business Process Execution Language)及其擴(kuò)展[1,2];基于領(lǐng)域特定語言的方法,如S[3]和Bite[4]。然而,這些方案應(yīng)用在微服務(wù)架構(gòu)之后都失敗了,問題在于其要求服務(wù)有定義良好的接口以及交互信息的強(qiáng)類型約束,但快速變化的微服務(wù)使得難以快速定義其接口并且難以被快速部署。Yahia等人[5]提出了一種基于事件驅(qū)動(dòng)的微服務(wù)組合平臺(tái),但存在驅(qū)動(dòng)事件形式單一,不支持細(xì)粒度數(shù)據(jù)訪問控制和微服務(wù)的動(dòng)態(tài)部署,缺乏可擴(kuò)展性、健壯性,無法檢測(cè)Web資源如XML文檔的更改事件從而觸發(fā)微服務(wù)組合的問題。
本文提出一種改進(jìn)的微服務(wù)組合平臺(tái),設(shè)計(jì)了一種支持細(xì)粒度數(shù)據(jù)訪問控制的微服務(wù)組合領(lǐng)域特定語言DSL(Domain-Specific Language),實(shí)現(xiàn)基于標(biāo)簽的、可配置的數(shù)據(jù)訪問控制,防止服務(wù)中的敏感數(shù)據(jù)泄漏給不受信任的服務(wù),并在DSL層面上豐富了驅(qū)動(dòng)事件的形式:事件之間的邏輯關(guān)系和疊加。同時(shí),在現(xiàn)有微服務(wù)組合平臺(tái)中引入Spring Cloud Netflix生態(tài)系統(tǒng),解決了微服務(wù)動(dòng)態(tài)部署的問題,增強(qiáng)了可擴(kuò)展性和容錯(cuò)性。通過設(shè)計(jì)新的XML文檔比較算法,實(shí)現(xiàn)對(duì)Web資源在內(nèi)容和結(jié)構(gòu)2個(gè)層面的變更檢測(cè),作為微服務(wù)組合的觸發(fā)條件,從而彌補(bǔ)了現(xiàn)有解決方案的不足。
本文設(shè)計(jì)的微服務(wù)組合平臺(tái),以領(lǐng)域特定語言DSL為基礎(chǔ),DSL可為編程人員在高級(jí)業(yè)務(wù)邏輯與底層系統(tǒng)實(shí)現(xiàn)之間提供抽象層,從而使編程人員能專注于業(yè)務(wù)邏輯的編寫。該平臺(tái)主要包括DSL編譯器、運(yùn)行時(shí)系統(tǒng)和Spring Cloud Netflix生態(tài)系統(tǒng)。平臺(tái)體系結(jié)構(gòu)如圖1所示。 編程人員首先利用DSL編寫要進(jìn)行編排的具體微服務(wù)組合的業(yè)務(wù)邏輯,由DSL編譯器將高級(jí)語言(DSL)代碼編譯成目標(biāo)代碼(JavaScript代碼),以在運(yùn)行時(shí)系統(tǒng)上運(yùn)行。在此過程中,微服務(wù)之間的組合被映射為進(jìn)程間通信。 運(yùn)行時(shí)系統(tǒng)基于Node.js構(gòu)建,它是一個(gè)基于Chrome V8 JavaScript引擎開發(fā)的JavaScript運(yùn)行時(shí)系統(tǒng)[6]。每個(gè)服務(wù)組合被隔離在不同的沙箱里面,因此不同的微服務(wù)組合之間不會(huì)互相影響。整個(gè)微服務(wù)組合平臺(tái)是輕量級(jí)的,可在有限資源的服務(wù)器如樹莓派和Docker容器中部署運(yùn)行。Spring Cloud Netflix生態(tài)系統(tǒng)中的Zuul Gateway網(wǎng)關(guān)、Eureka服務(wù)注冊(cè)中心、Ribbon負(fù)載均衡組件和Hystrix服務(wù)熔斷機(jī)制將為平臺(tái)提供微服務(wù)動(dòng)態(tài)部署的支持,提高平臺(tái)健壯性。
Figure 1 Architecture of microservice composition platform圖1 微服務(wù)組合平臺(tái)體系結(jié)構(gòu)
為了實(shí)現(xiàn)微服務(wù)的組合,本文定義了一種領(lǐng)域特定語言DSL,使編程人員能夠以較高抽象層次描述微服務(wù)的組合邏輯。本文對(duì)現(xiàn)有的微服務(wù)組合平臺(tái)進(jìn)行改進(jìn):通過在DSL層面定義基于標(biāo)簽的訪問控制機(jī)制,實(shí)現(xiàn)可配置的細(xì)粒度數(shù)據(jù)訪問控制,防止服務(wù)中的敏感數(shù)據(jù)泄漏給不受信任的服務(wù)。對(duì)于驅(qū)動(dòng)的事件,能對(duì)Web資源不同層面的變化進(jìn)行變更檢測(cè),并對(duì)驅(qū)動(dòng)事件的形式進(jìn)行擴(kuò)展,以適應(yīng)更加復(fù)雜的應(yīng)用場(chǎng)景,如事件之間的與關(guān)系和或關(guān)系組合,同一事件重復(fù)出現(xiàn)多次的情況下才觸發(fā)微服務(wù)組合。
DSL的語法以BNF范式的形式定義如下:
comp::= composition{decl+ rule+}
decl::=pool? process ident=require(string);
|ident.init(json?);
|ident.add(ident*(,ident)*);
|ident.setlabel(user-label);
|user-label.setpolicy(motion,object-label);
rule::=on event do {action+}
event::= evt|event and evt|event or evt|(event)|evt countto integer
evt::= evt_kind(as ident)?
evt_kind::= ident:out|ident:err|ident:close| uri changed
action::=stream ident=ident.invoke(json?);
|ident.invoke(json?)
|if(expr) action(else action)?
|rule
|xpath.assign(object-label);
expr::=!expr|expr binop expr|(expr)|ident|string|integer|float|jsonpath|method(expr*(,expr)*)
xpath::={{string}}
jsonpath::={{string}}
method::=ident|jsonpath.ident
binop::=<|>|<=|>=|==|!=|&&|||
uri::=string
object-label::= confidential|secret|public
user-label::= manager|employee|stuff
motion::= read|write
在DSL的語法中,require方法創(chuàng)建進(jìn)程,返回一個(gè)新的進(jìn)程實(shí)例;init表示使用用戶定義的參數(shù)初始化一個(gè)進(jìn)程;invoke方法表示調(diào)用一個(gè)進(jìn)程,該方法返回進(jìn)程調(diào)用產(chǎn)生的輸出流的引用。引入的進(jìn)程池用pool關(guān)鍵字聲明,表示可調(diào)用多個(gè)作用相同、可互相替代的進(jìn)程,當(dāng)其中一個(gè)進(jìn)程因錯(cuò)誤無法被調(diào)用時(shí),可調(diào)用進(jìn)程池中的其他進(jìn)程,保證了微服務(wù)組合中的容錯(cuò)性。add方法表示向進(jìn)程池內(nèi)添加新的進(jìn)程。
微服務(wù)組合中的事件驅(qū)動(dòng)規(guī)則則由rule來表示,具體為on event do {action+}:即當(dāng)事件(event)發(fā)生時(shí)觸發(fā)某一動(dòng)作(action)。該事件可為進(jìn)程被調(diào)用后生成的輸出流、Web資源的更改或事件之間的邏輯關(guān)系。
為了使服務(wù)中的敏感數(shù)據(jù)不被泄漏到其他不被授權(quán)的服務(wù)中,有必要在DSL層面上設(shè)計(jì)一種訪問控制機(jī)制。本文使用的訪問控制機(jī)制支持可配置的細(xì)粒度數(shù)據(jù)的訪問控制,而不是根據(jù)“全有或全無”的模式來定義訪問控制級(jí)別。此處的細(xì)粒度是指在XML文檔中屬性的內(nèi)容部分。因此,使用了基于標(biāo)簽的訪問控制方法LABAC(Lable-Based Access Control)[7]。
基于標(biāo)簽的訪問控制方法LABAC不同于基于角色的訪問控制RBAC(Role-Based Access Control)將權(quán)限僅分配給特定的角色,用戶只能屬于某一特定角色而被賦予權(quán)限,LABAC的核心在于policy的概念,其可以表示一組復(fù)雜的布爾規(guī)則集,用于對(duì)多種不同的屬性進(jìn)行評(píng)估,不僅可對(duì)用戶(user)賦予屬性,還可對(duì)資源、環(huán)境和操作賦予屬性,從而可以滿足幾乎所有的訪問控制需求[8]。
如圖2所示,object指需要施加訪問控制的對(duì)象,action表示可對(duì)對(duì)象進(jìn)行的操作,如讀寫等。policy表示三元組(user-label,action,object- label),其含義為具有某特定user-label的用戶可以對(duì)具有某object-label的對(duì)象進(jìn)行指定的action操作。如前文用BNF范式表示的DSL語法,user-label可為不同的屬性,如manager、employee、stuff,且user-label可具有層次嵌套結(jié)構(gòu),例如,stuff能訪問的數(shù)據(jù)均能被employee訪問;employee能訪問的數(shù)據(jù)均能被manager所訪問。object-label可給特定對(duì)象賦予如confidential、secret、public定義隱私級(jí)別的屬性,同樣具有層次嵌套結(jié)構(gòu)。setlabel和setpolicy分別表示設(shè)置用戶標(biāo)簽user-label、設(shè)置策略policy。為了給細(xì)粒度的數(shù)據(jù)賦予標(biāo)簽object-label,assign函數(shù)可對(duì)xpath中的對(duì)象進(jìn)行操作。xpath是一種用于XML的查詢語言。
Figure 2 Label-based access control model圖2 基于標(biāo)簽的訪問控制模型
2.1節(jié)中定義的DSL代碼,可由DSL編譯器將其轉(zhuǎn)化為可在運(yùn)行時(shí)系統(tǒng)中執(zhí)行的JavaScript目標(biāo)代碼。DSL編譯器借助ANTLR4[9]實(shí)現(xiàn),ANTLR4是一個(gè)語法解析器生成器,可以根據(jù)用戶所定義的語法生成語法解析器和監(jiān)聽器接口(listener interface)或訪問者(visitor),以根據(jù)需求生成目標(biāo)代碼。
ANTLR4定義了一種后綴為.g4的DSL語法文件。首先根據(jù).g4文件的語法要求,將2.1節(jié)所定義的BNF范式表示的語法轉(zhuǎn)化為.g4文件的語法。之后在Node.js的環(huán)境中,由ANTLR4根據(jù).g4文件生成所需要的語法解析器、監(jiān)聽器(listener)和訪問者。在此本文選擇以監(jiān)聽器(listener)的方式來生成目標(biāo)代碼。
根據(jù)為微服務(wù)組合定義的語法,ANTLR4生成了Complistener.js文件,其包含用戶所定義的每個(gè)語法規(guī)則的enter和exit函數(shù),但仍然需要用戶根據(jù)需求自己編寫為每個(gè)語法規(guī)則生成目標(biāo)代碼的指令。但是,這種方法的缺陷在于,一旦DSL被修改,ANTLR4需重新生成Complistener.js文件,該文件原先所有的內(nèi)容就被擦除,因此需要?jiǎng)?chuàng)建另一個(gè)名為JSlistener.js的文件,該JSlistener.js文件中再引入ANTLR4生成的Complistener.js文件,在新的listener文件中編寫代碼。
除了以上的listener文件,DSL編譯器將DSL高級(jí)代碼轉(zhuǎn)化為目標(biāo)代碼還需要一個(gè)額外的implement.js文件。該implement.js文件被引入到listener文件中,主要包含3個(gè)函數(shù):OpenTarget、CloseTarget和write,其作用分別是創(chuàng)建目標(biāo)代碼文件、將數(shù)組保存到目標(biāo)代碼文件中和將每一行目標(biāo)代碼寫入到數(shù)組中。
在現(xiàn)有的微服務(wù)組合平臺(tái)解決方案中,進(jìn)行微服務(wù)的組合作業(yè)之前需要先注冊(cè)每個(gè)微服務(wù)的端口等基本信息或定義“服務(wù)描述符”,這就使得無法在已有的微服務(wù)組合中動(dòng)態(tài)添加新的微服務(wù)。此時(shí)必須終止微服務(wù)組合,重新注冊(cè)每個(gè)微服務(wù)的基本信息,再啟動(dòng)微服務(wù)組合平臺(tái)。這使得微服務(wù)組合平臺(tái)缺乏動(dòng)態(tài)部署和可擴(kuò)展性。本文通過引入Spring Cloud Netflix生態(tài)系統(tǒng)中的Eureka服務(wù)注冊(cè)中心,則不需要事先注冊(cè)微服務(wù)信息,依靠服務(wù)發(fā)現(xiàn)模式即可動(dòng)態(tài)確定微服務(wù)的位置,解決了微服務(wù)動(dòng)態(tài)部署的問題,提高了可擴(kuò)展性。此外,Spring Cloud Netflix生態(tài)系統(tǒng)中的Zuul Gateway網(wǎng)關(guān)、Ribbon負(fù)載均衡組件和Hystrix服務(wù)熔斷機(jī)制將為平臺(tái)提供負(fù)載均衡、熔斷保護(hù)的功能[10],提高了平臺(tái)的容錯(cuò)性和健壯性。
現(xiàn)有的基于事件驅(qū)動(dòng)的微服務(wù)組合平臺(tái),缺少對(duì)Web資源如XML文檔的比較算法或變更檢測(cè)方法,Web資源如XML文檔的變更可作為微服務(wù)組合的觸發(fā)事件。現(xiàn)有的XML文檔比較算法多集中于對(duì)XML文檔內(nèi)容或結(jié)構(gòu)單一層面的比較,缺少對(duì)多種因素的綜合考慮[11]。本文提出一種新的XML文檔比較算法,能在內(nèi)容和結(jié)構(gòu)2個(gè)層面來比較XML文檔。具體而言,結(jié)合了內(nèi)容和結(jié)構(gòu)的相似度以實(shí)現(xiàn)綜合考慮的目的。對(duì)內(nèi)容層面的XML文檔比較,用更先進(jìn)的算法替換了原來的算法,提高了時(shí)間效率。
研究人員已經(jīng)提出了多種用于比較XML文檔的算法[12 - 15],然而這些算法主要依賴于XML文檔中的主鍵,但主鍵并非在所有情況下都能定義,也并非在文檔變化中一成不變,算法也欠缺一定的靈活性,無法針對(duì)XML文檔中某個(gè)特定的元素進(jìn)行相似度權(quán)重的配置。因此,Oliveira等人[16]提出了一種基于內(nèi)容相似度的XML文檔比較算法。但是,該算法沒有考慮到XML文檔結(jié)構(gòu)的相似度,算法的時(shí)間效率仍然可以提高。
對(duì)于結(jié)構(gòu)層面的XML比較,本文將XML文檔結(jié)構(gòu)轉(zhuǎn)化為時(shí)間序列,進(jìn)而通過離散時(shí)間傅里葉變換得到的頻譜來進(jìn)行比較[18],最后得到結(jié)構(gòu)相似度。
良好的相似度函數(shù)應(yīng)考慮到內(nèi)容和結(jié)構(gòu)的綜合,因此本文提出的相似度函數(shù)為內(nèi)容相似度和結(jié)構(gòu)相似度的加權(quán)平均值,如式(1)所示,內(nèi)容和結(jié)構(gòu)因素的權(quán)重均是可定制的,保證了一定的靈活性。
Similarity(d1,d2)=
(1)
其中,Similarity為總體相似度,contsim和strusim分別代表內(nèi)容相似度和結(jié)構(gòu)相似度,Wc和Ws分別代表內(nèi)容和結(jié)構(gòu)相似度的權(quán)重,d1和d2分別代表2個(gè)XML。
在2個(gè)XML文檔中,對(duì)于有子element的父element之間的相似度的衡量,本文采用動(dòng)態(tài)規(guī)劃的思想來處理,同樣構(gòu)造一個(gè)針對(duì)父element的相似度矩陣,用于衡量子element之間的相似度,這個(gè)過程一直持續(xù)到?jīng)]有更深層次結(jié)構(gòu)的子element為止。對(duì)于2個(gè)(子)element之間的相似度,分為4種分量:
(1)element名稱相似度分量NS。
此處的名稱指表示一個(gè)element“是什么類型”的字符串。若此項(xiàng)不相同,則無法進(jìn)行比較,因此假定XML文檔隨時(shí)間的演變,此項(xiàng)不會(huì)發(fā)生更改。
(2)內(nèi)容相似度分量CS。
“內(nèi)容”指element所包含的內(nèi)容,可能是以下4種格式:布爾值、數(shù)字、日期/時(shí)間和字符串。對(duì)于布爾值內(nèi)容,若相同,則該分量為1,不同則為0。若為數(shù)字內(nèi)容,則用式(2)來衡量數(shù)字之間的相似度:
CS(e1,e2)=
(2)
其中,CS代表數(shù)字之間的相似度,abs為絕對(duì)值函數(shù)。
若為日期/時(shí)間內(nèi)容,則將時(shí)間轉(zhuǎn)化為Unix時(shí)間戳,再利用式(2)計(jì)算相似度分量。若為字符串內(nèi)容,則利用最長(zhǎng)公共子序列LCS(Longest Common Subsequence)算法計(jì)算2個(gè)字符串之間的相似度。
(3)屬性相似度分量AS。
首先提取出2個(gè)element所包含的屬性名集合,若2個(gè)屬性名相同,則使用(2)中的方法比較2個(gè)屬性中內(nèi)容的值。若屬性名不同,則將不同的屬性視為一個(gè)新屬性。若另一個(gè)element中沒有屬性,則將其相似度設(shè)為0。最后,將所有得到的屬性相似度除以開始得到的屬性數(shù)量,得到總體的屬性相似度分量。
(4)子element相似度分量SES。
分量的計(jì)算也使用動(dòng)態(tài)規(guī)劃思想,遞歸地計(jì)算2個(gè)子element的相似度,得到相似度矩陣,由優(yōu)化算法得到總體相似度,作為子element相似度分量。
最后,2個(gè)XML element的總體相似度由上述4個(gè)分量進(jìn)行加權(quán)平均得到。每個(gè)分量的權(quán)值都是可定制的,默認(rèn)為25%。如式(3)所示:
Contsim(e1,e2)=(Wn*NS(e1,e2)+
Wc*CS(e1,e2)+Wa*AS(e1,e2)+
Ws*SES(e1,e2))/(Wc+Ws+Wa+Wn)
(3)
其中Contsim為內(nèi)容相似度;NS,CS,AS,SES分別為計(jì)算以上4個(gè)相似度分量的函數(shù);Wn,Wc,Wa,Ws分別為其相應(yīng)的權(quán)值。
本文采用的優(yōu)化算法為一種改進(jìn)的用于最大權(quán)二部圖匹配的分解算法,可以以更高的時(shí)間效率找出二部圖最大權(quán)匹配。該算法可以找出矩陣中滿足一定條件的元素值的最大和。在本文的背景下,即找出相似度矩陣中相似度最大的element的匹配,作為2個(gè)XML文檔的總體相似度的衡量。
找出相似度矩陣(無向帶權(quán)二部圖)中的最大element匹配的步驟如下所示:
(1)設(shè)矩陣中最大元素值為N。找出矩陣G中最大的2個(gè)元素值N和H2,并求出它們之間的差h=N-H2。記mm(G)為一個(gè)矩陣中滿足兩兩元素均不在同一行/列的元素值個(gè)數(shù)的最大值。MWBM(G)為一個(gè)矩陣中滿足兩兩元素均不在同一行/列,且元素之和最大的所有元素。Wt-MWBM(G)為MWBM(G)中所有元素之和。
(2)根據(jù)原矩陣G生成新矩陣Gh。新建一個(gè)矩陣Gh,其行列數(shù)與原矩陣相同。篩選出原矩陣中元素值在區(qū)間[N-h+1,N]內(nèi)的元素,并重新賦值,賦值規(guī)則為:原矩陣元素值-h。其余元素賦以0值。
(3)為了便于表達(dá)下文的含義,如表1所示是一個(gè)矩陣以表格形式表示的例子,表格中數(shù)字即為原矩陣中的值。A和B分別代表矩陣的行和列的標(biāo)號(hào)集合,Wt(A,B)表示矩陣中的元素值。定義一個(gè)函數(shù)C:A∪B→N0,滿足C(A)+C(B)≥Wt(A,B)。設(shè)Wt(C)= ∑x∈A∪BC(x)。當(dāng)Wt(C)最小時(shí),記C為一個(gè)最小覆蓋。求出矩陣Gh的最小覆蓋,記為Ch。
Table 1 Table representing matrix elements
用(5)得到的最終結(jié)果除以矩陣的秩,即可得到2個(gè)XML element的最大總體相似度。
算法偽代碼如算法1所示:
算法1最大權(quán)二部圖匹配
輸入:帶權(quán)無向二部圖G。
輸出:二部圖最大權(quán)匹配的權(quán)值和(Wt-MWBM(G))。
步驟1public static intWt-MWBM(G)= 0;/*初始值為0;*/
步驟2publicfindh(GraphG)/*計(jì)算出圖中最大2個(gè)權(quán)值之差h;*/
步驟3public classBipartiteMatching{
publicBipartiteMatching(GraphG) {}};//找出最大基數(shù)匹配mm(G)
步驟4publicformationGh(GraphG){};/*從圖G生成新圖Gh*/
步驟5public class MinimumWeightedVertexCover{
public static voidfindMinimumWeighted-VertexCoverApprox(ArrayList〈Edge〉graph,int[]weights){ };/*找出圖Gh的最小頂點(diǎn)覆蓋*/
步驟7BipartiteMatching(Gh);//計(jì)算出mm(Gh)
returnh*|mm(Gh)|;/*得到最終結(jié)果Wt-MWBM(G)*/
}else{
第2節(jié)所述的微服務(wù)組合平臺(tái)可用如下DSL代碼實(shí)現(xiàn)運(yùn)行:
composition {
process weather=require("getweather");
getweather.init({"latitude":"51.8498698","longitude":"-0.6637842"});
?
stream weather=getweather.invoke({"latitude":"51.8498698","longitude":"-0.6637842"});
on(weather:out as data) do {
weather-forecast.invoke("cityname":"beijing");}
DSL代碼作為高級(jí)代碼將被DSL編譯器編譯為可在運(yùn)行時(shí)系統(tǒng)中運(yùn)行的目標(biāo)代碼(JavaScript代碼)。運(yùn)行時(shí)系統(tǒng)Node.js的底層API被修改以適合微服務(wù)組合需求。如Node.js中的child_process.exec()函數(shù)應(yīng)作為啟動(dòng)Node.js微服務(wù)應(yīng)用程序進(jìn)程的函數(shù),其子進(jìn)程調(diào)用結(jié)束后的callback改為data或error,Node.js事件機(jī)制中的emitter.on(eventName,listener)修改為其函數(shù)參數(shù)與微服務(wù)組合代碼中事件驅(qū)動(dòng)的參數(shù)相匹配。對(duì)于驅(qū)動(dòng)微服務(wù)組合的事件形式,例如多個(gè)事件的疊加,采用基于事件訂閱/發(fā)布模式的EventProxy[19]中的after方法,可以偵聽多次相同事件或多次不同事件,待全部事件都發(fā)生后執(zhí)行相應(yīng)操作。
以上示例代碼將實(shí)現(xiàn)若接收到用戶查詢當(dāng)前天氣狀況的請(qǐng)求,作為事件驅(qū)動(dòng)條件,則給出未來24 h的白天、夜晚的平均溫度(開式度)和平均氣壓數(shù)據(jù)(帕)。如圖3所示,用戶查詢到當(dāng)前天氣之后,將自動(dòng)啟動(dòng)查詢未來天氣的微服務(wù),以及Spring Cloud組件中的Zuul Gateway網(wǎng)關(guān)、Eureka服務(wù)注冊(cè)中心、Ribbon負(fù)載均衡組件和Hystrix服務(wù)熔斷組件,并在瀏覽器中查看運(yùn)行結(jié)果。
Figure 3 Microservices after the composition of microservices and running results圖3 運(yùn)行微服務(wù)組合后的各項(xiàng)微服務(wù)和運(yùn)行結(jié)果
在微服務(wù)組合平臺(tái)中的細(xì)粒度數(shù)據(jù)訪問控制方面,本文采用的是基于標(biāo)簽的訪問控制方法?;跇?biāo)簽的訪問控制的實(shí)現(xiàn)借助PolicyLine[20],它是一個(gè)基于屬性的Node.js訪問控制庫,涉及對(duì)4種實(shí)體(user、env、action和resource,分別代表用戶、訪問環(huán)境、操作和所訪問資源)的操作。訪問控制策略policy用于檢查訪問權(quán)限并計(jì)算condition的對(duì)象。new Policy (rules)將根據(jù)規(guī)則rules創(chuàng)建一個(gè)新的policy對(duì)象。規(guī)則rules代碼如下所示:
let rules={
effect:"permit",
algorithm:"all",
condition:[ "resource.label=confidential"]};
let policy=new Policy (rules);
其中user.label、resource.label和action.name分別代表基于標(biāo)簽的訪問控制的3種標(biāo)簽。target 表示用于計(jì)算policy的一組邏輯條件,可以包含任何邏輯表達(dá)式。algorithm表示根據(jù)規(guī)則計(jì)算策略的算法,可以取值為all或any。取值為all表示所有規(guī)則rules都應(yīng)返回true,取值為any表示至少應(yīng)有一個(gè)規(guī)則返回true。effect表示對(duì)policy計(jì)算結(jié)果所施加的影響,可取permit或deny值。當(dāng)規(guī)則rules和算法algorithm綜合計(jì)算的結(jié)果為true時(shí),則由effect值決定返回policy為true或false值。若允許則policy返回true,若拒絕則policy返回false。condition表示用于訪問資源的一組條件,可由user、env、action和resource這4種參數(shù)組成邏輯表達(dá)式。
以以下描述微服務(wù)組合的DSL代碼為例:
?
stream issues=getNewIssues.invoke({"repository":"medley/repo" });
on (issues:out as issue) do {
sendEmail.invoke({
"to":"john@doe.com","body":"New issue:{{$.issue.url}}" })};
?
為了避免issues中的數(shù)據(jù)泄漏到服務(wù)sendEmail中,需要根據(jù)基于標(biāo)簽的訪問控制設(shè)定policy,核心代碼如前文規(guī)則rules所示,根據(jù)是否允許讀寫將effect的值改為permit或deny。利用Policy.check()方法驗(yàn)證實(shí)例sendEmail是否可以根據(jù)所定義的訪問控制策略訪問到目標(biāo)資源,結(jié)果將返回true或false。將代碼部署至CodeSandbox平臺(tái)上的運(yùn)行結(jié)果如圖4所示。
Figure 4 Different access results obtained by two different access strategies圖4 2種不同的訪問策略得到的不同訪問結(jié)果
本文利用JavaFX技術(shù)構(gòu)建了XML文檔比較工具,并選取不同文件大小的XML文檔組,進(jìn)行10次5組XML文檔比較,每組比較分別使用匈牙利算法和3.1.2節(jié)中的優(yōu)化算法,在Eclipse控制臺(tái)中記錄得到的執(zhí)行時(shí)間(ms),結(jié)果如圖5,從圖5中可看出算法執(zhí)行耗時(shí)確實(shí)有所下降。
Figure 5 Time-consuming comparison of the two algorithms圖5 2種算法耗時(shí)比較
以圖6a中的2個(gè)XML文檔為例,根據(jù)3.1節(jié)中的公式可得內(nèi)容相似度和結(jié)構(gòu)相似度分別為0.75和0.58。
Figure 6 Overall similarity changes of two XML documents with different structures and different contents圖6 2個(gè)結(jié)構(gòu)、內(nèi)容不同的XML文檔及其總體相似度變化的曲線
考慮XML文檔內(nèi)容和結(jié)構(gòu)的綜合特征,通過改變權(quán)值Wc和Ws,可得到總體相似度變化的曲線為一次函數(shù)s=0.17w+0.58,如圖6b所示,w表示內(nèi)容層面相似度。
本文設(shè)計(jì)了一種基于變更事件驅(qū)動(dòng)的微服務(wù)組合平臺(tái),其在領(lǐng)域特定語言層面上支持細(xì)粒度數(shù)據(jù)的訪問控制,防止敏感數(shù)據(jù)泄露給不受信任的服務(wù),豐富了事件驅(qū)動(dòng)的形式,并引入Spring Cloud Netflix生態(tài)系統(tǒng),支持微服務(wù)的動(dòng)態(tài)部署,提高了平臺(tái)的健壯性。對(duì)于觸發(fā)編排微服務(wù)組合事件的條件,增加了對(duì)Web資源(XML文檔)的變更檢測(cè),即對(duì)XML文檔從內(nèi)容和結(jié)構(gòu)2個(gè)層面綜合比較,并對(duì)現(xiàn)有的XML文檔內(nèi)容層面的比較算法進(jìn)行了優(yōu)化。未來的工作著眼于利用機(jī)器學(xué)習(xí)技術(shù),在執(zhí)行微服務(wù)組合作業(yè)的多節(jié)點(diǎn)集群的調(diào)度器中考慮每個(gè)組合的資源使用情況,以改進(jìn)作業(yè)分配策略,提高集群整體資源利用率。