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