之前我做過一個在線編程的軟體,目前用戶量大概有幾十萬,通過這個 App 不僅僅可以進行代碼的撰寫、運行還可以進行編程的學習,自己一直對 Serverless 架構情有獨鐘,恰好趕到我的這個 App 學習板塊被很多人吐槽難用,索性就對這個學習板塊進行重構,并且打算在重構的時候,直接將這個學習板塊搬上 Serverless 架構,
本文作者 Anycodes
基于 Serverless 架構重構是出于兩個方面考慮 —— 一是 Serverless 架構能讓個人開發者的運維作業變得簡單,尤其是不用操心服務器,也不用關心流量洪峰(當然,對于我的個人專案而言,也沒太多的洪峰),二是 Serverless 架構的按量付費,極大節約了成本,
整體設計
資料庫設計
這個部分在之前是若干個大模塊,現在統一整理到一個模塊中進行專案重構,所以這里繼續復用之前的資料庫:

在這個資料庫中,四個模塊分別是:新聞文章、開發檔案、基礎教程以及圖書資源,其中開發檔案包括大分類,子串列以及正文等內容,這里表關聯并沒有使用外鍵,而是直接用的 ID 進行表之間的關聯,
說實話,這個資料庫設計的并不是很好,原因是因為初次構建這個資料部分,絕大部分資料都是在其他站點采集而來,當時由于模塊快速上線,便直接按照原有格式存盤,所以可以認為這個資料庫中有很多表的欄位其實是無效的,或者針對這個專案是未被使用的,
后端設計
后端將會整體部署到一個函式上,功能整體結構:

整體功能就是云函式 SCF 系結 API 網關觸發器,用戶訪問 API 網關指定的地址,觸發云函式,然后函式在入口處進行功能拆分,請求不同的方法獲得對應的資料,
這里要額外說明一下,后端整體介面部署在一個函式的原因,是因為我這個模塊的使用量并不是非常頻繁,所以部署到一個函式上也不會出現超過最大實體的限制,如果超出限制是可以申請擴容的;
其次,所有的介面都是對資料庫增刪改查,放入到一個函式中,在一定程度上可以保證容器的活性,降低部分冷啟動帶來的問題,同時容器的復用,也可以在一定程度上降低后臺資料庫鏈接池的壓力;除此之外,所有的介面功能,都是只需要最少的記憶體(64M)即可完整運行,不會因為個別介面的預估記憶體較大,進而影響影響整體的成本,
所以這里評估之后,是可以將多個介面,放入到一個函式中,對外提供對應的服務,
前端設計
前端設計,預計在學習資源部分需要有 8 個頁面,主要就是科技類新聞、教程、檔案、圖書等相關功能,通過墨刀繪制的原型圖如下:

前端專案開發將會采用 Vue.js,并且將其部署到物件存盤中,通過騰訊云物件存盤的靜態網站功能對外提供服務,
專案開發
后端函式開發
后端函式開發主要包括三部分
- 部分資源的初始化,部分資源初始化,需要在函式外進行,這樣可以保證復用實體的時候不會再次建立鏈接,防止資料庫連接池出現問題:
def getConnection(dbName):
conn = pymysql.connect(host="",
user="root",
password="",
port=3306,
db=dbName,
charset='utf8',
cursorclass=pymysql.cursors.DictCursor,
)
conn.autocommit(1)
return conn
connectionArticle = getConnection("anycodes_article")
- 資料庫查詢操作
這一部分主要就是針對不同介面查詢資料庫,例如獲取文章分類:
def getArticleCategory():
connectionArticle.ping(reconnect=True)
cursor = connectionArticle.cursor()
search_stmt = ('SELECT * FROM `category` ORDER BY `sort`')
cursor.execute(search_stmt, ())
data = cursor.fetchall()
cursor.close()
result = {}
for eve_data in data:
if eve_data['pre_name'] not in result:
result[eve_data['pre_name']] = []
result[eve_data['pre_name']].append({
"id": eve_data["sort"],
"name": eve_data["name"]
})
return result
例如獲取文章串列:
def getArticleList(cid):
connectionArticle.ping(reconnect=True)
cursor = connectionArticle.cursor()
search_stmt = ('SELECT * FROM `article` WHERE `category` = %s ORDER BY `sort`')
cursor.execute(search_stmt, (cid,))
data = https://www.cnblogs.com/serverlesscloud/p/cursor.fetchall()
cursor.close()
result = [{
"id": eve_data["aid"],
"title": eve_data["title"]
} for eve_data in data]
return result
- 最后一部分就是函式的入口,函式入口部分就是做功能分發和介面識別:
def main_handler(event, context):
try:
result_data = https://www.cnblogs.com/serverlesscloud/p/{
"error": False
}
req_type = event["pathParameters"]["type"]
if req_type == "get_book_list":
result_data["data"] = getBookList()
elif req_type == "get_book_info":
result_data["data"] = getBookContent(event["queryString"]["id"])
elif req_type == "get_daily_content":
result_data["data"] = getDailyContent(event["queryString"]["id"])
elif req_type == "get_daily_list":
result_data["data"] = getDailyList(event["queryString"]["category"])
elif req_type == "get_dictionary_result":
result_data["data"] = getDictionaryResult(event["queryString"]["word"])
elif req_type == "get_dev_content":
result_data["data"] = getDevContent(event["queryString"]["id"])
elif req_type == "get_dev_section":
result_data["data"] = getDevSection(event["queryString"]["id"])
elif req_type == "get_dev_chapter":
result_data["data"] = getDevChapter(event["queryString"]["id"])
elif req_type == "get_dev_list":
result_data["data"] = getDevList()
elif req_type == "get_article_content":
result_data["data"] = getArticle(event["queryString"]["id"])
elif req_type == "get_article_list":
result_data["data"] = getArticleList(event["queryString"]["id"])
elif req_type == "get_article_category":
result_data["data"] = getArticleCategory()
return result_data
except Exception as e:
print(e)
return {"error": True}
函式部分完成之后,可以配置 API 網關部分:

在整個后端介面開發程序中,其實并沒有遇到什么太大的問題,因為這個學習功能的模塊基本上就是對資料庫進行查詢的操作,所以相對來說非常順利,
效果預覽
整體預覽結果:一共包括十幾個頁面,這里取其中8個主要的頁面進行效果展示:

整個頁面基本上是還原了設計稿的樣子,并且和原有專案進行了部分的整合,無論是串列頁面還是圖書頁面等,資料加載速度表現良好,
通過 PostMan 進行基本測驗:

對介面進行 1000 次訪問測驗:

可以看到,介面表現良好,并未出現失敗的情況,對該測驗結果進行耗時的可視化:

其中最大的時間消耗是 219 毫秒,最小是 27 毫秒,平均值 35 毫秒,可以看到整體的效果還是非常不錯,
這樣一個專案開發完成,上線之后,前端部分被放到物件存盤 COS 中,后端業務被放到云函式 SCF 中,觸發器使用的是 API 網關,在監控層面,函式計算有著比較不錯的監控緯度:

同時函式并發,彈性伸縮等問題都由云廠商來解決,可以這樣說,自從這個組件部署到了 Serverless 架構上,我所做的操作就是如果業務代碼有問題,進行簡單修復和簡單維護,講真,整個效果還是不錯的,
通過按量付費,可以看到我后端服務產生的費用:

由于云函式沒辦法看到單個資源的費用,所以整個函式我有幾十個,一共花費的費用也遠遠比服務器的一個月便宜很多,
當然雖然說在計算服務這里整體費用只有幾元錢相對來說非常便宜,但是其還有 API 網關的費用和物件存盤的費用,例如 API 網關費用:

同樣,我這里的 API 網關也是有很多服務的,不僅僅是 Anycodes 這樣一個服務產生的,但是整體加一起 2 月份只有 1 元錢,相對來說也是蠻低的,
總結
通過個人專案中的一個子模塊重構程序,將該專案部署到 Serverless 架構上:
-
在開發程序中,我覺得是蠻方便的,一方面自己不需要在服務器中安裝各類軟體,也不需要搭建 web 服務,不需要對 web 服務進行優化,做的只是讀取資料庫,按照一定的格式進行 return,至于 web 服務等相關模塊交給 API 網關來實作,整個一個后端開發大概耗時大約是一個多小時;前端開發是比較耗時的,因為我個人不是專業做前端的,所以無論是布局還是邏輯開發,都是有點障礙的,但是也只用了 2 天時間;所以這個模塊從開發到上線只用了 2 天時間;
-
專案在部署的時候非常流暢,基于 Serverless Framework 的開發者工具一鍵部署,后期更新維護,只需要重新部署即可,線上也是無縫切換,不會出現更新服務造成的服務中斷,也不用為更新服務可能造成服務中斷而欄位外的操作,整體后期更新程序快速且簡單易用;
-
資源消耗部分就是使用按量付費,通過一個月的觀察,整個資源消耗是蠻低的,整體性能保證的同時,成本也逐漸的被壓低,對于個人開發者來說,確實是一個福音,
通過這樣一個簡單上 Serverless 架構的程序,也讓我對 Serverless 架構有了更深入的了解和認識,作為一種新技識訓者說新的架構,Serverless 的成長還需要一段時間,但是我相信,他的成長,會很快速,
Serverless Framework 30 天試用計劃
我們誠邀您來體驗最便捷的 Serverless 開發和部署方式,在試用期內,相關聯的產品及服務均提供免費資源和專業的技術支持,幫助您的業務快速、便捷地實作 Serverless!
詳情可查閱:Serverless Framework 試用計劃
One More Thing
3 秒你能做什么?喝一口水,看一封郵件,還是 —— 部署一個完整的 Serverless 應用?
復制鏈接至 PC 瀏覽器訪問:https://serverless.cloud.tencent.com/deploy/express
3 秒極速部署,立即體驗史上最快的 Serverless HTTP 實戰開發!
傳送門:
- GitHub: github.com/serverless
- 官網:serverless.com
歡迎訪問:Serverless 中文網,您可以在 最佳實踐 里體驗更多關于 Serverless 應用的開發!
推薦閱讀:《Serverless 架構:從原理、設計到專案實戰》
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/6761.html
標籤:其他
