如何使用Serverless框架?

  • 回答 (7)
  • 关注 (1)
  • 查看 (593)

从行业趋势看,Serverless是云计算必经的一场革命,无服务器云函数是实现微服务的最好的方法之一,该如何使用Serverless框架?

汐夜汐夜提问于
rg759955努力前行的程序员回答于
推荐

我对于 serverless 的第一认知是:Serverless 是由一堆云服务构建后端服务的,如存储、计算、授权都是由不同的服务来构建的。而作为一个开发人员,我们所要做的就是了解如何搭配不同的云服务。

因此,在进行更多的定义之前,我打算先熟悉一下 serverless,以便于我更好地了解什么是 serverless 应用开发。

Serverless 框架 hello, world

先按官网的 demo,进行实验。

一、安装 serverless 框架

npm install -g serverless

或者,和我一样使用:

yarn global add serverless

二、设置 aws 凭证。

1.登录 AWS 账号,然后点击进入 IAM (即,Identity & Access Management)。

2.点击用户,然后添加用户,如 serveless-admin,并在『选择 AWS 访问类型』里,勾上编程访问。

编程访问 serverless

3.点击下一步权限,选择『直接附加现有策略』,输入AdministratorAccess,然后创建用户。

注意:由于是 AdministratorAccess 权限,所以不要泄漏你的密钥出去。

  1. 创建用户。随后,会生成访问密钥 ID 和 私有访问密钥。请妥善保存好。

然后导出证书,并使用 serverless depoy 保存到本地。

export AWS_ACCESS_KEY_ID=<your-key-here>export AWS_SECRET_ACCESS_KEY=<your-secret-key-here>serverless deploy

将会自动生成配置到 ~/.aws/credentials

或者,如官方的示例:

serverless config credentials --provider aws --key AKIAIOSFODNN7EXAMPLE --secret wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

三、创建 hello-world 服务

serverless create --template aws-nodejs --path hello-world
Serverless: Generating boilerplate...Serverless: Generating boilerplate in "/Users/fdhuang/learing/serverless-guide/hello-world" _______                             __|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --||____   |_____|__|  \___/|_____|__| |__|_____|_____|_____||   |   |             The Serverless Application Framework|       |                           serverless.com, v1.23.0 -------'Serverless: Successfully generated boilerplate for template: "aws-nodejs"(play-env)

生成两个文件;

├── handler.js└── serverless.yml

其中的 handler.js 的内容是:

'use strict';module.exports.hello = (event, context, callback) => {  const response = {    statusCode: 200,    body: JSON.stringify({      message: 'Go Serverless v1.0! Your function executed successfully!',      input: event,    }),  };  callback(null, response);  // Use this code if you don't use the http event with the LAMBDA-PROXY integration  // callback(null, { message: 'Go Serverless v1.0! Your function executed successfully!', event });};

serverless.yml 的内容,因为注释所有的内容,因此相当于是空的。

四、部署及测试:

$serverless deploy -v

日志如下:

Serverless: Packaging service...Serverless: Excluding development dependencies...Serverless: Uploading CloudFormation file to S3...Serverless: Uploading artifacts...Serverless: Uploading service .zip file to S3 (409 B)...Serverless: Validating template...Serverless: Updating Stack...Serverless: Checking Stack update progress...CloudFormation - UPDATE_IN_PROGRESS - AWS::CloudFormation::Stack - hello-world-devCloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - HelloLogGroupCloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecutionCloudFormation - CREATE_IN_PROGRESS - AWS::Logs::LogGroup - HelloLogGroupCloudFormation - CREATE_IN_PROGRESS - AWS::IAM::Role - IamRoleLambdaExecutionCloudFormation - CREATE_COMPLETE - AWS::Logs::LogGroup - HelloLogGroupCloudFormation - CREATE_COMPLETE - AWS::IAM::Role - IamRoleLambdaExecutionCloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunctionCloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Function - HelloLambdaFunctionCloudFormation - CREATE_COMPLETE - AWS::Lambda::Function - HelloLambdaFunctionCloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - HelloLambdaVersionPSzzisjnTvvYknuXwQOlAvdkQZ67qXYSvgoAi9T8W0CloudFormation - CREATE_IN_PROGRESS - AWS::Lambda::Version - HelloLambdaVersionPSzzisjnTvvYknuXwQOlAvdkQZ67qXYSvgoAi9T8W0CloudFormation - CREATE_COMPLETE - AWS::Lambda::Version - HelloLambdaVersionPSzzisjnTvvYknuXwQOlAvdkQZ67qXYSvgoAi9T8W0CloudFormation - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS - AWS::CloudFormation::Stack - hello-world-devCloudFormation - UPDATE_COMPLETE - AWS::CloudFormation::Stack - hello-world-devServerless: Stack update finished...Service Informationservice: hello-worldstage: devregion: us-east-1stack: hello-world-devapi keys:  Noneendpoints:  Nonefunctions:  hello: hello-world-dev-helloStack OutputsHelloLambdaFunctionQualifiedArn: arn:aws:lambda:us-east-1:706605665335:function:hello-world-dev-hello:1ServerlessDeploymentBucketName: hello-world-dev-serverlessdeploymentbucket-bk066p5c9zgl

然后,让我们来触发一下这个函数:

$ serverless invoke -f hello -l

服务器返回了下面的结果:

{    "statusCode": 200,    "body": "{\"message\":\"Go Serverless v1.0! Your function executed successfully!\",\"input\":{}}"}--------------------------------------------------------------------START RequestId: 041138f9-bc81-11e7-aa63-0dbab83f773d Version: $LATESTEND RequestId: 041138f9-bc81-11e7-aa63-0dbab83f773dREPORT RequestId: 041138f9-bc81-11e7-aa63-0dbab83f773d    Duration: 2.49 ms   Billed Duration: 100 ms     Memory Size: 1024 MB    Max Memory Used: 20 MB

这意味着,我们的第一个服务已经成功上线了。

我们也可以通过下面的命令来获取相应的日志:

serverless logs -f hello -t

末了,记得执行:

$ serverless remove

它可以帮你省很多钱

萌萌呆想玩游戏却不知道这么开机的吃瓜少年。回答于

我说一个比较新颖的,使用 Serverless 进行 AI 预测推理

模型准备

在这里我们使用 TensorFlow 中的 MNIST 实验作为案例来进行下面的介绍。MNIST 是一个包含了 6 万训练图片和 1 万测试图片的手写数字图片集合,图片为 28x28-pixel 大小的黑白图片。此训练集通常用来训练对数字的识别能力。

关于如何编写代码,使用 MNIST 训练集完成模型训练,可以见 TF层指南:建立卷积神经网络,这篇文章详细介绍了如何通过使用 Tensorflow layer 构建卷积神经网络,并设置如何进行训练和评估。

而在进行训练和评估后,就可以进行模型的导出了。TensorFlow 的模型文件包含了深度学习模型的 Graph 和参数,也就是 checkpoint 文件。在导出模型文件后,我们可以加载模型文件继续训练或者对外提供推理服务。

这里我们可以通过 SavedModelBuilder 模块来进行模型到处保存,更具体的文档和操作方法可见 训练和导出 TF 模型

导出后的文件,为 saved_model.pb 文件, variables 文件夹及包含的若干variables文件,分别是模型的图文件和参数文件。后续在提供推理能力时,就是使用这些图及变量文件,加载到 TF Serving 内。

为了便于后续的操作,我们在这里也直接提供我们导出的模型文件供后续操作,可以点击这里的导出模型文件来下载。

测试文件准备

测试文件我们可以从 MNIST 的测试集中随意抽取若干,用于验证我们最终推理 API 的工作状态。同样,我们也在这里准备了若干图片用于最终验证,可以点击这里的测试图片文件来下载。或者记录以下连接,用于直接测试在线图片的推理情况。

https://main.qcloudimg.com/raw/84783c178cdc6d6b2302bc1b4749b91b.bmp
https://main.qcloudimg.com/raw/0f4630a815c44107a79a224d3263da2c.bmp
https://main.qcloudimg.com/raw/360a7cdd638d22d4145c94e67b3c059f.bmp
https://main.qcloudimg.com/raw/90067917b01d4b4d31f207ac78e70416.bmp
https://main.qcloudimg.com/raw/7828379e768aa5c8a6d09a3d58f64921.bmp
https://main.qcloudimg.com/raw/79e0c07766c739c880dfed8d0433ff83.bmp
https://main.qcloudimg.com/raw/b5f1c6f4ba08c3376c333c5a62f0c1dd.bmp
https://main.qcloudimg.com/raw/40adedc18205428276c3753bac51e740.bmp
https://main.qcloudimg.com/raw/4c750171b4b31772f0b923beef92c9f3.bmp
https://main.qcloudimg.com/raw/8504482825667f97b21209b9570249e6.bmp
https://main.qcloudimg.com/raw/5f22f6f83d26a3f267c823cd5437bdfc.bmp
https://main.qcloudimg.com/raw/fb1f59a3fdbcad0a140045508f28f688.bmp

函数创建及测试

我们使用如下示例来创建函数程序包。

准备函数文件

创建目录 mnist_demo,并在根目录下创建文件 mnist.py,文件内容如下。

#!/usr/bin/env python2.7

import os
import sys
import base64
import urllib
import tensorflow as tf
import numpy as np
import utils
import json

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

# Load model
cur_dir = os.getcwd()
model_dir = cur_dir+"/export/4"
sess = tf.Session(graph=tf.Graph())
meta_graph_def = tf.saved_model.loader.load(sess, [tf.saved_model.tag_constants.SERVING], model_dir)
x = sess.graph.get_tensor_by_name('x:0')
y = sess.graph.get_tensor_by_name('y:0')

def run(event):
    local_path = ""
    if event['image_base64'] != "":
        data=base64.b64decode(event['image_base64'])
        local_path = '/tmp/test_image.xxx'
        file=open(local_path,'wb')
        file.write(data)
        file.close()
    elif event['image_url'] != "":
        img_url = event['image_url']
        filename = urllib.unquote(img_url).decode('utf8').split('/')[-1]
        local_path = os.path.join('/tmp/', filename)
        if not utils.download_image(event['image_url'], local_path):
            return False, -1
    else:
        print('Please specify a image.')

    try:
        x_ = utils.get_image_array(local_path)
        predict = tf.argmax(y, 1)
        res = sess.run(predict, feed_dict={x: x_})[0] 
        return True, sess.run(predict, feed_dict={x: x_})[0]
    except Exception as e:
        print(e)
        return False, -1

def demo(event, context):
    res, num = run(event)
    print num
    return num
        
def apigw_interface(event, context):
    if 'requestContext' not in event.keys():
        return {"errMsg":"request not from api gw"}
    body_str = event['body']
    body_info = json.loads(body_str)
    res, num = run(body_info)
    return {"result":num}

从代码中我们可以看到,函数在初始化时就将目录 export 下的文件作为模型加载到了 TensorFlow 中。在实际的事件处理中,既可以从事件中抽取 base64 编码后的图片,也可以识别 url 参数,并均把图片保存至本地 /tmp 目录下。然后在使用 util 工具,对图片进行规整处理后,将处理后的数据送入 TensorFlow,获得推理结果并返回。

在根目录下同时创建 util.py,代码内容如下。此模块提供了图片下载、图片处理等辅助能力。

#!/usr/bin/env python2.7

import urllib2
import numpy as np
from PIL import Image

def download_image(img_url, local_file):
    ret = True
    try: 
      f = urllib2.urlopen(img_url)
      data = f.read()
      with open(local_file, "wb") as img:
          img.write(data)
    except Exception as e:
        print(e)
        ret = False
    return ret

def get_image_array(img_path):
    x_s = 28
    y_s = 28
    n0 = 0
    n255 = 0
    threshold = 100
    im = None
    im = Image.open(img_path)

    img = np.array(im.resize((x_s, y_s), Image.ANTIALIAS).convert('L'))

    for x in range(x_s):
      for y in range(y_s):
        if img[x][y] > threshold:
          n255 = n255 + 1
        else:
          n0 = n0 + 1

    if(n255 > n0) :
      for x in range(x_s):
        for y in range(y_s):
          img[x][y] = 255 - img[x][y]
          if(img[x][y] < threshold) :
            img[x][y] = 0

    arr = img.reshape((1, 784))
    arr = arr.astype(np.float32)
    arr = np.multiply(arr, 1.0 / 255.0)
    return arr

同时由于 util.py 中使用了 PIL 库,需要在代码根目录下提供 PIL 库,可以使用此 PIL库文件 来下载库并解压后放置在代码根目录。

准备函数部署包

最终,我们得到的代码目录结构为如下结构,其中PIL文件夹下由于文件过多就不进行展开了。

mnist_demo
|
|-- mnist.py
|-- utils.py
| export
    | 4
        |-- saved_model.pb
        | variables
            |-- variables.data-00000-of-00001
            |-- variables.index
| PIL
    |-- ...

在 mnist_demo 这个目录下,我们选择所有文件然后打包为 zip 包。注意,这些文件需要在 zip 包的根目录下,而不是 mnist_demo 文件夹在zip包的根目录。

最终我们得到了一个可以上传到云函数的 zip 包。如果对于前面的操作都不想进行,也可以直接在这里下载已经打好的包即可。

创建函数

由于创建的函数部署包稍大,所以我们需要通过对象存储来上传代码包。

我们可以在腾讯云对象存储 COS 中先创建一个 bucket,例如在广州区创建名为 code 的 bucket,并将上一步获取的代码包上传 bucket,作为我们后续创建函数的代码来源。

进入腾讯云无服务器云函数 SCF 的控制台,选择广州区以后,点击新建函数,为函数起一个比较容易记住的名字,例如 testai,选择运行环境为 Python 2.7,然后下一步到代码配置页面。

在代码配置页面,选择代码输入种类为 通过 COS 上传 zip 包,选择刚刚创建的bucket为 cos,并填写对象文件为 /mnist_demo.zip

同时,函数执行方法需要确定为 mnist.apigw_interface,对应代码包中的 mnist 文件和 apigw_interface 函数。

测试函数

点击函数界面右上角的测试按钮,并使用如下测试模版来测试函数。

{
  "requestContext": {
    "serviceName": "testsvc",
    "path": "/test/{path}",
    "httpMethod": "POST",
    "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "identity": {
      "secretId": "abdcdxxxxxxxsdfs"
    },
    "sourceIp": "10.0.2.14",
    "stage": "prod"
  },
  "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": "{\"image_base64\": \"\", \"image_url\": \"https://main.qcloudimg.com/raw/84783c178cdc6d6b2302bc1b4749b91b.bmp\"}",
  "pathParameters": {
    "path": "value"
  },
  "queryStringParameters": {
    "foo": "bar"
  },
  "headerParameters":{
    "Refer": "10.0.2.14"
  },
  "stageVariables": {
    "stage": "test"
  },
  "path": "/test/value?foo=bar",
  "httpMethod": "POST"
}

这里可以看到,我们主要使用了body字段,并在body字段内填写的数据结构为:

{
  "image_base64": "",
  "image_url": "https://main.qcloudimg.com/raw/84783c178cdc6d6b2302bc1b4749b91b.bmp"
}

这个数据结构也是我们创建的函数所能接受和处理的结构,如果有 base64 编码的图片文件内容,则使用编码的内容,或者使用url传入的图片地址,将图片下载到本地后交由 TensorFlow 进行预测推理。在这里测试时,我们可以用上我们在一开始准备的图片地址,而在实际推理时,可以替换成其他可访问的图片地址。

点击测试运行后,如果使用的是上面的地址,使用的是第一副图片,那么函数的返回内容将是 {"result": 0},标识其推理出来的图片内是数值 0。

使用 API 网关进行 API 封装

接下来我们通过 API 网关服务,来创建一个 API 对刚刚创建的推理函数进行封装,并对外提供 API 服务。

创建 API 服务及 API

首先在 API 网关的控制台,在广州区创建一个 API 服务。服务名可以起一个容易记住的名字,例如 testai。

接着进入API 管理,创建 API。同样可以起一个容易记住的名字,例如 ai。请求路径可以写为 /ai,请求方法为 POST。为了方便调试,我们这里可以勾选上免鉴权。

接着下一步,后端类型选择为 cloud function,并选择我们在前面创建的函数 testai。

最后一步填入响应内容为 JSON,描述正确示例为 {"result":0},错误示例为 {"errMsg":"error info"} 即可。

调试 API

点击 API 查看界面的 API 调试,进入调试页面。确定 Content-Type 为 application/json,输入框内填入以下内容后点击发送请求。

{
  "image_base64": "",
  "image_url": "https://main.qcloudimg.com/raw/84783c178cdc6d6b2302bc1b4749b91b.bmp"
}

确认响应的 body 为 {"result": 0},符合预期。同理,这里的 url 地址同样可以更改,并且响应内容随图片的不同而不同。

API 发布及外网测试

在 API 调试成功后,我们可以在服务列表页面,将我们刚刚创建的 testai 服务发布到 发布环境

然后根据 testai 的服务域名,我们可以得到刚才的 API 的完整路径为:http://service-kzeyrb6x-1253970226.ap-beijing.apigateway.myqcloud.com/release/ai。我们可以使用 http request 的发起工具,例如 Postman,或 restclient 等,向此 API 地址发起 POST请求,POST内容可以为如下内容。

{
  "image_base64": "",
  "image_url": "https://main.qcloudimg.com/raw/84783c178cdc6d6b2302bc1b4749b91b.bmp"
}

{
  "image_base64": "Qk1mCQAAAAAAADYAAAAoAAAAHAAAABwAAAABABgAAAAAADAJAAAAAAAAAAAAAAAAAAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAA////////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////AAAAAAAA////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////",
  "image_url": ""
}

这两个不同的数据结构,分别测试了使用 base64 编码的图片内容,或者使用图片 url 地址传递图片内容的方式。同时可以根据自身需求,修改数据结构内的 image_base64 或 image_url 内容,查看测试结果。

第三蓝河亚热带生物CallLin回答于

在 serverless落地场景中,对对象文件的处理很常见。对象文件处理指的是对对象文件进行操作后的回调处理。回调通常是在对象文件创建或删除操作后产生的事件。云函数可以在获取到这个事件后进行后续的处理。这里常见的处理逻辑是下面几种,比如说图片处理,针对图片去生成各种尺寸的缩略图或者进行裁剪,然后再次存储到对象存储数据中,之后可以根据不同客户端的请求展示不同大小的图片到前端。

文件批量打包,用户需要进行文件筛选和打包的时候可以通过使用云函数来处理。在上传文件后,如果需要选择哪些文件来打包,把文件生成压缩包以供下载,这都可以由事件处理来进行。

日志归档分析,以及业务系统回调,也是云函数所承载的业务逻辑。比如说日志归档分析这种用法,用户会把每天的前端应用服务器的日志上传到对象存储中归档,归档后会触发云函数执行,云函数会拉下这些日志文件进行实时分析,它会抽取这些日志中的错误数,或者是其他业务相关或者用户关注的内容,然后再把它抽取到的信息或者统计到的信息写回数据库,供用户后续进行排查、使用。用户自身API调用也是,例如用户生成的一些视频文件上传到对象存储,会触发云函数,将上传文件的信息通知到用户的转码系统,通过视频转码转成不同分辨率然后再进行存储。当然转码是用户自身实现的业务系统,这块通过回调通知,通知它自身的业务系统。这些就是云函数在Serverless架构和对象存储连用的落地场景。

刺猬Christian.CS.真理使人得自由.回答于

利用定时器触发。原本大家更多是在运维场景下使用定时任务,在原有使用 crontab 脚本的情况下,大家通常还要关心脚本运行是否成功,这台虚拟机是否还在工作。云函数抛弃了大家使用传统的虚拟机或者物理机来去写crontab脚本还要确保可靠性的问题。而在实际使用定时器触发的场景下,这里也有几种用法:一种是业务拨测。这个是周期性的去拨测业务是否还在工作,如果出现异常的情况下能够及时的发出告警,发出邮件或者短信告诉到运维或开发人员。

愤怒的白菜PostgreSQL DBA回答于

Serverless架构本身给用户带来什么?它实际上就是允许我们更关注业务代码,因此可以更快速的构建业务然后上线。现在互联网开发速度越来越快,因此大家期望的是进一步加快开发和业务真正上线的速度,提高迭代的能力。因此,使用Serverless的话可以更快速让业务上线,让我们更快实现我们的想法。而按需使用是我们这个业务在上线之后,在真正产生请求后,业务才会被调动触发,才会有计算。而如果你的业务产生了爆发式增长,其实也不需要担心平台承载能力或者业务扩展是否跟得上,因为平台提供自动扩展能力,降低了大家对运维的诉求,大家不用关心很底层的东西,而运维人员也可以更偏重流程化和业务相关的运维。这就是Serverless架构给大家带来的一些好处。而作为Serverless里的核心,函数即服务这种产品,是Serverless中所呈现出来的计算型的组件,大家也可以看到它和触发源和后端的各种产品或服务有紧密关联,它可以更多的被看做是云时代的脚本,类似于黏合剂,把前面的触发源和后端的各种存储,数据,服务进行了黏合,真正实现架构落地,才是真正实现业务逻辑落地的能力。

qzuser回答于

Serverless 在事件驱动方面具有天然的优势,可以做聊天机器人

大秦回答于

定时备份,这个是在所需要的周期内,比如每天,或者每两天对数据库进行备份,针对数据库需要做数据导出,导出后再将导出内容以文件的形式存储到合适的地方,例如对象存储中,做好定时备份。

可能回答问题的人

  • 腾讯云计算产品团队

    腾讯云 · 产品团队 (已认证)

    136 粉丝0 提问0 回答
  • CVM 产品团队

    24 粉丝0 提问7 回答
  • 小仙女和科学家

    9 粉丝0 提问0 回答
  • 怕冷的阳阳

    腾讯云 · 高级工程师 (已认证)

    19 粉丝1 提问0 回答
  • DRRR

    腾讯云 · 产品经理 (已认证)

    6 粉丝0 提问4 回答
  • 腾讯云serverless团队

    腾讯云 · 产品团队 (已认证)

    78 粉丝0 提问24 回答

扫码关注云+社区

领取腾讯云代金券