什么是函数计算?

函数计算,也称为Function Compute,是一种事件驱动的计算服务,它为您提供了一个安全的环境,使您能够在全面监控和日志记录的情况下执行代码。通过函数计算,您将免去管理基础设施、网络资源、实例缩放和系统负载平衡的困扰。您只需要上传您的代码到我们的服务,我们会保障您应用的高可用性和高可拓展性。您可以更专注于开发业务逻辑。函数计算与阿里云许多其他云服务无缝集成。您可以使用阿里云其他云服务触发函数执行。

FC 函数是什么?

FC 函数是您上传到我们服务的一段业务代码。我们提供了多种编程语言编写您的函数,目前支持的开发语言类型请参考开发语言列表 。 关于函数的详细信息,请参考函数简介

触发器是什么?

触发器是触发函数执行的机制。您可以通过 SDK&API 调用函数执行的或在函数上设置触发器调用函数。函数计算集成很多阿里云其他产品的触发器触发您函数的执行。例如:您可以在 OSS bucket 上设置一个触发器,以便在对象上传到 bucket 时触发函数的执行。 关于触发器的详细信息与支持触发器的完整列表,请参考触发器列表

我可以使用什么语言编写函数呢?

请参考开发语言列表

在函数中如何访问其他服务?

函数计算只是提供一个执行环境,在函数中访问其他服务例如OSS、MNS、数据库、自建的HTTP服务等,甚至是访问函数计算(例如调用触发一个函数),与您在本地访问这些服务是没有差异的:您只需要将相应的依赖库跟函数代码一起打包上传,就可以在函数中访问相应的服务。依赖打包请参考为函数安装第三方依赖

函数要运行多久呢?

函数的默认超时时间是 3 秒,您可以将函数超时时间设置为 1 到 600 秒之间的任何值。

我应该什么时候使用函数计算,什么时候使用 ECS ?

ECS 提供了各种各样的执行环境和选项定制操作系统、网络、安全设置、软件日志记录、软件监视和软件负载平衡,从而允许您自定义端到端的软件栈解决方案。您拥有对 ECS 实例的完全控制和所有权。您可以使用 ECS 定制自己的伸缩逻辑,或者利用容器服务管理 ECS 上的容器集群。 函数计算抽象底层基础结构,并为您提供统一的计算环境。使用函数计算,您可以在管理基础架构和操作系统中解放出来。函数计算将提供函数执行的基础平台,并提供全面的监测和日志记录功能。您不必担心服务的拓展和负载平衡,因为函数计算将自动为您处理。您只需要专注于业务逻辑的开发。

函数计算如何保证我代码的安全?

函数计算提供了代码加密并将其存储在 OSS 中。每当使用代码时,我们都执行完整性检查。代码执行与它自己的文件系统和网络命名空间相隔离。

如何弹性扩展函数的执行?

函数计算最大的好处之一是不需要提供任何资源扩展函数执行,这也是 serverless 的特点。函数计算将根据您函数请求的并发数弹性伸缩资源执行您的函数。

可以访问运行函数的机器吗?

不可以,函数计算自行帮您维护所有基础设施,包括健康检查、应用安全补丁、操作系统更新和其他日常维护。

如何监控函数执行?

函数计算每次执行都会生成执行计量数据,并将其输出到 云监控。 您可以在云监视器控制台中查看函数运行情况,使用云监控来监控函数计算运行情况请参考监控数据。也可以为服务执行设置日志服务保存您的执行过程和结果。为函数计算配置日志请参考函数日志

什么是 VPC ?

虚拟私有云(Virtual Private Cloud)是为私人使用而构建的隔离云网络。它允许您在虚拟网络环境中逻辑地隔离云资源。所有函数都运行在函数计算拥有的 VPC 网络环境中。由于 VPC 网络隔离的性质,FC 函数缺省情况下是不能访问您的私有 VPC 资源。

如何用函数访问私有 VPC 资源?

函数计算允许您配置您的函数以访问特定的 VPC。您可以授予函数计算操作弹性网络接口(ENIs),并提供特定的 VPC 配置信息,包括 VPC ID、交换机ID 和安全组 ID。一旦 VPC 配置被启用,您的函数就可以运行在特定的 VPC 内部里。

函数可以访问多少个 VPC?

每个函数可以配置为最多一个私有 VPC。如果您的函数需要访问一个以上的私有VPC,您可以将您的私有VPC 拼接成一个大VPC,并授予您的函数访问这个大VPC 的权限即可达到访问多个VPC环境。

在 VPC 环境里如何访问经典网络中的资源?

当 FC 函数运行在某个VPC 网络环境时,如果您需要访问经典网络的资源,您可以使用经典网络链接将资源链接到您的私有 VPC,然后授予您的函数访问您的私有 VPC。您的函数可以通过您的私有 VPC 访问经典网络中的资源。

在 VPC 中的函数如何访问公网?

函数计算在 VPC 功能里提供了一个启用或禁用您的函数的公网访问的功能。一旦启用公网访问,函数计算将具有公网访能力。您可以通过设置 internetAccess 选项启用或禁用公网访问。也可以在您的私有 VPC 中搭建公网 NAT 授权您的 VPC 函数接入公网,这个功能能让您的应用非常灵活的设置在VPC环境里访问公网。

遇到 VSwitch is in unsupported zone 的错误怎么办?

根据错误信息,找到函数计算所支持的可用区(Zone),在您的VPC中,在这个可用区创建一个虚拟交换机(VSwitch),然后以此交换机配置函数计算服务的VPC配置。配置成功后,在函数就可以访问您的VPC资源了。同一个VPC内不同可用区的交换机默认内网互通,原理可参考文档创建专有网络

函数计算只支持 Node.js,我用 C++ 写的程序怎么运行?

我们会根据用户需求不断拓展支持的语言种类。当前我们支持的编程语言请参考开发语言列表,如果您的程序是用我们还未支持的语言实现的,您可以采用以下做法:

  • 用函数计算支持的语言改写。Node.js,Python等语言包含了非常丰富的类库,开发效率很高。
  • 将 C/C++ 等程序编译为可执行文件,通过fork等系统调用的方式运行可执行文件。
  • 将 C/C++ 模块编译为shared library,在Python等语言中通过binding的方式调用。

下表总结了以上方法的优缺点:

构建方式 实施难度 性能损失 适用场景
重写逻辑 取决于逻辑复杂度 取决于语言以及具体应用场景 适用于逻辑不太复杂的场景
调用可执行文件 适合对延时不敏感的场景,例如异步后台文件处理等等
调用shared library 适合性能要求很高的场景

如果以上方法仍不能解决您的问题,请联系我们。我们还可以为您定制其他方法。

现在 docker 这么火,为什么函数计算不支持用户自定义 docker 镜像?

实际上支持用户自定义镜像本身不是特别难,难的是支持特别大的自定义镜像。为了保证实时伸缩,系统必须在很短的时间内将容器启动。如果用户自定义的镜像特别大,下载镜像的时间可能就长达几分钟,这样的性能损失很难接受。我们希望您能使用微服务的开发方式,将逻辑解耦,每个函数的功能明确。这样函数代码一般不会有特别复杂的依赖,更容易构建。

函数计算的运行环境中所依赖的包如何自动安装?

函数计算要求您上传的代码包中包含了所有的依赖。不同的语言包管理机制不同,例如在 Node.js 中,您可以使用 npm 将依赖的包安装到代码目录中并打包上传。您可以使用我们的命令行工具 fcli 安装依赖并打包,可参考云栖社区在各种 runtime 中增加三方包或者动态链接库的方式。

函数运行

我在函数里要运行一个可执行文件,在本地调试通过,为什么在函数计算的环境中返回 permission denied 错误?

通常在 Windows 系统中开发函数会遇到类似的问题,主要的原因是在打包代码时, Windows 平台下的有些压缩工具丢失了文件/文件夹的属性。当代码在函数计算的运行环境中解压后(Linux),就会遇到没有权限的问题。请确保您的压缩工具保留了文件或者文件夹的others权限,例如755或者664。或者使用 Linux/Mac OS 开发。

如果我程序要产生很大一个文件,或者需要一个比较大的空间,我什么地方能申请到?

您的函数在运行时有512MB的临时存储空间。如果还不够用,请考虑用流式的方式处理数据,通常这样会更加高效。通过流式的方式,将一个函数从原来消耗1G内存,运行几分钟,优化到消耗256MB内存,运行10秒钟。请参考示例,详见示例。如果仍然不能解决您的问题,请联系我们

在程序运行过程中,实际使用了多少内存,我从哪些接口能获取到?

函数调用的返回信息中会包含最大内存消耗等信息。您也可以从性能监控指标中查看连续一段时间的函数运行资源消耗情况。

函数可以相互调用吗?

函数可以相互调用。由于函数可能运行在不同的机器上,所以是通过 RPC 的方式远程调用。您可以使用我们的 Invoke API 调用指定函数。您可以参考各个不同语言的 SDK 相关调用示例,需要注意的是,您可以从入口函数参数 Context 对象中获取相关的临时 token 来构造对应的 FC client。

除了函数直接调用方式以外,您也可以使用函数工作流编排函数,请参见函数工作流

我的函数如果出现死循环,我怎么杀掉函数进程?

死循环可以分为两种:1) 单个函数运行逻辑出现死循环。2)多个函数调用出现无限递归,无法中止的情况。例如函数 A 调用 B,B 又调用 A。情况1比较容易,函数超时后,系统会自动中止函数,您会收到超时错误,但不会有财务损失。情况2比较麻烦,对系统来说,会认为这种调用是合法的。此时需要您通过函数级别的指标监控报警。此外,我们在用户粒度上设置了函数的最大并发度,确保您的费用消耗是可控的,详情请参见使用限制

如何避免循环触发?

一个典型的循环触发场景是OSS的某个Bucket上传文件触发了一个函数,这个函数处理事件,又生成了一个或多个文件,写回到OSS的Bucket里,这个写入动作又触发了函数执行,形成了链状循环...

上述过程类似于一个无限递归,为了避免这种循环触发函数,需要设定一个递归终止条件,例如将触发函数的Bucket目录前缀设置成src/,生成的文件写入的目录前缀设置为dst/,这样生成的文件就不会再次触发函数,一定要尽量避免循环执行导致不必要的费用。

函数计算一个用户下的最大并发度只有100,所以我构建的服务每秒最多只能处理100个请求?这也太小了吧。

每秒处理请求数(qps)和最大并发度有关系,但二者不是一个概念。您可以用下面的公式估计:每秒请求数 * 请求处理时间(秒) = 最大并发度。例如,假设您预期每秒10000个请求,平均每个请求处理时间为1秒,那么所需的最大并发度为10000;如果平均每个请求处理时间为10毫秒,那么所需的最大并发度是10000 * 0.01秒 = 100。此外,最大并发度的目的是对用户的保护,防止用户的费用失控,例如上面提到的函数相互调用无限递归而无法中止的例子。如果默认的值不够,您可以联系我们调整成您期望的值,联系方式请参见联系我们

我的执行环境是否是独立安全的?怎么保障?

确保安全是函数计算最重要的目标。我们在产品和系统设计的每个方面都把安全作为最高优先级的目标。您的程序在函数计算环境中运行的隔离保护和阿里云的 ECS 是同一级别,即我们是在虚拟机级别隔离运行,而非容器。此外我们还在网络,数据,代码,防 DDos 攻击等方面做了完备的保护,确保您的信息安全。

我的客户端不关心函数执行结果,我不希望我的客户端一直等函数返回怎么办?

您可以使用函数计算的异步调用,异步调用会将您的请求加入到后端队列,客户端会立即返回。函数计算后端会将队列中的请求做并发调用。可以参考各 SDK 的 async invoke:

临时磁盘空间什么时候被释放?

临时磁盘空间与底层执行函数的容器生命周期一致。如果您持续有请求,那么这个容器会一直存在,因此您之前在磁盘上留下的数据也会存在。但如果函数很长一段时间没有请求,容器被系统回收后,磁盘上的数据也会消失。

当前目录不可写怎么办?

用户函数中使用的一些库,可能会尝试在当前目录写入一些配置文件,此时会遇到 "[Errno 30] Read-only file system: '/code/.xxx" 的错误,解决办法是在函数开始执行前,把进程的当前目录设置为 /tmp (/tmp是可读写的目录)。

Python:

def my_handler(event, context):
    import os
    os.chdir('/tmp')
    // 其他代码           

Nodejs:

exports.handler = function(event, context, callback) {
  process.chdir('/tmp');
  // 其他代码
};            

我的函数会运行很久,超过函数最大 timeout 时间怎么办?有什么可以让函数一直运行的方法吗?

函数最长运行时间为 10 分钟,如果您函数的运行时间远大于 10 分钟,建议您将大函数拆分成几个小函数独立运行,建议使用函数工作流编排函数,流程中所有函数运行时间支持最长 1 年。

如果您的函数运行时间稍大于 10 分钟但不超过 15 分钟,且很难拆分,可以联系我们为您调大限制。联系方式请参见联系我们

我有10个函数,都用到了同一个公共库。我能否只上传一份公共库的代码,让这些函数共享同一份库代码?

不同的函数,负载有高有低,tps 10000 和 100 的函数,对资源的伸缩要求肯定不同。因此函数计算中各个函数的资源伸缩是独立进行的,函数之间代码包是独立的,不能共享。

如何快速定位线上问题?

可以开通阿里云日志服务,然后在您的代码中添加日志,通过查询记录 request ID 和日志查询快速定位问题。详情请参见函数访问日志服务

为什么我的 node.js 函数莫名其妙地超时了?

  • 如果使用了HTTP trigger,确认您是否有调用response.send()
  • 如果没有使用HTTP trigger, 确认您是否有调用入口函数handler中的callback
  • 如果还是不确定可以通过添加日志定位超时原因。详情请参见如何快速定位线上问题?

遇到 The service or function doesn't belong to you的错误怎么办?

请检查您的endpoint中的阿里云账号ID是否正确,必须使用主账号的ID,而不能是RAM子账号ID。

遇到 SDK.ServerUnreachable : SocketTimeoutException has occurred on a socket read or accept 的问题怎么办?

请检查您调用 java sdk 的代码,确保配置的 ReadTimeoutMillis 要大于您的函数超时时间。

为什么通过浏览器访问 HTTP Trigger 对应的函数会强制下载?

自 2018-11-19 起,对于新创建的 HTTP 触发器,在 invokeFunction 时,服务端会为 response header 中强制添加 content-disposition: attachment 字段,此字段会使得返回结果在浏览器中以附件的方式打开。此字段无法覆盖,使用自定义域名将不受影响。

如何确定函数内部访问其他服务的网络连通性问题?

  • 如果您是在VPC网络环境中访问外网连接,请打开VPC公网访问排除公网访问的问题;
  • 可以在函数中增加类似以下的代码并调用函数,然后在控制台观察输出来确定网络连通性及服务可用性:
    • os.system("dig " + host) 确定 DNS 域名解析是否正常;
    • os.system("ping -c 5 " + host_or_ip) 确定 IP 连通性问题;
    • os.system("nc -v " + host_or_ip + " " + port) 确定连接的服务端口是否正常及是否可连接;
    • os.system("curl -v " + endpoint) 验证 HTTP 服务是否可服务。
  • 到所请求的服务查找相关连接日志,确定对应时间段内是否有来自函数计算的请求。

函数返回后,执行环境也会随之释放吗?我能复用上一次调用缓存的资源/状态吗?

函数运行在容器的环境里。返回后,容器不会立即释放。只有在一段时间内(取决于系统的调度算法,通常在几分钟到几十分钟),该容器都没有收到任何请求,才会被释放。如果有持续的请求,可以认为函数是常驻的。因此,您可以通过全局变量等方式缓存资源优化性能。但是,您的程序正确性不能依赖缓存一直可用这个假设。例如,当出现容器/机器宕机等情况,缓存的数据就不再有效。

程序运行过程中产生的日志我如何批量下载?

如果您的日志保存在日志服务的 LogStore 中,您可以通过日志服务的 API 查询和下载相关内容。

函数调用正常,为什么在监控页面看不到调用次数等指标?

请检查您使用的账户是否是子账户,是否具备云监控的只读权限。

函数计算如何访问RDS?

由于函数运行时的IP是不固定的,您需要设置 RDS 允许所有IP访问。但是这样会有风险,不建议这样做。函数计算会支持 VPC 功能,上线后用户可以通过授权的方式安全地访问 VPC 中的资源。

我使用函数的 context 参数中的 access key id/secret 等信息访问其他云资源,为什么身份验证失败,收到 The AccessKeyID does not exist 的错误?

函数 context 中提供了访问云资源的临时密钥,包含 access key id,access key secret,security token 3元组。请不要遗漏了security token。下图是在 python 函数中访问 OSS 代码示例。

import json
import oss2
def my_handler(event, context):
    evt = json.loads(event)
    creds = context.credentials
    # 身份验证时,请不要遗漏了 security_token!
    # Do not miss the "security_token" for the authentication!
    auth = oss2.StsAuth(creds.access_key_id, creds.access_key_secret, creds.security_token)
    bucket = oss2.Bucket(auth, evt['endpoint'], evt['bucket'])
    bucket.put_object(evt['objectName'], evt['message'])
    return 'success'
			

如何让别的用户授权我的函数访问他的资源?

假设用户 A 要授权用户 B 的函数访问他的云资源,可采用如下步骤:

  1. 用户 A 创建一个角色,授权对象是 user-B@fc.aliyuncs.com
  2. 用户 B 创建一个函数,并指定 service role
  3. 用户 B 调用函数,在函数中使用 context.credentials 去扮演步骤 1 中创建的角色
  4. 用户 B 拿到扮演角色所得到的 credentials 去访问用户 A 的资源
说明 在您使用日志服务时,也会遇到类似的场景。例如把用户 A 的日志投递到用户 B 的 OSS bucket 中。

为什么我在函数里无法通过内网 endpoint 访问 OSS 等云服务?

要在函数里通过内网 endpoint 访问云服务,您需要确保函数和要访问的云服务在同一个区域内。