Пользовательский HTTP-сервер с Godot 4.3 не может обрабатывать более 5 SSE-соединений.

Вопрос или проблема

Поскольку в Godot нет встроенного HTTP-сервера, а только TCP-сервер, мне удалось правильно настроить ответы вручную. JavaScript, CSS и HTML загружаются и работают должным образом, можно даже сказать, беспрепятственно.
Однако…..
Как только я перешел на /events для обновления с сервера, чтобы перезагрузить страницу, я столкнулся с лимитом в 5 соединений, после чего все вкладки замирают.

func connect_SSE(client:StreamPeerTCP)->PackedByteArray:
    if SSEConnections.size()==5:return str("").to_utf8_buffer()
    var response:String =""
    #строим ответ
    response = "HTTP/1.1 200 OK\r\n" +\
            "Content-Type: text/event-stream\r\n" +\
            "Cache-Control: no-cache\r\n" +\
            "Connection: keep-alive\r\n\r\n"
    SSEConnections.append(client)
    if(debug_tcp):print_rich("[color=magenta]SSE connection established ",SSEConnections.size(),"[/color]")
    return response.to_utf8_buffer()

Здесь вы видите одну из функций, которую я использую в ответ на запрос. Она вызывается из этого фрагмента:

func serve_any(client: StreamPeerTCP, request:String) ->PackedByteArray:
    if request.contains("/events"): 
        return connect_SSE(client)

Сейчас я ограничил количество соединений до 5, чтобы продолжить работу над проектом, прежде чем я пойму, что с этим делать.
Мой вопрос заключается в том, могу ли я использовать что-то другое вместо keep-alive здесь, потому что, похоже, это вызывает перегрузку сервера, или что может вызвать проблемы?

(редактирование)
Я также проверил с помощью инструментов разработчика браузера, что, как только количество соединений SSE вновь достигает пяти, все различные JavaScript-запросы моментально получают свои ответы:

function changeTitle() {
    fetch('/event-title', { method: 'POST' })
        .then(response => response.text())
        .then(data => {
            document.getElementById('title').innerText = data; // Обновляет название с новым временем каждую секунду. Время получено с сервера
        });
}

setInterval(function() {
   changeTitle();
 }, 1000);

Ответ или решение

Создание пользовательского HTTP-сервера в Godot 4.3 с поддержкой Server-Sent Events (SSE) может столкнуться с рядом технических проблем, особенно в том, что касается ограничения количества одновременных подключений. В вашем случае вы упомянули, что сервер не может обработать более 5 подключений SSE, что вызывает "замороженность" вкладок в браузере. Давайте разберемся, как можно улучшить эту ситуацию.

Теория

Концепция Server-Sent Events (SSE)

Server-Sent Events (SSE) позволяют серверу отправлять обновления в реальном времени клиентам через HTTP. Это соединение открывается клиентом и поддерживается сервером в течение длительного времени. В отличие от WebSocket, SSE является однонаправленным протоколом, который передает информацию только от сервера к клиенту. Это делает его идеальным для приложений, где частые обновления должны отправляться клиентам.

Ограничения подключения и "keep-alive"

Опция "Connection: keep-alive" используется для поддержания соединения открытым после отправки ответа, что может создать нагрузку на сервер при большом количестве соединений. Каждый открытый поток потребляет ресурсы сервера, такие как память и вычислительная мощность, что может быстро исчерпать доступные ресурсы.

Пример

Ваш текущий код ограничивает количество подключений до 5, что может быть симптомом нехватки ресурсов. Это ограничение является временной мерой для продолжения разработки, но не решает основную проблему.

func connect_SSE(client: StreamPeerTCP) -> PackedByteArray:
    if SSEConnections.size() == 5:
        return str("").to_utf8_buffer()
    var response: String = ""
    response = "HTTP/1.1 200 OK\r\n" +\
               "Content-Type: text/event-stream\r\n" +\
               "Cache-Control: no-cache\r\n" +\
               "Connection: keep-alive\r\n\r\n"
    SSEConnections.append(client)
    if(debug_tcp):
        print_rich("[color=magenta]SSE connection established ", SSEConnections.size(), "[/color]")
    return response.to_utf8_buffer()

Ваша функция connect_SSE строит ответ, который указывает, что соединение должно оставаться открытым. Пока соединение открыто, никакие другие соединения не могут быть установлены, если они превышают лимит.

Применение

Управление ресурсами и оптимизация

  1. Пределы соединений: Проверьте ваши системные настройки на предмет ограничений по количеству соединений. Возможно, потребуется настройка операционной системы или специфических сетевых параметров для увеличения лимита.

  2. Отключение неактивных соединений: Рекомендуется реализовать логику, которая бы отключала неактивные соединения после определенного времени. Это может быть осуществлено с помощью таймеров или других механизмов отслеживания активности.

  3. Балансировка нагрузки: Рассмотрите возможность использования балансировки нагрузки, если ваш сервер будет обслуживать большое количество клиентов. Это может включать использование реверс-прокси или распределение нагрузки между несколькими экземплярами приложения.

  4. Оптимизация кода: Убедитесь, что ваш код оптимизирован, а также что значение переменной debug_tcp выключено в продакшене, чтобы избежать лишних операций ввода-вывода.

  5. Альтернативы SSE: Если проблемы с производительностью продолжаются, рассмотрите использование альтернативных технологий, таких как WebSockets, которые могут быть более эффективны в условиях высоконагруженного соединения.

Рекомендуется также провести нагрузочное тестирование вашего сервера, чтобы выявить узкие места и протестировать производительность в условиях, близких к реальным. Это позволит лучше понять, как ваш сервер будет вести себя при увеличении нагрузки, и поможет разработать стратегию для более эффективного управления соединениями.

Оцените материал
Добавить комментарий

Капча загружается...