摘要:最近嘗試將應(yīng)用的頁(yè)面錯(cuò)誤報(bào)警功能通過(guò)來(lái)實(shí)現(xiàn)。可以根據(jù)實(shí)際情況修改函數(shù)服務(wù)名和函數(shù)名。實(shí)現(xiàn)報(bào)警功能的主要邏輯,就寫在里面。阿里云的函數(shù)計(jì)算可以使用阿里云日志服務(wù)來(lái)存儲(chǔ)日志。
最近嘗試將應(yīng)用的頁(yè)面 JS 錯(cuò)誤報(bào)警功能通過(guò) Serverless 來(lái)實(shí)現(xiàn)。本文主要介紹一下具體實(shí)現(xiàn)過(guò)程,以及遇到的一些問(wèn)題。
報(bào)警功能的需求也很簡(jiǎn)單,就是定時(shí)(如每隔 1 分鐘)去讀取 ARMS 的錯(cuò)誤日志,如果有錯(cuò)誤日志,則通過(guò)釘釘消息發(fā)送錯(cuò)誤詳情進(jìn)行報(bào)警。
在這之前,我通過(guò)定時(shí)任務(wù)實(shí)現(xiàn)了該功能。從成本上來(lái)說(shuō),這種方案就需要多帶帶申請(qǐng)一臺(tái)服務(wù)器資源;而且定時(shí)任務(wù)只在對(duì)應(yīng)的時(shí)間才執(zhí)行,這件意味著,服務(wù)器有很長(zhǎng)的時(shí)間都是空閑的,這就造成了資源的浪費(fèi)。而使用 Serverless,就不需要再申請(qǐng)服務(wù)器,函數(shù)只需要在需要的時(shí)候執(zhí)行,這就大大節(jié)省了成本。
總的來(lái)說(shuō),我覺(jué)得函數(shù)計(jì)算的優(yōu)勢(shì)就是:
對(duì)于開發(fā)者,只需要關(guān)系業(yè)務(wù)邏輯的實(shí)現(xiàn),不需要關(guān)心代碼所運(yùn)行的環(huán)境、硬件資源、以及運(yùn)維
節(jié)省成本
通過(guò) Serverless 實(shí)現(xiàn)前端日志報(bào)警,依賴的云服務(wù)是阿里云函數(shù)計(jì)算,依賴的其他工具還有:
函數(shù)計(jì)算的命令行工具 fun,用于本地調(diào)試、部署函數(shù)
函數(shù)計(jì)算的可交互式工具 fcli,用于本地測(cè)試
阿里云 JS SDK aliyun-sdk-js,用于讀取 SLS 日志,ARMS 的日志是存儲(chǔ)在 SLS 中的
編程語(yǔ)言使用 Node.js
安裝和配置 fun初次使用需要先安裝 fun
$ npm install @alicloud/fun -g
安裝完成之后,需要通過(guò) fun config 配置一下賬號(hào)信息 Aliyun Account ID Aliyun Access Key ID Aliyun Secret Access Key 以及默認(rèn)的地域。地域這里有個(gè)需要注意的是,如果需要使用 SLS 記錄函數(shù)日志,則需要 SLS 和函數(shù)服務(wù)在同一個(gè)地域。這里稍后會(huì)詳細(xì)介紹。
$ fun config ? Aliyun Account ID ****** ? Aliyun Access Key ID ****** ? Aliyun Secret Access Key ****** ? Default region name cn-shanghai ? The timeout in seconds for each SDK client invoking 60 ? The maximum number of retries for each SDK client 6
Aliyun Account ID Aliyun Access Key ID Aliyun Secret Access Key 可以在阿里云的控制臺(tái)中查找和設(shè)置。
Aliyun Account ID
![Aliyun Account ID]
Aliyun Access Key ID Aliyun Secret Access Key
函數(shù)初始化先通過(guò) fun 創(chuàng)建一個(gè) Node.js 的 demo,之后可以在這個(gè) demo 的基礎(chǔ)上進(jìn)行開發(fā)。
$ fun init -n alarm helloworld-nodejs8 Start rendering template... + /Users/jh/inbox/func/code/alarm + /Users/jh/inbox/func/code/alarm/index.js + /Users/jh/inbox/func/code/alarm/template.yml finish rendering template.
執(zhí)行成功后,分別創(chuàng)建了兩個(gè)文件 index.js 和 template.yml。
其中 template.yml 是函數(shù)的規(guī)范文檔,在里面定義了函數(shù)需要的資源、觸發(fā)函數(shù)的事件等等。
template.yml接下來(lái)簡(jiǎn)單看看生成的默認(rèn)的 template.yml 配置文件。
ROSTemplateFormatVersion: "2015-09-01" Transform: "Aliyun::Serverless-2018-04-03" Resources: alarm: Type: "Aliyun::Serverless::Service" Properties: Description: "helloworld" alarm: Type: "Aliyun::Serverless::Function" Properties: Handler: index.handler Runtime: nodejs8 CodeUri: "index.js"
首先定義了規(guī)范文檔的版本 ROSTemplateFormatVersion 和 Transform,這兩個(gè)都不用修改。
Resources 里面定義了一個(gè)名為 alarm 的函數(shù)服務(wù)(Type: Aliyun::Serverless::Service 表示該屬性為函數(shù)服務(wù)),并且該服務(wù)里面定義了名為 alarm 的函數(shù)(Type: "Aliyun::Serverless::Function"表示該屬性為函數(shù))。
函數(shù)服務(wù)里面可以包含多個(gè)函數(shù),就相當(dāng)于是一個(gè)函數(shù)組。后面我們會(huì)提到的函數(shù)日志,是配置到函數(shù)服務(wù)上的。函數(shù)服務(wù)里面的所有函數(shù),都用同一個(gè)日志。
可以根據(jù)實(shí)際情況修改函數(shù)服務(wù)名和函數(shù)名。下面就將函數(shù)服務(wù)名稱改為 yunzhi,函數(shù)名依舊保留為 alarm。
ROSTemplateFormatVersion: "2015-09-01" Transform: "Aliyun::Serverless-2018-04-03" Resources: yunzhi: # 函數(shù)服務(wù)的名稱 Type: "Aliyun::Serverless::Service" # 表示 yunzhi 是一個(gè)函數(shù)服務(wù) Properties: Description: "helloworld" # 函數(shù)服務(wù)的描述 alarm: # 函數(shù)的名稱 Type: "Aliyun::Serverless::Function" # 表示 alarm 是一個(gè)函數(shù) Properties: Handler: index.handler # 函數(shù)的調(diào)用入口 Runtime: nodejs8 # 函數(shù)的運(yùn)行環(huán)境 CodeUri: "index.js" # 代碼的目錄
alarm 函數(shù)里面的 Properties 定義了函數(shù)的調(diào)用入口、運(yùn)行環(huán)境等,如上面的注釋所示。
關(guān)于 template.yml 的配置詳見 Serverless Application Model。
index.jsindex.js 文件就是函數(shù)的調(diào)用入口了。index.handler 就表示,函數(shù)的調(diào)用的是 index.[extension] 文件中的 handler 函數(shù)。
module.exports.handler = function(event, context, callback) { console.log("hello world"); callback(null, "hello world"); };
初始化之后的代碼就上面這幾行,很簡(jiǎn)單。主要是理解上面的幾個(gè)參數(shù)。
event 調(diào)用函數(shù)時(shí)傳入的參數(shù)
context 函數(shù)運(yùn)行時(shí)的一些信息
callback 函數(shù)執(zhí)行之后的回調(diào)
必須要要調(diào)用 callback 函數(shù),才會(huì)被認(rèn)為函數(shù)執(zhí)行結(jié)束。如果沒(méi)有調(diào)用,則函數(shù)會(huì)一直運(yùn)行到超時(shí)
callback 調(diào)用之后,函數(shù)就結(jié)束了
callback 的第一個(gè)參數(shù)是 error 對(duì)象,這和 JS 回調(diào)編程的思想一致
關(guān)于 event 和 context,詳見 Nodejs 函數(shù)入口。
實(shí)現(xiàn)報(bào)警功能的主要邏輯,就寫在 index.js 里面。具體的實(shí)現(xiàn),就不細(xì)說(shuō),下面用偽代碼來(lái)描述:
alarm/alarm.js
// alarm/alarm.js // 實(shí)現(xiàn)報(bào)警功能 module.exports = function() { return new Promise((resolve, reject) => { // 查詢 SLS 日志 // - 如果沒(méi)有錯(cuò)誤日志,則 resolve // - 如果有錯(cuò)誤日志,則發(fā)送釘釘消息 // - 如果釘釘消息發(fā)送失敗,則 reject // - 如果釘釘消息發(fā)送成功,則 resolve resolve(); }) }
alarm/index.js
// alarm/index.js // 調(diào)用報(bào)警函數(shù) const alarm = require("./alarm"); module.exports.handler = function(event, context, callback) { alarm() .then(() => { callback(null, "success"); }) .catch(error => { callback(error); }) };CodeUri
如果函數(shù)里面引入了自定義的其他模塊,比如在 index.js 里面引入了 alarm.js const alarm = require("./alarm");,則需要修改默認(rèn)的 codeUri 為當(dāng)前代碼目錄 ./。否則默認(rèn)的 codeUri 只定義了 index.js,部署的時(shí)候只會(huì)部署 index.js。
ROSTemplateFormatVersion: "2015-09-01" Transform: "Aliyun::Serverless-2018-04-03" Resources: yunzhi: # 函數(shù)服務(wù)的名稱 Type: "Aliyun::Serverless::Service" # 表示 yunzhi 是一個(gè)函數(shù)服務(wù) Properties: Description: "helloworld" # 函數(shù)服務(wù)的描述 alarm: # 函數(shù)的名稱 Type: "Aliyun::Serverless::Function" # 表示 alarm 是一個(gè)函數(shù) Properties: Handler: index.handler # 函數(shù)的調(diào)用入口 Runtime: nodejs8 # 函數(shù)的運(yùn)行環(huán)境 CodeUri: "./" # 代碼的目錄
如果沒(méi)有修改 CodeUri,則會(huì)有類似下面的報(bào)錯(cuò)
$ fun local invoke alarm FC Invoke End RequestId: 16e3099e-6a40-43cb-99a0-f0c75f3422c6 { "errorMessage": "Cannot find module "./alarm"", "errorType": "Error", "stackTrace": [ "Error: Cannot find module "./alarm"", "at Module._resolveFilename (module.js:536:15)", "at Module._load (module.js:466:25)", "at Module.require (module.js:579:17)", "at require (internal/module.js:11:18)", "at (/code/index.js:9:15)", "at Module._compile (module.js:635:30)", "at Module._extensions..js (module.js:646:10)", "at Module.load (module.js:554:32)", "at tryModuleLoad (module.js:497:12)", "at Module._load (module.js:489:3)" ] }
fun local invoke alarm 是本地調(diào)試的命令,接下來(lái)會(huì)講到。
本地調(diào)試在開發(fā)過(guò)程中,肯定需要本地調(diào)試。fun 提供了 fun local 支持本地調(diào)試。
fun local 的命令格式為 fun local invoke [options] <[service/]function>,其中 options 和 service 都可以忽略。比如調(diào)試上面的報(bào)警功能的命令就是 fun local invoke alarm。
需要注意的是,本地調(diào)試需要先安裝 docker。
$ brew cask install docker
安裝成功后啟動(dòng) docker。
如果 docker 沒(méi)有啟動(dòng),運(yùn)行 fun local 可能會(huì)有如下報(bào)錯(cuò)
$ fun local invoke alarm Reading event data from stdin, which can be ended with Enter then Ctrl+D (you can also pass it from file with -e) connect ENOENT /var/run/docker.sock
正常的輸出如下
$ fun local invoke alarm Reading event data from stdin, which can be ended with Enter then Ctrl+D (you can also pass it from file with -e) skip pulling image aliyunfc/runtime-nodejs8:1.5.0... FC Invoke Start RequestId: 9360768c-5c52-4bf5-978b-774edfce9e40 load code for handler:index.handler FC Invoke End RequestId: 9360768c-5c52-4bf5-978b-774edfce9e40 success RequestId: 9360768c-5c52-4bf5-978b-774edfce9e40 Billed Duration: 79 ms Memory Size: 1998 MB Max Memory Used: 54 MB
第一次調(diào)試的話,會(huì)安裝 runtime 的鏡像,可能需要點(diǎn)時(shí)間。默認(rèn)的 Docker 鏡像下載會(huì)很慢,可以使用國(guó)內(nèi)的加速站點(diǎn)加速下載。
出現(xiàn) Reading event data from stdin, which can be ended with Enter then Ctrl+D 的提示時(shí),如果不需要輸入,可以按 ctrl+D 跳過(guò)。
函數(shù)部署開發(fā)完成之后,就需要將函數(shù)部署到阿里云的函數(shù)計(jì)算上面了。部署可以通過(guò) fun deploy 命令。
前面已經(jīng)在安裝 fun 之后,通過(guò) fun config 命令配置了阿里云的賬號(hào)和地域信息,fun deploy 會(huì)將函數(shù)自動(dòng)部署到對(duì)應(yīng)的賬號(hào)和地域下。
在 template.yml 中,也配置了函數(shù)的服務(wù)名和函數(shù)名。如果在函數(shù)計(jì)算中沒(méi)有對(duì)應(yīng)的服務(wù)或函數(shù),fun deploy 會(huì)自動(dòng)創(chuàng)建;如果已經(jīng)存在,則會(huì)更新。
$ fun deploy using region: cn-shanghai using accountId: ***********4698 using accessKeyId: ***********UfpF using timeout: 60 Waiting for service yunzhi to be deployed... Waiting for function alarm to be deployed... Waiting for packaging function alarm code... package function alarm code done function alarm deploy success service yunzhi deploy success
部署成功之后,就可以在函數(shù)計(jì)算的控制臺(tái)中看到對(duì)應(yīng)的函數(shù)服務(wù)和函數(shù)了。目前還沒(méi)有配置觸發(fā)器,可以手動(dòng)在控制臺(tái)中點(diǎn)擊“執(zhí)行”按鈕來(lái)執(zhí)行函數(shù)。
觸發(fā)器對(duì)于應(yīng)用到生產(chǎn)環(huán)境的函數(shù),肯定不會(huì)像上面一樣手動(dòng)去執(zhí)行它,而是通過(guò)配置觸發(fā)器去執(zhí)行。觸發(fā)器就相當(dāng)于是一個(gè)特定的事件,當(dāng)函數(shù)計(jì)算接收到該事件的時(shí)候,就去調(diào)用對(duì)應(yīng)的函數(shù)。
阿里云的函數(shù)計(jì)算支持 HTTP 觸發(fā)器(接收到 HTTP 請(qǐng)求之后調(diào)用函數(shù))、定時(shí)觸發(fā)器(定時(shí)調(diào)用函數(shù))、OSS 觸發(fā)器等等。詳見 觸發(fā)器列表。
對(duì)于報(bào)警功能,需要用到的是定時(shí)觸發(fā)器,因?yàn)樾枰g隔一定的時(shí)間就調(diào)用函數(shù)。
觸發(fā)器是配置到函數(shù)中的,可以通過(guò)函數(shù)的 Event 屬性去配置
ROSTemplateFormatVersion: "2015-09-01" Transform: "Aliyun::Serverless-2018-04-03" Resources: yunzhi: Type: "Aliyun::Serverless::Service" Properties: Description: "helloworld" alarm: Type: "Aliyun::Serverless::Function" Properties: Handler: index.handler Runtime: nodejs8 CodeUri: "./" Events: # 配置 alarm 函數(shù)的觸發(fā)器 TimeTrigger: # 觸發(fā)器的名稱 Type: Timer # 表示該觸發(fā)器是定時(shí)觸發(fā)器 Properties: CronExpression: "0 0/1 * * * *" # 每 1 分鐘執(zhí)行一次 Enable: true # 是否啟用該定時(shí)觸發(fā)器
上面的配置,就為 alarm 配置了一個(gè)名為 TimeTrigger 的定時(shí)觸發(fā)器,觸發(fā)器每隔 1 分鐘執(zhí)行一次,也就是每隔 1 分鐘調(diào)用一次函數(shù)。
配置完成之后,再執(zhí)行 fun deploy 就可以發(fā)布函數(shù)及觸發(fā)器到函數(shù)計(jì)算上。
這里需要注意的是,阿里云函數(shù)計(jì)算服務(wù)目前支持的觸發(fā)器,最小的間隔時(shí)間為 1 分鐘。如果小于 1 分鐘,則無(wú)法設(shè)置成功。定時(shí)觸發(fā)器的詳細(xì)介紹可參考文檔 定時(shí)觸發(fā)函數(shù)。
函數(shù)日志對(duì)于 serverless 應(yīng)用,雖然不用關(guān)心運(yùn)維了,其實(shí)我們也并不知道我們的函數(shù)運(yùn)行在哪臺(tái)服務(wù)器上。這個(gè)時(shí)候,函數(shù)的日志就尤為重要了。沒(méi)有日志,我們很難知道程序運(yùn)行狀態(tài),遇到問(wèn)題更是無(wú)從下手。
所以接下來(lái)需要對(duì)函數(shù)配置日志。阿里云的函數(shù)計(jì)算可以使用阿里云日志服務(wù) SLS來(lái)存儲(chǔ)日志。如果要存儲(chǔ)日志,則需要先開通 日志服務(wù)。
不存在日志庫(kù)如果是第一次使用日志服務(wù),則肯定不存在日志庫(kù)??梢栽?template.yml 像定義函數(shù)服務(wù)一樣,通過(guò) Resource 來(lái)定義日志資源。
前面也提到,函數(shù)日志是配置到對(duì)應(yīng)的服務(wù)上的,具體配置也很簡(jiǎn)單,就是通過(guò)函數(shù)服務(wù)的 LogConfig 屬性來(lái)配置。
完整的 template.yml 如下
ROSTemplateFormatVersion: "2015-09-01" Transform: "Aliyun::Serverless-2018-04-03" Resources: log-yunzhi: # 日志項(xiàng)目名稱為 log-yunzhi Type: "Aliyun::Serverless::Log" # 表示該資源是阿里云的日志服務(wù) Properties: Description: "yunzhi function service log project" log-yunzhi-store: # 日志的 logstore Type: "Aliyun::Serverless::Log::Logstore" Properties: TTL: 10 ShardCount: 1 log-another-logstore: # 日志的另一個(gè) logstore Type: "Aliyun::Serverless::Log::Logstore" Properties: TTL: 10 ShardCount: 1 yunzhi: Type: "Aliyun::Serverless::Service" Properties: Description: "helloworld" LogConfig: # 配置函數(shù)的日志 Project: "log-yunzhi" # 存儲(chǔ)函數(shù)日志 SLS 項(xiàng)目: log-yunzhi Logstore: "log-yunzhi-store" # 存儲(chǔ)函數(shù)日志的 SLS logstore: log-yunzhi-store alarm: Type: "Aliyun::Serverless::Function" Properties: Handler: index.handler Runtime: nodejs8 CodeUri: "./" Events: TimeTrigger: Type: Timer Properties: CronExpression: "0 0/1 * * * *" Enable: true
在上面的配置中,就定義了名為 log-yunzhi 的日志項(xiàng)目(Project),并且在該 Project 中創(chuàng)建了兩個(gè)日志倉(cāng)庫(kù)(LogStore):log-yunzhi-store 和 log-yunzhi-store。一個(gè) Project 可以包含多個(gè) LogStore。
注意:日志項(xiàng)目的名稱必須全局唯一。 即配置中,og-yunzhi 這個(gè)項(xiàng)目名稱是全局唯一的。
執(zhí)行 fun deploy 之后,就會(huì)自動(dòng)在函數(shù)服務(wù)對(duì)應(yīng)的地域創(chuàng)建日志 Project 及日志 logstore,同時(shí)也會(huì)自動(dòng)為 logstore 加上全文索引,然后自動(dòng)為函數(shù)服務(wù)配置日志倉(cāng)庫(kù)。
之后函數(shù)的運(yùn)行日志都會(huì)存儲(chǔ)在對(duì)應(yīng)的 logstore 里。
$ fun deploy using region: cn-shanghai using accountId: ***********4698 using accessKeyId: ***********UfpF using timeout: 60 Waiting for log service project log-yunzhi to be deployed... Waiting for log service logstore log-yunzhi-store to be deployed... retry 1 times Waiting for log service logstore log-yunzhi-store default index to be deployed... log service logstore log-yunzhi-store default index deploy success log serivce logstore log-yunzhi-store deploy success Waiting for log service logstore log-another-logstore to be deployed... Waiting for log service logstore log-another-logstore default index to be deployed... log service logstore log-another-logstore default index deploy success log serivce logstore log-another-logstore deploy success log serivce project log-yunzhi deploy success Waiting for service yunzhi to be deployed... Waiting for function alarm to be deployed... Waiting for packaging function alarm code... package function alarm code done Waiting for Timer trigger TimeTrigger to be deployed... function TimeTrigger deploy success function alarm deploy success service yunzhi deploy success
如果日志庫(kù)已經(jīng)存在,且定義了日志資源,則 fun deploy 會(huì)按照 template.yml 中的配置更新日志庫(kù)。
存在日志庫(kù)如果日志庫(kù)已經(jīng)存在,即已經(jīng)在日志服務(wù)中創(chuàng)建了日志項(xiàng)目 Project 和日志庫(kù) Logstore ,就可以直接為函數(shù)服務(wù)添加 LogConfig,不用再定義日志資源。
注意,日志庫(kù)需要和函數(shù)服務(wù)在同一個(gè)地域 Region。否則不能部署成功。
下面是一個(gè)配置函數(shù)日志到已經(jīng)存在的 Project 和 Logstore 中的例子。
ROSTemplateFormatVersion: "2015-09-01" Transform: "Aliyun::Serverless-2018-04-03" Resources: yunzhi: Type: "Aliyun::Serverless::Service" Properties: Description: "helloworld" LogConfig: # 配置函數(shù)的日志 Project: "log-yunzhi-exist" # 存儲(chǔ)函數(shù)日志到已經(jīng)存在的 Project: log-yunzhi-exist Logstore: "logstore-exist" # 存儲(chǔ)函數(shù)日志到已經(jīng)存在的 logstore: logstore-exist alarm: Type: "Aliyun::Serverless::Function" Properties: Handler: index.handler Runtime: nodejs8 CodeUri: "./" Events: TimeTrigger: Type: Timer Properties: CronExpression: "0 0/1 * * * *" Enable: true
如果日志庫(kù)和函數(shù)服務(wù)不在同一個(gè)地域,函數(shù)服務(wù)就會(huì)找不到日志庫(kù),fun deploy 也會(huì)報(bào)錯(cuò)。如下所示,yunzhi-log-qingdao 是我創(chuàng)建的一個(gè)青島地域的日志 Project。
$ fun deploy using region: cn-shanghai using accountId: ***********4698 using accessKeyId: ***********UfpF using timeout: 60 Waiting for service yunzhi to be deployed... retry 1 times retry 2 times retry 3 times retry 4 times retry 5 times retry 6 times retry 7 times PUT /services/yunzhi failed with 400. requestid: 6af2afb8-cbd9-0d3e-bf16-fe623834b4ee, message: project "yunzhi-log-qingdao" does not exist.其他問(wèn)題 子賬號(hào) AccessDenied
如果是使用 RAM 子賬號(hào)來(lái)開發(fā)、部署函數(shù)計(jì)算,則 fun 工具的配置中 Aliyun Access Key ID Aliyun Secret Access Key
是對(duì)應(yīng)子賬戶的信息,但 Aliyun Account ID 還是主賬號(hào)的信息。RAM 子賬號(hào)有一個(gè) UID,這個(gè)不是 Account ID。
如果 Aliyun Account ID 寫錯(cuò)了,則使用 fun 或 fcli 的時(shí)候,可能會(huì)遇到下面的錯(cuò)誤
Error: { "HttpStatus": 403, "RequestId": "b8eaff86-e0c1-c7aa-a9e8-2e7893acd545", "ErrorCode": "AccessDenied", "ErrorMessage": "The service or function doesn"t belong to you." }代碼版本的管理
在實(shí)現(xiàn)報(bào)警功能的過(guò)程中,我依舊使用了 GitLab 來(lái)存儲(chǔ)代碼。每次開發(fā)完成之后,將代碼 push 到 GitLab,然后再將代碼部署到函數(shù)計(jì)算上。不過(guò)這兩個(gè)過(guò)程是獨(dú)立的,還是不那么方便。
環(huán)境問(wèn)題一般我們開發(fā)的時(shí)候,需要日常、預(yù)發(fā)、線上多個(gè)環(huán)境部署、測(cè)試。阿里云函數(shù)計(jì)算是一個(gè)云產(chǎn)品,沒(méi)有環(huán)境的區(qū)分。但對(duì)于報(bào)警整個(gè)功能,我也沒(méi)有去區(qū)分環(huán)境,只是本地開發(fā)的時(shí)候,將報(bào)警消息發(fā)到一個(gè)測(cè)試的釘釘群,所以也沒(méi)有特別去關(guān)注。
經(jīng)濟(jì)成本使用函數(shù)計(jì)算的經(jīng)濟(jì)成本,相比于購(gòu)買云服務(wù)器部署應(yīng)用,成本低了非常多。
本文中涉及到函數(shù)計(jì)算和日志服務(wù)兩個(gè)云產(chǎn)品,都有一定的免費(fèi)額度。其中函數(shù)計(jì)算每月前 100 萬(wàn)次函數(shù)調(diào)用免費(fèi),日志服務(wù)每月也有 500M 的免費(fèi)存儲(chǔ)空間和讀寫流量。所以只用來(lái)測(cè)試或者實(shí)現(xiàn)一些調(diào)用量很小的功能,基本是免費(fèi)的。
函數(shù)計(jì)算計(jì)費(fèi)方式
日志服務(wù)產(chǎn)品定價(jià)
總結(jié)配置了函數(shù)的日志之后,將函數(shù)部署到函數(shù)計(jì)算上,就算是正式發(fā)布上線了。
現(xiàn)在回過(guò)頭來(lái)看,整個(gè)流程還算比較簡(jiǎn)單。但從零開始一步一步到部署上線的過(guò)程,還是遇到了很多問(wèn)題。比如文中的許多注意事項(xiàng),都是在不斷嘗試中得出的結(jié)論。
最近 serverless 這個(gè)話題也很火熱,也期待這個(gè)技術(shù)即將帶來(lái)的變革。
more https://github.com/nodejh/nodejh.github.io/issues
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/102957.html
摘要:本文以開發(fā)一個(gè)類似語(yǔ)音口令紅包小程序?yàn)槔?,向您講解如何使用阿里云函數(shù)計(jì)算快速構(gòu)建微信小程序的服務(wù)端。 前言 這篇文章適合所有的想微信小程序開發(fā)新手、老鳥以及想準(zhǔn)備學(xué)習(xí)開發(fā)微信小程序的程序猿。本文以開發(fā)一個(gè)類似語(yǔ)音口令紅包小程序?yàn)槔蚰v解如何使用阿里云函數(shù)計(jì)算快速構(gòu)建微信小程序的服務(wù)端。通過(guò)本文,您將會(huì)了解以下內(nèi)容: demo概覽 傳統(tǒng)服務(wù)器架構(gòu) VS Serverless架構(gòu) S...
摘要:本文以開發(fā)一個(gè)類似語(yǔ)音口令紅包小程序?yàn)槔?,向您講解如何使用阿里云函數(shù)計(jì)算快速構(gòu)建微信小程序的服務(wù)端。 前言 這篇文章適合所有的想微信小程序開發(fā)新手、老鳥以及想準(zhǔn)備學(xué)習(xí)開發(fā)微信小程序的程序猿。本文以開發(fā)一個(gè)類似語(yǔ)音口令紅包小程序?yàn)槔?,向您講解如何使用阿里云函數(shù)計(jì)算快速構(gòu)建微信小程序的服務(wù)端。通過(guò)本文,您將會(huì)了解以下內(nèi)容: demo概覽 傳統(tǒng)服務(wù)器架構(gòu) VS Serverless架構(gòu) S...
摘要:摘要阿里云函數(shù)計(jì)算是一個(gè)事件驅(qū)動(dòng)的全托管計(jì)算服務(wù)。微信小程序是一種不需要下載安裝即可使用的應(yīng)用,它可以在微信內(nèi)被便捷地獲取和傳播。本文以開發(fā)一個(gè)類似語(yǔ)音口令紅包小程序?yàn)槔?,向您講解如何使用阿里云函數(shù)計(jì)算快速構(gòu)建微信小程序的服務(wù)端。 摘要: 阿里云函數(shù)計(jì)算是一個(gè)事件驅(qū)動(dòng)的全托管計(jì)算服務(wù)。通過(guò)函數(shù)計(jì)算,您無(wú)需管理服務(wù)器等基礎(chǔ)設(shè)施,只需編寫代碼并上傳。微信小程序是一種不需要下載安裝即可使用的...
摘要:摘要阿里云函數(shù)計(jì)算是一個(gè)事件驅(qū)動(dòng)的全托管計(jì)算服務(wù)。微信小程序是一種不需要下載安裝即可使用的應(yīng)用,它可以在微信內(nèi)被便捷地獲取和傳播。本文以開發(fā)一個(gè)類似語(yǔ)音口令紅包小程序?yàn)槔蚰v解如何使用阿里云函數(shù)計(jì)算快速構(gòu)建微信小程序的服務(wù)端。 摘要: 阿里云函數(shù)計(jì)算是一個(gè)事件驅(qū)動(dòng)的全托管計(jì)算服務(wù)。通過(guò)函數(shù)計(jì)算,您無(wú)需管理服務(wù)器等基礎(chǔ)設(shè)施,只需編寫代碼并上傳。微信小程序是一種不需要下載安裝即可使用的...
摘要:無(wú)服務(wù)器計(jì)算是目前最被看好的云端計(jì)算執(zhí)行模型。阿里云函數(shù)計(jì)算是事件驅(qū)動(dòng)的全托管計(jì)算服務(wù)。通過(guò)函數(shù)計(jì)算,您無(wú)需管理服務(wù)器等基礎(chǔ)設(shè)施,只需編寫代碼并上傳。Serverless Computing(無(wú)服務(wù)器計(jì)算)是目前最被看好的云端計(jì)算執(zhí)行模型。其最大的好處是提供分布式彈性可伸縮的計(jì)算執(zhí)行環(huán)境,僅為實(shí)際使用資源付費(fèi),并且將應(yīng)用維護(hù)者從常規(guī)的運(yùn)維事務(wù)中解放出來(lái),更利于專注到具體的業(yè)務(wù)上。 在主流的應(yīng)...
閱讀 3171·2021-11-23 09:51
閱讀 1122·2021-09-02 15:21
閱讀 3086·2019-08-30 13:56
閱讀 1921·2019-08-29 14:12
閱讀 791·2019-08-29 13:53
閱讀 1766·2019-08-29 11:32
閱讀 1484·2019-08-29 11:25
閱讀 1570·2019-08-28 17:51