Вопрос или проблема
У меня есть приложение Flask, которое работает на AWS-инстансе с изображением Linux. Скрипт – это бот-скрипт на Python, который использует Selenium для выполнения некоторых задач. Я вызываю API через простой POST-запрос. Проблема, с которой я столкнулся, заключается в том, что выполнение завершается через 60 секунд. Тем не менее, мой бот-скрипт успешно выполняется, но задача не выполняется должным образом. Я добавил некоторые операторы печати, и код проходит через них, что заставляет меня предполагать, что сам скрипт Selenium работает нормально.
Теперь конфигурация, которую я использую, включает gunicorn и nginx для запуска моего API на EC2. Конфигурации приведены ниже.
Мой файл конфигурации nginx на EC2:
server {
listen 80;
server_name 18.201.215.193;
location / {
proxy_pass http://unix:/home/ec2-user/python_script/app.sock;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
send_timeout 300s;
}
}
[1]: Мой конфигурационный файл для nginx на EC2.
Мой конфигурационный файл gunicorn выглядит следующим образом:
[Unit]
Description=Gunicorn instance to serve myproject
After=network.target
[Service]
User=ec2-user
Group=www-data
WorkingDirectory=/home/ec2-user/python_script
ExecStart=/home/ec2-user/.local/bin/gunicorn --workers 5 --bind unix:app.sock --timeout 300 wsgi:app
[Install]
WantedBy=multi-user.target
Я увеличил время ожидания до 300 секунд, но процесс все равно возвращает ошибку через 60 секунд. Код инициализации моего скрипта, который работает на инстансе, приведен ниже:
class Ec2Handler:
def __init__(self, user_creds, invatation_url):
self.user_creds = user_creds
self.invatation_url = invatation_url
def api_trigger(self):
api_url="http://18.201.215.193/run-script"
payload = {
'invatation_url': self.invatation_url,
'user_creds': self.user_creds
}
response = requests.post(api_url,json=payload,headers={"Content-Type":"application/json"},timeout=None)
#response = requests.get(api_url,headers={"Content-Type": "application/json"},timeout=450)
if response.status_code == 200:
print('Script executed successfully:', response.json())
else:
print('Error executing script:', response)
И это сам бот-скрипт:
@app.route('/run-script', methods=['POST'])
def run_script():
# Выполните ваш скрипт с предоставленными аргументами
print('Starting')
data = request.get_json()
user_creds = data['user_creds']
with SB(headless2=True, undetectable=True) as sb:
print("AS")
print('Ok reached here')
sb.driver.uc_open_with_reconnect("https://accounts.snapchat.com/accounts/v2/login", 4)
...остальной код...
sb.driver.sleep(4)
print('OK Reached here')
print('QUITTING')
sb.driver.quit()
return jsonify({'message': 'Script triggered successfully'}), 200
return jsonify({'message': 'Script triggered successfully'}), 200
В результате моя функция возвращает только это:
Ошибка выполнения скрипта: <Response [504]>
Буду признателен за любые отзывы об этом! Заранее спасибо
Ответ или решение
Для решения проблемы с тайм-аутом и ошибкой 504 при запуске Flask-приложения на AWS EC2 с использованием Gunicorn и Nginx необходимо применить систематический подход, учитывающий несколько ключевых аспектов.
Теория
Ошибка 504 Gateway Timeout обычно возникает, когда прокси-сервер (в данном случае Nginx) не получает ответ от сервера приложений (Gunicorn) в отведенное время. Это может произойти из-за неправильных настроек тайм-аутов, переполненности рабочей нагрузки или задержек в обработке запросов на сервере приложений.
Пример
Ваше текущее окружение настроено так, чтобы давать более длительные тайм-ауты для Nginx и Gunicorn. Однако, несмотря на увеличение тайм-аутов до 300 секунд, проблема сохраняется, что указывает на возможные другие узкие места:
-
Gunicorn:
- Конфигурация Gunicorn включает в себя корректное использование
--timeout
, что должно означать увеличение времени ожидания до 300 секунд для выполнения запроса.
- Конфигурация Gunicorn включает в себя корректное использование
-
Nginx:
- В конфигурации Nginx вы также увеличили значения
proxy_connect_timeout
,proxy_send_timeout
, иproxy_read_timeout
до 300 секунд. Этого должно быть достаточно для более длительных задач, выполняемых через API.
- В конфигурации Nginx вы также увеличили значения
Применение
Следует провести дополнительные расследования и оптимизации:
-
Проверка Concurrency:
- Убедитесь, что количество воркеров в Gunicorn (5 воркеров) соответствует предполагаемой нагрузке. Для скриптов, которые требуют значительного времени выполнения, необходимо удостовериться, что именно количество воркеров соответствует количеству одновременных соединений, которое требуется поддерживать.
-
Логирование:
- Используйте более детализированное логирование, как на уровне Nginx, так и Gunicorn, для идентификации потенциальных узких мест или ошибок времени выполнения. Это поможет понять, в какой именно момент возникают тайм-ауты.
-
Асинхронная обработка:
- Рассмотрите возможность использования асинхронных инструментов для очень долгих операций. Перенос выполнения задачи в очередь, такое как Redis с Celery, разгрузит основной процесс и позволит вам немедленно отвечать пользователю через HTTP.
-
Оптимизация скрипта:
- Проверьте ваш скрипт на предмет неэффективностей или точек, которые могут привести к задержкам в выполнении. Инструментирование и профилирование кода может помочь в этом.
Таким образом, чтобы устранить ошибку 504, необходимо не только рассмотреть параметры конфигурации сервера, но и проверить фоновые процессы скрипта, в том числе серверную архитектуру и особенности выполнения кода.