Fun 发布 2.0 新版本啦

简介: 不久前,我们发布了 Fun 的 2.0 版本。欢迎大家使用! Fun 是什么 Fun 是 have Fun with Serverless 的缩写,是一款 Serverless 应用开发的工具,可以帮助用户定义函数计算、API 网关、日志服务等资源。

不久前,我们发布了 Fun 的 2.0 版本。欢迎大家使用!

Fun 是什么

Fun 是 have Fun with Serverless 的缩写,是一款 Serverless 应用开发的工具,可以帮助用户定义函数计算、API 网关、日志服务等资源。

为什么需要 Fun

Serverless 的出现,为我们的开发效率带来了巨大的提升。我们可以将 Serverless 看成是一种 "OpsLess" 的开发方式。利用 Serverless 产品开发出的应用,先天就是高度弹性可扩展的、按使用量付费的。

Serverless 已经极大的提升了开发效率以及应用发布后的运维效率。但在使用传统方式开发 Serverless 应用时,因为生态的相对不成熟,还是面临一些问题:

管理困难。FaaS 作为 Serverless 平台体系中的一部分,提供了一种更小粒度的开发模型。实现一个函数,就和我们过往开发中实现一个接口方法类似。因此,在一个 Serverless 应用中,往往包含多个函数,一部分函数可以用于功能的实现,一部分函数可以用于云服务间的粘合,这就导致了要管理非常多的的资源数量,如果再考虑到需要将函数部署在多个 region 中,那么要管理的资源数量还要乘上 region 数量。

交付困难。应用开发完成后,除了代码本身,还要附带详细的配置文档。

移植困难。在不同的 Region 下配置相同的应用,如果是手动操作,操作十分繁琐,也不利于维护。

Fun 就是致力于解决这些问题的一款工具。

全新的 Fun 2.0

2.0 我们依旧致力于为客户提供一款更好用的、提升开发效率的工具。2.0 的新功能参见

2.0 相对于之前的版本,主要两个变化:

1. 定义了全新的 Serverless Application Model

为了解决传统方式开发 Serverless 应用面临的问题。Fun 2.0 版本引入了全新设计的 Serverless Application Model(SAM) 规范。

SAM 作为一种基础设施即代码(Infrastructure as Code),允许用户描述函数计算及其相关云资源,可以使用同一份模板文件,进行跨 region 或者账户部署您的云应用。描述云资源的模板文件,也会成为项目代码的一部分,在不同开发者之间共享。这极大的降低了 Serverless 应用的交付难度、管理难度、移植难度。

SAM 在设计之初,就考虑到对 ROS 的兼容,在未来,我们会将 ROS 已有的能力纳入进来,与 ROS 相互赋能。

2. 对其描述能力进行了增强

除了 1.0 支持的函数、API 网关的配置,我们在 2.0 中:

  • 增强了对函数的描述能力:环境变量、日志服务、角色属性、VPC 属性等。
  • 支持配置新的应用资源,比如 Table Store、日志服务等。
  • 代码上传可以指定文件、目录、压缩包以及 OSS 路径。
  • 更多的 API 网关参数配置
  • 等等

Fun 使用示例

下面我们用 nodejs 编写一个结合函数计算、表格存储以及 API 网关的 demo,该 demo 可以用于统计网站的访问者数量。

首先,创建一个名为 index.js 的文件,内容为:

'use strict';

const TableStore = require('tablestore');
const Long = TableStore.Long;

async function getClient(context) {
    return new TableStore.Client({
        accessKeyId: context.credentials.accessKeyId,
        secretAccessKey: context.credentials.accessKeySecret,
        stsToken: context.credentials.securityToken,
        endpoint: process.env['Endpoint'],
        instancename: process.env['InstanceName']
    });
}

async function getCount(client) {
    var params = {
        tableName: process.env['TableName'],
        primaryKey: [{ 'count_name': 'views' }],
        maxVersions: 1
    };

    const tableName = process.env['TableName'];
    const response = await client.getRow(params); 
    const row = response.row;

    if (row && row.primaryKey) {
        return row.attributes[0].columnValue.toNumber();
    }
    return null;
}

exports.handler = function(event, context, callback) {

    (async () => {
        let views = null;

        const client = await getClient(context);
        let success = false;

        do {
            views = await getCount(client);

            if (views) { 
                try {
                    await client.updateRow({
                        tableName: process.env['TableName'],
                        condition: new TableStore.Condition(TableStore.RowExistenceExpectation.IGNORE, new TableStore.SingleColumnCondition('count', Long.fromNumber(views), TableStore.ComparatorType.EQUAL)),
                        primaryKey: [{ 'count_name': 'views' }],
                        updateOfAttributeColumns: [
                            { 'PUT': [{'count': Long.fromNumber(views + 1)}]}
                        ],
                        returnContent: { returnType: TableStore.ReturnType.Primarykey }
                    });
                    success = true;
                } catch (ex) {
                    if (ex.code !== 403) {
                        callback(ex, null);
                    }
                }
            } else {
                try {
                    views = 1;
                    const res = await client.updateRow({
                        tableName: process.env['TableName'],
                        condition: new TableStore.Condition(TableStore.RowExistenceExpectation.EXPECT_NOT_EXIST, null),
                        primaryKey: [{ 'count_name': 'views' }],
                        updateOfAttributeColumns: [
                            { 'PUT': [{'count': Long.fromNumber(views)}]}
                        ]
                    });
                    success = true;
                } catch (ex) {
                    console.log(ex);
                }
            }
        } while(!success);

        var response = {
            isBase64Encoded: false,
            statusCode: 200,
            body: `You are the ${views}th visitor!`
        };

        callback(null, response);
    })();
};

这里我们需要处理表格存在、表格不存在的两种情况,分别保证他们的操作的原子性。

可以看到,这里我们对于表格存储的配置都是直接从环境变量中读取的。即使后续的开发过程中,修改了表格的名字,只需要修改配置即可,不用修改代码。

接下来,我们直接在 template 中定义函数、表格存储以及 API 网关:

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
  views-count-demo: # service name
    Type: 'Aliyun::Serverless::Service'
    Properties:
      Description: 'Module as a service'
      Policies: 
        - AliyunOTSFullAccess
    views-count: # function name
      Type: 'Aliyun::Serverless::Function'
      Properties:
        Handler: index.handler
        CodeUri: './'
        Description: 'views counts'
        Runtime: nodejs8
        EnvironmentVariables:
          InstanceName: views-count-inst
          TableName: viewsTablesName
          Endpoint: https://views-count-inst.cn-shanghai.ots.aliyuncs.com

  views-count-inst: 
    Type: 'Aliyun::Serverless::TableStore'
    Properties:
      ClusterType: HYBRID
      Description: used for views_count_demo
    viewsTablesName: # table name
      Type: 'Aliyun::Serverless::TableStore::Table'
      Properties:
          PrimaryKeyList:
            - Name: count_name
              Type: STRING

  views_count_apis:
    Type: 'Aliyun::Serverless::Api'
    Properties:
      StageName: RELEASE
      DefinitionBody:
        '/':
          get:
            x-aliyun-apigateway-api-name: views
            x-aliyun-apigateway-request-config:
              requestMode: "PASSTHROUGH"
              requestProtocol: "http"
            x-aliyun-apigateway-fc:
              arn: acs:fc:::services/${views-count-demo.Arn}/functions/${views-count.Arn}/

执行 fun deploy,即可创建、配置并部署好相关服务:

$ fun deploy

Waiting for service views-count-demo to be deployed...
    Waiting for function views-count to be deployed...
    function views-count deploy success
service views-count-demo deploy success

Waiting for table store views-count-inst to be deployed...
    Waiting for table store viewsTablesName to be created...
    create table store viewsTablesName successfully
table store views-count-inst deploy success

Waiting for api gateway views_count_apis to be deployed...
    URL: GET http://81f67bf5fce5478fa5dc18864a1fda18-cn-shanghai.alicloudapi.com/
      stage: RELEASE, deployed, version: 20180702222529788
      stage: PRE, undeployed
      stage: TEST, undeployed
api gateway views_count_apis deploy success

用浏览器打开提示的链接 http://81f67bf5fce5478fa5dc18864a1fda18-cn-shanghai.alicloudapi.com/,即可预览效果。

demo 完整代码

未来展望

Fun 2.0 对我们来说,只是前进了一小步。Fun 工具还有很多地方需要改进,接下来我们会在以下三个方向上作出努力:

  • 功能更完善:提供对更多资源的支持,比如 ots trigger、oss 及其触发器等。提供对 ROS 的支持,将 ROS 的能力整合进来。
  • 开发更连贯:提供提供初始化工程的功能,并且支持线上配置导出为模板文件,即使手边没有模板文件,也能将线上配置一键导出为模板文件,助您持续地开发,高效地迭代。
  • 调试更容易:提供本地运行调试、依赖安装打包等功能的支持,本地运行结果即为线上预期结果。

大家有什么新的需求或者使用过程中有任何问题,请随时联系:@倚贤 @小默 @朴灵

Fun 相关文档

使用入门:中文英文

Serverless Application Model 规范文档:中文英文

github demos

目录
相关文章
9kr
|
应用服务中间件 网络安全 nginx
通过宝塔Nginx反代HomeAssistant并添加SSL实现隐藏端口号与域名访问
HomeAssistant默认使用8123端口,带端口访问既不美观也不方便。 通过宝塔Nginx默认反代配置会出现各种意外错误,本文将通过修改HomeAssistant与反代配置解决该问题。
9kr
5882 1
通过宝塔Nginx反代HomeAssistant并添加SSL实现隐藏端口号与域名访问
|
存储 Kubernetes 调度
k8s常见的排错指南Node,svc,Pod等以及K8s网络不通问题
k8s常见的排错指南Node,svc,Pod等以及K8s网络不通问题
5559 1
|
10月前
|
开发工具 开发者
HarmonyOS实战:腾讯IM之聊天详情页面搭建(二)
本文讲解了在鸿蒙系统中实现腾讯IM聊天功能的完整流程,涵盖对话列表展示、历史消息获取、实时消息更新及文本消息发送等核心功能。通过实际代码示例,详细说明了如何利用IM SDK实现聊天业务逻辑。适合开发者逐步学习并实践,建议点赞收藏以便参考。
275 9
HarmonyOS实战:腾讯IM之聊天详情页面搭建(二)
|
存储 Kubernetes 调度
在K8S中,怎样实现数据持久化?
在K8S中,怎样实现数据持久化?
|
9月前
|
索引
鸿蒙开发:自定义切换动画实现Swiper层叠滑动效果
customContentTransition不仅仅可以实现平移上的改变,很多的效果,我们都可以实现,比如放大缩小,旋转等等。
447 2
鸿蒙开发:自定义切换动画实现Swiper层叠滑动效果
|
10月前
|
开发工具 Android开发 iOS开发
HarmonyOS实战:腾讯IM之聊天列表搭建(一)
本文详细介绍了在鸿蒙系统中实现腾讯IM聊天列表页面的过程。由于腾讯仅提供了接口而无现成UI,需自行开发。文章涵盖需求分析(如删除功能、时间排序、消息更新)、技术实现(展示会话列表、新增会话、删除会话)等内容,并附代码示例。最终实现了类似微信的聊天列表功能,建议点赞收藏以便后续参考。
373 5
HarmonyOS实战:腾讯IM之聊天列表搭建(一)
|
10月前
|
JavaScript Java 开发工具
零基础用 DevEco Studio 打造你的首个 HarmonyOS 应用,开启鸿蒙生态的创新之旅,实现你的技术探索梦想
在鸿蒙生态蓬勃发展的当下,越来越多的开发者怀揣着热情与创意,渴望投身于HarmonyOS应用开发的浪潮之中。
零基础用 DevEco Studio 打造你的首个 HarmonyOS 应用,开启鸿蒙生态的创新之旅,实现你的技术探索梦想
|
10月前
|
人工智能 弹性计算 运维
阿里云邀请您参加 2025 中国 Serverless 用户调查
阿里云邀请您参加 2025 中国 Serverless 用户调查
|
10月前
|
数据采集 运维 监控
Serverless爬虫架构揭秘:动态IP、冷启动与成本优化
随着互联网数据采集需求的增长,传统爬虫架构因固定IP易封禁、资源浪费及扩展性差等问题逐渐显现。本文提出基于Serverless与代理IP技术的新一代爬虫方案,通过动态轮换IP、弹性调度任务等特性,显著提升启动效率、降低成本并增强并发能力。架构图与代码示例详细展示了其工作原理,性能对比数据显示采集成功率从71%提升至92%。行业案例表明,该方案在电商情报与价格对比平台中效果显著,未来有望成为主流趋势。
439 0
Serverless爬虫架构揭秘:动态IP、冷启动与成本优化
|
并行计算 监控 Linux
《CST Studio Suite 2024 GPU加速计算指南》
《GPU Computing Guide》是Dassault Systèmes发布的CST Studio Suite 2024的GPU计算指南,涵盖了硬件支持、操作系统支持、许可证、启用方法、NVIDIA和AMD GPU的详细信息及使用指南和故障排除等内容。硬件支持包括NVIDIA和AMD的多种GPU型号,操作系统支持多种版本,许可证通过加速令牌或SimUnit令牌授权。启用方法包括交互式模拟和批处理模式。使用指南和故障排除部分提供了详细的配置和问题解决方法。
1718 9