實驗室站遷移 Serverless 之路(上)

本文為 Serverless 社區成員撰稿。作者高晨遠,研發工程師,熟悉 Python 開發,常寫 Web 和爬蟲

前言

2 月份,TencentServerless 舉辦了系列在線課堂分享,講解了 Serverless 概念、架構、最佳實踐以及如何開發一個 component 等技術知識。

因為對 Serverless 非常感興趣,每次都參加了直播學習並提交了課堂作業,一路下來感覺還不錯,因此決定把自己的實驗室站遷移到 Serverless 試試看。

1. TencentServerless 介紹

不得不感嘆互聯網時代科技的進步,之前我的實驗室站採用的是傳統方法發佈網站的環境部署,雖然現在熟悉了操作並不覺得很麻煩,但是對於從來沒接觸過這塊的人來說就比較難懂了。

而現在有了 Serverless,就可以完全無視上面的操作步驟了,這裡引用官網的兩段話:

Serverless Framework 可以幫您以更少的成本和開銷, 快速構建 Serverless 應用。它能夠完美支持無服務器應用的開發,部署,測試,監控等環節。Serverless 是面向未來的運維方式。

Serverless 建立在下一代公共雲服務之上,該服務僅在使用時自動擴容和收費。當規模,所用容量和成本管理實現自動化時,可節省 99% 的成本管理。

無服務器架構是全新的,因此我們需要改變先前對老架構和工作流的看法。Serverless Framework 的目標是以一種簡單,強大而優雅的使用體驗為開發者、團隊提供開發和運行 serverless 應用程序所需的所有工具。

這種方式非常方便,本人現在倒是覺得對於個人開發者來說,如果想構建輕量應用的話,用 Serverless 應該會節省非常多的時間。當然 Serverless 對比傳統型應用還是有區別的,目前它並不能完美支持,舉一個例子:Flask CLI 就不支持,不過相信隨著 Serverless 技術的發展,Serverless 的支持將更加全面。

對於企業開發者來說也是同理的,想快速上線一套網站的話,部署在一個服務器上倒是好說,可是當訪問量上升之後,需要擴容的時候就比較麻煩了,這時候你得在多個服務器上部署並且配置負載均衡等等。

對我個人來說,我覺得 Serverless 最大的優點在於運維部署方面,通過 Serverless 部署,還是非常方便的。

2. 安裝 Serverless Framework

Serverless Framework 是基於 Node.js 的開源 CLI,注:需 Node 8+ 全局安裝:

<code>npm install serverless -g/<code>

這裡沒有使用 cnpm 的原因是因為網絡還算 ok 沒有特別耗時,另外忘記了之前在哪裡看到過 cnpm 不會更新 package-lock.json,因此也就沒有再去用第三方源。之後更新的話就

<code>npm install serverless -g/<code>

官網的快速開始教程之後快速部署了個 demo,即:

<code>serverless create -t tencent-nodejs/<code>

命令裡的 tencent-nodejs 是眾多組件中的一個,組件列表:https://github.com/serverless/components

3. 部署 Python Flask 框架

因為本人對 Flask 還算熟悉,所以乾脆把部署這個 Component 當成 Hello World 好了。其中官網簡介裡寫道:任何支持 WSGI(Web Server Gateway Interface)的 Python 服務端框架都可以通過該組件進行部署,例如 Falcon 框架等。

1) 創建新項目

  • 基於模板

通過 sls 直接根據模板創建服務,Serverless github 上有很多模板 比如:https://github.com/serverless/components/tree/master/templates/tencent-flask

<code>serverless create --template-url https://github.com/serverless/components/tree/master/templates/tencent-flask/<code>

源碼如下:

<code># -*- coding: utf8 -*-

import json
from flask import Flask, jsonify, request
app = Flask(__name__)


@app.route("/")
def index():

return "Hello Flash"

@app.route('/user', methods = ['POST'])
def addUser():
# we must get request body from clound function event;
event = request.environ['event']
user = json.loads(event['body'])
return jsonify(data=user)


@app.route("/user", methods = ['GET'])
def listUser():
users = [{'name': 'test1'}, {'name': 'test2'}]
return jsonify(data=users)


@app.route("/user/<id>", methods = ['GET'])
def getUser(id):
return jsonify(data={'name': 'test1'})/<code>
  • 不基於模板

在 Pycharm 創建一個新的 Flask 項目:LAB_Serverless 以區別之前的 LAB

實驗室站遷移 Serverless 之路(上)

實驗室站遷移 Serverless 之路(上)

源碼如下:

<code>from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello World!'

if __name__ == '__main__':
app.run()/<code>

2) 配置Serverless

  • 創建serverless.yml,這裡更改了幾處配置
<code>
MyComponent:
component: '@serverless/tencent-flask'
inputs:
region: ap-beijing
functionName: LAB_Serverless
code: ./
functionConf:
timeout: 10
memorySize: 128
environment:
variables:
TEST: value
Version: 2020-2-23_21:01:44
vpcConfig:
subnetId: ''
vpcId: ''
apigatewayConf:
protocol: https
environment: test
/<code>
  • 創建.env,寫入密匙(因為懶得每次部署都得拿起手機掃一掃授權(^_−)☆
<code>TENCENT_SECRET_ID=<rm>
TENCENT_SECRET_KEY=<rm>/<code>

3) 部署

serverless 的縮寫是 sls,因此也可以用 sls 簡化命令。但是這裡報錯了……報錯的原因是requirements文件夾不存在。

查看終端

<code>Microsoft Windows [版本10.0.17763.1039]
(c) 2018 Microsoft Corporation。保留所有權利。

D:\\yuangezhizao\\Documents\\PycharmProjects\\LAB_Serverless>sls --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─Compressing function LAB_Serverless file to D:\\yuangezhizao\\Documents\\PycharmProjects\\LAB_Serverless\\.serverless/LAB_Serverless.zip.
(node:22500) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, stat 'D:\\yuangezhizao\\Documents\\PycharmProjects\\LAB_Serverless\\.
serverless\\requirements'eploying
at Object.statSync (fs.js:946:3)
at Object.statSync (C:\\Users\\yuangezhizao\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\[email protected]@graceful-fs\\polyfills.js:308:16
)
at WriteStream.<anonymous> (C:\\Users\\yuangezhizao\\.serverless\\components\\registry\\npm\\@serverless\\[email protected]\\node_modules\\@serverless\\tencen
t-flask\\node_modules\\@serverless\\tencent-scf\\library\\utils.js:124:20)
at WriteStream.emit (events.js:304:20)
at C:\\Users\\yuangezhizao\\.serverless\\components\\registry\\npm\\@serverless\\[email protected]\\node_modules\\@serverless\\tencent-flask\\node_modules\\grac
eful-fs\\graceful-fs.js:298:14
at C:\\Users\\yuangezhizao\\.serverless\\components\\registry\\npm\\@serverless\\[email protected]\\node_modules\\@serverless\\tencent-flask\\node_modules\\grac
eful-fs\\graceful-fs.js:325:16
at C:\\Users\\yuangezhizao\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\[email protected]@graceful-fs\\graceful-fs.js:325:16
at FSReqCallback.oncomplete (fs.js:152:23)
(node:22500) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without
a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:22500) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will termi
nate the Node.js process with a non-zero exit code.

194s»MyComponent»canceled

終止批處理操作嗎(Y/N)? Y

D:\\yuangezhizao\\Documents\\PycharmProjects\\LAB_Serverless>/<code>

然後去 .serverless 文件下的 Template.MyComponent.pyRequirements.json 文件中看到了requirements.txt。這裡其實是故意操作的(特意沒添加requirements.txt),說明 requirements.txt 必須存在!

實驗室站遷移 Serverless 之路(上)

因此,去創建文件內容為 Flask 的 requirements.txt

<code>D:\\yuangezhizao\\Documents\\PycharmProjects\\LAB_Serverless>sls --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─Generated requirements from D:\\yuangezhizao\\Documents\\PycharmProjects\\LAB_Serverless\\requirements.txt in D:\\yuangezhizao\\Documents\\PycharmProje
cts\\LAB_Serverless\\.serverless\\requirements.txt...
DEBUG─Installing requirements from C:\\Users\\yuangezhizao\\AppData\\Local\\Yugasun\\serverless-python-requirements\\Cache\\2a1a661c4e3e6faadab5d001bc10cc3ac
ccf648921aad7c279d94f138eaaf833_slspyc\\requirements.txt ...
DEBUG─Using download cache directory C:\\Users\\yuangezhizao\\AppData\\Local\\Yugasun\\serverless-python-requirements\\Cache\\downloadCacheslspyc
DEBUG─Running ...
DEBUG─Compressing function LAB_Serverless file to D:\\yuangezhizao\\Documents\\PycharmProjects\\LAB_Serverless\\.serverless/LAB_Serverless.zip.
DEBUG─Compressed function LAB_Serverless file successful
DEBUG─Uploading service package to cos[sls-cloudfunction-ap-beijing-code]. sls-cloudfunction-default-LAB_Serverless-1582464464.zip
DEBUG─Uploaded package successful D:\\yuangezhizao\\Documents\\PycharmProjects\\LAB_Serverless\\.serverless/LAB_Serverless.zip
DEBUG─Creating function LAB_Serverless
DEBUG─Created function LAB_Serverless successful
DEBUG─Setting tags for function LAB_Serverless
DEBUG─Creating trigger for function LAB_Serverless
DEBUG─Deployed function LAB_Serverless successful
DEBUG─Starting API-Gateway deployment with name MyComponent.TencentApiGateway in the ap-beijing region
DEBUG─Service with ID service-0ok85tqh created.
DEBUG─API with id api-ivk6tk0y created.
DEBUG─Deploying service with id service-0ok85tqh.
DEBUG─Deployment successful for the api named MyComponent.TencentApiGateway in the ap-beijing region.

MyComponent:
region: ap-beijing
functionName: LAB_Serverless
apiGatewayServiceId: service-0ok85tqh
url: http://service-0ok85tqh-1251901037.bj.apigw.tencentcs.com/test/

44s»MyComponent»done


D:\\yuangezhizao\\Documents\\PycharmProjects\\LAB_Serverless>/<code>

趁機看下部署成功之後的 .serverless 文件夾:

實驗室站遷移 Serverless 之路(上)

這裡 Template.MyComponent.TencentCloudFunction.json 即雲函數

<code>{
"deployed": {
"Name": "LAB_Serverless",
"Runtime": "Python3.6",
"Handler": "api_service.handler",
"MemorySize": 128,
"Timeout": 10,
"Region": "ap-beijing",
"Description": "This is a template function"
}
}/<code>

第三方包全在這裡:

實驗室站遷移 Serverless 之路(上)

Template.MyComponent.TencentApiGateway.json 即 API 網關

<code>{
"protocols": [
"http"
],
"subDomain": "service-0ok85tqh-1251901037.bj.apigw.tencentcs.com",
"environment": "test",
"region": "ap-beijing",
"service": {
"value": "service-0ok85tqh",
"created": true
},
"apis": [
{
"path": "/",
"method": "ANY",
"apiId": {
"value": "api-ivk6tk0y",
"created": true
}
}
]
}/<code>

也就是說CLI自動幫我們創建SCF並將運行環境一併上傳,再創建API 網關配置到SCF的觸發器上。

<code>apigatewayConf:
protocol: https
environment: test/<code>

到這裡demo就搞定了,已經可以正常訪問了 。

實驗室站遷移 Serverless 之路(上)

4. 原理深入

去雲函數看實際運行環境,發現把.idea文件夾也給上傳了 另外,多瞭如下倆本地沒有的文件:

實驗室站遷移 Serverless 之路(上)

實驗室站遷移 Serverless 之路(上)

其實這就是Serverless的核心了,Serverless配置靜態頁面的原理自己是清楚的。比如Hexo就是生成頁面之後上傳到COS上就能訪問了。

但是,對於動態頁面就比較好奇了,這是怎麼實現的呢?其實就是靠著serverless.wsgi 這個文件等等。能看到這個模塊描述:此模塊將 AWS APIGateway 代理請求轉換為 WSGI 請求。

<code>"""
This module converts an AWS API Gateway proxied request to a WSGI request.

Inspired by: https://github.com/miserlou/zappa

Author: Logan Raarup <[email protected]>
"""/<code>

還是相當有意思的。

5. 遷移 LAB

接下來就得一點兒一點兒進行遷移了,不難想到應該有非常多的坑的,比如如何訪問自己的 MySQL、Redis、 MongoDB,再比如Celery計劃任務,自己是用RabbitMQ 的消息隊列,這東西要怎麼上雲?這些問題都是自己需要後期去解決的。畢竟上大學就開始寫的網站,有非常非常多的依賴……

更新日誌:當前 git 版本:7a65018,總提交 824 次

遷移註定是一個大工程,下一篇將詳細介紹遷移遇到的各種坑和填坑操作。


分享到:


相關文章: