Чрезмерное использование S3 заканчивается закрытием сокета?
Этот вопрос касается конкретно облака приложений Swisscom, а не Amazon.
Мое приложение использует 50 потоков. В сумме они делают, возможно, 25-200 запросов в секунду к S3. После запуска их в течение 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.access$300(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 секунд.
Есть ли ограничение по скорости запросов?
2 ответа
Нет ограничений на исходящий трафик или DoS-защиту.
В Swisscom AppCloud активирована политика DoS для доступа S3 (обозначается как Dynstrg, Vendor - EMC Atmos), который перехватывает запросы после определенного уровня. Этот критерий обнаружения в настоящее время срабатывает на 200 TPS (транзакций в секунду, TCP-сеансов) на исходный IP-адрес, затем этот IP-адрес блокируется как минимум на 120 секунд.
Swisscom в настоящее время обсуждает, чтобы увеличить эти триггеры.
Почему бы вам не узнать, есть ли у поставщика Cloud Foundry какое-либо ограничение на исходящий трафик? Кроме того, вам нужно исключить возможность того, что ваше приложение имеет какой-то недостаток или дефект.
Итак, чтобы выяснить, есть ли какие-либо ограничения на исходящие запросы и исключить вероятность того, что в вашем приложении возникла какая-то проблема, мы можем выполнить следующие шаги:
- Разверните любое приложение веб-службы на внешнем сервере. Другими словами, который не развернут в том же домене Cloud Foundry (то есть не развернут в Swisscom AppCloud). На самом деле, это не обязательно должен быть правильный веб-сервис, но "nc -l PORT" уже выполнит свою работу - просто для прослушивания порта TCP.
- Затем мы можем развернуть приложение в Cloud Foundry (то есть Swisscom AppCloud), которое отправляет около 300 запросов в секунду к приложению внешней веб-службы, которое мы развернули на шаге 1. Таким образом, мы имитируем приложение WITHIN Cloud Foundry (в этом в случае Swisscom AppCloud), который ведет себя так же, как вы упоминали в своем сценарии.
Хорошо, но теперь вопрос: как технически / практически достичь таких шагов? Разве это не много работы?
Ну, это возможно, и нет, это не так много работы. Я потратил 20 минут и придумал набор команд /scripts/docker image для имитации этого.
Итак, шаг 1 вы можете выполнить самостоятельно. Может быть, развернуть простой веб-сервис где-нибудь еще, и все. Шаг 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", без имени хоста, без маршрута и без какого-либо типа проверки работоспособности. Кроме того, мы указываем образ докера (gsmachado/loadtest-docker), который уже опубликован на DockerHub, но вы можете проверить исходный код здесь (укажите звездочку! Это открытый исходный код!). Параметр '-c' указывает команду для запуска в этом док-контейнере, который, по сути, является приложением, запущенным в Cloud Foundry. Этот док-контейнер использует загрузочный тест проекта для выполнения запросов к определенной веб-цели. Вы можете проверить всю документацию и создать собственную команду '-c'. В этом конкретном примере мы определили, что в течение 20 секунд мы хотим выполнять 20 запросов в секунду, используя 10 одновременных клиентов. Выполнение команды cf push занимает некоторое время, так как Cloud Foundry должен развернуть весь докер-контейнер.
Вы можете проверить результаты нагрузочного теста, проверив 'cf logs':
cf logs LoadTestFromCloudFoundry
Кроме того, здесь есть пример манифеста, а также документация README.
Выполнение таких нагрузочных тестов с ориентацией на внешнее приложение может дать вам четкое представление о том, есть ли проблема в вашем приложении, ИЛИ если поставщик Cloud Foundry (в данном случае Swisscom AppCloud) действительно блокирует определенное количество запросов в секунду (RPS).
Однако теперь, если вы решите, что поставщик Cloud Foundry каким-то образом блокирует, вы должны обратиться в его службу поддержки. Приличный поставщик не должен налагать какие-либо ограничения исходящих RPS на клиентов, оплачивающих их услуги.
Это мои 2 цента на эту тему.:-)