将AWS Lambda函数放入VPC,然后开始发生“ IOException:对等方重置连接”,但仅偶尔发生

问题描述

我有一个Java AWS Lambda函数,可通过API网关用作API。在过去的几个月中,它一直在24/7上运行,并且之前从未出现过此特定错误。

今天,我做了一个更新以添加Elasticache,这需要我将Lambda放入与Elasticache相同的VPC中。在此之前,Lambda尚未分配给任何VPC,只是正常运行。

经过大量的配置调整后,看来我终于可以正常使用-Lambda JAR现在可以连接到Elasticache,同时仍然可以连接到它需要的其他功能。

但是,在部署后几分钟,我开始从Algorithmia调用中得到此错误:

java.util.concurrent.ExecutionException: java.io.IOException: Connection reset by peer
at org.apache.http.concurrent.BasicFuture.getResult(BasicFuture.java:71)
at org.apache.http.concurrent.BasicFuture.get(BasicFuture.java:102)
at com.algorithmia.algo.FutureAlgoResponse.get(FutureAlgoResponse.java:41)
at <place that we invoke it>

发生错误的调用代码非常简单:

        FutureAlgoResponse futureAlgoResponse = algo.pipeAsync(<stuff>);
        AlgoResponse result = futureAlgoResponse.get(3L,TimeUnit.SECONDS);

更重要的是,它已经生产了将近一年,而从未出现此错误。

所以我想它一定与VPC有关!但是,它在大多数时间都有效。我们每隔几秒钟运行一次该代码,并且每隔几分钟就会失败。如果失败,通常通常会连续出现1-3个请求。

我们的Lambda设置为15秒超时,失败的请求在大约1秒后响应,并且重申一下,直到今天将Lambda移入VPC之前,我们从未见过此错误。

Lambda VPC配置相当混乱且复杂,因此我确定我在某个地方搞砸了。但是,事实是每隔几分钟就会发生几次,这使我很难用有限的AWS知识进行调试。我希望有人可以分享一些可能的原因!

这是我进行设置的方式:

  • 创建一个新的VPC
  • 在VPC中创建2个子网(和相应的路由表),一个为公网,一个为私有
  • 为VPC创建Internet网关,为公共子网创建NAT网关。
  • 为NAT网关分配一个弹性IP。
  • 启用安全组的所有传入和传出(可能不需要传入,但我们将回过头来解决此问题)
  • 在该VPC中启动Elasticache
  • 将Lambda分配给该VPC,尤其是专用子网+前面提到的安全组

老实说,我没有丝毫线索进一步研究此事,所以我真的希望有人知道“哦,是的,因为_____,连接可能在VPC中超时”。另外,不胜感激如何更好地调试它的任何提示。

编辑:更多搜索表明可能与NAT设置有关?我基本上只是做了一个默认的“创建NAT网关”,然后将其扔到了专用子网中。

解决方法

Amazon支持来自诊断和解决方案!

tl; dr是的,超时是问题所在。建议的解决方案是实施TCP保持活动状态,以使350秒的空闲超时没有达到(或只有更多的流量,这实际上对我们不起作用)。

最后我们实际上所做的只是从Elasticache转移。这是我们需要将Lambda放入VPC的唯一原因,在考虑了这一点之后,我们认为距离我们的流量达到真正使Elasticache的利益真正可见的水平还需要一段时间(相对于简单的EC2托管) Redis实例)。因此,现在我们的缓存只是在EC2上运行的常规Redis实例。

这是完整的答复:

“ ...但是,在过去两天里,我确实看到了许多NAT网关空闲超时,您怀疑这可能是问题所在。请参阅下面的NAT网关指标。

这样说,IdleTimeoutCount指标计算从活动状态转换为空闲状态的连接数。如果未正常关闭活动的连接并且在过去的350秒内没有任何活动,则该连接将转换为空闲。大于零的值表示存在已移至空闲状态的连接。如果IdleTimeoutCount的值增加,则可能表明NAT网关后面的客户端正在重新使用陈旧的连接。

如故障排除文档中所述,为防止断开连接,可以通过该连接启动更多流量。或者,您也可以在实例上启用TCP Keepalive(如果可能的话,其值小于350秒)。以固定的间隔发送keepalive探测将确保有一些流量通过NAT网关和远程终端服务器之间的连接。 Keepalive数据包将重置350秒的空闲超时计数器,从而使连接在应用程序需要的时间内保持有效状态。

要回答您的问题:“这是这里发生的吗?”

答案:在从VPC角度验证所有内容是否适合Lambda功能(SG,NACL,路由表)之后,此处NAT网关空闲超时的可能性肯定很大。上面提供的IdleTimeoutCount指标也证实了这一点,该指标表明连接由于不活动而超时。”

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...