日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

在日常生活中,我們經常會遇到搜索照片的情況,如果是要尋找已經過去很久的照片,并且記憶中僅剩下零散記憶,常用的檢索照片的方法是定位到大致的時間,然后一張一張的去查看。但這種做法效率低下,經常還會漏掉目標圖片,所以在這種時候,我們很需要一款可以搜索圖片的軟件,即通過簡單的文字描述就能實現圖片的快速檢索。

近幾年微信小程序的發展速度飛快,從張小龍在 2017 微信公開課 Pro 上發布小程序正式上線到目前為止,小程序已經覆蓋了超過 200 個細分行業,服務超過 1000 億人次用戶,年交易增長超過 600%,創造超過 5000 億的商業價值。

本實例將會通過微信小程序,在 Serverless 架構上實現一款基于人工智能的相冊小工具,在保證基礎相冊功能(新建相冊、刪除相冊、上傳圖片、查看圖片、刪除圖片)的基礎上,增加搜索功能,即用戶上傳圖片之后,基于 Image Caption 技術自動對圖片進行描述,實現 Image to Text 的過程,當用戶進行搜索時,通過文本間的相似度返回給用戶最貼近的圖片。

基礎設計

基于 Serverless Framework 的人工智能小程序開發

 

該項目設計主要包括登錄功能、相冊新建、圖片上傳、相關預覽以及搜索功能,整體如圖所示。

基于 Serverless Framework 的人工智能小程序開發

 

其中注冊功能的主要作用是,通過獲取用戶的唯一 Id(微信中的 OpenId),將用戶信息存儲到數據庫中,之后的所有操作都需要根據該 Id 作為區分。相冊功能主要包括相冊添加、修改、刪除以及查看等。圖片功能包括圖片上傳功能、刪除功能、查看功能。搜索功能主要是可以查看指定標簽對應的圖片列表,以及指定搜索內容對應的列表。當然這四個主要功能和模塊是與前端關系緊密的部分,除此之外還有后端異步操作的兩個模塊,分別是圖像壓縮功能和圖像描述功能。

注冊功能

注冊功能主要是用戶點擊注冊賬號之后執行的動作。該動作需要注意,用戶點擊注冊賬號注冊的時候要先判斷用戶是否已經注冊過,如果已經注冊過則默認登陸,否則進行注冊并登陸。當用戶不想注冊時,可以點擊體驗程序,可以對程序大部分頁面進行預覽。但是不能實現有關數據庫的增刪改查等功能。

登錄功能頁面如圖所示。

基于 Serverless Framework 的人工智能小程序開發

 

相冊功能

當用戶注冊登錄之后,可以在相冊管理頁面進行相冊相關的管理,包括編輯功能、刪除功能以及新建功能,此處在進行添加和修改的時候,需要注意相冊名稱是否已經存在;在進行刪除、修改相冊等操作時要判斷用戶是否有操作該相冊的權限等。

下圖是相冊功能相關原型圖。

基于 Serverless Framework 的人工智能小程序開發

 

圖片功能

圖片功能主要包括圖片列表以及圖片獲取、圖片刪除以及圖片上傳功能,在圖片獲取與刪除的過程中,要對用戶是否有該項操作的權限進行判斷,圖片上傳時也要判斷用戶是否有上傳到指定相冊的權限。圖片功能相關原型圖如所示。

基于 Serverless Framework 的人工智能小程序開發

 

圖片功能部分除了用戶側可見的功能,還有定時任務,當用戶上傳圖片之后,系統會在后臺異步進行圖像壓縮以及圖像的描述、關鍵詞提取等。

整體流程如圖所示:

基于 Serverless Framework 的人工智能小程序開發

 

搜索功能

搜索功能指的是通過關鍵詞或者使用者的描述,獲得目標數據的過程,這一功能原型圖如圖所示:

基于 Serverless Framework 的人工智能小程序開發

 

這一部分的難點和重點在于通過用戶的描述,搜索到目標數據。這個過程的基本流程如圖所示:

基于 Serverless Framework 的人工智能小程序開發

 

項目開發

初步了解 Serverless Cli

Serverless 架構具備按量付費、低成本運維、高效率開發等優點,可以幫助我們快速開發,快速迭代項目。而 Serverless Framework 則是一個非常高效的工具,其兼容了 AWS,google Cloud 以及騰訊云等多家廠商的 Serverless 架構,為開發者提供一個多云的開發者工具,若以騰訊云為例,其擁有 Plugin 和 Components 兩個部分。

Plugin 和 Components 這兩個部分可以說是各有千秋,具體操作大家可以參看官方說明,我在這里想列舉幾點:

  • Plugin 部署到線上的函數會自動變更名字,例如函數是 myFunction,服務和階段是 myService-Dev,那么函數部署到線上就是 myService-Dev-myFunction,這樣的函數名,很可能會讓函數間調用等部分產生很多不可控因素。例如現在的環境是 Dev,函數間調用就要寫函數名是 myService-Dev-myFunction,如果環境是 Test,此時就要寫 myService-Test-myFunction,我始終覺得,更改環境應該只需要更改配置,而不是更深入的代碼邏輯。
  • Plugin 也是有優勢的,例如 Invoke、Remove 以及部署單個函數的功能,同時 Plugin 也有全局變量,這更像是一個開發者工具,可以開發、部署、調用、查看一些信息、指標,刪除回滾等操作也可以通過 Plugin 完成;
  • Components 可以看作是一個組件集,這里面包括了很多的 Components,既有基礎的 Components,例如 cos、scf、apigateway 等,也有一些拓展的 Components,例如在 cos 上拓展出來的 website,可以直接部署靜態網站等,還有一些框架級的,例如 Koa、Express 等;
  • Components 除了支持的產品多,可以部署框架之外,更有吸引力的是其部署到線上的函數名字就是我指定的名字,不會出現額外的東西;
  • 相比 Plugin,Components 在功能上略顯單薄,除了部署和刪除,再沒有其他功能了。如果有多個功能要部署,并寫在了一個 Components 的 yaml 上,那么每次部署都要部署所有的功能。換句話說,如果你只修改了一個函數,并且因為不想重新部署函數,而希望注釋掉其它函數,這個是無法實現的,在 Components 看來就只有一個函數,并且它還會幫你把注釋掉的函數在線上刪除;
  • Components 更多的定義是組件,所以每個組件就是一個東西,在 Components 上是沒有全局變量的。

綜上所述,對比 Plugin 和 Components 各有優劣,我很期待產品策略能夠將二者合并或者功能對齊。在本文,我選擇了 Components 來做這個項目。

造輪子:全局變量組件

使用 Components 做項目,我遇到的第一個難題是配置文件怎么辦?我有很多的配置,我難道要在每個函數中寫一遍?

于是,我做了一個新的: serverless-global 。這是一個 Components 功能,用來滿足全局變量的需求。

復制代碼

Conf:  component: "serverless-global"  inputs:    MySQL_host: gz-cdb-mytest.sql.tencentcdb.com    mysql_user: mytest    mysql_password: mytest    mysql_port: 62580    mysql_db: mytest    mini_program_App_id: mytest    mini_program_app_secret: mytest

在使用的時候,只需要使用${}就可以引用,例如:

復制代碼

Album_Login:  component: "@serverless/tencent-scf"  inputs:    name: Album_Login    codeUri: ./album/login    handler: index.main_handler    runtime: Python3.6    region: ap-shanghai    environment:      variables:        mysql_host: ${Conf.mysql_host}        mysql_port: ${Conf.mysql_port}        mysql_user: ${Conf.mysql_user}        mysql_password: ${Conf.mysql_password}        mysql_db: ${Conf.mysql_db}

利用這個功能就可以很輕松將配置信息統一提取到了一個地方。需要說明的是,為什么我要把一些配置信息放在環境變量,而不是統一放在一個配置文件中,因為環境變量在 SCF 中會真的打到環境中,也就是說,你可以直接取到,我個人覺得比每次創建實例讀取一次配置文件性能要好一些,雖然性能優勢有限,但是,我還是覺得這樣做是比較優雅的。最主要的是,相比寫到代碼中和配置到單獨的配置文件中,這樣做可以將代碼分享給別人,并更好的保護敏感信息。

數據庫設計

基于 Serverless Framework 的人工智能小程序開發

 

數據庫部分主要對相關的表和表之間的關系進行建立。首先需要創建項目所必須的表:

復制代碼

 CREATE DATABASE `album`;CREATE TABLE `album`.`tags` ( `tid` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(255) NOT NULL , `remark` TEXT NULL , PRIMARY KEY (`tid`)) ENGINE = InnoDB;CREATE TABLE `album`.`category` ( `cid` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(255) NOT NULL , `sorted` INT NOT NULL DEFAULT '1' , `user` INT NOT NULL , `remark` TEXT NULL , `publish` DATE NOT NULL , `area` VARCHAR(255) NULL , PRIMARY KEY (`cid`)) ENGINE = InnoDB;CREATE TABLE `album`.`users` ( `uid` INT NOT NULL AUTO_INCREMENT , `nickname` TEXT NOT NULL , `wechat` VARCHAR(255) NOT NULL , `remark` TEXT NULL , PRIMARY KEY (`uid`)) ENGINE = InnoDB;CREATE TABLE `album`.`photo` ( `pid` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(255) NOT NULL , `small` VARCHAR(255) NOT NULL , `large` VARCHAR(255) NOT NULL , `category` INT NOT NULL , `tags` VARCHAR(255) NULL , `remark` TEXT NULL , `creattime` DATE NOT NULL , `creatarea` VARCHAR(255) NOT NULL , `user` INT NOT NULL ,  PRIMARY KEY (`pid`)) ENGINE = InnoDB;CREATE TABLE `album`.`photo_tags` ( `ptid` INT NOT NULL AUTO_INCREMENT , `tag` INT NOT NULL , `photo` INT NOT NULL , `remark` INT NULL , PRIMARY KEY (`ptid`)) ENGINE = InnoDB; 

創建之后,逐步添加表之間的關系以及部分限制條件:

復制代碼

 ALTER TABLE `photo_tags` ADD CONSTRAINT `photo_tags_tags_alter` FOREIGN KEY (`tag`) REFERENCES `tags`(`tid`) ON DELETE CASCADE ON UPDATE RESTRICT; ALTER TABLE `photo_tags` ADD CONSTRAINT `photo_tags_photo_alter` FOREIGN KEY (`photo`) REFERENCES `photo`(`pid`) ON DELETE CASCADE ON UPDATE RESTRICT;ALTER TABLE `photo` ADD CONSTRAINT `photo_category_alter` FOREIGN KEY (`category`) REFERENCES `category`(`cid`) ON DELETE CASCADE ON UPDATE RESTRICT;ALTER TABLE `photo` ADD CONSTRAINT `photo_user_alter` FOREIGN KEY (`user`) REFERENCES `users`(`uid`) ON DELETE CASCADE ON UPDATE RESTRICT;ALTER TABLE `category` ADD CONSTRAINT `category_user_alter` FOREIGN KEY (`user`) REFERENCES `users`(`uid`) ON DELETE CASCADE ON UPDATE RESTRICT;ALTER TABLE `tags` ADD unique(`name`); 

函數功能開發

接下來,開始寫第一個函數——注冊登錄函數。因為這是一個小程序,所以注冊登錄實際上就是拿著用戶的 openId 去數據庫查查有沒有信息,有信息的話,就執行登錄,沒有信息的話就 insert 一下。那么問題來了,如何連接數據庫?之所以有這樣的問題,是源自兩個因素:

  • 我們平時做項目的時候,并不是每次請求都連接一次數據庫,很多時候,數據庫的連接是可以保持下來的,但是在 Serverless 架構下可以實現嗎?或者我們需要去哪里連接數據庫呢?
  • 傳統項目,我們做數據庫連接只用一個方法就可以搞定,但是函數中,每個函數都是單獨存在的,是否每個函數都要連接一下數據庫?

初始化資源探索

針對問題 1,我們來做一個實驗,先在騰訊云云函數創建一個 test:

基于 Serverless Framework 的人工智能小程序開發

 

創建之后,瘋狂點擊測試按鈕,多次記錄運行日志:

第一次

復制代碼

START RequestId: 4facbf59-3787-11ea-8026-52540029942f Event RequestId: 4facbf59-3787-11ea-8026-52540029942f 11111111 222222222  END RequestId: 4facbf59-3787-11ea-8026-52540029942f Report RequestId: 4facbf59-3787-11ea-8026-52540029942f Duration:1ms Memory:128MB MaxMemoryUsed:27.3164MB

第二次

復制代碼

START RequestId: 7aaf7921-3787-11ea-aba7-525400e4521d Event RequestId: 7aaf7921-3787-11ea-aba7-525400e4521d 222222222  END RequestId: 7aaf7921-3787-11ea-aba7-525400e4521d Report RequestId: 7aaf7921-3787-11ea-aba7-525400e4521d Duration:1ms Memory:128MB MaxMemoryUsed:27.1953MB

第三次

復制代碼

START RequestId: 742be57a-3787-11ea-b5c5-52540047de0f Event RequestId: 742be57a-3787-11ea-b5c5-52540047de0f 222222222  END RequestId: 742be57a-3787-11ea-b5c5-52540047de0f Report RequestId: 742be57a-3787-11ea-b5c5-52540047de0f Duration:1ms Memory:128MB MaxMemoryUsed:27.1953MB

第四次

復制代碼

START RequestId: 6faf934b-3787-11ea-8026-52540029942f Event RequestId: 6faf934b-3787-11ea-8026-52540029942f 222222222  END RequestId: 6faf934b-3787-11ea-8026-52540029942f Report RequestId: 6faf934b-3787-11ea-8026-52540029942f Duration:1ms Memory:128MB MaxMemoryUsed:27.1953MB

大家仔細觀察,發現了什么?我在函數外側寫的print("11111111")實際上只出現了一次,也就是說只運行了一次,而函數內的print("222222222")則是出現了多次,確切來說是每次都會出現,函數在創建的時候,會讓我們寫一個執行方法,例如index.main_handler,就是說默認的入口文件就是index.py下的main_handler方法。通過剛才的小實驗,是不是可以認為,云函數實際上是隨著機器或者容器啟動同時啟動了一個進程(這個時候會走一次外圍的一些代碼邏輯),然后當函數執行的時候,會走我們指定的方法,當函數執行完,這個容器并不會被馬上銷毀,而是進入銷毀的倒計時,這個時候如果有請求來了,那么很可能復用這個容器,此時就沒有容器啟動的說法,會直接執行我們的方法。

按照這個邏輯,是不是我們的函數,如果要在我們的方法之外,初始化數據庫就可以保證盡可能少的數據庫連接建立,而滿足更多的請求呢?換句話說,是不是和容器復用類似,我們就可以復用數據庫的連接了?

所以,我們可以嘗試這樣寫整個代碼(login 為例)

復制代碼

# -*- coding: utf8 -*- import osimport pymysqlimport json connection = pymysql.connect(host=os.environ.get('mysql_host'),                             user="root",                             password=os.environ.get('mysql_password'),                             port=int(62580),                             db="mini_album",                             charset='utf8',                             cursorclass=pymysql.cursors.DictCursor,                             autocommit=1) def getUserInfor(connection, wecaht):    try:        connection.ping(reconnect=True)        cursor = connection.cursor()        search_stmt = (            "SELECT * FROM `users` WHERE `wechat`=%s"        )        data = (wecaht)        cursor.execute(search_stmt, data)        cursor.close()        result = cursor.fetchall()        return len(result)    except Exception as e:        print("getUserInfor", e)        try:            cursor.close()        except:            pass        return False def addUseerInfor(connection, wecaht, nickname, remark):    try:        connection.ping(reconnect=True)        cursor = connection.cursor()        insert_stmt = (            "INSERT INTO users(wechat,nickname,remark) "            "VALUES (%s,%s,%s)"        )        data = (wecaht, nickname, remark)        cursor.execute(insert_stmt, data)        cursor.close()        connection.close()        return True    except Exception as e:        print(e)        try:            cursor.close()        except:            pass        return False  def main_handler(event, context):    print(event)    body = json.loads(event['body'])    wecaht = body['wechat']    nickname = body['nickname']    remark = str(body['remark'])     if getUserInfor(connection, wecaht) == 0:        if addUseerInfor(connection, wecaht, nickname, remark):            result = True        else:            result = False    else:        result = True     return {        "result": result    } 

公共組件的編寫

  • 如果這個函數要作為小程序的一個接口,那么就要接 APIGW,那么如何才能實現本地測試呢?每次都發到線上配置 APIGW 觸發器才能測試,這顯然是不現實的。
  • 這個函數需要數據庫的連接,需要獲取用戶的信息等,難道別的函數不需要嗎?如果需要,那么是否每個函數都要重復寫這部分代碼?或者說,代碼的復用應該如何處理呢?是否可以提取公共組件呢?

所以,我將這個函數進行了規范化和完整化:

復制代碼

# -*- coding: utf8 -*- import json try:    import returnCommon    from mysqlCommon import mysqlCommonexcept:    import common.testCommon     common.testCommon.setEnv()     import common.returnCommon as returnCommon    from common.mysqlCommon import mysqlCommon  mysql = mysqlCommon()  def main_handler(event, context):    try:        print(event)         body = json.loads(event['body'])         wecaht = body['wechat']        nickname = body['nickname']        remark = str(body['remark'])         if not wecaht:            return returnCommon.return_msg(True, "請使用微信小程序登陸本頁面。")         if not mysql.getUserInfor(wecaht):            if not nickname:                return returnCommon.return_msg(True, "參數異常,請重試。")            if mysql.addUserInfor(wecaht, nickname, remark):                return returnCommon.return_msg(False, "注冊成功")            return returnCommon.return_msg(True, "注冊失敗,請重試。")        return returnCommon.return_msg(False, "登錄成功")    except Exception as e:        print(e)    return returnCommon.return_msg(True, "用戶信息異常,請聯系管理員處理") def test():    event = {        "requestContext": {            "serviceId": "service-f94sy04v",            "path": "/test/{path}",            "httpMethod": "POST",            "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",            "identity": {                "secretId": "abdcdxxxxxxxsdfs"            },            "sourceIp": "14.17.22.34",            "stage": "release"        },        "headers": {            "Accept-Language": "en-US,en,cn",            "Accept": "text/html,application/xml,application/json",            "Host": "service-3ei3tii4-251000691.ap-guangzhou.apigateway.myqloud.com",            "User-Agent": "User Agent String"        },        "body": json.dumps({            "wechat": "12345",            "nickname": "test",            "remark": "",        }),        "pathParameters": {            "path": "value"        },        "queryStringParameters": {            "foo": "bar"        },        "headerParameters": {            "Refer": "10.0.2.14"        },        "stageVariables": {            "stage": "release"        },        "path": "/test/value",        "queryString": {            "foo": "bar",            "bob": "alice"        },        "httpMethod": "POST"    }    print(main_handler(event, None))  if __name__ == "__main__":    test()

數據庫等一些公共組件,統一放在common目錄下,例如mysqlCommon.py(部分):

復制代碼

# -*- coding: utf8 -*- import osimport randomimport pymysqlimport datetime try:    import cosClientexcept:    import common.cosClient as cosClient  class mysqlCommon:    def __init__(self):        self.getConnection({            "host": os.environ.get('mysql_host'),            "user": os.environ.get('mysql_user'),            "port": int(os.environ.get('mysql_port')),            "db": os.environ.get('mysql_db'),            "password": os.environ.get('mysql_password')        })     def getConnection(self, conf):        self.connection = pymysql.connect(host=conf['host'],                                          user=conf['user'],                                          password=conf['password'],                                          port=int(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:            print(e)            try:                cursor.close()            except:                pass            return False     def addUserInfor(self, wecaht, nickname, remark):        insert_stmt = (            "INSERT INTO users(wechat, nickname, remark) "            "VALUES (%s,%s,%s)"        )        data = (wecaht, nickname, remark)        result = self.doAction(insert_stmt, data)        return False if result == False else True       

這樣做的好處是:

  • 將數據庫提取出一個公共組件,便于維護
  • 在 login 函數中,根據不同的時期(本地開發和線上)可以導入不同的模塊

便于開發與測試的方法

由于云函數的測試非常不友好,所以為了在編寫代碼時可以更快地模擬線上環境,我選擇通過增加test()方法來模擬觸發器情況,進行簡單的測試。

復制代碼

try:    import cosClientexcept:    import common.cosClient as cosClient

這樣會更加便利,同時模擬網關,做一個測試方法:

復制代碼

def test():    event = {        "requestContext": {            "serviceId": "service-f94sy04v",            "path": "/test/{path}",            "httpMethod": "POST",            "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",            "identity": {                "secretId": "abdcdxxxxxxxsdfs"            },            "sourceIp": "14.17.22.34",            "stage": "release"        },        "headers": {            "Accept-Language": "en-US,en,cn",            "Accept": "text/html,application/xml,application/json",            "Host": "service-3ei3tii4-251000691.ap-guangzhou.apigateway.myqloud.com",            "User-Agent": "User Agent String"        },        "body": json.dumps({            "wechat": "12345",            "nickname": "test",            "remark": "",        }),        "pathParameters": {            "path": "value"        },        "queryStringParameters": {            "foo": "bar"        },        "headerParameters": {            "Refer": "10.0.2.14"        },        "stageVariables": {            "stage": "release"        },        "path": "/test/value",        "queryString": {            "foo": "bar",            "bob": "alice"        },        "httpMethod": "POST"    }    print(main_handler(event, None))

增加本地測試時,指定test()方法:

復制代碼

if __name__ == "__main__":    test()

這樣,線上觸發時會默認執行main_handler, 而本地執行,則會通過test走入main_handler,我們可以邊開發,邊測試,全部弄好之后再部署到線上。

線上獲取配置信息是通過獲取環境變量,本地又該如何執行?我們需要先進行這個操作:

復制代碼

# -*- coding: utf8 -*- import yamlimport os  def setEnv():    file = open("/Users/dfounderliu/Documents/code/AIAlbum/serverless.yaml", 'r', encoding="utf-8")    file_data = file.read()    file.close()     data = yaml.load(file_data)    for eveKey, eveValue in data['Conf']['inputs'].items():        print(eveKey, eveValue)        os.environ[eveKey] = str(eveValue) 

這樣,我們這個文件就既可以線上直接用,也可以本地直接用了!

那么,Yaml 怎么寫?

基于 Serverless Framework 的人工智能小程序開發

 

然后,我們可以在部署函數的時候將公共組件引入項目中。

本地形式:

基于 Serverless Framework 的人工智能小程序開發

 

線上形式:

基于 Serverless Framework 的人工智能小程序開發

 

項目部署

  • 在使用之前,需要先有一個騰訊云的賬號,并且開通了 COS、COS、APIGW 以及 CDB 等相關產品權限;
  • 將項目 clone 到本地,配置自己的密鑰信息、數據庫信息。配置文件在cloudFunction目錄下的serverless.yaml中:

復制代碼

# 函數們的整體配置信息Conf:  component: "serverless-global"  inputs:    region: ap-shanghai    runtime: Python3.6    handler: index.main_handler    include_common: ./common    mysql_host: gz-c************************.com    mysql_user: root    mysql_password: S************************!    mysql_port: 6************************0    mysql_db: album    mini_program_app_id: asdsa************************dddd    mini_program_app_secret: fd340c4************************8744ee    tencent_secret_id: AKID1y************************l1q0kK    tencent_secret_key: cCoJ************************FZj5Oa    tencent_appid: 1256773370    cos_bucket: 'album-1256773370'    domain: album.0duzahn.com

由于我目前使用的是 Serverless Components,沒有全局變量等,所以在此處增加了全局變量組件,在這里設置好全局變量,在之后的 Components 中可以直接引用,例如:

復制代碼

# 創建存儲桶CosBucket:  component: '@serverless/tencent-website'  inputs:    code:      src: ./cos    region:  ${Conf.region}    bucketName: ${Conf.cos_bucket}
  • 安裝必備工具,例如必須要安裝 Serverless Framework(可以參考: https://cloud.tencent.com/document/product/1154/39005), 同樣由于本項目后臺開發語言是 Python,您也需要一些 Python 的開發工具以及包管理工具,以及小程序云開發的 IDE;
  • 在部分文件夾下安裝相對應的依賴:cloudFunction/album/prdiction需要安裝 Pillow, opencv,tensorflow,jiebacloudFunction/album/getPhotoSearch需要安裝 gensim,jieba 以及 collectionscloudFunction/album/compression需要安裝 Pillow
    注意,在安裝的時候一定要用 centos 操作系統,并且 Python 要 3.6 版本,如果沒相對應系統,可以在這里打包對應的依賴: http://serverless.0duzhan.com/app/scf_python_package_download/
  • 將項目部署到云端,只需要通過指令serverless --debug即可:

復制代碼

DEBUG ─ Resolving the template's static variables.  DEBUG ─ Collecting components from the template.  DEBUG ─ Downloading any NPM components found in the template.  DEBUG ─ Analyzing the template's components dependencies.  DEBUG ─ Creating the template's components graph.  DEBUG ─ Syncing template state.  DEBUG ─ Executing the template's components graph.  DEBUG ─ Starting API-Gateway deployment with name APIService in the ap-shanghai region     ... ...   DEBUG ─ Updating configure...   DEBUG ─ Created function Album_Get_Photo_Search successful  DEBUG ─ Setting tags for function Album_Get_Photo_Search  DEBUG ─ Creating trigger for function Album_Get_Photo_Search  DEBUG ─ Deployed function Album_Get_Photo_Search successful  DEBUG ─ Uploaded package successful /Users/dfounderliu/Documents/code/AIAlbum/.serverless/Album_Prediction.zip  DEBUG ─ Creating function Album_Prediction  DEBUG ─ Updating code...   DEBUG ─ Updating configure...   DEBUG ─ Created function Album_Prediction successful  DEBUG ─ Setting tags for function Album_Prediction  DEBUG ─ Creating trigger for function Album_Prediction  DEBUG ─ Trigger timer: timer not changed  DEBUG ─ Deployed function Album_Prediction successful   Conf:     region:                  ap-shanghai            ... ...            -         path:   /photo/delete        method: ANY        apiId:  api-g9u6r9wq      -         path:   /album/delete        method: ANY        apiId:  api-b4c4xrq8      -         path:   /album/add        method: ANY        apiId:  api-ml6q5koy   156s › APIService › done 

這個過程只用了 156s 就部署了所有函數,然后打開小程序的 id 帶入miniProgram目錄,并且填寫自己的appid在文件project.config.json的第 17 行,同時也要配置自己項目的基礎目錄,就是 API 網關給我們返回的地址,寫在app.js的第 10 行,此時項目就可以運行起來了。

總結

本文中的例子是通過 Serverless 架構使用 Python 語言開發了一個微信小程序,這里面涉及到了數據庫的增刪改查,公共組件的提取,如何定義 Components 的全局變量,如何本地調試和線上觸發二者兼得,以及在什么地方初始化數據庫"性價比較高"。希望通過這樣一個簡單的例子,可以讓 Serverless 在更多的領域都有實際的應用價值,可以給更多人靈感和啟發:Serverless?萬物都可以 Serverless 么?讓我們一起來嘗試更多 Serverless 架構的應用領域吧。

分享到:
標簽:Serverless Framework
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定