У меня установлено приложение Flask с сервером официантки. Всегда только один клиентский браузер обращается к серверу (это внутренний проект). Предполагается, что большая база данных изображений будет транслироваться в браузере по одному изображению за раз (изображения загружаются с сервера, который выполняет итерацию по базе данных).
Сторона сервера
После некоторой настройки, приложение передает базу данных изображений по URL some_ip_address/get_next_image
. После получения каждого запроса на get_next_image
сервер получает следующее изображение, предварительно обрабатывает его и отправляет файл в качестве ответа. Сервер запускается с использованием waitress.serve(app, host='0.0.0.0', port=5000)
Клиентская сторона
После перенаправления на some_ip_address/stream
в браузере отображается html файл stream.html
. Эта страница немедленно вызывает streamNextImage()
и отправляет GET-запрос на get_next_image
. Как только изображение загружено, оно устанавливается как свойство src
изображения, которое отображается на странице stream
, а также устанавливается тайм-аут для запроса нового изображения (около 0,2 с).
Проблема
Сервер работает по назначению в течение некоторого времени (иногда в течение часа, иногда больше), но в конечном итоге время отклика начинает становиться ошибочным c (зависает на 10 секунд, затем снова отвечает нормально) , позже интервалы между ответами увеличиваются до 10 секунд, и в конечном итоге сервер вообще перестает отправлять изображения.
Когда это происходит, даже другие URL-адреса не отвечают в браузере, но в журнале сервера я получаю сообщение [WARNING] Task queue depth is 1
, и хотя сервер ничего не отправляет (или не получает запросы), использование ЦП на машина, на которой она работает, высока, но я понятия не имею, что она делает.
Похоже, что сервер перегружен предыдущими запросами, но я не понимаю почему, поскольку клиент JS настроен в таком способ, которым новый запрос отправляется только после получения текущего изображения, поэтому переполнение не должно быть возможным.
Как я могу отладить это или в чем может быть проблема?
Код сервера
@app.route("/get_next_image")
def get_next_image():
row_idx, row, _ = next(app.config["db_iterator"])
image = preprocess_image(row_idx, row)
cv2.imwrite('stream_image.jpg', image)
return send_file(image_path)
Код обозревателя клиента
# stream.html
<html>
<meta http-equiv='cache-control' content='no-cache'>
<meta http-equiv='expires' content='0'>
<meta http-equiv='pragma' content='no-cache'>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
function streamNextImage() {
// Change images only when the new one is already downloaded
nextImgSrc = '{{ url_for('get_next_image') }}?' + new Date().getTime(); // Add current time as param to prevent browser caching of this URL
tmpImg.src = nextImgSrc;
tmpImg.onload = function () {
$('#face_image').attr('src', nextImgSrc);
setTimeout(streamNextImage, 1000 * "{{ wait_period }}");
}
}
var tmpImg = new Image();
streamNextImage()
</script>
</head>
<body>
<img src='' alt="Image" id="face_image" name="face_image">
</body>
</html>
Вывод окончательного журнала сервера, когда сервер перестает отвечать
2020-05-28 05:05:16 [INFO ] Streaming idx:6134/53122)
2020-05-28 05:05:17 [INFO ] <Request 'http://localhost:5000/get_next_image?1590642317559' [GET]>
2020-05-28 05:05:17 [INFO ] Streaming idx:6135/53122)
2020-05-28 05:05:26 [INFO ] <Request 'http://localhost:5000/get_next_image?1590642326559' [GET]>
2020-05-28 05:05:26 [INFO ] Streaming idx:6136/53122)
2020-05-28 05:05:27 [INFO ] <Request 'http://localhost:5000/get_next_image?1590642327559' [GET]>
2020-05-28 05:05:27 [INFO ] Streaming idx:6137/53122)
2020-05-28 05:05:35 [INFO ] <Request 'http://localhost:5000/get_next_image?1590642332559' [GET]>
2020-05-28 05:05:35 [INFO ] Streaming idx:6138/53122)
2020-05-28 05:05:36 [INFO ] <Request 'http://localhost:5000/get_next_image?1590642336559' [GET]>
2020-05-28 05:05:36 [INFO ] Streaming idx:6139/53122)
2020-05-28 08:05:22 [WARNI] Task queue depth is 1