在進行微信小程序開發時,常常會在微信的文檔中看到一段話前端
本接口應在服務器端調用,詳細說明參見服務端API。本接口支持雲調用。需開發者工具版本 >= 1.02.1904090(最新穩定版下載),wx-server-sdk >= 0.4.0node
這裏提到的雲調用,就是微信提供的小程序Serverless雲開發服務,包括雲函數、雲數據庫、文件存儲等一系列後端服務。在小程序中使用雲開發服務,可讓開發人員更專一於代碼和業務自己,不用關心服務器和底層的運維設施,而且它還有着比服務器端更方便的鑑權步驟,可讓開發人員更快更容易的開發小程序。ios
Serverless 架構是指大量依賴第三方服務(也叫作後端即服務,即「BaaS」)或暫存容器中運行的自定義代碼(函數即服務,即「FaaS」)的應用程序,函數是無服務器架構中抽象語言運行時的最小單位。在這種架構中,咱們並不看重運行一個函數須要多少 CPU 或 RAM 或任何其餘資源,而是更看重運行函數所需的時間,咱們也只爲這些函數的運行時間付費。
Serverless是一個從大約2016年被開發者所關注的架構,從他的發展趨勢來看,直到如今,它都還保持着上升的勢頭,這是一個很是有潛力的架構。從字面上看,Serverless架構,即無服務器架構,這並非說真的沒有沒有服務器,而是對物理服務器進行了抽象和虛擬化。Serverless架構主要有如下特色。程序員
這實際上是開發人員長久以來一直在作的事,爲了解決各類環境問題,想出了一系列的隔離方法。從虛擬機、虛擬環境到docker等容器技術,利用這些技術,將代碼和運行代碼的硬件以及操做系統隔離開,將應用操做和服務器操做隔離開。這樣作以後,就避免了出現bug時還要先排查環境問題的窘境。Serverless架構就能夠很好地隔離操做系統,甚至更深層的技術細節。在Serverless架構的應用中,開發者只須要專一於業務邏輯的實現,而徹底不須要操心底層的運維等工做。web
與隔離一樣的,虛擬化也是一個發展已久的技術。但與隔離的目的不一樣,虛擬化是雲計算的重要技術,主要用於物力資源的池化,從而能夠彈性地分配給用戶。物力資源包括服務器,網絡和存儲。虛擬化的思想能夠追溯到IBM機器的邏輯分區,即把一臺機器劃分紅若干臺邏輯的服務器,每臺邏輯服務器擁有獨佔的計算資源(CPU、內存、硬盤、網卡),能夠單獨安裝和運行操做系統。劃分爲更小的計算單元,大大減小了資源的浪費,提升了生產效率。雲計算是經過使計算分佈在大量的分佈式計算機上,而非本地計算機或遠程服務器中,企業數據中心的運行將與互聯網更類似。這使得企業可以將資源切換到須要的應用上,根據需求訪問計算機和存儲系統。對於雲計算來講,虛擬化是必不可少的。隨着雲計算的的流行和發展,虛擬化技術也日漸成熟,咱們已經能夠自動管理虛擬化的計算資源。在Serverless架構中,應用是真正的按需使用,只有請求到來的時候,應用纔開始運行計算。docker
事件驅動編程(英語:Event-driven programming)是一種電腦程序設計模型。這種模型的程序運行流程是由用戶的動做(如鼠標的按鍵,鍵盤的按鍵動做)或者是由其餘程序的消息來決定的。相對於批處理程序設計(batch programming)而言,程序運行的流程是由程序員來決定。批量的程序設計在初級程序設計教學課程上是一種方式。然而,事件驅動程序設計這種設計模型是在交互程序(Interactive program)的狀況下孕育而生的。
Serverless只有在請求到來的時候纔開始計算,這就是一種事件驅動編程。也就是說,這和咱們在編寫GUI程序,好比桌面程序和web應用時同樣,經過監聽用戶的操做,纔開始進行相應的處理。Serverless則是在用戶使用的時候,纔會開始對用戶的行爲進行響應。數據庫
Serverless包含的兩部份內容Baas和Faas,Baas嚴重或徹底依賴第三方應用程序/服務(好比雲平臺)管理服務器端邏輯和狀態,Faas也須要將服務器端的應用邏輯(微服務甚至粒度更小的服務)以事件驅動的方式運行在無狀態的臨時的容器中,而且這些容器、計算資源都是由第三方管理。所以,Serverless架構對於雲平臺或第三方服務的依賴度很是高。國外的主要平臺如AWS Lambda,國內也有阿里雲和騰訊雲等服務。因爲Serverless的運行特性,這些第三方服務商也大都是按運行時間和內存來進行收費,實際的開銷並不大,用得少甚至不要錢。npm
serverless deploy
就能完成部署或更新,在微信雲函數上只要點擊部署就能夠。因爲這些特性,Serverless主要被應用於一些實時性要求不高,且不會長期大量使用的場景。如通知分發,定時任務,一些輕量級api或者初創公司的產品上。編程
進入正題,微信雲開發。微信雲開發就是微信爲小程序提供的Serverless服務。小程序在不少時候都被用做一個導流工具,其中的通知和消息的功能就很適合用Serverless來進行處理。而且使用雲開發,會減小不少請求校驗的流程,開發人員能夠更專一於業務邏輯。微信雲開發中的Serverless主要包括瞭如下三個功能。json
同時,小程序還提供了兩個環境,區分線上和測試。開通雲開發功能後,就能夠建立環境和選擇配額。若是小程序訪問量不大,選擇基礎的配額,是不須要付費的。開啓雲開發的功能後,就能夠開始愉快的寫雲函數了。首先要建立雲函數的目錄,通常來講,存放雲函數的文件夾最好和小程序源碼平行,好比雲函數的文件夾叫functions
,小程序的文件夾叫miniprogram
,而後在project.config.json
中分別定義這兩個目錄。這樣結構更清晰,而且小程序運行時也不會加載無關代碼。
這三個功能均可以經過小程序直接調用,也能夠經過api由本身的服務器調用,不過固然這須要必定的鑑權。同時微信還提供了雲調用功能,能夠在雲函數中調用數據庫和文件存儲。接下來主要要講雲函數的功能。
在新建雲函數的時候,系統會默認建立一個package.json
文件。這也是雲函數的一個特色,每個函數都有一個package.jaon
,它們的依賴項也是相互獨立的。你能夠選擇本地安裝npm依賴,也能夠選擇去雲端安裝依賴,這取決你是否要在本地調試。
每個雲函數都有一個惟一的main函數做爲入口,傳入參數有兩個,一個是event
對象,一個是context
對象。event
指的是觸發雲函數的事件,當小程序端調用雲函數時,event
就是小程序端調用雲函數時傳入的參數。context
對象包含了此處調用的調用信息和運行狀態,能夠用它來了解服務運行的狀況。因此一個簡單的雲函數就像這樣。
// ... exports.main = async (event, context) => { // ... return { sum: event.a + event.b } }
在小程序中調用雲函數,要先將雲函數部署到雲端,這時就能夠選擇是否在雲端安裝依賴。部署完成後,經過wx.cloud.callFunction
來調用雲函數。
wx.cloud.callFunction({ // 雲函數名稱 name: 'add', // 傳給雲函數的參數 data: { a: 1, b: 2, }, success: function(res) { console.log(res.result.sum) // 3 }, fail: console.error })
或者用Promise風格的調用。
wx.cloud.callFunction({ // 雲函數名稱 name: 'add', // 傳給雲函數的參數 data: { a: 1, b: 2, }, }) .then(res => { console.log(res.result) // 3 }) .catch(console.error)
雲函數全部的調用日誌,微信也都存着,排查問題也比較方便。固然這裏也有一個問題,部署好的雲函數,就無法在服務端進行調試了,好比打斷什麼的更是不可能的。若是出現錯誤,要麼看日誌,要麼就只有不停添加console.log
而後部署,而後再觸發,很是不方便。
首先在開發者工具中配置用雲函數處理客服消息。能夠選擇處理特定的消息類型,這裏選擇了小程序卡片和進入客服會話事件,那麼就只有這兩種消息會發送給雲函數進行處理,其餘消息仍是發給客服或者服務器處理。
要調用微信客服消息接口,因此要先在package.json
中加上依賴項"wx-server-sdk":"latest"
,同時在index.js
中引入wx-server-sdk
,這是一個能夠在雲函數中操做數據庫、存儲以及調用其餘雲函數的微信提供的庫。而後咱們就能夠用微信的sdk來獲取用戶活動信息,而且調用openapi進行回覆。
// 雲函數入口文件 const cloud = require('wx-server-sdk') cloud.init() // 雲函數入口函數 exports.main = async(event, context) => { const wxContext = cloud.getWXContext() console.log(event); await cloud.openapi.customerServiceMessage.send({ touser: wxContext.OPENID, msgtype: 'text', text: { content: '收到', } }) return 'success' }
在雲函數中,也能夠發送網絡請求,藉助http
、request
或axios
等庫,就跟在node.js中發送請求同樣。這樣,咱們就能夠根據用戶消息中帶上的參數來回復特定的內容。例如,在小程序卡片的pagePath
或者是進入會話事件中的session-from
字段中,帶上須要的參數。這裏用request-promise
來作網絡請求,一樣的,先在package.json
中添加依賴項"request-promise": "^4.2.5"
。
const cloud = require('wx-server-sdk') const rp = require('request-promise'); cloud.init() exports.main = async(event, context) => { const wxContext = cloud.getWXContext() if (event.MsgType === 'miniprogrampage') { await rp({ uri: 'url', method: 'POST', body: JSON.parse(event.pagePath.split('=')[1]), json: true }).then(async res => { await cloud.openapi.customerServiceMessage.send({ touser: wxContext.OPENID, msgtype: 'link', link: { title: 'title', description: 'description', url: res.result.url, thumb_url: res.result.imageUrl } }) }) } else if (event.MsgType === 'event') { console.log(JSON.parse(event.SessionFrom)); } return 'success' }
目前沒有試過雲開發中的數據庫和存儲,只是初探了雲函數的使用。雲函數在處理一些簡單的業務邏輯上很是方便,微信也給雲函數開了一些綠色通道,好比各類校驗,可是也有一個很大的缺陷,就是調試的問題。本地調試沒什麼問題,遠程調試只能一次次加console.log而後部署而後看日誌,不知道會不會有更方便的辦法。