Labelhub 是一家致力於爲人工智能企業提供完善的數據與模型解決方案公司,能夠幫助 AI 企業更好的管理數據,從而提升其核心 AI 產品迭代速度,Labelhub 擁有優秀的敏捷團隊,開發領域涉及機器學習、模型訓練以及軟件應用。目前已經與多家大中型企業進行深度合做,在行業相關比賽中也屢次獲獎。html
Labelhub 團隊在業務極速擴張的時期,選擇使用騰訊雲 Serverless
技術來打造一個輕量的內部運維及數據可視化系統。經過使用 Tencent Serverless Framework,基於雲上 Serverless 服務(雲函數及觸發器等),無需配置和部署,便可快速開發一套定製化數據可視化系統,騰訊雲 Serverless
技術不只知足了業務發展的需求,並且不須要耗費太多的人力和資金成本,是 Labelhub 的不二之選。 python
在實踐中,做者對騰訊雲 Serverless 產品逐漸產生了濃厚的興趣,但願能把本身對騰訊雲 Serverless 技術的理解,以及如何使用騰訊雲 Serverless 技術進行項目開發的實踐經驗分享給你們。mysql
我所在的團隊開發了一款針對人工智能企業數據標註產品Labelhub,目前正式的銷售工做處於摸索階段,對於目標客戶,產品的定位,一直沒有很好進行梳理。隨着業務的逐漸開展,平臺的運維安全也並無進行系統的監控管理。所以我考慮將產品的業務數據、服務器數據及應用監控數據作一個基本的內部運維及數據可視化系統。 git
雖然有不少的開源工具選擇,可是都避免不了部署及配置,二次開發也比較麻煩,所以考慮自行開發一套簡單的按內部需求徹底定製化的系統。github
最終,我決定使用 Serverless
來打造這樣一個輕量的內部系統,Serverless
無疑是時下最熱的 IT 詞彙之一,做爲一種新型的互聯網軟件產品架構,雖然早在 2012 年就被提出,但隨着近幾年容器技術、IoT
、區塊鏈以及 5G技術的快速發展,Serverless
的概念也借勢得以迅速發展。 sql
它究竟可以帶來什麼,它的紅利是否有門檻,離咱們究竟有多遠,值不值得如今開始投入,我會經過這一個項目的一系列文章來和你們一塊兒探討,從一名普通開發者的角度去看看 Serverless
。數據庫
我但願此係列文章可以淺顯易懂,我會盡量詳細的介紹我在開發這個系統的過程當中,對於Serverless
的理解。經過這一系列文章,我但願可以提供給你們的內容包括:json
real world serverless app
(若是想到更多會繼續補全)
此係列文章是基於 騰訊Serverless Framework 工具,同時後端使用 Python
進行開發後端
搭建後端項目結構api
Serverless Framework
的文檔中內心,框架支持裏目前有 Flask
以及 Django
,按照文檔示例中進行,會發現部署一個簡單的 rest api
十分容易,整個過程如官方宣稱的極速部署。
但看一下項目的結構會發現,只有一個 yml
配置文件、一個依賴文本和一個 app.py
文件,因爲配置文件中會使用 hooks
參數將依賴安裝到當前文件夾,這是一個很是簡單的一個示例。
在搭建後端項目目錄的時候,一般狀況下本地開發時並不須要考慮如下兩點:
對於 Serverless
,則須要考慮這兩個問題。
當在示例中執行 sls deploy
,部署成功後能夠在控制檯查看函數代碼,此時會發現依賴文件也在文件列表中,這很好的解釋了爲何說 一個函數是一個應用
。
可是實際開發過程當中,咱們不可能每個功能模塊都會去安裝一次依賴,所以咱們能夠藉助公共模塊來解決這個問題。可是公共模塊如何進行引入呢。
因爲 Serverless cli Component v2
已經取消了 include
配置,對於 v1
能夠很輕鬆的使用 include
配置將公共組件包含在函數中,從而各子函數可以很方便的進行調用。而對於 v2
,其實咱們能夠經過 Layer
來解決這個問題。
對於 v1 和 v2 的區別以及詳細介紹,可參考 Serverless Framework Cli的版本進化
模塊的拆分,咱們則能夠經過應用管理中的多實例管理來進行。
項目根目錄的處理
建立項目文件夾
mkdir labelhub-dashboard
在項目根目錄下應用配置文件
cd labelhub-dashboard touch serverless.yml
在應用配置文件中只用定義應用的名稱
app: labelhub-dashboard
公共文件及三方依賴目錄的處理
在根目錄文件夾下建立公共模塊文件夾
mkdir common
咱們將依賴以及公共函數放到common
中便於其餘模塊進行調用
# labelhub-dashboard/common touch requirements.txt # 建立數據庫鏈接工具類 touch dataUtils.py
因爲只是測試,也能夠直接在 common
下運行 pip install pymysql -t ./
將依賴安裝到當前路徑下。
這裏使用pymysql來鏈接數據庫進行測試
編輯 dataUtils.py
文件:
import pymysql class MysqlUtils: def __init__(self): self.getConn({ 'host': 'xxx', 'user': 'xxx', 'port': 3306, 'db': 'xxx', 'password': 'xxx' }) def getConn(self, conf): self.connection = pymysql.connect( host=conf['host'], user=conf['user'], password=conf['password'], port=conf['port'], db=conf['db'], charset='utf8', cursorclass=pymysql.cursors.DictCursor, autocommit=1 ) def doAction(self, stmt, data): try: self.connection.ping(reconnect=True) cursor = self.connection.cursor() cursor.execute(stmt, data) result = cursor cursor.close() return result except Exception as e: try: cursor.close() except: pass return False
準備就緒,就能夠進行部署了。前面說過,由於 common
咱們會做爲 公共函數及三方庫
存放的地方,所以咱們須要用 Layer
組件來進行部署。在 common
中建立配置文件
touch serverless.yml
編輯配置文件:
component: layer # 注意,這裏使用的是layer組件 name: common-layer org: labelhub-dashboard app: labelhub-dashboard stage: dev inputs: name: commonfiles # 記住這個名字 region: ap-guangzhou src: src: ./ exclude: - .env runtimes: - Python3.6 description: packages
而後執行 sls deploy
,Layer
層部署成功後,會出現函數的詳細信息,須要注意其中version
字段的值,部署完成後咱們開始建立功能模塊目錄。
功能模塊目錄的處理
在根目錄下建立一個測試子模塊
mkdir user-data
建立測試文件
touch index.py
編輯測試文件
from mysqlUtils import MysqlUtils import json db = MysqlUtils() def get_users(): search_stmt = ( "SELECT * FROM `user` limit 100;" ) result = db.doAction(search_stmt, ()) if result == False: return False return result def main_handler(event, context): result = get_users() data = [{'id': user['id'], 'name': str(user['name']), 'created_at': user['created_at'].strftime('%Y-%m-%d %H:%M:%S')} for user in result.fetchall()] return data
這裏有兩點須要說明:
mysqlUtils
是在 common
文件夾中,而這裏卻直接引入 mysqlUtils
,稍後在配置文件中會說明get_users()
爲什麼寫在這裏。其實也能夠寫在 mysqlUtils.py
中,可是由於 mysqlUtils.py
是在 Layer
層,而 Layer
層的部署目前使用狀況來看,比函數組件部署要耗時更長,所以我把它放在須要使用的函數文件中。即儘可能不去修改 common
裏的文件。準備就緒後就能夠部署函數了。首先仍然是建立配置文件:
touch serverless.yml
編輯配置文件:
component: scf # 注意,這裏使用的是scf組件 name: userdata stage: dev app: labelhub-dashboard org: labelhub-dashboard #組件參數 inputs: name: ${name}-${stage}-${app} #函數名稱 src: src: ./ #代碼路徑 exclude: - .env handler: index.main_handler #入口 runtime: Python3.6 # 雲函數運行時的環境 region: ap-guangzhou # 雲函數所在區域 layers: - name: commonfiles version: 1 events: # 觸發器 - apigw: # 網關觸發器 parameters: endpoints: - path: / method: GET
經過配置文件,咱們能夠發現,其中的 layers
配置中的 name
以及 version
,就是在部署 common
時的名稱和部署成功後的版本號。
最後執行 sls deploy
完成部署,直接訪問生成的 url
地址,能夠查看到正確的返回信息。
小結
最終文件夾的結構爲:
labelhub-dashboard/ ------------------serverless.yml ------------------common/ ------------------------requirements.txt ------------------------serverless.yml ------------------------mysqlUtils.py ------------------user-data/ ---------------------------serverless.yml ---------------------------index.py
在部署 user-data
函數時,咱們看到引入 mysqlUtils
,是經過直接引入的方式,而在 user-data
函數的配置文件中能夠看到咱們使用了對應的 layers
配置。從這裏能夠看出,在函數的配置中,layers
其實就至關於 v1
中的 include
配置,默認 Layer
組件中的文件與函數文件在相同目錄下。
其實咱們能夠將全部文件建立好後,在根目錄中執行 sls deploy --all
來一次性進行部署,但在使用過程當中會出現函數組件部署報錯,找不到對應的 Layer
組件,這也是由於函數組件部署過程當中會去讀取 layers
的配置,而經過實際使用過程當中發現 Layer
組件的部署幾乎都會比函數組件慢不少,所以官方也是建議優先部署 Layer
組件,以後再統一部署函數組件。那麼咱們就須要考慮,函數的應用根目錄,是否能夠和公共組件目錄同級,這樣在使用 sls deploy --all
的時候,才能夠避免同時更新 Layer 層。
至此,簡單的後端開發環境就已經搭建好了,相比於官方提供的文檔的示例,完善了對於實際開發過程當中三方依賴和公共函數的處理,後續開發過程當中若須要更多依賴,只須要在對應的組件中進行添加便可,而對於功能模塊的擴展,也只須要建立相應的目錄去進行擴展。
後面的文章,我會詳細介紹對於單個模塊功能的開發過程,更多依賴的添加進行嘗試,儘量按照實際開發過程來進一步優化項目的結構。
當即體驗騰訊雲 Serverless Demo,領取 Serverless 新用戶禮包 👉 serverless/start
歡迎訪問: Serverless 中文網!