头图

Serverless multi-function development example

Serverless
中文

01. What is Serverless?

The definition and understanding of Serverless will be interpreted differently in different perspectives and scenarios. AWS defines Serverless (on the AWS cloud) as "a way to describe services, practices, and strategies, enabling you to build more agile Application, which can innovate faster and respond to changes" a service. Red Hat believes that Serverless is a development model that "allows developers to focus on building and running applications without managing servers", and further divides Serverless products into two categories: BaaS (back-end as a service, allowing developers to access A variety of third-party services and applications) and FaaS (function as a service, developers write logic, deploy it in a container fully managed by the platform, and then execute it on demand). The Serverless Framework believes that Serverless is "a movement that is promoted by developers and enterprises, allowing a single developer to complete high-traffic application development, while focusing only on the aspects that generate value."

No matter which aspect or perspective, Serverless has the following common characteristics:

  1. Rapid development, rapid deployment
  2. Pay as you go, reduce costs
  3. Automatic expansion, no maintenance

At present, it is implemented based on the FaaS services of various cloud vendors, such as: Tencent Cloud's SCF, AWS's Lambda, Azure Cloud's Azure Funcitons, etc.

What problem does Serverless solve?

As computing power increases, system complexity increases, and user scale increases, software problems (also referred to as software crises below) will also increase exponentially.

  • Unpredictable software development progress
  • Software development costs are difficult to control
  • Software product quality cannot be guaranteed
  • Software products are difficult to maintain

On the other hand, Serverless can propose a solution to the software crisis in the following ways:

  • The function of the system is divided into smaller granularities, which is more convenient for design, development, testing and maintenance.
  • By billing according to the amount, the overhead cost when resources are idle is greatly reduced, and the server cost is reduced.
  • Through automatic expansion and cloud platform support, the workload of operation and maintenance and software maintenance costs are greatly reduced.

At the same time, in the modern working environment where agile working methods are generally advocated, Serverless also provides the best practices of development methods for rapid verification of ideas and iterative functions. At the same time, there is no need to worry about code changes that will affect other functions of the system, and no need to consider deployment. Server configuration before and maintenance after deployment.

02. Serverless Framework

Serverless Framework is a very popular serverless application framework in the industry. Through close cooperation with many first-class cloud providers such as Tencent Cloud, AWS, etc., it provides developers with no services that can write and deploy codes without caring about the underlying infrastructure. Development experience.

Serverless Framework also provides resource management, auto-scaling, statistical analysis and other capabilities, allowing developers to save operation and maintenance costs, and truly "pay by volume" without having to spend energy on tasks such as log collection and abnormal statistics.

Serverless Framework works closely with Tencent Cloud through CLI tools to provide Chinese users with a complete solution based on Serverless Components. Covers the entire life cycle of serviceless application coding, testing, deployment, etc., and at the same time suits the usage scenarios and habits of Chinese users.

Why choose Serverless Framework?

With just a few lines of configuration files and CLI tools of Serverless Framework, developers can get additional:

  • Perform function development locally and deploy to the cloud with one click, without additional adaptation of cloud functions, and no need to log in to the console.
  • Support the deployment of traditional development framework applications (such as Express, Next.js, Flask, Laravel, etc.) as Serverless applications.
  • Debug the function code locally, or use the remote development mode to view and debug the log output of the deployment service locally in real time.
  • All infrastructure configurations can be completed through simple configuration (such as: API gateway, COS storage, DB link, etc.)
  • Quickly switch the deployment environment (development, demonstration, production) and region of the application.
  • More detailed and easy understanding of application status, view logs, error statistics and other information.

03. Multi-function development example

This example uses the multi-function component (multi-scf) of the Serverless Framework and the PostgreSQL component (postgresql) to implement the following three API interfaces.

  • GET /todos/ get all todo matters
  • POST /todos/ Create a new todo item
  • POST /todos/{id}/actions/complete complete todo matters

And use the invoke and logs functions provided by the Serverless Framework to debug and view real-time logs in the production environment.

The relevant code of this example can be obtained in Git repository .

Step 1: Install Serverless Framework

Execute the following command to install Serverless Framework

$ npm install serverless -g

If you have installed Serverless Framework before, you can upgrade to the latest version with the following command:

$ npm update serverless -g

This command will install the latest Serverless Framework to your computer. After the installation is successful, you can start using Serverless Framework serverless or sls

Step 2: Initialize the multi-function project

$ sls init multi-scf-nodejs --name sls-demo-msn-todo

This command will use the application template multi-scf-nodejs initialize an application directory my-multi-scf-demo After the initialization is successful, the directory structure is

.
├── README.md
├── index.js
└── serverless.yml

The purpose of the file here is as follows:

  • index.js: function file.
  • serverless.yml: Serverless Framework configuration file.

    • app: Application name, which will be used as the unique identifier for application identification.
    • Stage: Application environment, through different environments, deploy different application instances.
    • component: component name
    • name: component instance name
    • inputs: input parameters for component deployment

Step 3: Link to the database

Because Serverless is stateless (it will be destroyed after running), it is necessary to link the database to persist todo information. Adding a database requires a VPC network connection first.

1. Add VPC

Create a subdirectory vpc and add a new serverless.yml file in the subdirectory as follows:

component: vpc # [必选]要使用组件,更多组件请查看 https://github.com/serverless-components
name: sls-demo-msn-vpc # [必选]组件实例名称

inputs:
  region: ap-guangzhou # 实例所属地区
  zone: ap-guangzhou-2 # 实例所属地区区域
  vpcName: ${name} # 实例名称,这里复用字段 name 作为名称。
  subnetName: sls-demo-msn-subnet # 子网的名称

For more VPC configuration content, see VPC private network for more details.

In the configuration file of the child component, the app name will automatically inherit the configuration in the serverless.yml of the parent directory. At the same time, the app name of the same application needs to be consistent.

2. Add database

Create a subdirectory db and add a new serverless.yml file in the subdirectory as follows:

component: postgresql #(必填) 引用 component 的名称,当前用到的是 postgresql 组件
name: sls-demo-msn-DB # (必填) 该 postgresql 组件创建的实例名称

inputs:
  region: ap-guangzhou # 实例所属地区
  zone: ap-guangzhou-2 # 实例所属地区区域
  dBInstanceName: ${name}-${stage} # 数据库实例名称唯一,且同一个数据库只能存在同一个vpc内。
  extranetAccess: true # 是否开启实例外网访问
  vpcConfig: # vpc网络配置
    vpcId: ${output:${stage}:${app}:sls-demo-msn-vpc.vpcId} # 私有网络Id
    subnetId: ${output:${stage}:${app}:sls-demo-msn-vpc.subnetId} # 子网Id

Add the database to the vpc network in the database configuration, and use the output variable (output) to dynamically obtain the id information of the vpc.

For more variable configuration content, see Serverless variable for more details.

For more PostgreSQL configuration content, see PostgreSQL database for more details.

After the component is deployed, you can use sls info view the output variables of the component in the component catalog, or you can go to the Tencent Cloud application console to view related information.

3. Initialize the application directory

  1. Create a subdirectory src and move the created index.js (renamed todos.js ) and serverless.yml to the directory.
  2. npm init in the src directory to initialize the Node.js project.
  3. npm i pg --save in the src directory to install the database link dependency package pg .
  4. Add the root configuration file serverless.yml in the project root directory, the files are as follows:
app: sls-demo-msn-todo-3e5a2134 # 应用唯一识别标识,同账号下需要保持唯一。
stage: dev # 应用部署环境名称,这里使用环境变量 STAGE 的值。
The configuration file information of the root directory will be inherited by the subcomponents, and there is no need to repeat the definition in the subcomponents. (Only for app and stage).

The directory structure of the final project is as follows:

.
├── README.md
├── db # 数据库
│   └── serverless.yml # 数据库配置文件
├── serverless.yml
├── src # 多函数应用
│   ├── node_modules
│   ├── package-lock.json
│   ├── package.json # Node.js依赖文件
│   ├── serverless.yml # 多函数应用配置文件
│   └── todos.js # todo 应用主文件
└── vpc # vpc
    └── serverless.yml # vpc配置文件

4. Modify the multi-function application configuration

Modify the configuration file in the multi-function directory src

component: multi-scf
name: sls-demo-msn

inputs:
  src:
    src: ./
    exclude:
      - .env
      - "node_modules/**" # 部署时忽略node_modules目录中所有文件,以加快部署速度
  environments: # 应用环境变量信息
    - key: PG_CONNECT_STRING
      value: ${output:${stage}:${app}:sls-demo-msn-DB.private.connectionString}
  region: ap-guangzhou
  runtime: Nodejs12.16
  memorySize: 128
  vpc: # vpc网络配置
    vpcId: ${output:${stage}:${app}:sls-demo-msn-vpc.vpcId} # 私有网络Id
    subnetId: ${output:${stage}:${app}:sls-demo-msn-vpc.subnetId} # 子网Id
  installDependency: true # 是否在线安装依赖
  timeout: 6 # 默认超时时间(秒)
  functions: # 多函数定义
    allTodo: # 函数别名
      handler: todos.all # 处理函数
      memorySize: 256 # 自定义次函数的内存空间
    addTodo:
      handler: todos.add
      timeout: 9 # 自定义此函数的超时时间(秒)
    completeTodo:
      handler: todos.comp
      timeout: 9
  triggers: # 触发器配置
    - type: apigw
      parameters:
        name: todosAPIGW
        protocols:
          - https
          - http
        apis: # API配置
          - path: /todos/ # 路由路径
            method: GET # 路由方法
            function: allTodo # 路由处理函数别名
          - path: /todos/
            method: POST
            function: addTodo
          - path: /todos/{id}/actions/complete
            method: POST
            function: completeTodo
            param: # 动态路由参数配置
              - name: id
                position: PATH
                required: true
                type: number
                desc: Todo ID

The main contents of the modifications here are:

  • After using installDependency start deployment, rely on automatic installation and ignore node_module directory (no need to upload node_modules to speed up deployment)
  • Use vpc add a vpc network and link to the same vpc network of the project.
  • Use environments add project environment variables, and use output variables to dynamically generate database connection strings.
  • Use functions to declare the functions and their aliases in the project.
  • Use triggers declare the trigger of the function, and configure the path and parameter information of each function apis

For more configuration content and details of function development, see PostgreSQL database for more details.

For more descriptions of function development, see Function Development for more details.

Step 4: develop features

Modify todos.js and complete the development of related functions. The final code of the file is as follows:

"use strict";
const { Client } = require("pg");

const client = new Client({
  connectionString: process.env.PG_CONNECT_STRING,
});

/**
 * 初始化数据库和表结构
 */
const initDB = async () => {
  const isConnected = client && client._connected;

  if (!isConnected) {
    await client.connect();

    await client.query(`
    CREATE TABLE IF NOT EXISTS todo (
      ID              SERIAL          NOT NULL,
      TITLE           VARCHAR         NOT NULL,
      NOTE            TEXT,
      IS_COMPLETE     BOOLEAN         DEFAULT FALSE
    );`);
  }
};

/**
 * 获取所有Todo事项
 */
exports.all = async (event, context) => {
  // async 需要关闭事件循环等待,以避免日志记录超时或函数无返回的问题。
  context.callbackWaitsForEmptyEventLoop = false;
  await initDB();

  const { rows } = await client.query({ text: "SELECT * FROM todo" });

  return {
    message: "Tencent SCF execute successful!",
    data: rows,
  };
};

/**
 * 添加新的Todo事项
 */
exports.add = async (event, context) => {
  // async 需要关闭事件循环等待,以避免日志记录超时或函数无返回的问题。
  context.callbackWaitsForEmptyEventLoop = false;
  const { title, note } = JSON.parse(event.body);
  if (!title) {
    return {
      statusCode: 400,
      message: "Missing Todo Title",
    };
  }

  await initDB();
  const { rowCount } = await client.query({
    text: "INSERT INTO todo (title, note) VALUES($1, $2)",
    values: [title, note],
  });

  return rowCount === 1
    ? {
        statusCode: 201,
        message: "Todo added success.",
      }
    : {
        statusCode: 400,
        message: "Todo added failed.",
      };
};

/**
 * 完成指定Todo事项
 */
exports.comp = async (event, context) => {
  // async 需要关闭事件循环等待,以避免日志记录超时或函数无返回的问题。
  context.callbackWaitsForEmptyEventLoop = false;
  const todoId = event.pathParameters.id;

  if (!todoId && !isNaN(todoId)) {
    return {
      statusCode: 400,
      message: "Missing Todo Id",
    };
  }

  await initDB();
  const { rowCount } = await client.query({
    text: "UPDATE todo SET is_complete = true WHERE id=$1",
    values: [todoId],
  });

  return rowCount === 1
    ? {
        statusCode: 200,
        message: "Todo Complete success.",
      }
    : {
        statusCode: 400,
        message: "Todo Complete failed.",
      };
};

Step 5: Debug function

1. Invoke debugging

To debug the code, in addition to using third-party development tools to debug through the configured API gateway url, you can also use the Invoke function or remote debugging function of the Serverless Framework. Here, the invoke function is used to demonstrate how to debug function functions.

Invoke and remote debugging functions need to be executed in the component's directory.

2. Get all Todo

Execute in the src directory

$ serverless invoke -f allTodo

The results that can be obtained after execution

使用授权信息 default 授权中,如果需要使用临时密钥,请使用 --login 重新登陆
billDuration:      36
duration:          36
errMsg:
functionRequestId: fe6d302d-f6db-42ad-9c7b-8d0c61ead9b3
invokeResult:      0
log:
  """
    START RequestId: fe6d302d-f6db-42ad-9c7b-8d0c61ead9b3
    Event RequestId: fe6d302d-f6db-42ad-9c7b-8d0c61ead9b3

    END RequestId: fe6d302d-f6db-42ad-9c7b-8d0c61ead9b3
    Report RequestId: fe6d302d-f6db-42ad-9c7b-8d0c61ead9b3 Duration:36ms Memory:256MB MemUsage:11.3984MB
  """
memUsage:          11952128
---------------------------------------------
Serverless: 调用成功

{
  message: 'Tencent SCF execute successful!',
  data: []
}

The result returned by invoke will contain the meta information after the function is executed, such as running time, error, RequestId, execution log and the result returned by the function.

3. Create a new Todo

Execute in the src directory

$  serverless invoke -f addTodo --data "{\"body\":\"{\\\"title\\\":\\\"Create multi-scf project demo\\\",\\\"note\\\":\\\"Todo App with postgreSQL\\\"}\"}"

The results that can be obtained after execution

使用授权信息 default 授权中,如果需要使用临时密钥,请使用 --login 重新登陆
billDuration:      35
duration:          35
errMsg:
functionRequestId: 93f50016-064f-468d-9e98-31645fc254fd
invokeResult:      0
log:
  """
    START RequestId: 93f50016-064f-468d-9e98-31645fc254fd
    Event RequestId: 93f50016-064f-468d-9e98-31645fc254fd

    END RequestId: 93f50016-064f-468d-9e98-31645fc254fd
    Report RequestId: 93f50016-064f-468d-9e98-31645fc254fd Duration:35ms Memory:128MB MemUsage:11.293MB
  """
memUsage:          11841536
---------------------------------------------
Serverless: 调用成功

{
  statusCode: 201,
  message: 'Todo added success.'
}

Step 6: Deployment and logging

1. Deploy the code to the production environment

Use the following command to quickly deploy the project to the production environment (the production environment is named prod )

$ serverless deploy --stage prod

2. Instantly view the production environment log

Execute the following command in the project directory src to view the instant log information of the project

$ sls logs --tail -f allTodo --stage prod

The following is the returned result:

使用授权信息 default 授权中,如果需要使用临时密钥,请使用 --login 重新登陆

serverless ⚡components
Action: "logs" - Stage: "prod" - App: "sls-demo-msn-todo-3e5a2134" - Name: "sls-demo-msn"

START RequestId:6f31857109130f092c547337c073ea91

Response RequestId:dbb3a8ed63a32be8e6b7a2dd8a32bbe2 RetMsg:{"message":"Tencent SCF execute successful!","data":[{"id":1,"title":"Create multi-scf project demo","note":"Todo App with postgreSQL","is_complete":false}]}
END RequestId:dbb3a8ed63a32be8e6b7a2dd8a32bbe2
Report RequestId:dbb3a8ed63a32be8e6b7a2dd8a32bbe2 Duration:4ms Memory:256MB MemUsage:12.113281MB

Response RequestId:485a87cfc6ad385b7e9c84343962391b RetMsg:{"message":"Tencent SCF execute successful!","data":[{"id":1,"title":"Create multi-scf project demo","note":"Todo App with postgreSQL","is_complete":false}]}
END RequestId:485a87cfc6ad385b7e9c84343962391b
Report RequestId:485a87cfc6ad385b7e9c84343962391b Duration:4ms Memory:256MB MemUsage:11.886719MB

START RequestId:0ede6d26dca55362a701c10ff51c9021


Serverless › 监听中 ...

to sum up

Thanks to the vast number of developers who have supported the Serverless Framework for a long time. In the future, we will continue to iterate the product, introduce new features, and improve the product experience. Finally, we will create a set of serverless development for Chinese developers that conforms to the habits of Chinese developers. Complete solution.

Also welcome everyone to the Serverless Chinese community to share experiences and ideas, as well as feedback questions and BUGs.

Serverless Chinese Community: https://github.com/serverless/serverless-tencent/discussions

Finally, I hope everyone can participate in our prize-winning questionnaire: https://www.surveymonkey.com/r/blog-msntodo

One More Thing

Experience Tencent Cloud Serverless Demo now and receive the Serverless new user gift pack Tencent Cloud Serverless newbie experience .

阅读 301

玩转Serverless
我们专注于 Serverless 架构最佳实践,欢迎关注:[链接]

Serverless 中文社区是由一群拥有相同价值观和理念的志愿者们共同发起,于 2019 年 12 月正式成立。

124 声望
13 粉丝
0 条评论
你知道吗?

Serverless 中文社区是由一群拥有相同价值观和理念的志愿者们共同发起,于 2019 年 12 月正式成立。

124 声望
13 粉丝
宣传栏