全部产品
云市场

按量实例

更新时间:2019-11-21 19:40:24

为了防止用户意外的过度调用导致费用失控,每个账号在当前 region 中拥有 最大并发度,所有函数共享同时处理请求的最大限制值。

例如:账号 12345789 的并发度限制是 100,用户有func-a/func-b/func-c, 3 个函数,在某一时刻所有正在处理调用的函数实例数之和最大为 100

函数计算1.0中,一个函数实例最多只能同时处理一个请求。即函数实例对应并发度限制。在函数计算2.0后,函数计算推出了单实例并发处理多请求功能,参考 单实例多并发

除了用户级别的实例数限制,函数计算为调用提供了更细粒度的按量调用实例数限制,用户可以通过控制台或 API 调用自行设置函数级别实例限制数来防止被单个函数被过度调用,保护后端资源,避免预期外的费用开销。

应用场景

  • 保护其他函数的正常并发度;
    • 例如有func-a/func-b 两个函数共享用户级实例限制数,其中func-a 需要保护的重点业务函数,而 func-b 有可能被过度调用而影响 func-a 的正常请求,可以单独为 func-b 设置实例限制防止过度争抢资源。
  • 保护下游服务;
    • 例如在函数计算中大量访问了 RDS 数据库,由于数据库处理能力可能有限,您可能需要保护 RDS 不被打垮,为单独访问 RDS 的函数配备限制。
  • 禁止某个函数的调用;
    • 如发现某个函数异常调用,可以设置最大函数实例数为0,禁止其调用。
  • 防止意外的过度调用导致费用失控的问题;
    • 浏览器端或 client 端在端用户,可能不受控制,设置函数级实例可以防止调用失控而产生意外费用。
  • 配合预留模式使用;
    • 通过设置按量实例数限制配合预留实例数达到只用预留、只用按量、或混合使用。

函数别名与按量实例限制

  • 函数级实例限制必须建立在别名/LATEST之上;
  • 可以针对函数的多个不同别名设置不同的实例限制;
  • 函数调用时,通过调用的 API 中的 qualifier 来区分实例数目流控;
  • 如果不使用不同别名,可以把限制规则设置在系统保留别名 LATEST 之上;

例如:

  • service s有多个版本 1, 2, 分别对应别名 prod, test,同时系统保留别名 LATEST 指向版本 2 即别名 test
  • 假设账号级别实例限制为 200,同时不与其他函数发生争抢的情况下,函数调用时:
serviceName qualifier functionName 调用 path 设置限制值 实例限制值
s prod func-foo /services/s.prod/functions/func-foo 100 100
s test func-foo /services/s.test/functions/func-foo 10 10
s LATEST func-foo /services/s.LATEST/functions/func-foo/services/s/functions/func-foo 20 20

限制后的调用行为

调用类型 调用行为
同步调用 函数调用所需要占用的实例数超过所设置的值后,超出请求会被拒绝,并收到 ResourceExhausted 流控错误
异步调用 函数调用所需要占用的实例数超过所设置的值后,请求不会被拒绝,异步调用处理速度变慢,占用实例数不超过所设置的值

更多参考 调用函数

函数级按量实例限制与预留实例的配合使用

在函数资源(对应到别名)拥有预留实例的设置前提下,优先使用预留资源,在预留资源用满的情况下,再使用按量实例资源。

例如,我们在 serviceName: service-1, qualifier: prod,functionName: foo 上分别按下述方式设定按量及预留资源,并使用 /services/service-1.prod/functions/foo 调用该函数:

按量资源限制 预留资源限制 行为
0 10 只使用预留模式的 10 个实例资源
20 0 不使用预留,只使用按量资源,最多使用 20 个按量资源实例
50 30 优先使用预留模式的 30 个实例资源,用满后再使用按量资源,最多使用 50 个按量实例资源,总共最多使用 80 个实例资源

限制项

  • 每个账号在当前 region 下最多设置 100 条规则;
  • 限制规则必须设置在 函数别名 或系统保留版本 LATEST 之上;
  • 每条规则的实例限制值不超过账号级实例限制值。

函数实例数与函数并发度及 TPS 的计算关系

  • 函数执行时间:请求到达用户函数内部开始计时,到用户函数处理完该请求返回给函数计算系统的时间;
  • 单实例最大并发值:函数计算1.0中,每个函数实例只能并发处理一个请求,函数计算2.0后,提供可自定义的多请求处理并发;
  • 并发度:某个时刻点所有正在处理的请求个数;
  • 如下图:
    • 假设每个实例最大并发度为 2,即单个实例最多同时处理 2 个请求;
    • 4个调用 ABCD 不等待上次调用结束依次并行发起调用请求;
    • t0 时刻只有实例1正在工作,此时只有请求 A 落在了实例1上被处理,只占用了1个并发度;
    • t1 时刻实例1实例2都在工作,此时ABCD 都在被处理,共占用了4个并发度。concurrency-instance
  • TPS:通常来说指一秒钟内服务所能处理的请求数目;
    • TPS = 1 / DurationInSecond * InstanceConcurrency * MaxInstances
  • 例如:
    • 一个函数执行平均时长 DurationInSecond0.1s,这个函数有 5 个函数实例,即 MaxInstances 为 5;
    • 如果单个实例最大并发 InstanceConcurrency1,那么理论上单个函数实例每秒能处理10个这样的请求,那么这5个函数实例每秒最多能处理 10 x 1 x 5 = 50 个请求,即 TPS50
    • 如果单个函数实例的最大并发 InstanceConcurrency2,那么这5个函数实例每秒最多能处理 10 x 2 x 5 = 100 个请求,即 TPS100

设置函数按量实例

控制台

  • 如图,我们打开 函数计算控制台 找到要配置的函数的 service,选择 按量资源,点击 配置实例数on-demand-resource
  • 如图,打开后,在 函数名称 中选择需要配置的函数,通过调整 时间范围,可以观察到该函数近期实际使用的实例个数曲线图on-demand-config-set
  • 通过了解近期实际实例个数后,可以估算所需要的实际实例数,在 最大实例数 的配置栏中为该函数设置最大实例数

SDK

  • java SDK 使用参考 Example;
  • golang SDK 使用参考:
  1. package main
  2. import (
  3. "fmt"
  4. fc "https://github.com/aliyun/fc-go-sdk"
  5. )
  6. const (
  7. endpoint = "your-endpoint"
  8. fcAPIVersion = "2016-08-15"
  9. AccessKeyID = "your-ak-id"
  10. AccessKeySecret = "your-ak-secret"
  11. )
  12. var (
  13. serviceName = "service-name"
  14. qualifier = "LATEST"
  15. functionName = "function-name"
  16. )
  17. func main() {
  18. fcClient, _ := fc.NewClient(endpoint, fcAPIVersion, AccessKeyID, AccessKeySecret)
  19. // set
  20. putInput := fc.NewPutOnDemandConfigInput(serviceName, qualifier, functionName)
  21. putInput.WithMaximumInstanceCount(10)
  22. putResp, err := fcClient.PutOnDemandConfig(putInput)
  23. fmt.Println("put on-demand config", putResp, err)
  24. // list
  25. listInput := fc.NewListOnDemandConfigsInput()
  26. listInput.WithPrefix(fmt.Sprintf("services/%s", serviceName))
  27. listResp, err := fcClient.ListOnDemandConfigs(listInput)
  28. fmt.Println("list on-demand configs", listResp, err)
  29. // get
  30. getInput := fc.NewGetOnDemandConfigInput(serviceName, qualifier, functionName)
  31. getResp, err := fcClient.GetOnDemandConfig(getInput)
  32. fmt.Println("get on-demand configs", getResp, err)
  33. // delete
  34. deleteInput := NewDeleteOnDemandConfigInput(serviceName, qualifier, functionName)
  35. deleteResp, err := fcClient.DeleteOnDemandConfig(deleteInput)
  36. fmt.Println("delete on-demand configs", deleteResp, err)
  37. }