實(shí)時(shí)和接近實(shí)時(shí)應(yīng)用開發(fā)之間的差異是微乎其微的,但每個(gè)人都會(huì)遭遇應(yīng)用程序在構(gòu)建和運(yùn)行上的延遲。
隨著微服務(wù)的出現(xiàn),構(gòu)建云應(yīng)用的最常見方法包括拆分每個(gè)組件,使其在單獨(dú)的環(huán)境中運(yùn)行。這種方法從維護(hù),可擴(kuò)展性和開發(fā)的角度來看是理想的,但卻會(huì)降低單個(gè)事務(wù)的處理速度。
開發(fā)人員可以為那些需要快速處理的工作負(fù)載構(gòu)建延遲在100毫秒內(nèi)的實(shí)時(shí)應(yīng)用,和幾秒鐘內(nèi)的接近實(shí)時(shí)應(yīng)用程序。接近實(shí)時(shí)對(duì)于許多應(yīng)用來說已經(jīng)足夠快了,但對(duì)于金融機(jī)構(gòu)或媒體公司中運(yùn)行的應(yīng)用來說則可能太慢。在本文中,我們將探討如何對(duì)一個(gè)在AWS上運(yùn)行的博客平臺(tái)進(jìn)行實(shí)時(shí)應(yīng)用的開發(fā)。
從用戶獲取輸入
當(dāng)一個(gè)用戶創(chuàng)建一個(gè)新的帖子時(shí),會(huì)通過一個(gè)HTML表單提交,然后通知后端應(yīng)用有新的內(nèi)容要處理和顯示。該應(yīng)用程序可能還需要做一些文本分析,識(shí)別出與帖子關(guān)聯(lián)的圖片類型,然后自動(dòng)發(fā)布到社交媒體。
將應(yīng)用劃分為單獨(dú)的幾個(gè)部分以使其可網(wǎng)絡(luò)擴(kuò)展,以便數(shù)百萬用戶可以同時(shí)發(fā)帖。當(dāng)用戶點(diǎn)擊Submit時(shí),平臺(tái)立即保存內(nèi)容并通知多個(gè)服務(wù)。在實(shí)時(shí)應(yīng)用開發(fā)中,這被稱為一個(gè)event。
監(jiān)聽者或事件模式
事件驅(qū)動(dòng)應(yīng)用程序的使用正變得越來越普遍。隨著Node.js的普及,更多的開發(fā)人員正在學(xué)習(xí)event emitters的概念。在Node.js中,許多對(duì)象在完成任務(wù)后會(huì)立即通知一部分代碼。這些代碼塊就是所謂的listeners;開發(fā)人員使用監(jiān)聽器的這種模式與使用Amazon Simple Queue Service(SQS),Amazon Simple Notification Service(SNS)或Amazon Kinesis的應(yīng)用程序非常相似。
event.on('ready', postToTwitter);
event.on('ready', postToFacebook);
event.on('ready', postToSnapchat);
event.on('ready', addImage); event.trigger('ready', articleData);
Batch processing with Amazon SQS
使用亞馬遜SQS進(jìn)行批處理
大多數(shù)開發(fā)人員都是用異步的方式來處理事件,這有助于應(yīng)用的可擴(kuò)展,但卻制造了額外的管理上的挑戰(zhàn)。在該博客平臺(tái)上,如果設(shè)置了異步過程來閱讀和發(fā)布故事,整個(gè)過程需要幾乎立即發(fā)生。撰寫和提交帖子的博主不想等著看到自己的帖子發(fā)布。在瀏覽器重新加載時(shí),有一定的延遲空間,但是許多用戶不能容忍任何超過500毫秒(ms)響應(yīng)的操作。
IT團(tuán)隊(duì)可能會(huì)遇到實(shí)時(shí)應(yīng)用開發(fā)延遲。例如,如果一個(gè)事件傳遞到SQS,在讀取之前會(huì)有一個(gè)自動(dòng)延遲——從100毫秒到幾秒鐘。SQS專為批處理而設(shè)計(jì),這有助于異步操作的處理,但卻難以處理實(shí)時(shí)事件。更糟糕的是,如果后端系統(tǒng)沒有跟上SQS請(qǐng)求,則可能在處理消息前可能有一個(gè)延遲的延遲。
使用Amazon SNS來觸發(fā)多操作
與Amazon Kinesis類似,Amazon SNS專為近實(shí)時(shí)事件處理而設(shè)計(jì)。它將輸入與各個(gè)處理節(jié)點(diǎn)分離。但是,與Kinesis不同,SNS被設(shè)計(jì)為基于一個(gè)事件觸發(fā)多個(gè)操作。在該博客平臺(tái),一個(gè)開發(fā)人員可以擁有一個(gè)SNS Topic,即Post Created。多個(gè)AWS Lambda函數(shù)可以訂閱該主題,一個(gè)發(fā)布到Twitter,一個(gè)發(fā)送到Facebook,另一個(gè)處理文檔以自動(dòng)識(shí)別與其關(guān)聯(lián)的正確圖片。解耦發(fā)生在SNS內(nèi),因此當(dāng)應(yīng)用程序還需要發(fā)布到Snapchat時(shí),在發(fā)布方面不需要更改任何代碼。另一個(gè)監(jiān)聽器會(huì)附加到該SNS主題,以便在發(fā)生事件時(shí)通知Snapchat微服務(wù)。
SNS不構(gòu)建一個(gè)隊(duì)列,它并行執(zhí)行所有的事件。因此,Twitter,F(xiàn)acebook,Snapchat和圖像微服務(wù)都會(huì)同時(shí)接收通知。例如,SNS無需等待Twitter發(fā)布后再發(fā)到Facebook。
SNS還允許開發(fā)人員配置應(yīng)用端點(diǎn),以立即和定期重試,直到事件處理成功——或達(dá)到指定的嘗試次數(shù)。但是SNS的初始延遲可能會(huì)超過幾秒鐘,因此它不是完全實(shí)時(shí)的。
隊(duì)列vs.管道
Amazon SQS和Amazon Simple Workflow Service都提供隊(duì)列來解耦請(qǐng)求和處理服務(wù)。這個(gè)模式構(gòu)建起來簡(jiǎn)單,并且非常的可擴(kuò)展。不幸的是,這也是一種最延遲管道的方式。隊(duì)列不是為提高速度而建;它們被構(gòu)建為用于擴(kuò)展——增加了至少100ms的延遲 - 即使這些隊(duì)列是空的,并且它們擴(kuò)展的速度也不快。隊(duì)列具有等待資源變得可用的事件的積壓。如果應(yīng)用不需要實(shí)時(shí)運(yùn)行,尤其是與競(jìng)價(jià)型實(shí)例相結(jié)合時(shí),這可能非常有用。
但對(duì)于實(shí)時(shí)應(yīng)用開發(fā),像Amazon Kinesis這樣的管道更合適。與隊(duì)列不同,管道設(shè)計(jì)用于實(shí)時(shí)流處理。不是將項(xiàng)目添加到一個(gè)列表中,而是以流的形式發(fā)送。雖然項(xiàng)目仍可在流中積壓,但只有在出現(xiàn)問題時(shí)才會(huì)發(fā)生。隊(duì)列和管道都支持容錯(cuò)和重試,但管道立即運(yùn)行。
與SQS不同,消息的延遲可以達(dá)到幾百毫秒,Kinesis延遲只有幾十毫秒。使用Kinesis這樣的管道服務(wù)的最重要的原因是它直接與AWS Lambda集成。這不只是一個(gè)更快的隊(duì)列服務(wù),它還是一個(gè)不同的設(shè)計(jì)模式。
使用Amazon Kinesis進(jìn)行實(shí)時(shí)處理
Amazon Kinesis為實(shí)時(shí)處理提供了更好的選擇。雖然Kinesis類似于SQS,它不直接排隊(duì),更像一個(gè)管道,允許開發(fā)人員將請(qǐng)求定向到一個(gè)或多個(gè)處理服務(wù)。雖然這些管道可以有積壓,但啟動(dòng)延遲通常明顯小于隊(duì)列服務(wù),并且事件可以在10ms內(nèi)接收并準(zhǔn)備就緒。
此外,Kinesis直接與Lambda連接,這允許服務(wù)實(shí)時(shí)動(dòng)態(tài)擴(kuò)展。當(dāng)Auto Scaling組識(shí)別到一個(gè)SQS的待辦事項(xiàng)時(shí),最多可能需要一個(gè)小時(shí)才能等到其他可用的資源,以減少延遲。使用Kinesis和Lambda,管道只是對(duì)每一個(gè)輸入到管道的事件觸發(fā)一個(gè)Lambda函數(shù);不需要對(duì)資源進(jìn)行配置,這意味著不會(huì)把時(shí)間浪費(fèi)在啟動(dòng)額外的彈性計(jì)算云實(shí)例。
其他事件也可以觸發(fā)Kinesis流,例如Amazon DynamoDB寫操作。在博客這個(gè)示例中,當(dāng)最終用戶添加一個(gè)新帖子時(shí),會(huì)直接添加到DynamoDB中,之后通過Kinesis Stream觸發(fā)一個(gè)Lambda函數(shù)。
將各種服務(wù)功能連接起來
事件和工作程序之間的連接可以造成10毫秒或10分鐘的延遲之差。對(duì)于計(jì)算密集型任務(wù),SQS允許應(yīng)用處理更長時(shí)間,正確處理超時(shí)事件并構(gòu)建可能具有長啟動(dòng)時(shí)間的自定義工作程序。這些任務(wù)需要一段時(shí)間來處理,因此來自SQS的額外的一兩秒延遲是可以容忍的。這些任務(wù)也可能運(yùn)行起來很昂貴,因此如果這些類型的事件的延遲可以接受,開發(fā)人員應(yīng)該考慮為工作進(jìn)程選擇競(jìng)價(jià)型實(shí)例。
開發(fā)人員可以將SNS與SQS結(jié)合使用,用于需要處理多個(gè)事件的進(jìn)程。 SNS可以發(fā)送其他不需要實(shí)時(shí)發(fā)生的通知(電子郵件或短信)。請(qǐng)記住,運(yùn)營商或電子郵件提供商的延遲總是會(huì)比SNS強(qiáng)加的延遲更長。
對(duì)于博客,開發(fā)人員將使用Amazon Kinesis來實(shí)時(shí)傳送到博客平臺(tái)。對(duì)于Twitter,F(xiàn)acebook和Snapchat消息,SNS將交付給Lambda函數(shù)。對(duì)于可能需要大量計(jì)算的圖像處理系統(tǒng),開發(fā)人員可以添加另一個(gè)SNS監(jiān)聽器,但將其傳遞給SQS隊(duì)列,以使用定制的長時(shí)間運(yùn)行的進(jìn)程來處理圖像處理相關(guān)的計(jì)算密集型工作負(fù)載。如果其他客戶端需要通過自定義的渠道接受通知,請(qǐng)?jiān)O(shè)置額外的Kinesis流,以便這些可以實(shí)時(shí)發(fā)生,或添加監(jiān)聽器到用于電子郵件,短信或其他近實(shí)時(shí)通知的SNS主題。
在所有情況下,傳輸介質(zhì)都必須是實(shí)時(shí)處理或接近實(shí)時(shí)處理。這只取決于IT團(tuán)隊(duì)需要多快來傳輸信息。