任何可以產(chǎn)生事件,觸發(fā)云函數(shù)執(zhí)行的均可以被稱為觸發(fā)器,而定時(shí)觸發(fā)器則是可以處理周期性的事情,比如時(shí)報(bào)、日?qǐng)?bào)、周報(bào)等通知提醒,也可以處理倒計(jì)時(shí)任務(wù),比如節(jié)假日、紀(jì)念日以及你可以指定一個(gè)具體時(shí)間的倒計(jì)時(shí)任務(wù),除此之外,定時(shí)觸發(fā)器還可以用來(lái)周期性處理一些定時(shí)任務(wù)。比如定期清理一些不必要的數(shù)據(jù),定期更新集合內(nèi)的數(shù)據(jù)。
配置了定時(shí)觸發(fā)器的云函數(shù),會(huì)在相應(yīng)時(shí)間點(diǎn)被自動(dòng)觸發(fā),云函數(shù)的返回結(jié)果不會(huì)返回給調(diào)用方。在對(duì)某個(gè)云函數(shù)使用定時(shí)觸發(fā)器前,首先要保證該云函數(shù)在小程序端可以調(diào)用成功,更準(zhǔn)確的說(shuō)是能夠在不傳入?yún)?shù)的情況下在云開發(fā)控制臺(tái)的云端測(cè)試能調(diào)試成功(小程序端調(diào)用有登錄態(tài))。
云函數(shù)目錄里的config.json文件可以用來(lái)配置權(quán)限和定時(shí)觸發(fā)器,如果你的云函數(shù)目錄下面沒(méi)有這個(gè)配置文件,可以自己創(chuàng)建一個(gè),創(chuàng)建的結(jié)構(gòu)目錄如下:
test //云函數(shù)目錄
├── config.json //權(quán)限和定時(shí)觸發(fā)器等的配置文件
├── index.js //云函數(shù)
├── package.json //云函數(shù)的依賴管理
然后再來(lái)在配置文件config.json里進(jìn)行類似如何格式的配置,config.json嚴(yán)格遵循配置文件所要求的格式,比如數(shù)組最后一項(xiàng)不能有逗號(hào),
;配置文件里不能有注釋等
{
"triggers": [
{
"name": "tomylove",
"type": "timer",
"config": "*/5 * 9-12 * * * *"
}
]
}
當(dāng)我們?cè)谛薷挠|發(fā)器配置文件config.json后,首先鼠標(biāo)右鍵config.json選擇“云函數(shù)增量上傳:更新文件”,然后再右鍵config.json選擇“上傳觸發(fā)器”。這里的“云函數(shù)增量上傳:更新文件”是讓云函數(shù)端的觸發(fā)器文件更新;而“上傳觸發(fā)器”則是讓觸發(fā)器開始生效執(zhí)行。如果在云函數(shù)端的觸發(fā)器沒(méi)有更新的情況下就“上傳觸發(fā)器”來(lái)執(zhí)行定時(shí)觸發(fā),文件可能沒(méi)有更新,執(zhí)行的還是舊的觸發(fā)器內(nèi)容。當(dāng)我們想暫?;騽h除觸發(fā)器時(shí),可以右鍵選擇“刪除觸發(fā)器”。
Cron表達(dá)式有七個(gè)必填字段,按空格分隔,既不能多寫也不能少寫,每一個(gè)字段都有它的含義對(duì)應(yīng)著不同的時(shí)間點(diǎn),表達(dá)式的取值都為整數(shù)且為時(shí)間制的范圍(注意月在星期的前面):
第一位 | 第二位 | 第三位 | 第四位 | 第五位 | 第六位 | 第七位 |
---|---|---|---|---|---|---|
秒(0-59 ) | 分鐘(0-59) | 小時(shí)(0-23) | 日(1-31) | 月(1-12或三個(gè)字母的英文縮寫) | 星期(0-6或三個(gè)字母的英文縮寫) | 年(1970\~2099 ) |
下面是cron表達(dá)式的案例,以及我們需要了解一下cron表達(dá)式里的通配符以及直接寫數(shù)字的含義:
,
,表示并集,在時(shí)間的表述里是“和”的意思,比如在“小時(shí)”字段中, 1,2,3
表示1點(diǎn)、2點(diǎn)和3點(diǎn);-
,指定范圍的所有值,在時(shí)間的表述里是“到”的意思,比如在“日”字段中,1-15
包含指定月份的1號(hào)到15號(hào);*
,表示所有值,在時(shí)間的表述里是“每”的意思,比如在“小時(shí)”字段中,*
表示每小時(shí);/
,指定步長(zhǎng),在時(shí)間的表述里是“隔”的意思,比如在“秒”字段中,*/5
表示每隔5秒;5
表示每月的第5日;//表示每隔5秒觸發(fā)一次,
*/5 * * * * * *
//表示在每月的1日的凌晨2點(diǎn)觸發(fā)
0 0 2 1 * * *
//表示在周一到周五每天上午10:15觸發(fā)
0 15 10 * * MON-FRI *
//表示在每天上午10點(diǎn),下午2點(diǎn),4點(diǎn)觸發(fā)
0 0 10,14,16 * * * *
//表示在每天上午9點(diǎn)到下午5點(diǎn)內(nèi)每半小時(shí)觸發(fā)
0 */30 9-17 * * * *
//表示在每個(gè)星期三中午12點(diǎn)觸發(fā)
0 0 12 * * WED *
定時(shí)觸發(fā)器的Cron語(yǔ)法沒(méi)法實(shí)現(xiàn)每隔90秒鐘或90分鐘發(fā)送一次這樣的效果,因?yàn)?0秒超過(guò)了秒的時(shí)間制上限60,而cron在跨位組合(比如90秒需要結(jié)合秒和分)上無(wú)法覆蓋所有的時(shí)間;除此之外,云開發(fā)的觸發(fā)器暫時(shí)不支持多個(gè)定時(shí)觸發(fā)器的疊加;在 Cron 表達(dá)式中的“日”和“星期”字段同時(shí)指定值時(shí),兩者為“或”的關(guān)系,即兩者的條件均生效;值得一提的是,盡管云函數(shù)的時(shí)區(qū)為UTC+0 時(shí)區(qū),但是定時(shí)觸發(fā)器的時(shí)間還是北京時(shí)間。
定時(shí)觸發(fā)器的使用非常簡(jiǎn)單,使用開發(fā)者工具新建一個(gè)云函數(shù)比如trigger,然后在index.js里輸入以下代碼:
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV,
})
exports.main = async (event, context) => {
console.log(event)
return event
}
再在trigger云函數(shù)目錄下的config.json(如果沒(méi)有這個(gè)文件,就創(chuàng)建一個(gè)),然后輸入以下觸發(fā)器,為了調(diào)試方便,我們可以每隔5秒觸發(fā)一次:
{
"permissions": {
"openapi": [
]
},
"triggers": [
{
"name": "tomylove",
"type": "timer",
"config": "*/5 * * * * * *"
}
]
}
然后分別右鍵index.js和config.json,選擇“云函數(shù)增量上傳:更新文件”,然后再來(lái)右鍵config.json選擇“上傳觸發(fā)器”。云函數(shù)就會(huì)每隔5秒自動(dòng)觸發(fā),相關(guān)的日志我們可以在開發(fā)者工具的云開發(fā)控制臺(tái)以及騰訊云云開發(fā)網(wǎng)頁(yè)控制臺(tái)的云函數(shù)的日志里查看。
注意小程序端調(diào)用trigger云函數(shù)返回的event對(duì)象,和使用定時(shí)觸發(fā)器返回的event對(duì)象的不同,用定時(shí)觸發(fā)器觸發(fā)云函數(shù)是獲取不到openId的,同時(shí)這里有一個(gè)Time時(shí)間是時(shí)區(qū)為UTC+0 的時(shí)間,比北京時(shí)間晚8個(gè)小時(shí):
//在小程序端調(diào)用trigger云函數(shù)之后返回的event對(duì)象
{
"userInfo":{
"appId":"wxda99******7046",
"openId":"oUL-m5F******buEDsn8"
}
}
//使用定時(shí)觸發(fā)器觸發(fā)云函數(shù)之后返回的event對(duì)象
{
"Message":"",
"Time":"2020-06-11T11:43:35Z",
"TriggerName":"tomylove",
"Type":"timer",
"userInfo":{
"appId":"wxda99********46"
}
}
定時(shí)觸發(fā)器的應(yīng)用非常廣泛,以下僅舉一些常用案例,并加以說(shuō)明:
這里的消息推送不僅僅只是指訂閱消息,還可以是統(tǒng)一服務(wù)消息、公眾號(hào)的消息(可以用云函數(shù)開發(fā)微信公眾號(hào))、小程序內(nèi)自己開發(fā)的通知(只是用戶只有在打開小程序時(shí)才能看到)、Email郵件等等。
比如用戶訂閱了日?qǐng)?bào)、周報(bào)、月報(bào)等周期性的通知提醒或者我們需要給用戶發(fā)送一些匯總信息,就可以固定寫一個(gè)定時(shí)觸發(fā)器,比如我們需要給指定用戶發(fā)送工作周報(bào),每周五晚上17點(diǎn)30分就定時(shí)從數(shù)據(jù)庫(kù)獲取數(shù)據(jù)發(fā)送消息,cron表達(dá)式寫法如下:
* 30 17 * * FRI *
還可以用來(lái)處理一些倒計(jì)時(shí)(指定時(shí)間點(diǎn))的任務(wù),比如節(jié)假日、紀(jì)念日以及一些活動(dòng)時(shí)間節(jié)點(diǎn)(定時(shí)觸發(fā)器目前只能一個(gè)云函數(shù)配一個(gè)觸發(fā)器,但是可以提前管理),比如我們希望在六一兒童節(jié)的早上9點(diǎn)調(diào)用云函數(shù)給指定用戶群體發(fā)送消息:
0 0 9 1 6 * *
當(dāng)然這樣的具體時(shí)間點(diǎn)顯得過(guò)于的不靈活,但是如果把時(shí)間與云開發(fā)數(shù)據(jù)庫(kù)結(jié)合起來(lái),靈活性就會(huì)大很多,比如在運(yùn)營(yíng)上每天早上11點(diǎn)是你們用戶訪問(wèn)最多的時(shí)間點(diǎn),你只需要寫一個(gè)云函數(shù),把所有的活動(dòng)都在這個(gè)時(shí)間點(diǎn)來(lái)推送,讓定時(shí)觸發(fā)器每天這個(gè)時(shí)間點(diǎn)都觸發(fā),有活動(dòng)(數(shù)據(jù)庫(kù)里有數(shù)據(jù))就會(huì)發(fā)消息,如果沒(méi)有就不發(fā)(云函數(shù)調(diào)用一次的成本極低)。
如果是實(shí)時(shí)數(shù)據(jù),我們還可以把定時(shí)觸發(fā)器的頻率調(diào)高,每5秒就觸發(fā)一次,比如我們的數(shù)據(jù)庫(kù)只要有最新的數(shù)據(jù),就會(huì)發(fā)消息給指定用戶。盡管不是完全的實(shí)時(shí),但是5秒的頻率和實(shí)時(shí)的差別也就不大了。你也可以根據(jù)情況,來(lái)調(diào)整觸發(fā)器的頻率,畢竟5秒和1分鐘的頻率給用戶的體驗(yàn)差異并沒(méi)有太大,但是成本卻是12倍的關(guān)系。
可能你還希望在指定的時(shí)間段才觸發(fā)云函數(shù),比如你只希望在工作日、或者在早上9點(diǎn)到晚上18點(diǎn)才觸發(fā),在指定的時(shí)間段才觸發(fā)既可以讓觸發(fā)更精準(zhǔn)不擾民,也可以節(jié)約成本,比如下面的觸發(fā)器就是工作日早上9點(diǎn)到12點(diǎn)和下午14點(diǎn)到18點(diǎn)這個(gè)時(shí)間段,每5秒觸發(fā)一次。
*/5 * 9-12,14-18 * MON,TUE,WED,THU,FRI *
從以上案例我們可以了解到,云函數(shù)的定時(shí)觸發(fā)可以來(lái)自于cron表達(dá)式的配置,我們可以指定時(shí)間點(diǎn)時(shí)間段和頻率來(lái)達(dá)到我們想要的效果,同時(shí)這個(gè)時(shí)間“也可以來(lái)自于數(shù)據(jù)庫(kù)的配置”(偽裝),意思是我們可以設(shè)置觸發(fā)器的時(shí)間段或頻率,如果數(shù)據(jù)庫(kù)里有數(shù)據(jù)就發(fā)送,沒(méi)有數(shù)據(jù)就不發(fā)送,這樣就可以達(dá)到觸發(fā)器在時(shí)間上的靈活性了。
有的時(shí)候我們的數(shù)據(jù)并不是來(lái)自于數(shù)據(jù)庫(kù),而是來(lái)自于第三方服務(wù),比如前面介紹過(guò)的歷史上的今天的API,天氣的API,知乎日?qǐng)?bào)的API等等,以及一些webhook,這些API和第三方服務(wù)提供的是json格式的文件,API的數(shù)據(jù)也會(huì)隨時(shí)更新,但是它們更新了卻并不會(huì)主動(dòng)通知我們,這時(shí)我們可以使用定時(shí)觸發(fā)器向這些API發(fā)起請(qǐng)求,如果數(shù)據(jù)出現(xiàn)更新,我們就可以將更新的數(shù)據(jù)存儲(chǔ)到我們的數(shù)據(jù)庫(kù)或者進(jìn)行其他處理,比如企業(yè)微信的機(jī)器人等機(jī)器人通知服務(wù)就是如此。
當(dāng)然定期獲取的數(shù)據(jù)還可以是爬蟲,比如我們可以定期抓取指定關(guān)鍵詞的新聞或者指定網(wǎng)站的動(dòng)態(tài),當(dāng)爬蟲獲取到了不同的數(shù)據(jù)的時(shí)候,就將最新的動(dòng)態(tài)以機(jī)器人消息或者其他方式進(jìn)行及時(shí)的處理。
也就是說(shuō),我們無(wú)法實(shí)時(shí)監(jiān)聽(tīng)到第三方API或者網(wǎng)站數(shù)據(jù)的變動(dòng),但是可以用定時(shí)觸發(fā)器來(lái)發(fā)起請(qǐng)求或者爬蟲抓取數(shù)據(jù),通過(guò)數(shù)據(jù)的變化來(lái)達(dá)到“實(shí)時(shí)”獲取數(shù)據(jù)的目的。
在數(shù)據(jù)庫(kù)的設(shè)計(jì)里,我們就提到有時(shí)候需要對(duì)數(shù)據(jù)庫(kù)里的數(shù)據(jù)進(jìn)行定期的備份與刪除等清理維護(hù)工作,比如超過(guò)一定時(shí)間的日志,具有很強(qiáng)時(shí)效性的活動(dòng)數(shù)據(jù),以及為了性能考慮而做的虛假刪除(數(shù)據(jù)庫(kù)性能與優(yōu)化有介紹)等,畢竟數(shù)據(jù)庫(kù)有一定的存儲(chǔ)成本而且過(guò)多無(wú)用數(shù)據(jù)也會(huì)影響數(shù)據(jù)庫(kù)的性能,我們可以寫一個(gè)云函數(shù)用定時(shí)觸發(fā)器來(lái)執(zhí)行此類任務(wù)。
我們還可以在用戶并發(fā)比較少的時(shí)間段(比如凌晨幾點(diǎn))來(lái)處理一些比較耗云函數(shù)、數(shù)據(jù)庫(kù)性能的任務(wù),比如圖片的審核與裁剪、縮略等處理,用戶評(píng)論是否包含敏感詞匯(盡管經(jīng)過(guò)安全處理,但是有時(shí)候我們還會(huì)設(shè)置特別的敏感詞),數(shù)據(jù)的匯總,云存儲(chǔ)里廢棄文件的刪除,用戶信息是否完整等等。
也就是說(shuō),結(jié)合定時(shí)觸發(fā)器,我們可以實(shí)現(xiàn)一些任務(wù)的自動(dòng)化處理。
我們知道云函數(shù)在處理一些復(fù)雜性的任務(wù)時(shí)是有一些限制的,一是執(zhí)行時(shí)間的限制,建議在設(shè)置時(shí)執(zhí)行時(shí)間一般不要超過(guò)20s,最長(zhǎng)不要超過(guò)60s;二是并發(fā)的限制,云函數(shù)最大的并發(fā)為1000;三是云函數(shù)在查詢數(shù)據(jù)庫(kù)時(shí)一次可以獲取最多1000條的數(shù)據(jù),面對(duì)這三個(gè)限制,我們應(yīng)該如何處理密集型的任務(wù)呢,比如發(fā)送100萬(wàn)封郵件,導(dǎo)出幾百萬(wàn)條數(shù)據(jù)到Excel,發(fā)送十萬(wàn)級(jí)的訂閱消息或消息等等,這個(gè)時(shí)候就可以使用到定時(shí)觸發(fā)器來(lái)處理了。
借助于定時(shí)觸發(fā)器,我們可以將需要耗時(shí)較長(zhǎng)、對(duì)并發(fā)要求較高以及數(shù)據(jù)庫(kù)請(qǐng)求等的任務(wù)進(jìn)行分批處理,比如我們要給100萬(wàn)人發(fā)郵件:云函數(shù)發(fā)起數(shù)據(jù)庫(kù)請(qǐng)求,一次只請(qǐng)求1000條未發(fā)送過(guò)郵件的用戶(用where條件查詢某個(gè)字段,比如status:false
),然后將郵件發(fā)給1000個(gè)人(可以參考前面的郵件發(fā)送),發(fā)完郵件并對(duì)這1000條數(shù)據(jù)進(jìn)行標(biāo)記(比如使用更新指令將status改為true),這樣下次查詢未發(fā)送過(guò)郵件的用戶時(shí),就不會(huì)重復(fù)發(fā)送了。通過(guò)定時(shí)觸發(fā)器,每2秒執(zhí)行一次發(fā)送任務(wù),幾十分鐘就可以處理完任務(wù)。
更多建議: