人人都是 Serverless 架构师 | “盲盒抽奖”创意营销活动实践
簡(jiǎn)介:當(dāng) Serverless 與低代碼這兩個(gè)不同的技術(shù)共同相交于同一個(gè)業(yè)務(wù)時(shí)會(huì)有怎樣的價(jià)值展現(xiàn)?本文以 “盲盒抽獎(jiǎng)” 這個(gè) Serverless Devs 做過(guò)的創(chuàng)意營(yíng)銷(xiāo)活動(dòng)為例,為大家講述 Serverless 和低代碼是如何搭配來(lái)滿(mǎn)足一個(gè)業(yè)務(wù)訴求的。
作者 | 寒斜 & 江昱
當(dāng) Serverless 與低代碼這兩個(gè)不同的技術(shù)共同相交于同一個(gè)業(yè)務(wù)時(shí)會(huì)有怎樣的價(jià)值展現(xiàn)?本文以 “盲盒抽獎(jiǎng)” ?這個(gè) Serverless Devs 做過(guò)的創(chuàng)意營(yíng)銷(xiāo)活動(dòng)為例,為大家講述 Serverless 和低代碼是如何搭配來(lái)滿(mǎn)足一個(gè)業(yè)務(wù)訴求的。
前言
線上 H5 創(chuàng)意動(dòng)畫(huà)結(jié)合線下實(shí)體獎(jiǎng)勵(lì)是互聯(lián)網(wǎng)營(yíng)銷(xiāo)活動(dòng)的一種常見(jiàn)手段。為了抓住關(guān)鍵時(shí)間節(jié)點(diǎn),活動(dòng)從策劃到落地的周期一般都比較短,短時(shí)間內(nèi)落地線上服務(wù)對(duì)于做技術(shù)開(kāi)發(fā)的同學(xué)有著不小的挑戰(zhàn)。
尤其是當(dāng)有更多需求,比如增加后臺(tái)管理以及關(guān)鍵前端訪問(wèn)數(shù)據(jù)埋點(diǎn)等需求時(shí),挑戰(zhàn)難度往往會(huì)加倍。對(duì)于開(kāi)發(fā)而言除了完成業(yè)務(wù)核心訴求,往往還需要關(guān)注非業(yè)務(wù)訴求以外的其他狀況,比如系統(tǒng)訪問(wèn)安全,高并發(fā)流量應(yīng)對(duì),系統(tǒng)運(yùn)行指標(biāo)可觀測(cè)等。
在以前這類(lèi)需求往往需要跟多的角色參與,如產(chǎn)品,前端,后端,設(shè)計(jì),測(cè)試,運(yùn)營(yíng),運(yùn)維等,使得投入產(chǎn)出比變得比較低,活動(dòng)持續(xù)性比較差。今天使用 Serverless + 低代碼的技術(shù)我們可以大幅縮減做此類(lèi)活動(dòng)的成本,讓它變成持續(xù)性的活動(dòng),從而大大提高運(yùn)營(yíng)效果。
實(shí)際上 Serverless Devs 此次的盲盒抽獎(jiǎng)活動(dòng)僅僅投了 3.5 個(gè)人,便完成了活動(dòng)策劃,產(chǎn)品設(shè)計(jì), 前后端實(shí)現(xiàn),系統(tǒng)部署運(yùn)維等工作。并且借助于 Serverless 的服務(wù)能力,輕松應(yīng)對(duì)了系統(tǒng)訪問(wèn)安全,高并發(fā)流量,系統(tǒng)可觀測(cè)等這些非業(yè)務(wù)挑戰(zhàn)。功能性的補(bǔ)齊 + 效率提升,讓本次運(yùn)營(yíng)取得了非常好的收益,活動(dòng)服務(wù)的模板化沉淀又為后續(xù)同類(lèi)活動(dòng)奠定好了良好的基礎(chǔ)。
“盲盒抽獎(jiǎng)” 活動(dòng)的整體流程如下:
應(yīng)用效果預(yù)覽:
“1 分鐘 Serverless 極速部署盲盒” 抽獎(jiǎng)活動(dòng)目前已經(jīng)結(jié)束,但是感興趣的同學(xué)仍可以體驗(yàn)一下:
1 分鐘 Serverless 極速抽盲盒
架構(gòu)預(yù)覽:
本次的部署架構(gòu)沒(méi)有使用阿里云API網(wǎng)關(guān),而是直接用函數(shù)計(jì)算 Custom Runtime 作為托管形態(tài),這樣做是因?yàn)楸敬涡枨蟮奶厥庑?#xff0c;我們是“自己部署自己抽”,實(shí)際上意味著端側(cè)訪問(wèn)是非中心化的,端側(cè)訪問(wèn)的服務(wù)做的也比較薄,只是數(shù)據(jù)處理接口調(diào)用和提供靜態(tài)渲染服務(wù),后經(jīng)過(guò)一個(gè)中心化的邏輯后臺(tái)處理中獎(jiǎng)概率,管理獎(jiǎng)品查詢(xún)數(shù)據(jù)庫(kù)等。
如果您是自己做中心化的的活動(dòng)后臺(tái)的話建議參考下面的架構(gòu)模式,采用 API網(wǎng)關(guān)作為流量入口。方便做更多的安全限制以及更靈活的擴(kuò)展
實(shí)現(xiàn)解析
前端交互低代碼實(shí)現(xiàn)
本次前端實(shí)現(xiàn)使用低代碼工作 hype4,hype4 的具體使用這里不做詳細(xì)介紹,有興趣的同學(xué)可以自行搜索。
設(shè)計(jì)稿除了之后將需要的圖切出來(lái),然后跟處理 Flash 一樣將動(dòng)畫(huà)效果實(shí)現(xiàn),最后就是添加 js 代碼實(shí)現(xiàn)接口訪問(wèn),場(chǎng)景切換等能力。整個(gè)流程會(huì)比全編碼要快很多,尤其是動(dòng)效實(shí)現(xiàn)上比純手寫(xiě)效率高 2-3 倍。
數(shù)據(jù)層 Serverless 服務(wù)
如架構(gòu)所示,這里的數(shù)據(jù)層實(shí)際上就是我們理解的 SSF ,這層僅做數(shù)據(jù)轉(zhuǎn)發(fā)和靜態(tài)的渲染。代碼實(shí)現(xiàn)比較簡(jiǎn)單,采用 express 框架,然后以函數(shù)計(jì)算 Custom runtime 形式部署。
目的是為了這個(gè)服務(wù)既可以托管靜態(tài)內(nèi)容也可以做動(dòng)態(tài)的數(shù)據(jù)轉(zhuǎn)發(fā)。值得注意的是,用戶(hù)的信息獲取也是在這層實(shí)現(xiàn)的。
這里我們獲取的是阿里云用戶(hù)的 accountId,方便對(duì)齊中獎(jiǎng)信息發(fā)放獎(jiǎng)品。對(duì)于普通開(kāi)發(fā)者而言這個(gè)參數(shù)沒(méi)有太大意義。
我們會(huì)提前將搖獎(jiǎng)后臺(tái)部署完畢,接下來(lái)就是,每個(gè)用戶(hù)自己部署完這層服務(wù)后,訪問(wèn)自己部署好的服務(wù),然后向搖獎(jiǎng)后臺(tái)傳遞 uid 等基本信息,發(fā)起搖獎(jiǎng)。最終返回中獎(jiǎng)結(jié)果透?jìng)鹘o前端展示。作為管理員則可以通過(guò)后臺(tái)操作設(shè)置獎(jiǎng)品和概率等。
后臺(tái)抽獎(jiǎng)邏輯實(shí)現(xiàn)
后端服務(wù)采用 Python Web 框架:Django 進(jìn)行實(shí)現(xiàn),主要方法有:
1.獲取用戶(hù)的 uid 信息,并對(duì)uid信息進(jìn)行校驗(yàn),以確保:
- uid 信息的準(zhǔn)確性
- 該客戶(hù)端服務(wù)是通過(guò) Serverless Devs 開(kāi)發(fā)者工具進(jìn)行部署;
2.當(dāng)日獎(jiǎng)品池的構(gòu)建;
3.用戶(hù)中獎(jiǎng)信息的初步確定;
4.用戶(hù)中獎(jiǎng)信息的復(fù)核;
5.返回最終的結(jié)果給客戶(hù)端;
基本流程
1.用戶(hù)在本地,將盲盒抽獎(jiǎng)的客戶(hù)端服務(wù),通過(guò) Serverless Devs 開(kāi)發(fā)者工具進(jìn)行部署,部署到用戶(hù)自己的賬號(hào)下;
在部署期間,需要給用戶(hù)下發(fā)一個(gè)臨時(shí)域名 (這個(gè)臨時(shí)域名需要用到用戶(hù)的 uid),Serverless Devs 在進(jìn)行臨時(shí)域名下發(fā)的過(guò)程中,會(huì)生成部分的客戶(hù)端token,并記錄到 Serverless Devs 后端服務(wù)中;這個(gè)token實(shí)際上就是鑒定用戶(hù)身份的重要標(biāo)記;
(如果用戶(hù)在 Yaml 中聲明了不使用系統(tǒng)自動(dòng)下發(fā)的域名信息,可能就沒(méi)辦法順利參加本次活動(dòng))。
2.用戶(hù)部署完成之后,會(huì)返回一個(gè)Serverless Devs下發(fā)的臨時(shí)域名,供用戶(hù)學(xué)習(xí)和測(cè)試使用。
3.接下來(lái)用戶(hù)通過(guò)瀏覽器,打開(kāi)該臨時(shí)域名,便可以看到抽獎(jiǎng)的相關(guān)頁(yè)面,用戶(hù)可以點(diǎn)擊進(jìn)行抽獎(jiǎng)操作。
4.用戶(hù)點(diǎn)擊抽獎(jiǎng)操作之后,會(huì)發(fā)起請(qǐng)求,請(qǐng)求用戶(hù)賬號(hào)下的 Serverless 服務(wù),該服務(wù)會(huì)根據(jù)用戶(hù)的 uid 信息進(jìn)行相關(guān)的處理,并發(fā)起真正的抽獎(jiǎng)?wù)埱蟮奖敬位顒?dòng)的后端 Serverless 服務(wù)上;
5.本次活動(dòng)的后端 Serverless 服務(wù)接收到用戶(hù)的抽獎(jiǎng)?wù)埱髸r(shí),會(huì):
抽獎(jiǎng)核心實(shí)現(xiàn)
在抽獎(jiǎng)操作的過(guò)程中,也是對(duì)當(dāng)前系統(tǒng)進(jìn)行了初步的評(píng)估,設(shè)定了一個(gè)簡(jiǎn)單的,易于實(shí)現(xiàn)的,可以針對(duì)小規(guī)模抽獎(jiǎng)活動(dòng)的抽獎(jiǎng)功能:
關(guān)于這一部分,Django項(xiàng)目的實(shí)現(xiàn)方法:
@csrf_exempt
def prize(request):
? ?uid = request.POST.get("uid", None)
? ?if not uid:
? ? ? ?return JsonResponse({"Error": "Uid is required."})
? ?temp_url = "<獲取uid的合法性和有效性,重要判斷依據(jù)>?uid=" + str(uid)
? ?if json.loads(urllib.request.urlopen(temp_url).read().decode("utf-8"))["Response"] == '0':
? ? ? ?return JsonResponse({"Error": "Uid is required."})
? ?token = randomStr(10)
? ?# 獲取當(dāng)日獎(jiǎng)品
? ?prizes = {}
? ?for eve_prize in PrizeModel.objects.filter(date=time.strftime("%Y-%m-%d", time.localtime())):
? ? ? ?prizes[eve_prize.name] = {
? ? ? ? ? ?"count": eve_prize.count,
? ? ? ? ? ?"rate": eve_prize.rate
? ? ? ?}
? ?# 構(gòu)建抽獎(jiǎng)池
? ?prize_list = []
? ?for evePrize, eveInfo in prizes.items():
? ? ? ?temp_prize_list = [evePrize, ] * int((100 * eveInfo['rate']))
? ? ? ?prize_list = prize_list + temp_prize_list
? ?none_list = [None, ] * (100 - len(prize_list))
? ?prize_list = prize_list + none_list
? ?pre_prize = random.choice(prize_list)
? ?# 數(shù)據(jù)入庫(kù)
? ?try:
? ? ? ?UserModel.objects.create(uid=uid,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? token=token,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pre_prize=pre_prize,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result=False)
? ?except:
? ? ? ?try:
? ? ? ? ? ?if not UserModel.objects.get(uid=uid).result:
? ? ? ? ? ? ? ?return JsonResponse({"Result": "0"})
? ? ? ?except:
? ? ? ? ? ?pass
? ? ? ?return JsonResponse({"Error": "Everyone can only participate once."})
? ?if not pre_prize:
? ? ? ?return JsonResponse({"Result": "0"})
? ?user_id = UserModel.objects.get(uid=uid, token=token).id
? ?users_count = UserModel.objects.filter(pre_prize=pre_prize, id__lt=user_id, date=time.strftime("%Y-%m-%d", time.localtime())).count()
? ?# 是否獲獎(jiǎng)的最終判斷
? ?if users_count >= prizes.get(pre_prize, {}).get("count", 0):
? ? ? ?return JsonResponse({"Result": "0"})
? ?UserModel.objects.filter(uid=uid, token=token).update(result=True)
? ?return JsonResponse({"Result": {
? ? ? ?"token": token,
? ? ? ?"prize": pre_prize
? ?}})
系統(tǒng)安全設(shè)定
當(dāng)用戶(hù)中獎(jiǎng)之后,系統(tǒng)會(huì)生成一個(gè)token,該token與uid的組合,是用來(lái)判斷用戶(hù)是否中獎(jiǎng)的重要依據(jù),這里可能涉及到一個(gè)問(wèn)題:什么有了uid,還要增加一個(gè)token來(lái)進(jìn)行組合判斷呢?其實(shí)原因很簡(jiǎn)單的,提交中獎(jiǎng)信息和查詢(xún)中獎(jiǎng)信息,如果是通過(guò)uid來(lái)直接進(jìn)行處理的,那么很有可能會(huì)有用戶(hù)通過(guò)遍歷等手段,非法獲取到其他用戶(hù)提交過(guò)的信息,而這一部分信息很有可能涉及到用戶(hù)提交的收貨地址等,所以為了安全,增加了一個(gè)token,在一定程度上,提升了被暴力遍歷的復(fù)雜度。而這一部分的方法也很簡(jiǎn)單:
@csrf_exempt
def information(request):
? ?uid = request.GET.get("uid", None)
? ?token = request.GET.get("token", None)
? ?if None in [uid, token]:
? ? ? ?return JsonResponse({"Error": "Uid and token are required."})
? ?userInfor = UserModel.objects.filter(uid=uid, token=token)
? ?if userInfor.count() == 0:
? ? ? ?return JsonResponse({"Error": "No information found yet."})
? ?if not userInfor[0].result:
? ? ? ?return JsonResponse({"Error": "No winning information has been found yet."})
? ?if request.method == "GET":
? ? ? ?return JsonResponse({
? ? ? ? ? ?"Result": {
? ? ? ? ? ? ? ?"prize": userInfor[0].pre_prize,
? ? ? ? ? ? ? ?"name": userInfor[0].name,
? ? ? ? ? ? ? ?"phone": userInfor[0].phone,
? ? ? ? ? ? ? ?"address": userInfor[0].address
? ? ? ? ? ?}
? ? ? ?})
? ?elif request.method == "POST":
? ? ? ?name = request.POST.get("name", None)
? ? ? ?phone = request.POST.get("phone", None)
? ? ? ?address = request.POST.get("address", None)
? ? ? ?if None in [name, phone, address]:
? ? ? ? ? ?return JsonResponse({"Error": "Name, phone and address are required."})
? ? ? ?userInfor.update(name=name,
? ? ? ? ? ? ? ? ? ? ? ? phone=phone,
? ? ? ? ? ? ? ? ? ? ? ? address=address)
? ? ? ?return JsonResponse({"Result": "Saved successfully."})
整個(gè)流程是:
其他安全方面的補(bǔ)充:
部署準(zhǔn)備工作
本次部署無(wú)需域名,使用函數(shù)計(jì)算生成的自定義域名即可,依然需要安裝好 Serverless Devs 工具,本次只需開(kāi)通函數(shù)計(jì)算即可。
操作步驟
搖獎(jiǎng)后臺(tái)的部分模板還在準(zhǔn)備中,僅演示部署前端和數(shù)據(jù)層的服務(wù)。
步驟1:秘鑰配置
參考Serverless devs 阿里云秘鑰配置
步驟2:初始化
使用serverless devs 命令行工具執(zhí)行:
s init blindbox-game
進(jìn)入引導(dǎo)式操作:
步驟3:構(gòu)建部署
修改一下相關(guān)的配置信息,執(zhí)行s deploy
效果查看
函數(shù)部署情況:
頁(yè)面效果:
搖獎(jiǎng)部分的應(yīng)用模板正在準(zhǔn)備中,后續(xù)也會(huì)統(tǒng)一在這個(gè)應(yīng)用模板給大家提供展示。
結(jié)語(yǔ)
上面實(shí)踐結(jié)束后關(guān)于低代碼和 Serverless 這個(gè)話題想跟大家再展開(kāi)一下,以下部分并會(huì)以理論性為主,希望能夠給讀者帶來(lái)不一樣的收獲。
開(kāi)發(fā)者視角的 Serverless + 低代碼
就我自身而言的話,明確的結(jié)論是我并不排斥兩者的相容,反而非常期待這兩者結(jié)合能夠進(jìn)一步讓我的工作更加高效,安全。
本次活動(dòng)我的最大感觸是,如果低代碼平臺(tái)能夠跟 Serverless 無(wú)縫銜接就好了,比如我在低代碼上調(diào)用接口現(xiàn)在只能構(gòu)建發(fā)到線上之后才能測(cè)試,這點(diǎn)天然集成好的平臺(tái)優(yōu)勢(shì)就會(huì)很明顯。另外就是發(fā)布構(gòu)建好前端之后還得再去跟后端接口組裝,這個(gè)如果是統(tǒng)一平臺(tái)的話搞完需求就可以一鍵發(fā)布,會(huì)省不少事。不過(guò)這里也比較矛盾,因?yàn)槲乙矒?dān)心一旦低代碼的前端跟 Serverless 的后端耦合在一起就會(huì)變得不靈活,被服務(wù)商鎖定。
供應(yīng)商視角的 Serverless + 低代碼
可以看到現(xiàn)在云服務(wù)商的 Serverless 和低代碼的服務(wù)商在互相融合。比如低代碼平臺(tái)領(lǐng)導(dǎo)者 outsystem 早在 2016 年就開(kāi)始使用 AWS 的服務(wù),比如 Lambda 等為他們的客戶(hù)提供原生 APP 服務(wù)的構(gòu)建。
以 serverless & model-driven application 作為主體服務(wù)的低代碼平臺(tái) Trillo 則是以 Google 云服務(wù)構(gòu)為基礎(chǔ)幫助他們的用戶(hù)構(gòu)建 Serverless 服務(wù)和前端應(yīng)用,當(dāng)然國(guó)內(nèi)外的各家云廠商也沒(méi)閑著 Azure 將自家的低代碼產(chǎn)品 Power Apps 融入了 Serverless 的能力形成 Serverless Power Apps,將二者的優(yōu)勢(shì)做了充分融合。
Aws 將前端的集成都交給了伙伴,自身更專(zhuān)注于服務(wù)側(cè)的 Serverless 集成,并且推出了 Step Functions Workflow Studio 產(chǎn)品將 Serverless 跟自家?guī)缀跛械漠a(chǎn)品串聯(lián)到了一起。
國(guó)內(nèi)騰訊推出了微搭低代碼平臺(tái),也是主打 Serverless + 低代碼,在小程序場(chǎng)景發(fā)力,各廠商的跟進(jìn)也說(shuō)明了對(duì)這個(gè)領(lǐng)域的重視。
打造 Serverless + 低代碼平臺(tái)的設(shè)想
Serverless + 低代碼平臺(tái)的價(jià)值是比較明確的,效率,安全,成本都是它的關(guān)鍵詞。那么假設(shè)我們要去建設(shè)這樣的平臺(tái)需要做哪些方面的考慮呢?
首先是從平臺(tái)能力上,應(yīng)該要做到能夠覆蓋一個(gè)應(yīng)用開(kāi)發(fā)從前到后的方方面面。比如:
- 數(shù)據(jù)建模
- 數(shù)據(jù)模型 API 化
- 使用 Serverless 構(gòu)建后端應(yīng)用邏輯
- 支持部署 Long-Runing 的后端服務(wù)
- 可擴(kuò)展的外部服務(wù)集成
- 文件存儲(chǔ)
- 邏輯編排
- 各種安全能力比如身份驗(yàn)證,權(quán)限控制等
- UI 編排
- CI/CD
- 應(yīng)用可觀測(cè)
這里可以簡(jiǎn)單理一下這個(gè)平臺(tái)的功能設(shè)計(jì),依托于云廠商的基礎(chǔ)設(shè)施構(gòu)建相應(yīng)的能力。
相關(guān)的低代碼能部分的能力有一些相關(guān)的開(kāi)源產(chǎn)品,這里可以分享給大家:
- ui 頁(yè)面搭建https://github.com/alibaba/designable
- 數(shù)據(jù)庫(kù)建模chiner: 元數(shù)建模,一款豐富數(shù)據(jù)庫(kù)生態(tài),獨(dú)立于具體數(shù)據(jù)庫(kù)之外的,數(shù)據(jù)庫(kù)關(guān)系模型設(shè)計(jì)平臺(tái)。
- 流程編排GitHub - i5ting/imove: Move your mouse, generate code from flow chart
另外跟云基礎(chǔ)設(shè)施打通部分可以考慮利用 Serverless Devs 的 Iac 能力,尤其是目前在跟 FC 的集成上成熟度比較高,可以很方便的對(duì)函數(shù)全生命周期進(jìn)行管理。
當(dāng)然以上僅是筆者的一些設(shè)想,我深知實(shí)現(xiàn)這樣的系統(tǒng)絕非易事,這里也只是拋轉(zhuǎn)引玉用。
追求生產(chǎn)效率的提升始終是企業(yè)生產(chǎn)的重要話題,Serverless 和低代碼在各自的技術(shù)領(lǐng)域上有著獨(dú)立的分工,卻也有著共同的提高生產(chǎn)效率的特性,學(xué)會(huì)同時(shí)掌握利用好這兩個(gè)生產(chǎn)力工具或許會(huì)是從事信息產(chǎn)業(yè)同學(xué)的重要競(jìng)爭(zhēng)力。
原文鏈接
本文為阿里云原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。?
總結(jié)
以上是生活随笔為你收集整理的人人都是 Serverless 架构师 | “盲盒抽奖”创意营销活动实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 深度干货|云原生分布式数据库 Polar
- 下一篇: YOLO升级版:YOLOv2和YOLO9