过度使用 S3 以套接字关闭结束?

Excessive usage of S3 ends with socket close?

这个问题专门针对 Swisscom Application Cloud,与 Amazon 无关。

我的应用程序使用 50 个线程。总之,他们每秒可能向 S3 发出 25-200 个请求。在 运行 他们 10-30 秒后,我开始遇到这样的异常:

2016-10-29 14:36:58 [APP/PROC/WEB/0] OUT com.amazonaws.AmazonClientException: Unable to execute HTTP request: Socket is closed
2016-10-29 14:36:58 [APP/PROC/WEB/0] OUT at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:956)
2016-10-29 14:36:58 [APP/PROC/WEB/0] OUT at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:661)
2016-10-29 14:36:58 [APP/PROC/WEB/0] OUT at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:635)
2016-10-29 14:36:58 [APP/PROC/WEB/0] OUT at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:618)
2016-10-29 14:36:58 [APP/PROC/WEB/0] OUT at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access0(AmazonHttpClient.java:586)
2016-10-29 14:36:58 [APP/PROC/WEB/0] OUT at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:573)
2016-10-29 14:36:58 [APP/PROC/WEB/0] OUT at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:445)
2016-10-29 14:36:58 [APP/PROC/WEB/0] OUT at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:4041)
2016-10-29 14:36:58 [APP/PROC/WEB/0] OUT at com.amazonaws.services.s3.AmazonS3Client.putObject(AmazonS3Client.java:1581)
2016-10-29 14:36:58 [APP/PROC/WEB/0] OUT at <my_code_from_here>.putFile(S3Service.java:49)

重新启动应用程序或等待几分钟后,问题就解决了,但是当我启动并再次加载到 S3 上时,我在 10-30 秒后再次遇到这些异常。

请求速率有没有限制?

您为什么不自己发现 Cloud Foundry 提供商是否有任何类型的出站流量限制?此外,您需要排除您的应用程序存在某种缺陷或缺陷的可能性。

所以,为了发现是否有任何出站请求限制排除您的应用程序出现某种问题的可能性,我们可以按照以下步骤操作:

  1. 外部服务器中部署任何网络服务应用程序。换句话说, 未部署 在同一个 Cloud Foundry 域(即,未部署在 Swisscom AppCloud 中)。实际上,它不需要是一个适当的 Web 服务,但 "nc -l PORT" 已经可以完成这项工作 - 只需监听一个 TCP 端口。
  2. 然后,我们可以在 Cloud Foundry(即 Swisscom AppCloud)中部署一个应用程序,该应用程序每秒向我们在步骤 1 中部署的外部 Web 服务应用程序发出大约 300 个请求。通过这种方式,我们在内部模拟了一个应用程序Cloud Foundry(在这种情况下,在 Swisscom AppCloud 中)具有与您在场景中提到的相同的行为。

好的,但是,现在的问题是:如何technically/practically实现这样的步骤?是不是工作量很大?

嗯,这是可能的,不,这不是很多工作。我花了 20 分钟想出了一组 commands/scripts/docker 图像来模拟它。

所以,第1步你可以自己实现。也许在其他地方部署一个简单的 Web 服务,仅此而已。更复杂的步骤 2 可以简单地通过执行以下 CF CLI 命令来实现:

cf push LoadTestFromCloudFoundry --no-hostname --no-route --docker-image gsmachado/loadtest-docker --health-check-type none -c 'loadtest -t 20 -c 10 --rps 10 -k https://IP_ADDRESS_TO_YOUR_EXTERNAL_WEBSERVICE:PORT'

在这个例子中,我们正在推送一个名为 "LoadtestFromCloudFoundry" 的应用程序,没有任何主机名,没有任何路由,也没有任何健康检查类型。此外,我们指定了一个 docker 图像 (gsmachado/loadtest-docker),它已在 DockerHub 上发布,但您可以查看源代码 here (give it a star! it's open source!). The options '-c' specifies the command to run in this docker container, which, in fact, is an app running in Cloud Foundry. This docker container uses the project loadtest 以执行对特定 Web 目标的请求。您可以查看所有文档并提出自己的“-c”命令。在此特定示例中,我们定义了在 20 秒内,我们希望使用 10 个并发客户端每秒执行 20 个请求。 cf push 命令需要一段时间才能执行,因为 Cloud Foundry 应该部署整个 docker 容器。

您可以通过检查 'cf logs':

来查看负载测试的结果
cf logs LoadTestFromCloudFoundry

此外,还有一个清单示例 here, also with README documentation here

如果问题出在您的应用程序中,或者如果 Cloud Foundry 提供商(在本例中为 Swisscom AppCloud)确实每秒阻止一定数量的请求,则针对外部应用程序执行此类负载测试可能会给您深刻的见解(RPS).

但是,现在,如果您断定 Cloud Foundry 提供商正在以某种方式阻止,您必须联系他们的支持。一个体面的供应商不应该对支付他们服务的客户施加任何类型的出站 RPS 限制。

这是我在这个问题上的 2 美分。 :-)

没有出站流量限制或 DoS 保护。

Swisscom AppCloud 有一个针对 S3(品牌为 Dynstrg,供应商是 EMC Atmos)访问激活的 DoS 策略,它在一定级别后拦截请求。此检测标准当前由每个源 IP 200 TPS(每秒事务数,TCP 会话)触发,然后此 IP 被阻止至少 120 秒。

Swisscom 目前正在讨论增加这些触发器。