云開發(fā) 定時(shí)觸發(fā)器

2020-07-22 15:32 更新

任何可以產(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ā)器使用說(shuō)明

1、定時(shí)觸發(fā)器的配置與部署

配置了定時(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 字段是觸發(fā)器數(shù)組,但是目前云函數(shù)只支持一個(gè)觸發(fā)器,即數(shù)組只能填寫一個(gè),不可添加多個(gè);

  • name 是觸發(fā)器的名字,最大支持 60 個(gè)字符,支持 a-z, A-Z, 0-9, - 和 _,必須以字母開頭;

  • type 為觸發(fā)器類型,timer是定時(shí)觸發(fā)器

  • config 是觸發(fā)器的定時(shí)配置,里面為cron表達(dá)式(后面有介紹),cron有七個(gè)必需字段,不能多也不能少(以下為每天早上9點(diǎn)到12點(diǎn)每隔5秒觸發(fā)一次);

{
  "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ā)器”。

2、Cron表達(dá)式語(yǔ)法

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秒;

  • 直接寫數(shù)字,在時(shí)間的表述里是“”(時(shí)間點(diǎn))的意思,比如在“月”字段中,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ā)器調(diào)用云函數(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)用

定時(shí)觸發(fā)器的應(yīng)用非常廣泛,以下僅舉一些常用案例,并加以說(shuō)明:

1、結(jié)合消息推送

這里的消息推送不僅僅只是指訂閱消息,還可以是統(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í)間上的靈活性了。

2、實(shí)時(shí)獲取數(shù)據(jù)

有的時(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ù)的目的。

3、自動(dòng)化處理

在數(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)化處理。

4、密集型任務(wù)分流

我們知道云函數(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ù)。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)