搭建基于云端的中间层以支持跨平台的智能视觉服务
不斷演進的應用場景
初級應用場景—宅在家里
場景:Bob同學有一天在網(wǎng)上看到了一張建筑物的圖片,大發(fā)感慨:"好漂亮啊!這是哪里?我要去親眼看看!"Bob同學不想問別人,可笑的自尊心讓他覺得這肯定是個著名的建筑,如果自己不知道多丟臉!怎么解決Bob同學的煩惱呢?
?
我們看看微軟認知服務是否能幫助到Bob同學,打開這個鏈接:
https://azure.microsoft.com/zh-cn/services/cognitive-services/computer-vision/
向下卷滾屏幕,到"識別名人和地標"部分,在"圖像URL"編輯框里輸入了這張圖片的網(wǎng)絡地址,然后點擊"提交",一兩秒后,就能看到關(guān)于這張圖片的文字信息了(見下圖),原來這個建筑叫做"Space Needle"!但是呢,不太人性化,因為是JSON文件格式的,幸好Bob同學是個程序員,Bob同學想把這個場景做成一個實際的應用,以幫助他人解決類似問題。
?
Bob同學剛學習了微軟認知服務的應用教程,于是打開Windows 10 PC,啟動VS2017,安裝了Visual Studio Tools for AI后,先在Server Explorer->AI Tools->Azure Cognitive Services上點擊鼠標右鍵,Create New Cognitive Service,API Type選擇ComputerVision (如果已經(jīng)有了就不需要重復申請了),得到了Key和Endpoint,按照《漫畫翻譯篇》教程所講述的過程,照貓畫虎,花了一兩個小時,就把應用做好了。
開發(fā)技術(shù)文檔在這個鏈接里面。
目前Bob的同學的應用架構(gòu)是這樣的:
(上圖中右側(cè)的框圖內(nèi)的文字是“地標識別”,下同)?
中級應用場景—出門在外
Bob同學很滿意地試著自己的作品,長城,天安門,故宮……都能認出來!但是,Bob同學忽然想到,如果出門在外遇到一個漂亮建筑,沒有PC,只有手機怎么辦?于是Bob同學又啟動了VS2017,創(chuàng)建了一個Xamarin項目,重用了PC上的code,把這個場景搞定了:拿起Android或者iOS手機,對著建筑物一框,幾秒后就會有結(jié)果返回,告訴用戶眼前的這個建筑叫什么名字。太方便啦!
所以,Bob同學的應用架構(gòu)進化了一些:
高級應用場景—擴展信息
Bob同學用手機給很多同學們安裝后顯擺了幾天,有人問他:"Space Needle是啥?"
"這個……這個……哦!你可以在Bing上搜索一下啊!"
"你的程序能不能順便幫我們搜索一下呢?"
"嗯……啊……當然啦!"硬著頭皮說了這句話后,Bob同學趕緊回去查微軟認知服務的網(wǎng)站了。Bingo! 在這里了:
https://azure.microsoft.com/zh-cn/services/cognitive-services/bing-entity-search-api/
與前面的教程里描述的類似,申請了搜索服務后,也得到了Endpoint和Key,照貓畫虎地把客戶端改了一下,增加了搜索服務的功能,銜接到了地標識別邏輯的后面,也就是把地標識別的結(jié)果"Space Needle"作為關(guān)鍵字傳送給實體搜索服務,然后再把結(jié)果展示出來。
注意這里要申請的API在Bing.Search.v7里面,技術(shù)文檔在這個鏈接里面。
于是Bob同學的應用架構(gòu)變成了這個樣子:
(上圖中右側(cè)的框圖內(nèi)的文字是“實體搜索”,下同)
這個圖的連接線看著好奇怪,黃色的線為什么不連接到左側(cè)的客戶端上呢?這里特意這樣畫,為了表示黃色的連接(REST API調(diào)用)是接在藍色的連接之后的,有依賴關(guān)系。在下一個場景里,大家會看到更復雜的例子。
終級的應用場景—并發(fā)處理
在一陣手忙腳亂的部署之后,所有的同學的手機都可以使用這個新App了,Bob同學很自豪。這時,學習委員走過來了(也是體育課代表),問Bob:"出門旅游的機會不多,我想用這個App做更多的日常的事情,比如掃一張照片,就能知道這個明星的名字和背景資料,或者是照一件衣服就能知道在哪里買,還有看到一個電話號碼后,想用手機掃一下就能記錄下來……這些能辦到嗎?"
Bob同學邊聽邊鎮(zhèn)靜地點頭,其實后背都濕透了,嘴上不能服軟:"我回去想想辦法吧!"
Bob同學翻閱了微軟認知服務的所有技能,在紙上畫了一個草圖,來解決學習委員的問題:
(上圖中右側(cè)的框圖內(nèi)的文字是“名人識別”,下同)
同時有三根藍線都從同一個客戶端連接到不同的認知服務上,是因為客戶端程序并不知道要識別的物體是建筑物呢,還是人臉呢,或是電話號碼呢?需要一個個的去嘗試調(diào)用三個API,如果返回有效的結(jié)果,就代表識別出了該實體的類型。
畫完圖后,本來以為會輕松的Bob同學,忽然發(fā)現(xiàn)他需要不斷更新三個客戶端的代碼:PC,Android,iOS,來滿足更多的學習委員的需要(如同右側(cè)那個上下方向的箭頭一樣是可擴充的),然后再分別發(fā)布出去!并且他意識到了另外一個問題:每個客戶端需要訪問認知服務四次才能完成這個場景!不但網(wǎng)絡速度對用戶體驗造成了影響,而且流量就是錢啊!如果將來需要支持更多的識別類型,連接線的增長速率將會是幾何級別的!
My Omnipotent God!Tell Me How!
重構(gòu)
Bob同學想起了剛買到的《構(gòu)建之法》第三版,仔細閱讀了第9,10,11三章,明白了一些基本的概念:
需求是不斷演進的,任何一個軟件都需要不斷迭代
定位典型用戶(學習委員)和常用場景(出門旅游還是宅在家里)
在需求分析階段,要搞清楚在現(xiàn)實世界里,都有哪些實體,如何抽象出我們真正關(guān)心的屬性和方法
PM/用戶提出的需求,程序員需要認真理解,深入到實際問題中進行抽象,找到實體和屬性/方法在軟件系統(tǒng)中的表現(xiàn),構(gòu)建框架,然后再編碼(想明白了再動手,不能頭疼醫(yī)頭,腳疼醫(yī)腳)
"我要重構(gòu)!"房間里響起了Bob同學的吶喊聲,把隔壁鄰居嚇了一跳:"這小伙子是不是又失戀了?"
小提示:需求的"演進"與"變化"是兩回事兒,不要混為一談來掩蓋項目經(jīng)理對需求的分析與把握的不足。簡單地舉例來說,當項目經(jīng)理說"地標識別看上去很少有人用,廢掉吧,咱們做個名人識別",這個屬于需求變化。
認知服務應用構(gòu)建方式
兩種構(gòu)建方式的比較
微軟認知服務應用方式有兩大類:
用客戶端直接訪問認知服務
客戶端通過中間服務層訪問認知服務
第一種模式很好理解:微軟認知服務7x24小時在云端提供服務,開發(fā)者在智能手機或者PC上編寫客戶端應用程序,調(diào)用REST API直接訪問云端。但是這種模式有一些潛在的問題,如:
客戶端代碼量大邏輯復雜
客戶端需要密集發(fā)布并持續(xù)維護
客戶端與服務器端耦合度高
客戶端多次訪問服務器
網(wǎng)絡安全性低
無論客戶端有多少,依賴的認知服務有多少,其實還是下圖所示的模式:
目前Bob同學就是使用這種方式,來不斷演進他的應用,終于遇到了棘手的問題。
為什么呢?因為客戶端一旦發(fā)布到用戶手里,對發(fā)布者來說就比較被動了,需要非常小心地維護升級,每次都要全面測試,測試點多而復雜。即使有應用商店可以幫助發(fā)布,但要把所有用戶都升級到最新版本,還是需要很長時間的,這意味著你還需要向后兼容。
第二種模式可以用簡單的圖來表示:
有規(guī)模的商業(yè)化應用,一般都采用這種模式搭建應用架構(gòu),以便得到以下好處:
客戶端代碼量小邏輯簡單
客戶端不需要密集發(fā)布和維護
客戶端與認知服務的耦合度低
客戶端單次訪問服務器
網(wǎng)絡安全性高
拉個表格,一目了然:
直接訪問模式 | 中間服務層模式 | |
客戶端代碼 | 量大,邏輯復雜 | 量小,邏輯簡單 |
發(fā)布與維護 | 密集,改一點兒東西都需要重新發(fā)布新版本 | 中間層服務能屏蔽大量邏輯,不需要在客戶端代碼中體現(xiàn) |
客戶端與認知服務的耦合度 | 極高 | 很低 |
客戶端與認知服務的通信量 | 頻繁,多次 | 單次 |
對認知服務密鑰的保護 | 低,用Fiddler就可以"看到"認知服務密鑰 | 高,把費德勒叫來也不行 |
服務器端代碼 | 無 | 有 |
多種客戶端支持 | 復雜 | 簡單 |
如果有了中間服務層,客戶端的工作就簡化到只做與中間服務層通信,提交請求,接收數(shù)據(jù),用戶交互等等,而復雜的商業(yè)邏輯,可以在中間服務層實現(xiàn)。而且在更新業(yè)務邏輯的時候,大多數(shù)情況下,只需要修改中間服務層的代碼,無需更新客戶端。
對于多種客戶端的支持問題,用微軟VS2017提供的跨平臺Xamarin架構(gòu)可以解決,開發(fā)者只需要寫C#程序,就可以把應用部署在Windows/Android/iOS設備上,一套代碼搞定。
中間層服務也不是十全十美,帶來的問題有二:1)需要云端支持,要花錢的;2)圖片傳輸?shù)倪^程會發(fā)生兩次,第一次是從客戶端到中間層,第二次是中間層到微軟認知服務,這樣會增加網(wǎng)絡時間上的開銷。但是有個好消息是第二次傳輸所花費的時間要比第一次小一個數(shù)量級,因為是服務器對服務器的通信,如果你自己的服務器也放在Azure上,那么和微軟認知服務的服務器就可能在一個大機房里了,局域網(wǎng)的速度!并且,這個開銷與客戶端多次訪問服務器相比,也是占優(yōu)的選擇,所以大家可以在有條件的情況下盡量使用第二種方式做商業(yè)應用。
另外一種分類方式
如果關(guān)注于對認知服務的使用,也可以用另外一種分類方式:
單獨使用某個服務
串行使用兩個以上的服務
并行使用兩個以上的服務
串并行混合使用三個以上的服務
比如上面的最后的場景,實際上是第四種方式:先并行使用了地標識別、名人識別、OCR,然后又串行使用了實體搜索服務。
合理的應用架構(gòu)
我們來幫助Bob同學重新設計一下他的應用架構(gòu):
上圖只是個粗略的架構(gòu),中間服務層具體如何實現(xiàn)呢?
我們常聽到的一句話是"這個問題你只要充值就能解決了" 沒錯,做信仰充值:先安裝Visual Studio 2017 and Tools for AI,再接著往下看。
從零開始構(gòu)建中間服務層
環(huán)境要求與基本步驟
環(huán)境要求:
強烈建議使用Windows 10 較新的版本(筆者使用的是Version 1803)。使用Windows 7也應該可以,但是筆者沒有做過具體測試。
至少8G內(nèi)存。只有4G的話可能會比較吃力。
CPU主頻2.5GHz以上,最好是i7。1.9GHz + i5的配置比較吃力。
可以訪問互聯(lián)網(wǎng)上的微軟認知服務
基本步驟:
安裝Visual Studio 2017 Community或以上版本,注意要安裝服務器開發(fā)包,否則找不到第4步的模板。
下載安裝Microsoft Visual Studio Tools for AI擴展包,安裝完后重啟VS2017。
在Server Explorer中的AI Tools->Azure Cognitive Services菜單上,點擊鼠標右鍵,申請兩個認知服務:Bing.Search.V7和ComputerVision。關(guān)于如何申請服務,請看本系列文章的上一篇。
在VS2017中創(chuàng)建一個ASP.NET Core Web Application,在里面編寫中間服務層的邏輯代碼。
利用簡單的客戶端進行測試。
下面我們展開第4步做詳細說明。
創(chuàng)建應用服務
在VS2017中創(chuàng)建一個新項目,選擇Web->ASP.NET Core Web Application,如下圖:
給項目取個名字叫做"CognitiveMiddlewareService",Location自己隨便選,然后點擊OK進入下圖:
在上圖中選擇"API",不要動其他任何選項,點擊OK,VS一陣忙碌之后,就會生成下圖的解決方案:
這是一個最基本的ASP.NET Core Web App的框架代碼,我們將會在這個基礎上增加我們自己的邏輯。在寫代碼之前,我們先一起搞清楚兩個關(guān)于ASP.NET Core框架的基本概念。
ASP.NET Core的兩個基本概念
依賴注入
ASP.NET Core?支持依賴關(guān)系注入?(DI)?軟件設計模式,這是一種在類及其依賴關(guān)系之間實現(xiàn)控制反轉(zhuǎn)?(IoC)?的技術(shù),原文鏈接在這里。簡單的說就是:
定義一個接口
定義一個類實現(xiàn)這個接口
在框架代碼Startup.cs中注冊這個接口和類
在要用到這個服務的類(使用者)的構(gòu)造函數(shù)中引入該接口,并保存到成員變量中
在使用者中直接使用該成員變量->方法名稱
我們在后面的代碼中會有進一步的說明。
發(fā)起HTTP請求
框架提供了一種機制,可以通過注冊IHttpClientFactory用于創(chuàng)建HttpClient實例,這種方式帶來以下好處:
提供一個集中位置,用于命名和配置HttpClient實例
通過委托HttpClient中的處理程序來提供中間層服務
管理基礎HttpClientMessageHandler實例的池和生存期,避免在手動管理HttpClient生存期時出現(xiàn)常見的DNS問題
添加可配置的記錄體驗,以處理HttpClientFactory創(chuàng)建的客戶端發(fā)送的所有請求
以上是原文提供的解釋,鏈接在這里。可能比較難理解,但坊間一直流傳著HttpClient不能釋放的問題,所以用IHttpClientFactory應該至少可以解決這個問題。
但是在使用它之前,我們需要安裝一個NuGet包。在解決方案的名字上點擊鼠標右鍵,在出現(xiàn)的菜單中選擇"Manage NuGet Packages…",在出現(xiàn)的如下窗口中,輸入"Microsoft.extensions.http",然后安裝Microsoft.Extensions.Http包:
安裝完畢后,需要在Startup.cs文件里增加依賴注入:services.AddHttpClient()。
文件目錄組織方式和層次關(guān)系
先在生成好的框架代碼的基礎上,建立下圖所示的文件夾:
CognitiveServices
MiddlewareService
Processors
Controllers是基礎框架帶的文件夾,不需要自己創(chuàng)建。
創(chuàng)建這些文件夾的目的,是讓我們自己能夠縷清邏輯,寫代碼時注意調(diào)用和被調(diào)用的關(guān)系,用必要的層次來體現(xiàn)軟件的抽象。以本案例來說,模塊劃分與層次抽象應該如下圖所示(下圖中帶箭頭的實線表示調(diào)用關(guān)系):
基礎服務層
藍色的層,也就是CognitiveServices文件夾,包含了兩個訪問認知服務的基礎功能:VisionService和EntitySearchService。
它們返回了最底層的結(jié)果:VisionResult和EntityResult。這一層的每個服務,只專注于自己的網(wǎng)絡請求與接收結(jié)果的任務,不管其它的事情。如果認知服務編程接口有變化,只修改這一層的代碼。
集成服務層
黃色的層,也就是MiddlewareService文件夾,是我們自己包裝認知服務的邏輯層,在這個層中的代碼,每一個服務都是用串行方式訪問認知服務的:在用第一個輸入(假設是圖片)得到第一個認知服務的返回結(jié)果后(假設是文字),再把這個返回結(jié)果輸入到第二個認知服務中去,得到內(nèi)容更豐富的結(jié)果。
它們返回了集成后的結(jié)果:LandmarkResult和CelebrityResult,這兩個結(jié)果的定義已經(jīng)對認知服務返回的結(jié)果進行了進一步的抽象和隔離,其目的是讓后面的邏輯代碼只針對這一層的抽象進行處理,不必考慮更底層的數(shù)據(jù)結(jié)構(gòu)。
任務調(diào)度層
綠色的層,也就是Processors文件夾,是包裝業(yè)務邏輯的代碼,在本層中做任務分發(fā),用并行方式同時訪問兩個以上的認知服務,將返回的結(jié)果聚合在一起,并根據(jù)需要進行排序,最后生成要返回的結(jié)果AggregatedResult。
CognitiveServices文件夾
在這個文件夾中,我們需要添加以下文件:
IVisionService.cs
VisionService.cs
VisionResult.cs
IEntitySearchService.cs
EntitySearchService.cs
EntityResult.cs
Helper.cs
?
IVisionService.cs - 訪問影像服務的接口定義,需要依賴注入
VisionService.cs - 訪問影像服務的邏輯代碼
小提示:上面的代碼中的Key1/Key2是不可用的,請用自己申請的Key和對應的Endpoint來代替。
VisionResult.cs – 認知服務返回的結(jié)果類,用于反序列化
IEntitySearchService.cs – 訪問實體搜索服務的接口定義,需要依賴注入
EntitySearchService.cs – 訪問實體搜索服務的邏輯代碼
小提示:上面的代碼中的Key1/Key2是不可用的,請用自己申請的Key和對應的Endpoint來代替。
?
EntityResult.cs – 認知服務返回的結(jié)果類,用于反序列化
Helper.cs – 幫助函數(shù)
MiddlewareService文件夾
在這個文件夾中,我們需要添加以下文件:
ICelebrityService.cs
CelebrityService.cs
CelebrityResult.cs
ILandmarkService.cs
LandmarkService.cs
LandmarkResult.cs
?
ICelebrityService.cs – 包裝多個串行的認知服務來實現(xiàn)名人識別的中間服務層的接口定義,需要依賴注入
CelebrityService.cs?– 包裝多個串行的認知服務來實現(xiàn)名人識別中間服務層的邏輯代碼
小提示:上面的代碼中,用CelebrityResult接管了實體搜索結(jié)果和名人識別結(jié)果的部分有效字段,以達到解耦/隔離的作用,后面的代碼只關(guān)心CelebrityResult如何定義的即可。
?
CelebrityResult.cs – 抽象出來的名人識別服務的返回結(jié)果
ILandmarkService.cs – 包裝多個串行的認知服務來實現(xiàn)地標識別的中間服務層的接口定義,需要依賴注入
LandmarkService.cs – 包裝多個串行的認知服務來實現(xiàn)地標識別的中間服務層的邏輯代碼
小提示:上面的代碼中,用LandmarkResult接管了實體搜索結(jié)果和地標識別結(jié)果的部分有效字段,以達到解耦/隔離的作用,后面的代碼只關(guān)心LandmarkResult如何定義的即可。
?
LandmarkResult.cs – 抽象出來的地標識別服務的返回結(jié)果
Processors文件夾
在這個文件夾中,我們需要添加以下文件:
IProcessService.cs
ProcessService.cs
AggregatedResult.cs
?
IProcessService.cs – 任務調(diào)度層服務的接口定義,需要依賴注入
ProcessService.cs – 任務調(diào)度層服務的邏輯代碼
小提示:大家可以看到上面這個文件中有很多綠色的注釋,帶有todo文字的,對于一個更復雜的系統(tǒng),可以用這些todo中的描述來設計獨立的模塊。
AggregatedResult.cs – 任務調(diào)度層服務的最終聚合結(jié)果定義
其他文件的修改
ValuesControllers.cs 注意Post的參數(shù)從[FromBody]變成了[FromForm],以便接收上傳的圖片流數(shù)據(jù)
Startup.cs
除了第一行的services.AddMvc()以外,后面所有的行都是我們需要增加的依賴注入代碼。
層次關(guān)系總結(jié)
總結(jié)一下,從調(diào)用關(guān)系上看,是這個次序:
Controller -> ProcessService -> LandmarkService/CelebrityService -> VisionService/EntitySearchService
其中:
·???????????Controller是個Endpoint
·???????????ProcessService負責任務調(diào)度
·???????????LandmarkService/CelebrityService是個集成服務,封裝了串行調(diào)用底層服務的邏輯
·???????????VisionService/EntitySearchService是基礎服務,相當于最底層的原子操作
從數(shù)據(jù)結(jié)構(gòu)上看,進化的順序是這樣的:
VisionResult/EntityResult -> CelebrityResult/LandmarkResult -> AggregatedResult
其中:
·???????????VisionResult/EntityResult是最底層返回的原始結(jié)果,主要用于反序列化
·???????????CelebrityResult/LandmarkResult是集成了多個原始結(jié)果后的抽象結(jié)果,好處是隔離了原始結(jié)果中的一些噪音,解耦,只返回我們需要的字段
·???????????AggregatedResult是聚合在一起的結(jié)果,主要用于排序和生成返回JSON數(shù)據(jù)
?
完整的中間服務層系統(tǒng)棧
有的人會問了:有必要搞這么復雜嗎?這幾個調(diào)用在一個幫助函數(shù)里不就可以搞定了嗎?
確實是這樣,如果不考慮應用擴展什么的,那就用一個幫助函數(shù)搞定;如果想玩兒點大的,那么下面這張圖就是一個完整系統(tǒng)的Stack圖,這個系統(tǒng)通過組合調(diào)用多種微軟認知服務/微軟地圖服務/微軟實體服務等,能夠提供給用戶的智能設備豐富的視覺對象識別體驗。
上圖包含了以下層次:
·???????????Endpoints
?? 兩個Endpoint,一個處理圖片輸入,另一個處理文本輸入
·???????????Processing and Classifier
?? 包含圖像/文字的預處理/預分類
·???????????Task Dispatcher
?? 并行調(diào)用多種服務并協(xié)調(diào)同步關(guān)系
·???????????API agent and Recognizer
?? 組合調(diào)用各種API,內(nèi)置的識別器(比如正則表達式)
·???????????APIs
?? 各種認知服務API
·???????????Processors
?? 隔離層/聚合層/排序器的組合稱呼
·???????????Adaptive Card Generator
?? 生成微軟最新推出的Adaptive Card技術(shù)的數(shù)據(jù),供跨平臺客戶端接收并渲染
·???????????Assistant Component
?? 其它輔助組件
對中間服務層的測試
基本概念與環(huán)境搭建
做好了一個中間層服務,不是說簡單地向Azure上一部署就算完事兒了。任何一個商用的軟件,都需要嚴格的測試,對于普通的手機/客戶端軟件的測試,相信很多人都知道,覆蓋功能點,各種條件輸入,等等等等。對于中間層服務,除了功能點外,性能方面的測試尤其重要。
如何進行測試呢?工欲善其事必先利其器,先看工具:
ASP.NET Core Web API有一套測試工具,請看這個鏈接:https://docs.microsoft.com/en-us/aspnet/core/test/?view=aspnetcore-2.1,它講述了一些列的方法,我們不再贅述,本文所要描述的是三種面向場景的測試方法:負載(較重的壓力)測試,(較輕的壓力)性能測試,(中等的壓力)穩(wěn)定性測試。不是以show code為主,而是以講理念為主,懂得了理念,code容易寫啦。
對于一個普通的App,我們用界面交互的方式進行測試。對于一個service,它的界面就相當于REST API,我們可以從客戶端發(fā)起測試,自動化程度較高。
在Visual Studio 2017,有專門的Load Test工具可以幫助我們完成在客戶端編寫測試代碼,調(diào)整各種測試參數(shù),然后發(fā)起測試,具體的鏈接在這里。
有了工具,再看方法和理念:
在本文中,我們主要從概念上講解一下針對含有認知服務的中間服務層的測試方法,因為認知服務本身如果訪問量大的話,是要收取費用的!
小提示:各個認知服務的費用標準不同,請仔細閱讀相關(guān)網(wǎng)頁,以免在進行大量的測試時引起不必要的費用發(fā)生。
負載測試 Load Test
測試目的
模擬多個并發(fā)用戶訪問中間層服務,集中發(fā)生在一個持續(xù)的時間段內(nèi),以衡量服務質(zhì)量。負載測試不斷的發(fā)展下去,負載越來越大,就會變成極限測試,最終把機器跑癱為止。這種測試可以幫助開發(fā)者知道在單機環(huán)境下能支持多少用戶,進而決定在Azure上要申請多少機器。
測試環(huán)境
注意!我們不是在測試認知服務的性能,是要測試自己的中間層服務的性能,所以如下圖所示:
?
?
?
?
要把認知服務用一個模擬的mock up service來代替,這個mock up service可以自己簡單地用ASP.NET搭建一個,接收請求后,不做任何邏輯處理,直接返回JSON字符串,但是中間需要模擬認知服務的處理時間,故意延遲2~3秒。
另外一個原因是,認知服務比較復雜,可能不能滿足很高的QPS的要求,而用自己的模擬服務可以到達極高的QPS,這樣就不會正在測試中產(chǎn)生瓶頸。
網(wǎng)絡環(huán)境為局域網(wǎng)內(nèi)部,亦即客戶端、中間層、模擬服務都在局域網(wǎng)內(nèi)部即可,這樣可以避免網(wǎng)絡延遲帶來的干擾。
測試方法與結(jié)果
在本例中,我們測試了8輪,每輪都模擬不同的并發(fā)用戶數(shù)持續(xù)運行一小時,最終結(jié)果如下:
concurrent users? | Idle? | 1 user? | 3 users? | 5 users? | 10 users? | 25 users? | 50 users? | 75 users? | 100 users? |
CPU? | 0%? | <1%? | <1%? | 1%? | 2.5%? | 6%? | 12%? | 17%? | 21%? |
Memory(MB)? | 110? | 116? | 150? | 158? | 164? | 176? | 260? | 301? | 335? |
Latency(s)? | 0? | 2.61? | 2.61? | 2.61? | 2.62? | 2.63? | 2.64? | 2.67? | 2.7? |
Total Req.? | 0? | 1,377? | 4,124? | 6,885? | 13,666? | 34,221? | 67,976? | 100,948? | 132,894? |
Failed Req.? | 0? | 0? | 0? | 0? | 0? | 0? | 0? | 0? | 0? |
QPS? | 0.00? | 0.38? | 1.15? | 1.91? | 3.80? | 9.51? | 18.88? | 28.04? | 36.92? |
從圖表可以看出,CPU/Memory/QPS都是線性增長的,意味著是可以預測的。延遲(Latency)是平緩的,不會因為并發(fā)用戶變多而變慢,很健康。
?
可靠性測試 Stability Test
測試目的
在一個足夠長的時間內(nèi)持續(xù)測試服務,中等負載,以檢查其可靠性。"足夠長"一般定義為12小時、48小時、72小時等等。可以認為,被測對象只要跑夠了預定的時長,就算是穩(wěn)定性過關(guān)了。
測試環(huán)境
同理,我們要測試的是中間層服務,而不是認知服務。測試環(huán)境與上面相同,也是使用模擬的認知服務,因為72小時的測試時間,會發(fā)送大量的請求,很可能超出了當月限額而收取費用。
?
?
?
?
網(wǎng)絡環(huán)境仍然使用局域網(wǎng)。
測試方法與結(jié)果
模擬10個并發(fā)用戶,持續(xù)向中間層服務發(fā)請求12小時,測試結(jié)果如下表:
Sample point? | CPU? | Memory? | Latency? | Total Request? | Failed? | QPS? |
1:00:00? | 2.5%? | 140M? | 2.63 second? | 13,730? | 0? | 3.81? |
2:00:00? | 2.5%? | 160M? | 2.61 second? | 13,741? | 0? | 3.82? |
3:00:00? | 2.5%? | 150M? | 2.62 second? | 13,728? | 0? | 3.81? |
…...? | ||||||
Total/Average? | 2.5%? | 150M? | 2.62? | 164,772? | 0? | 3.81? |
從CPU/Memory/Latency/QPS上來看,在12個小時內(nèi),都保持得非常穩(wěn)定,說明服務器不會因為長時間運行而變得不穩(wěn)定。
性能測試 Performance Test
測試目的
測試端對端(e2e)的請求/響應時間。這是針對某個服務場景的測試,想得到具體的數(shù)值,所以不需要很大的負載壓力。
測試環(huán)境
?
?
?
這次我們需要使用真實的認知服務,網(wǎng)絡環(huán)境也使用真實的互聯(lián)網(wǎng)環(huán)境。亦即需要把中間服務層部署到互聯(lián)網(wǎng)上后進行測試,因為用模擬環(huán)境和局域網(wǎng)測試出來的數(shù)據(jù)不能代表實際的用戶使用情況。?
測試方法與結(jié)果
模擬1個用戶,持續(xù)向中間服務層發(fā)送請求1小時。然后模擬3個并發(fā)用戶,持續(xù)向中間服務層發(fā)送請求10分鐘。這兩種方法都不會對認知服務帶來很大的壓力。
在得到了一系列的數(shù)據(jù)以后,每組數(shù)據(jù)都會有響應時間,我們把它們按照從長(慢)到短(快)的順序排列,得到下圖(其中橫坐標是用戶數(shù),縱坐標是響應時間):
?
?
?
?
?
?
?
一般來說,我們要考察幾個點,P90/P95/P99,比如P90的含義是:有90%的用戶的響應時間小于等于2449ms。這意味著如果有極個別用戶響應時間在10秒以上時,是一種正常的情況;如果很多用戶(比如>5%)都在10秒以上就不正常了,需要立刻檢查服務器的運行狀態(tài)。
最后得到的結(jié)果如下表,亦即性能指標:
Percentage? | P90? | P95? | P99? | Average? |
KPI? | <3000ms? | <3250? | <4000? | N/A? |
Server-side processing time? | 2449ms? | 2652ms? | 3571ms? | 1675ms? |
Test client e2e latency? | 3160ms? | 3368ms? | 4369ms? | 2317ms? |
?Server-side processing time: 服務器從接收到請求到發(fā)送回結(jié)果所花費的時間
Test client e2e latency: 客戶端從發(fā)送請求到接收響應所經(jīng)歷的時間
習題與進階學習
增加OCR服務以提供識別文字的功能
在集成服務層增加可以識別具有標準模式的文字的服務,比如電話號碼、網(wǎng)絡地址、郵件地址,這需要同時在基礎服務層增加OCR底層服務,并在任務調(diào)度層增加一個并行任務。
部署到實際的Azure環(huán)境提供真實服務
在本地測試好服務器的基本功能后,部署到Azure上去,看看代碼在實際環(huán)境中運行會有什么問題。因為我們不能實時地監(jiān)控服務器,所以需要在服務層上增加log功能。
開發(fā)Android/iOS應用來提供影像/視覺感知
可以選擇像Bob同學那樣,先用第一種方式直接訪問微軟認知服務,然后一步步演進到中間層服務模式。建議使用VS2017 + Xamarin利器來實現(xiàn)跨平臺應用。
圖像基本分類
在任務調(diào)度層,增加一個本地的圖像分類器,如同"todo"里的preprocess,能夠把輸入圖片分類成"有人臉"、"有地標"、"有文字"等,然后再根據(jù)信心指數(shù)調(diào)用名人服務或地標服務,以減輕服務器的負擔,節(jié)省費用。比如,當"有地標"的信心指數(shù)小于0.5時,就終止后面的調(diào)用。這需要訓練一個圖片分類器,導出模型,再用Tools for AI做本地推理代碼。
原文地址:?https://www.cnblogs.com/ms-uap/p/9482470.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的搭建基于云端的中间层以支持跨平台的智能视觉服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CAP带你轻松玩转ASP.NETCore
- 下一篇: Microsoft宣布正式发布Linux