以前我作過一個在線編程的軟件,目前用戶量大概有幾十萬,經過這個 App 不只僅能夠進行代碼的編寫、運行還能夠進行編程的學習。本身一直對 Serverless 架構情有獨鍾,剛好趕到個人這個 App 學習板塊被不少人吐槽難用,索性就對這個學習板塊進行重構,而且打算在重構的時候,直接將這個學習板塊搬上 Serverless 架構。前端
本文做者 Anycodespython
基於 Serverless 架構重構是出於兩個方面考慮 —— 一是 Serverless 架構能讓我的開發者的運維工做變得簡單,尤爲是不用操心服務器,也不用關心流量洪峯(固然,對於個人我的項目而言,也沒太多的洪峯),二是 Serverless 架構的按量付費,極大節約了成本。mysql
這個部分在以前是若干個大模塊,如今統一整理到一個模塊中進行項目重構,因此這裏繼續複用以前的數據庫:git
在這個數據庫中,四個模塊分別是:新聞文章、開發文檔、基礎教程以及圖書資源。其中開發文檔包括大分類,子列表以及正文等內容,這裏表關聯並無使用外鍵,而是直接用的 ID 進行表之間的關聯。github
說實話,這個數據庫設計的並非很好,緣由是由於初次構建這個數據部分,絕大部分數據都是在其餘站點採集而來,當時因爲模塊快速上線,便直接按照原有格式存儲,因此能夠認爲這個數據庫中有不少表的字段實際上是無效的,或者針對這個項目是未被使用的。web
後端將會總體部署到一個函數上,功能總體結構:sql
總體功能就是雲函數 SCF 綁定 API 網關觸發器,用戶訪問 API 網關指定的地址,觸發雲函數,而後函數在入口處進行功能拆分,請求不一樣的方法得到對應的數據。數據庫
這裏要額外說明一下,後端總體接口部署在一個函數的緣由,是由於我這個模塊的使用量並非很是頻繁,因此部署到一個函數上也不會出現超過最大實例的限制,若是超出限制是能夠申請擴容的;express
其次,全部的接口都是對數據庫增刪改查,放入到一個函數中,在必定程度上能夠保證容器的活性,下降部分冷啓動帶來的問題,同時容器的複用,也能夠在必定程度上下降後臺數據庫連接池的壓力;除此以外,全部的接口功能,都是隻須要最少的內存(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 = 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 = { "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 開發和部署方式。在試用期內,相關聯的產品及服務均提供免費資源和專業的技術支持,幫助您的業務快速、便捷地實現 Serverless!
3 秒你能作什麼?喝一口水,看一封郵件,仍是 —— 部署一個完整的 Serverless 應用?
複製連接至 PC 瀏覽器訪問:https://serverless.cloud.tencent.com/deploy/express
3 秒極速部署,當即體驗史上最快的 Serverless HTTP 實戰開發!
傳送門:
- GitHub: github.com/serverless
- 官網:serverless.com
歡迎訪問:Serverless 中文網,您能夠在 最佳實踐 裏體驗更多關於 Serverless 應用的開發!