**本文來自騰訊雲技術沙龍,本次沙龍主題為Serverless架構開發與SCF部署實踐 **
演講嘉賓:黃文俊,曾負責企業級存儲、企業級容器平台等產品的架構與開發,目前主要負責SCF騰訊無服務器雲函數產品相關。對容器平台、微服務架構、無服務器架構以及DevOps等多種熱門技術領域均有涉獵。
大家好,自我介紹一下,目前我是騰訊雲無服務器雲函數產品負責人。我做了很多年后端開發。今天是從一個程序員角度講解一下我們怎么樣用Serverless架構。
我將本次講解分為幾塊:第一,Serverless架構介紹;第二,對雲函數產品介紹;第三,Serverless使用場景。
講Serverless架構之前我們可以來看一下整個雲的發展過程,在沒有雲之前大家可能都是用的物理服務器,早期時候大家都用的物理機托管方式,采購一些服務器在機房里托管,這個時候大家前期要選擇物理機型號,要做好IDC網絡;如果出了問題還要請IDC人員幫你操作。這些設備的投入和運維成本還是很高的。
雲時代到來之后,由於虛擬化技術的運用,我們用上了雲主機。雲主機是大家直接在雲上做虛擬機購買,開通就可以使用。這時候我們稱之為IaaS(基礎設施即服務),這種情況下就無需物理機運營,直接放到雲平台來做。而之后隨着容器技術的發展,我們有了容器平台,或者叫PaaS(平台即服務)。在容器平台到來之后實際上還存在一部分基礎設施運維問題,但是這時候基礎設施逐漸下沉到運維人員進行操作;而從應用開發者角度來看,他們已經不用再去關心虛擬機,或者操作系統。在這種情況下,應用開發人員更多的去關注應用所需要的計算資源或者存儲資源的使用。繼續向前發展,我們到了FaaS(函數即服務)。這時候運維人員不需要關注底層的運維,而是按需運行的能力。業務開發人員能夠進一步做與業務相關的事情。
接下來我們來看一下Serverless架構是什么。Serverless從物理機或虛擬機的使用上進行了分離,更關注上層業務的運行情況。Serverless架構包含兩塊:函數即服務和后端即服務。函數即服務提供的是計算能力。原有的計算能力,無論是容器也好,虛擬機也好都承載在一定的操作系統之上,函數即服務把計算能力進行了進一步抽象,我們在后文再繼續進行展開。另外,Serverless還有后端即服務,比如對象存儲,數據庫應用,緩存服務,我們也可以稱之為Serverless,因為這些服務也能夠在雲上提供開通即服務,開通即使用的能力。在使用這些產品時同樣不需要關注它的服務器是什么樣的,它的服務器部署在哪里,而是服務開通就可以使用了,后面的運維工作都交給了雲,所以不用感知它的最底層服務器,因此我們也可以把它稱之為Serverless。這種服務就稱之為Serverless后端即服務。這兩個合起來可以稱為Serverless架構。
函數即服務的工作原理是什么樣的?在Serverless上是怎樣提供計算能力的?大家原來使用容器或者虛擬機的時候都可以知道,我們把代碼上傳到容器或者上傳到虛擬機,然后啟動一個進程,代碼就可以運行,它就可以接受外部的請求,做一些實時的響應。Serverless和原有的容器或虛擬機不同,實現的是計算托管服務,Serverless用戶首先要做的,是把我們稱為雲函數的代碼,提交到平台上進行代碼托管;然后要做的是配置觸發器。為什么需要配置觸發器?因為雲函數的運行方式是觸發式運行,有觸發的時候,代碼才會真正運行起來。所以配置觸發器意味着我們給它設置了一個觸發源,也就是定義了在什么事件下代碼才真正運行起來。用戶代碼托管到平台之后,事件沒有到來之前,它僅僅是代碼文件和配置存儲,代碼並沒有運行。什么情況下運行?是當事件觸發真正到來的時候,雲函數才會真正啟動一個實例,這個實例就意味着一個計算單元。計算單元被拉起后,這個事件就被傳到這個計算單元中進行計算處理。如果這個觸發源的事件很多,並發很高的情況下,平台會根據事件的堆積情況,或者事件到達的速度,自動把同一份代碼和配置拉起多個實例進行並發處理。因此可以看到Serverless的運行是按需運行,意味着只有在事件到來的情況下,代碼才會被拉起,才會運行起來。
自動並發,是指雲函數平台會根據事件堆積情況自動的進行並發,自動拉起多個實例進行處理。而原有的容器或者虛擬機如果要進行並發的話還是要有一定的手工參與,比如啟動更多的容器,或者加入更多的虛擬機來承載高並發的請求。而函數即服務是完全自動的運行。
按需運行帶來的另外一個特點,是代碼在運行起來之后上才會占用計算資源。函數即服務的費用也是根據按需運行來的,也就是函數運行的時候才進行計費;而沒有使用的情況下不會計費。實際上大多數互聯網業務只有白天的時候,甚至六點之后大家下班之后業務才會迎來高峰,而到凌晨之后實際上沒有多少請求的,因此函數即服務能夠很好的滿足波峰波谷來削峰填谷的能力。
從上面的原理可以看出函數即服務的一些特點,比如說代碼托管,雲函數平台所提供的直接就是運行環境,也就是支持各種開發語言的環境;對於開發者或者函數服務使用者來說,並沒有感知到它下面的服務器在哪里,而是由函數平台完成了函數運行的調度。因此實際來講不需要運維,包括操作系統優化,服務器維護等等這些都是由平台進行承載。
而秒級部署意味着函數在真正的被請求的時候才運行。而這個請求才運行代表着當請求到達平台的時候函數才會被實時拉起並運行。運行完成后如果沒有后續請求,實例也會退還。
由於函數運行是事件觸發的,而事件其實包含很多種類,有各種觸發器都可以對接雲函數。有越多的觸發器對接,雲函數所能提供的場景也就越多。
對於開發者來說,使用雲函數的情況下,他真正關注的是應該業務,是使用代碼去聚焦他的業務邏輯,例如是拿到這個事件后該進行什么樣的邏輯操作,進行什么樣的業務存儲,而不需要去關注怎么使用業務代碼實現高並發,怎么樣實現高請求的承載能力。因此這里看到函數即服務能夠為應用開發者帶來一些便利,而自動並發本身也是函數即服務所具有的特點。
而對於騰訊雲無服務器雲函數,在最開始開發產品的時候,我們目標也是一樣,就是把計算進行托管。在計算托管的情況下,我們使用計算就像我們使用騰訊雲對象存儲一樣,在使用的時候不用關心最底層的運維,不用關心虛擬機或者物理機是否安全。和對象存儲進行對比也能看到,我們計算也是按照實際使用情況進行計費。當然現在雲函數還處於免費期,大家可以隨時使用。
從使用方法來說,雲函數本身,或者說函數即服務這種產品本身的使用方法都是很簡單的。我們在開發的時候更多的關注於核心代碼的編寫。核心代碼的意思實際上就是真正的業務邏輯。而且業務邏輯里不需要考慮高並發,因為由剛才給出來的函數即服務這種計算特點來看的話,在高並發請求的時候是通過多個實例處理進行,因此業務代碼在編寫的時候,就關注單個事件的處理就行。因此,第一步的核心的就是編寫核心業務代碼,就是用代碼要實現什么樣的業務。后續就是配置觸發方式。配置觸發方式就是把函數代碼和觸發源對接起來。和雲平台上其他的產品進行對接,需要什么樣的事件,處理什么樣的事件,進行什么樣的邏輯處理,做好這樣的觸發源對接后,函數就能夠在事件產生的情況下運行。
因此,從整個使用方法來看的話,大家真正要做的是兩步:第一,編寫代碼,第二,配置好觸發。而對於底層的基礎設施,環境配置這塊都不需要大家操心的。
目前,騰訊雲函數從運行環境來說目前已經支持了Python、Nodejs、PHP、Golang、Java等語言的開發運行環境。
接下來是觸發器,因為觸發器越多,雲函數所能去使用的場景其實也越多,我們已經實現的觸發器有定時觸發器;騰訊雲對象存儲服務,包括文件的上傳、刪除等時間;CMQ 消息隊列服務;API 網關服務,這個是通過serverless 架構實現 API 服務的一款重要觸發器;另外,還有ckafka,這個是騰訊雲提供的kafka能力。目前kafka算是一個開源產品,我們騰訊雲把它包裝后放到雲上來,也是兼容標准的kafka協議。因此在很多情況下直接遷移到騰訊雲不需要任何修改。因為kafka本身作為消息傳遞的載體,跟騰訊原有的消息隊列類似,由消息來執行雲函數。
下面介紹一下在什么場景下Serverless可以落地?第一,在Serverless場景中最常用到的就是API服務。大家知道實現一個API服務,無論是把API給到瀏覽器應用,還是給到手機APP使用,還是給到小程序應用,給到它們的時候是以API實現的。要實現這個要有WEB服務器接收連接,對接后端的業務代碼,如果你要再進行文件存儲,后端的結構化存儲,或者有一些緩存需要讀寫,你的應用服務器后面可能還要對接相應的文件存儲,結構化數據庫,后續如果想使用緩存,再對接到相應的服務器或相應產品。如果把現有的API服務向Serverless架構演進,那么它將怎么樣呈現呢?
在不改變 API 的情況下,它的前端瀏覽器應用、APP、小程序,都可以無縫對接上來。而使用API網關來承接 API 請求,當這個請求來到API網關,由它轉發給雲函數,觸發雲函數執行。雲函數執行時運行業務邏輯。實際上雲函數運行時要求無狀態,因此這樣的狀態存儲也需要用到后面的一些存儲,無論做緩存也好還是數據庫也好都要用上。因此,雲上提供的產品一樣可以進行對接。像文件存儲的話可以用對象存儲來進行。數據庫的話一樣的有相應的數據庫產品,結構化還是非結構化數據庫都有相應的產品可以使用。同樣的,緩存也有相應的產品做對接。雲函數通過代碼編寫,直接進行數據庫的讀寫,或者緩存的讀寫都是可以的。
從整個服務架構來看的話,我們使用最前面的API網關,提供是API能力,甚至進一步能夠直提供有SDK服務,更加的方便開發。SDK提供了各種開發語言來直接進行API調用。雲函數在中間起到的是業務邏輯處理的作用,而狀態數據或者其他業務數據的存儲是依賴於后面的文件存儲或者數據庫進行的。API服務也是Serverless最常用的一種落地形式。
這里介紹的場景,都是我們客戶在實際使用的場景。在 serverless落地場景中,對對象文件的處理也很常見。對象文件處理指的是對對象文件進行操作后的回調處理。回調通常是在對象文件創建或刪除操作后產生的事件。雲函數可以在獲取到這個事件后進行后續的處理。這里常見的處理邏輯是下面幾種,比如說圖片處理,針對圖片去生成各種尺寸的縮略圖或者進行裁剪,然后再次存儲到對象存儲數據中,之后可以根據不同客戶端的請求展示不同大小的圖片到前端。
文件批量打包,用戶需要進行文件篩選和打包的時候可以通過使用雲函數來處理。在上傳文件后,如果需要選擇哪些文件來打包,把文件生成壓縮包以供下載,這都可以由事件處理來進行。
日志歸檔分析,以及業務系統回調,也是雲函數所承載的業務邏輯。比如說日志歸檔分析這種用法,用戶會把每天的前端應用服務器的日志上傳到對象存儲中歸檔,歸檔后會觸發雲函數執行,雲函數會拉下這些日志文件進行實時分析,它會抽取這些日志中的錯誤數,或者是其他業務相關或者用戶關注的內容,然后再把它抽取到的信息或者統計到的信息寫回數據庫,供用戶后續進行排查、使用。用戶自身API調用也是,例如用戶生成的一些視頻文件上傳到對象存儲,會觸發雲函數,將上傳文件的信息通知到用戶的轉碼系統,通過視頻轉碼轉成不同分辨率然后再進行存儲。當然轉碼是用戶自身實現的業務系統,這塊通過回調通知,通知它自身的業務系統。這些就是雲函數在Serverless架構和對象存儲連用的落地場景。
再就是CKafka消息處理。CKafka目前比較多的應用場景是做日志存儲和日志搜集,例如有多台應用服務器在不斷產生日志的情況下,可以把日志寫到CKafka,然后CKafka再進行歸檔和后續分析。而 CKafka和雲函數對接是由CKafka收到的信息來進行觸發的。日志搜集后,要歸檔的日志,一般存儲到對象存儲當中。這種情況CKafka消息,會被推送給雲函數,雲函數再再把這些消息寫到對象存儲中去。有些用戶不是寫對象存儲,而是寫數據庫,以數據庫形式歸檔,其實也是一樣的。有的使用場景,需要進行消息分析,會實時拿到消息后立刻分析里面的關鍵字,如果捕捉到了關鍵字,會立刻把這些消息推送到ckafka 的另一個topic 中,去及時的發出告警給到業務和運維人員。這也是 serverless 的一種用法,就是對消息的分析和轉發。
消息隊列和CKafka類似,但是消息隊列一般不是進行日志的搜集,而是進行業務解耦。消息隊列 CMQ 是騰訊雲提供的一個高可靠金融級消息隊列,通常進行一些業務級消息轉發和處理。使用這個產品,實際上做的是業務解耦。雲函數在這里承載着消息的邏輯處理過程,它能夠在接收到消息后對消息立刻進行業務處理。這個業務處理就是實際的業務邏輯,比如我要根據里面某個消息進行判斷,判斷它是否合適,要不要進行后續的轉發,或者轉發到另外的業務系統中去?這就是業務之間執行的邏輯。
同時,我們也可以使用雲函數,再次進行消息的分派,做狀態轉移。這個狀態轉移和后面消息轉發都是一樣的,它會識別消息里的內容,根據消息里的內容進行轉發。這種情況下類似於我們使用雲函數進行邏輯處理,把它轉移到合適的消息隊列,然后再進行處理。這也是我們所見過直接用雲函數進行消息派發的使用方式。
最后一種形式現在也不少,就是利用定時器觸發。原本大家更多是在運維場景下使用定時任務,在原有使用 crontab 腳本的情況下,大家通常還要關心腳本運行是否成功,這台虛擬機是否還在工作。雲函數拋棄了大家使用傳統的虛擬機或者物理機來去寫crontab腳本還要確保可靠性的問題。而在實際使用定時器觸發的場景下,這里也有幾種用法:一種是業務撥測。這個是周期性的去撥測業務是否還在工作,如果出現異常的情況下能夠及時的發出告警,發出郵件或者短信告訴到運維或開發人員。
另一個是定時備份,這個是在所需要的周期內,比如每天,或者每兩天對數據庫進行備份,針對數據庫需要做數據導出,導出后再將導出內容以文件的形式存儲到合適的地方,例如對象存儲中,做好定時備份。
還有一個是定時數據計算。因為有些計算是根據一段時間內的統計之后,進行計算並展示。在實際場景中,我們騰訊雲內部有業務就是在進行定時數據計算,每兩小時做一次統計,然后再把統計數據寫到數據庫做后續業務的展示以及業務分析。
總結:Serverless架構本身給用戶帶來什么?它實際上就是允許我們更關注業務代碼,因此可以更快速的構建業務然后上線。現在互聯網開發速度越來越快,因此大家期望的是進一步加快開發和業務真正上線的速度,提高迭代的能力。因此,使用Serverless的話可以更快速讓業務上線,讓我們更快實現我們的想法。而按需使用是我們這個業務在上線之后,在真正產生請求后,業務才會被調動觸發,才會有計算。而如果你的業務產生了爆發式增長,其實也不需要擔心平台承載能力或者業務擴展是否跟得上,因為平台提供自動擴展能力,降低了大家對運維的訴求,大家不用關心很底層的東西,而運維人員也可以更偏重流程化和業務相關的運維。這就是Serverless架構給大家帶來的一些好處。而作為Serverless里的核心,函數即服務這種產品,是Serverless中所呈現出來的計算型的組件,大家也可以看到它和觸發源和后端的各種產品或服務有緊密關聯,它可以更多的被看做是雲時代的腳本,類似於黏合劑,把前面的觸發源和后端的各種存儲,數據,服務進行了黏合,真正實現架構落地,才是真正實現業務邏輯落地的能力。
Q&A
Q:雲函數有無限擴展能力,但是整個系統也有可能是有限制的,比如它的背后的數據庫和存儲,我能不能設這樣的一個擴展上限?
A:這可以設置上限的。目前可以通過提交工單的方式來設置期望的合適上限。擴展可以在后台設置一個合適值,並發實例擴展到這個就不會再擴展了,避免大量實例連接造成后端的數據庫或存儲超過連接數限制。
Q:實現 API 服務有哪些開發方式?
A:雲函數實現 API 服務的開發方式有好幾種,一個是全部在一個函數里完成,路徑和方法解析都在函數里進行。這也是偏傳統的開發方式。另外一種是進行拆解,每個函數處理一個 API 路徑和方法的請求,這種是微服務的開發方式。
而函數和函數之間調用也是可以實現。一種是直接使用雲API,一種是使用 API網關包裝后的 API。雲函數被觸發調用的話,除了介紹的很多觸發器,在不使用這些觸發器的情況下,通過代碼或者腳本也可以通過騰訊雲的雲API調用。
Q:在事件觸發的時候,就是CMQ事件觸發的時候,是否可以保證函數被執行呢?因為不像API網關,調用一下函數可以啟動,前端可以感知到。但是CMQ,就是扔到消息隊列能否保證這個函數被執行呢?
A:因為不像API網關是同步調用。同步調用就是這個調用在運行過程中如果出了問題,無論是平台,比如說資源不足,並發不夠,或者比如使用的超時了,這個時候可以立刻感知到。 而像CMQ或者CKafka都是異步的,這樣意味着調用后你感知不到,這個消息什么時候執行,執行結果都沒法感知。這種解決方法有兩種:一種是函數運行后的結果輸出,把消息處理后的輸出結果再放到另一個消息隊列中去,讓你外部的業務系統能夠感知到。當然這種對外通知也是異步通知。同步通知是另外一種,就是函數里可以對自身業務進行回調API,可以通過代碼知道現在的數據處理是什么樣的結果,處理完后可以立刻回調到API讓業務系統接收到處理結果。
Q:像COS觸發,拿視頻轉碼來說,這個有可能在300秒內處理不完。現在函數設置時間只能最高300秒,這個有什么解決方案嗎?
A:為什么各家的雲平台,都把這個時間大致定在這個范圍內,就是不希望在雲函數中進行太重的計算。視頻轉碼就屬於太重的計算,而雲函數提供的包括CPU能力,內存大小都有限,實際上都不太適合在雲函數內進行轉碼。實際上可以用一些視頻服務來實現轉碼,使用雲函數來做這兩者之間的橋梁,例如對象存儲的事件觸發后,雲函數拿到這個事件通過調用視頻轉碼服務來轉碼,而不是在雲函數轉碼。目前騰訊雲有這個服務,你可以試試看。
獲取更多詳細資料,請戳以下鏈接:
問答
serverless:如何刪除一個函數?
相關閱讀
讓業務感知不到服務器的存在——基於彈性計算的無服務器化實踐
使用 SCF 無服務器雲函數定時備份數據庫
雲學院 · 課程推薦 | 騰訊專項技術測試組長,結合8年經驗為你細說冷熱分離法則
**此文已由作者授權騰訊雲+社區發布,原文請點擊 **
搜索關注公眾號「雲加社區」,第一時間獲取技術干貨,關注后回復1024 送你一份技術課程大禮包!
海量技術實踐經驗,盡在雲加社區!