本文介绍单实例多并发的背景信息、优势、适用场景以及设置多并发的影响。
背景信息

假设同时有3个请求需要处理,当实例并发度设置为1时,函数计算需要创建3个实例来处理这3个请求,每个实例分别处理1个请求;当实例并发度设置为10时(即1个实例可以同时处理10个请求),函数计算只需要创建1个实例就能处理这3个请求。
单实例多并发优势
- 减少执行时长,节省费用。
例如,偏I/O的函数可以在一个实例内并发处理,减少实例数从而减少总的执行时长。
- 请求之间可以共享状态。
多个请求可以在一个实例内共用数据库连接池,从而减少和数据库之间的连接数。
- 降低冷启动概率。
由于多个请求可以在一个实例内处理,创建新实例的次数会变少,冷启动概率降低。
- 减少占用VPC IP
在相同负载下,单实例多并发可以降低总的实例数,从而减少VPC IP的占用。
单实例多并发应用场景
场景 | 适用性 | 理由 |
---|---|---|
函数中有较多时间在等待下游服务的响应 | 适用 | 等待响应一般不消耗资源,在一个实例内并发处理可以节省费用。 |
函数中有共享状态且不能并发访问 | 不适用 | 例如全局变量,多请求并发执行修改共享状态可能会导致错误。 |
单个请求的执行要消耗大量CPU及内存资源 | 不适用 | 多请求并发执行会造成资源争抢,可能会导致内存不足(OOM)或者延时增加。 |
设置单实例多并发的影响
设置了单实例多并发(InstanceConcurrency>1)之后,与单并发(InstanceConcurrency=1)有以下几个方面的区别:
- 计费
- 单实例单并发
函数实例在同一时间只能处理1个请求,1个请求处理完了再处理下一个请求。计费时长从处理第一个请求开始,到最后一个请求结束为止。
- 单实例多并发
多个请求在一个实例并发处理时,以实例的实际占用时间作为计费的执行时长,即从第一个请求开始,到最后一个请求结束期间的时长。
更多计费详情请参见计费概述。
- 单实例单并发
- 并发度流控
函数计算一个地域(Region)中按量实例数的上限默认值为300,一个地域可以同时处理的最大请求数为“300×InstanceConcurrency”。例如,设置InstanceConcurrency=10时,则一个地域最多允许同时处理3000个并发请求。当并发请求数超过函数计算可以处理的最大请求数时,会收到流控错误(ResourceExhausted)提示。
说明 如果您想要扩大一个地域的按量实例数上限,请联系我们。 - 日志
- 在单并发模式下,在调用函数时指定HTTP头
X-Fc-Log-Type: Tail
,函数计算会在响应头X-Fc-Log-Result
中包含本次调用所产生的函数日志。在多并发模式下,由于多个请求并发执行,无法获取某个特定请求的日志,响应头中不再包含本次调用的函数日志。 - 针对Node.js Runtime,原来的日志方式是使用
console.info()
函数,该方式会把当前请求的Request ID包含在日志内容中。当多请求在同一个实例并发处理时,当前请求可能有很多个,继续使用console.info()
打印日志会导致Request ID错乱,Request ID都会变成req 2
。打印日志示例如下。2019-11-06T14:23:37.587Z req1 [info] logger begin 2019-11-06T14:23:37.587Z req1 [info] ctxlogger begin 2019-11-06T14:23:37.587Z req2 [info] logger begin 2019-11-06T14:23:37.587Z req2 [info] ctxlogger begin 2019-11-06T14:23:40.587Z req1 [info] ctxlogger end 2019-11-06T14:23:40.587Z req2 [info] ctxlogger end 2019-11-06T14:23:37.587Z req2 [info] logger end 2019-11-06T14:23:37.587Z req2 [info] logger end
此时应该使用context.logger.info()
函数打印日志,该方式仍保留了请求的独立Resquest ID。代码示例如下。exports.handler = (event, context, callback) => { console.info('logger begin'); context.logger.info('ctxlogger begin'); setTimeout(function() { context.logger.info('ctxlogger end'); console.info('logger end'); callback(null, 'hello world'); }, 3000); };
- 在单并发模式下,在调用函数时指定HTTP头
- 错误处理
多个请求在一个实例并发处理时,由于一个请求处理不当导致进程退出或者崩溃,会导致正在并发处理的其他请求也收到错误信息。这要求您在编写函数时,尽量捕获请求级别的异常,不影响其他请求。Node.js代码示例如下。
exports.handler = (event, context, callback) => { try { JSON.parse(event); } catch (ex) { callback(ex); } callback(null, 'hello world'); };
- 共享变量
多个请求在一个实例并发处理时,同时修改一个共享的变量,可能会导致错误。这要求您在编写函数时,对于非线程安全的变量修改要进行互斥保护。Java代码示例如下。
public class App implements StreamRequestHandler { private static int counter = 0; @Override public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { synchronized (this) { counter = counter + 1; } outputStream.write(new String("hello world").getBytes()); } }
- 监控指标
设置函数的实例并发度后,在相同的负载下,可以在控制台的实例数监控图中看到函数的实例数有明显地减少。
使用限制
限制项 | 描述 |
---|---|
支持的Runtime |
|
实例并发度取值范围 | 1~100 |
调用响应中的函数日志(X-Fc-Log-Result) | InstanceConcurrency>1时不支持 |
在文档使用中是否遇到以下问题
更多建议
匿名提交