• 一文搞懂EMAS Serverless小程序开发|电子书免费下载


    >> 快来免费下载|电子书《五天玩转EMAS Serverless》 <<

    点击免费下载

    《五天玩转EMAS Serverless》

    EMAS Serverless 是什么

    EMAS Serverless 是阿里云提供的基于 Serverless 技术的一站式后端开发平台,为开发者提供高可用、弹性伸缩的云开发服务,包含云函数、云数据库、云存储、静态网站托管等功能,帮助开发者及企业客户快速实现一云多端应用的搭建,您无需管理服务器等基础设施,便可以无缝对接丰富的云资源。

    图1 EMAS Serverless 产品架构

     

    EMAS Serverless 应用场景

    ES 支持云函数、云数据库、云存储等能力,具有弹性伸缩、按量付费、 免运维三大特点。弹性伸缩让您免于频繁运维扩缩机器,轻松应对各种流量突发事件,为您节省大量时间。按量付费做到用多少付多少,函数计费精确到毫秒,为您节省大量开支。免运维让开发者不用花费更多的精力在服务器等底层资源上,而是可以将精力放在更具价值的业务逻辑上。因此 ES 广泛适用于电商、咨询、旅游、企业展示、社区、餐厅等行业场景。

    图2 EMAS Serverless 应用场景

    开通产品

    首先打开 EMAS 阿里云控制台: https://emas.console.aliyun.com,新建并进入项目。然后选择平台服务并创建一个服务空间。如图3和图4所示:

    图3 EMAS 控制台首页——项目管理

    图4 选中平台服务并创建服务空间

    计费方式

    支持按量付费和包年包月两种付费方式。

    • 按量付费(后付费):一种后付费模式,即先使用再付费。一般适用于有爆发业务量的应用或服务。
    • 包年包月(预付费):一种预付费模式,即先付费再使用。通过包年包月,您可以提前预留资源,同时享受更大的价格优惠,帮您更大程度节省支出。

    按量付费

    模块

    计费项

    单价(按量付费)

    云函数

    资源使用量(GBs)

    0.000110592

    调用次数(万次)

    0.0133

    出网流量(GB)

    0.8

    云数据库

    容量(GB/天)

    0.07

    读操作数(万次)

    0.015

    写操作数(万次)

    0.05

    云存储

    容量(GB/天)

    0.0043

    下载操作次数(万次)

    0.01

    上传操作次数(万次)

    0.01

    CDN流量(GB)

    0.18

    静态网站托管

    容量(GB/天)

    0.0043

    CDN流量(GB)

    0.18

    包年包月

    套餐规格

    价格(元/月)

    套餐描述

    开发者版

    Free

    适合练习、项目开发、启动初期使用。

    基础版

    5

    我们提供了多种规格的套餐,您可以基于业务规模、项目发展阶段按需选择,并伴随业务的增长进行套餐升配。

    标准版

    24

    专业版

    82

    企业版

    316

    旗舰版

    688

    具体的套餐资源量请参考 https://help.aliyun.com/document_detail/435837.html

    安装 SDK

    我们以开发支付宝小程序为例,演示如何快速借助 ES 能力快速开发部署。

    1. 首先运行在小程序项目根目录执行以下命令。
    npm install --save @alicloud/mpserverless-sdk

    微信或者支付宝小程序还有一些特殊配置,具体请参考:https://help.aliyun.com/document_detail/444395.html

    初始化 SDK

    在小程序端开始使用 Serverless 服务前,需要先调用 mpserverless.init 方法完成服务的初始化,且仅能初始化一次。较为通用的做法是在 onLaunch 生命周期中进行初始化操作,并将实例对象 mpserverless 挂载到小程序的全局对象 App,以便后续在其他文件中调用。

    这里演示使用的是匿名初始化,这种初始化方式无需在支付宝开放平台配置密钥,不过同时也无法获取小程序用户身份。更多细节请参考:https://help.aliyun.com/document_detail/444402.html

    // app.js
    import MPServerless from '@alicloud/mpserverless-sdk'
    
    const mpserverless = new MPServerless(my, {
        appId: '小程序 AppID',
        spaceId: '服务空间 SpaceId',
        clientSecret: '服务空间 Secret',
        endpoint: '服务空间 API Endpoint'
    });
    
    App({
        mpserverless: mpserverless,
        onLaunch() {
            mpserverless.init(
              authorType: 'anonymous'
            );
        },
    });

    云函数

    云函数(FaaS)是一段运行在云端的、轻量的、无关联的并且可重用的代码。无需管理服务器,只需编写和上传代码,即可获得对应的数据结果。云函数的入参只有一个 ctx 对象,出参结构由开发者自行定义:

    // 云函数入口定义在 index.js 中
    module.exports = async ctx => {
      // do something
      return result
    }

    ctx 对象结构

    字段

    类型

    含义

    ctx.args

    Object?

    开发者通过 SDK 调用云函数时传入的参数体。

    例如:mpserverless.function.invoke( 'function-name', args)

    HTTP 触发和定时任务触发的入参结构稍有不同,请参考官方文档。

    ctx.logger

    function

    日志工具,可以打印不同类型的日志信息,然后在云函数控制台中查看执行日志。

    • info
    • warn
    • error
    • debug

    ctx.mpserverless

    SDK

    在云函数中为您提供已经完成初始化的 mpserverless 对象,让您可以继续调用 Serverless 其他基础服务,API 使用方式和客户端基本一致。

    ctx.env

    Object

    在云函数中通过 ctx.env 来获取环境参数,例如 SpaceId、调用来源、客户端源 IP 和客户端 UserAgent 等信息。

    • MP_SPACE_ID 服务空间ID
    • MP_SOURCE 调用来源
      • server:服务端触发
      • function:云函数触发
      • client:客户端触发
      • http:HTTP 触发
      • timing:定时触发
    • MP_USER_AGENT 客户端标志,仅来自客户端的调用包含该字段
    • MP_CLIENT_IP 客户端IP,仅来自客户端的调用包含该字段
    • MP_APP_ID 小程序AppId,客户端非匿名授权后调用云函数包含该字段

    ctx.httpclient

    HttpClient

    通过该对象可以请求任何HTTP和HTTPS协议的Web服务。

    例如:ctx.httpclient.request( 'https://***' )

    开发部署与调试

    我们以开发一个两数四则运算的云函数 TwoNumOperation 为例:

    // index.js
    module.exports = async ctx => {
        const { action, x, y } = ctx.args;
    
        let result = 0
        switch (action) {
            case '+': result = x + y; break;
            case '-': result = x - y; break;
            case '*': result = x * y; break;
            case '/':
                if (y === 0) {
                    throw new Error('cannot divide by 0')
                }
                result = x / y; break;
            default:
                throw new Error('not support action ' + action)
        }
    
        return { result }
    }

    新建文件夹 TwoNumOperation,然后在文件夹下面新建文件 index.js 并放入上述代码,然后整体打包该文件夹得到压缩文件 TwoNumOperation.zip 。如下图5所示:

    图5 云函数代码包

    如下图6所示,首先我们在阿里云控制台新建一个云函数 TwoNumOperation,函数名称必须和文件夹名称一致。然后将压缩好的代码包上传部署。部署成功后可以在控制台测试运行,点击代码执行,输入函数执行参数即可运行云函数。点击日志可以查看云函数的执行日志,方便开发者调试。

     

    图6 云函数部署、执行、日志查看

    在小程序中调用云函数

    如图7所示在小程序中调用云函数。 index.axml 布局文件简单写了一个表单包含三个 input,绑定表单提交函数 invokeFunctionindex.js 文件首先从全局导入 mpserverless 对象,然后在表单提交函数中获取参数 actionxy,然后通过 mpserverless.function.invoke 调用云函数。

    图7 在小程序中调用云函数

    云数据库

    云数据库服务是基于 MongoDB 托管在云端的数据库,数据以 JSON 格式存储。作为开发者,您可以在客户端或者云函数中通过 mpserverless 对象读写数据。

    mpserverless.db.collection('user').findOne( { name: '张三' } )

    和 MySQL 对比

    ES 云数据库服务底层使用的是 MongoDB,以 JSON 格式存储数据。数据库中的每条记录都是一个 JSON 格式的文档,一个数据库可以包含多个集合(相当于关系型数据库中的表),每个集合可看做一个 JSON 文档数组。MongoDB 数据库和关系型数据库 MySQL 的对比如下表所示。

    云数据库 (MongoDB)

    关系型数据库 (MySQL)

    数据库(database)

    数据库(database)

    表(collection)

    表(table)

    记录(document)

    行(row)

    域(field)

    列(column)

    索引(index)

    索引(index)

    自动将_id字段作为主键

    主键(primary key)

    数据结构设计策略

    MongoDB 是一个基于分布式文件存储的 NoSQL 数据库,旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。以电商平台为例,通常电商平台的核心数据包含产品、用户、购物车和订单。订单是由用户购买产品产生的,订单就可以认为是产品和用户之间的关联关系产生的。在订单产生之前,产品和用户之间的关联关系是通过购物车来维持的。针对上述案例,可以设计一个名称为products的产品表存储以下信息:

    • 产品基础信息:包含展示信息、商品规格等;
    • 属性信息:属性都归属于一个产品,属于N对1的关系。因此作为子文档存储在 products 集合中较合适;
    • 库存及价格信息:库存不仅仅跟产品关联,更直接对应产品属性。因此也应该放在 products 集合中;
    {
      "id": 5573,
      "name": "Egg T恤",
      "desc": {
        "short": "限量版 Egg T恤,穿上它你离极客也不远了",
        "long": "这是一段非常长的描述",
        "category": {
          "_id": "48bf43a..29e90bc",
          "name": "上衣"
        }
      },
      "attributes": [
        {
          "id": 1151,
          "name": "尺寸",
          "values": [
            {
              "id": 3871,
              "value": "S"
            },
            {
              "id": 3874,
              "value": "M"
            },
            {
              "id": 3875,
              "value": "L"
            }
          ]
        },
        {
          "id": 1152,
          "name": "性别",
          "values": [
            {
              "id": 3872,
              "value": "男"
            },
            {
              "id": 3873,
              "value": "女"
            }
          ]
        }
      ],
      "sku": [
        {
          "id": 1153,
          "stock": 30,
          "attributeIds": [
            3871,
            3872
          ],
          "attributes": [
            {
              "key": "尺寸",
              "value": "S"
            },
            {
              "key": "性别",
              "value": "女"
            }
          ]
        }
      ]
    }

    创建数据表

    在阿里云控制台上点击“+”新建数据表

    图8 在控制台新建数据表

    添加数据记录

    insertOne

    插入用户张三

    mpserverless.db.collection('users').insertOne( { 
        name: '张三',
        age: 18
    } )

    insertMany

    mpserverless.db.collection('users').insertOne( [ 
        { name: '张三', age: 18 },
        { name: '李四', age: 17 }
    ] )

    删除数据记录

    deleteOne

    mpserverless.db.collection('users').deleteOne( { 
        name: '张三'
    } )

    deleteMany

    删除年龄小于18的用户

    mpserverless.db.collection('users').deleteMany( { 
        age: { $lt: 18 }
    } )

    查询数据记录

    findOne

    mpserverless.db.collection('users').findOne( { 
        age: { $gt: 18 }
    } )

    find

    查询所有大于18的用户 name,并将查询结果按年龄升序返回

    mpserverless.db.collection('users').find( {
        age: { $gt: 18 }
    }, {
        projection: { name: 1 },
        sort: { age: 1 }
    } )

    findOneAndDelete

    查询并删除小于且最接近18岁的一条数据

    mpserverless.db.collection('users').findOneAndDelete( {
        age: { $lt: 18 }
    }, {
        sort: { age: -1 }
    } )

    findOneAndReplace

    查询并替换 name 为张三的一条数据

    mpserverless.db.collection('users').findOneAndReplace( {
        name: "张三"
    }, {
        name: "张三三",
        age: 20
    }, {
        upsert: true // 如果不存在则插入
    } )

    findOneAndUpdate

    查询并更新 name 为张三的一条数据

    mpserverless.db.collection('users').findOneAndUpdate( {
        name: "张三"
    }, {
        $set: {
            name: "张三三",
            age: 20
        }
    }, {
        upsert: true // 如果不存在则插入
    } )

    更新数据记录

    updateOne

    更新第一个张三的年龄为22岁

    mpserverless.db.collection('users').updateOne( {
        name: "张三"
    }, {
        $set: {
            age: 22
        }
    } )

    updateMany

    把所有的张三年龄都设置为22岁

    mpserverless.db.collection('users').updateMany( {
        name: "张三"
    }, {
        $set: {
            age: 22
        }
    } )

    replaceOne

    把第一个张三姓名改为张阿三,年龄改为22岁

    mpserverless.db.collection('users').replaceOne( {
        name: "张三"
    }, {
        $set: {
            name: '张阿三',
            age: 22
        }
    }, {
        upsert: true // 如果不存在则插入,为 flase 时代表不存在则不做任何操作
    } )

    其他指令

    distinct

    返回 age 字段大于18的所有姓名(如果有相同的name 只返回一个)

    mpserverless.db.collection('users').distinct(
        'name', 
        { age: { $gt: 18 }
    )

    count

    查找集合 users 中所有 age 大于18的记录数量

    mpserverless.db.collection('users').count( {
        age: { $gt: 18 }
    } )

    aggregate

    聚合管道查询,该管道允许用户通过一系列基于阶段的操作来处理数据,详情请参考帮助文档 https://help.aliyun.com/document_detail/435909.html

    云存储

    mpserverless.file 对象提供 uploadFiledeleteFile 方法管理文件。上传的文件将通过CDN进行网络加速。单个文件要求小于100 MB。

    上传文件

    支付宝小程序上传文件示例

    my.chooseImage({
        chooseImage: 1,
        success: res => {
    
            const path = res.apFilePaths[0];
            const options = {
                filePath: path,
            };
    
            mpserverless.file.uploadFile(options)
            .then(res => { 
                console.log(res);  
            })
            .catch(err => {  
                console.log(err);
            });
    
        },
    });

    返回示例:

    {
        "fileUrl": "https://mp-…storage/2e7acad6-2212-4863-aaa7-4e89d7d8df4c.png", 
        "filePath": "cloudstorage/2e7acad6-2212-4863-aaa7-4e89d7d8df4c.png"
    }

    删除文件

    根据文件地址从服务空间中删除该文件

    const fileURL = 'https://mp...bspapp.com/xxx-xx/4b82ded0-0118-4de4-9f50-ab13110a1ffb.jpg';
    
    mpserverless.file.deleteFile(fileURL)

    总结

    EMAS Serverless 依托阿里巴巴数字经济技术能力和业务能力提供云函数、云存储、云数据库等 Serverless 服务。大大提升了前端工程师的价值,让开发者快速落地小程序开发工作,按量付费和自动弹性伸缩省时省力。此外, ES 还支持静态网站托管以及面向支付宝生态的云调用模块,技术与商业联动为开发者提供一站式地小程序生态服务。

    参考资料

    EMAS 控制台:https://emas.console.aliyun.com

    帮助文档:https://help.aliyun.com/document_detail/436030.html

    开发指南:https://help.aliyun.com/document_detail/444395.html

    >> 快来免费下载|电子书《五天玩转EMAS Serverless》 <<

  • 相关阅读:
    JS-(14)表单验证
    暴力求解欲哭无泪之保安问题
    (三)admin-boot项目之整合alibaba-druid连接池
    方差分析的核心概念“方差分解“
    FPGA按键消抖
    基于WiFi小车控制板的单片机小系统原理图
    CNN(八):Inception V1算法实战与解析
    如何通过美国多IP服务器优化大规模在线媒体传输?
    maven 打包 出现 Please refer to XXXX for the individual test results
    PerfView专题 (第十四篇): 洞察那些 C# 代码中的短命线程
  • 原文地址:https://blog.csdn.net/gangyikeji/article/details/126418668