Labelhub 基於騰訊雲 Serverless 技術爲人工智能企業提供數據與模型解決方案

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
  • 對於服務拆分的理解,如何更有效的利用資源
  • 現有的BaaS遷移至FaaS的設想
(若是想到更多會繼續補全)

此係列文章是基於 騰訊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 deployLayer 層部署成功後,會出現函數的詳細信息,須要注意其中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 層。

至此,簡單的後端開發環境就已經搭建好了,相比於官方提供的文檔的示例,完善了對於實際開發過程當中三方依賴和公共函數的處理,後續開發過程當中若須要更多依賴,只須要在對應的組件中進行添加便可,而對於功能模塊的擴展,也只須要建立相應的目錄去進行擴展。

後面的文章,我會詳細介紹對於單個模塊功能的開發過程,更多依賴的添加進行嘗試,儘量按照實際開發過程來進一步優化項目的結構。

One More Thing

當即體驗騰訊雲 Serverless Demo,領取 Serverless 新用戶禮包 👉 serverless/start

歡迎訪問: Serverless 中文網
相關文章
相關標籤/搜索