Lorawan-stack: Консоль блокировки потоков событий, когда не отправляются стартовые события

Созданный на 21 июл. 2020  ·  14Комментарии  ·  Источник: TheThingsNetwork/lorawan-stack

Резюме

Начиная с https://github.com/TheThingsNetwork/lorawan-stack/pull/2565 потоки событий в блоке консоли после щелчка мышью в консоли.

Действия по воспроизведению

  1. Перейдите на https://tti.staging1.cloud.thethings.industries/console/gateways.
  2. На одной вкладке откройте шлюз и используйте хлебные крошки, чтобы вернуться
  3. Повторите для каждого шлюза

Что ты видишь сейчас?

В какой-то момент консоль продолжает загружаться. Похоже, это вызвано «слишком большим количеством открытых подключений», потому что запросы /api/v3/events не закрыты.

Что вы хотите увидеть вместо этого?

Консоль должна оставаться отзывчивой.

Среда

Сборка на основе текущей master ветки 3df51cd750f57b37c3acffc28b417441babdbf30 (не обращайте внимания на 3.8.5, отображаемую консолью)

Как вы предлагаете это реализовать?

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

Итак, чтобы исследовать, я предлагаю:

  • Проверяем, правильно ли мы пишем заголовок
  • Проверьте, правильно ли шлюз gRPC записывает и сбрасывает заголовок
  • Проверьте, не мешает ли материал Echo / Mux

Как вы предлагаете это проверить?

Попробуйте шаги воспроизведения

shared dependencies

Самый полезный комментарий

Так что это либо что-то в наших зависимостях (grpc-gateway не сбрасывает заголовки должным образом), либо в нашем общем коде (возможно, какое-то промежуточное ПО grpc или http не сбрасывает заголовки).

Удаление ярлыка bug потому что в настоящее время он не влияет на наших пользователей.

Все 14 Комментарий

Консоль Firefox загружается вечно, если есть 6 открытых вкладок - если, например, обновляется одна из рабочих вкладок - одна из вкладок загрузки разблокируется, но иногда кажется, что это не удается.

Во всяком случае, я пробовал отправлять сообщения начала / окончания, но это ничего не изменило - оно все равно зависает после 6 вкладок.

Примечание: все вкладки предназначены для просмотра данных шлюза (2 разных)

@kschiffer есть идеи?

Консоль Firefox загружается вечно, если есть 6 открытых вкладок - если, например, обновляется одна из рабочих вкладок - одна из вкладок загрузки разблокируется, но иногда кажется, что это не удается.

Это ожидается, и ограничение на отключение потоков событий без использования HTTP / 2 :

Когда SSE не используется через HTTP / 2 , у него есть ограничение на максимальное количество открытых подключений, что может быть особенно болезненным при открытии различных вкладок, поскольку ограничение составляет _ на браузер_ и установлено очень маленькое число (6). Проблема была помечена как «Не исправить» в Chrome и Firefox . Этот предел установлен для браузера + домена, поэтому это означает, что вы можете открыть 6 подключений SSE на всех вкладках к www.example1.com и еще 6 подключений SSE к www.example2.com. (из Stackoverflow ). При использовании HTTP / 2 максимальное количество одновременных _HTTP-потоков_ согласовывается между сервером и клиентом (по умолчанию 100).

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

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

Я могу это подтвердить. Запросы будут остановлены, если они не получат заголовок ответа. После открытия шести таких подключений все последующие XHR также остановятся.

До # 2565 это не было проблемой, поскольку поток событий всегда немедленно отправлял «сообщение о запуске потока», что приводило к отправке заголовков.

Таким образом, я не считаю это проблемой внешнего интерфейса. Единственное, что имеет смысл изменить во внешнем интерфейсе, - это убедиться, что застрявшие потоковые соединения прерываются через определенное время.

Таким образом, проблема возникает, когда потоки событий не отправляют никаких данных. XHR, выполняющий соединение с потоком событий, разрешится только после получения первого сообщения, в противном случае он зависнет в состоянии pending . После открытия 6 из этих подключений все остальные также будут зависать, поскольку было достигнуто максимальное количество одновременных TCP-подключений. Таким образом, похоже, что XHR ожидает от сервера какого-то подтверждения, что поток установлен.

До # 2565 это не было проблемой, поскольку поток событий всегда отправлял «сообщение о запуске потока».

В настоящее время я пытаюсь выяснить, можно ли и как это исправить на стороне интерфейса.

По моему опыту, отправка «начального сообщения» не помогает в решении этой проблемы. Пожалуйста, попробуйте сами со следующей разницей:

diff --git a/pkg/events/grpc/grpc.go b/pkg/events/grpc/grpc.go
index 03f229ca0..5a305b5ac 100644
--- a/pkg/events/grpc/grpc.go
+++ b/pkg/events/grpc/grpc.go
@@ -119,6 +119,10 @@ func (srv *EventsServer) Stream(req *ttnpb.StreamEventsRequest, stream ttnpb.Eve
    if err := stream.SendHeader(metadata.MD{}); err != nil {
        return err
    }
+   if err := stream.Send(&ttnpb.Event{}); err != nil {
+       return err
+   }
+   defer stream.Send(&ttnpb.Event{})

    for {
        select {

Вот видео:
https://youtu.be/0Ir0lakV-Mc

Я вижу разницу.

На master БЕЗ разницы:

htdvisser % curl -v 'http://localhost:1885/api/v3/events' --compressed -H 'Authorization: Bearer MFRWG.DVTINRZNJDORITWD64NUJRIYVIXWCKJ3Q6VYLQY.E4K63GZ3WWTZGCIFMD7XLN7A7ACA35YCQSMFCBVCTEOMATCYGG6Q' -H 'Accept: text/event-stream' -H 'Content-Type: application/json' --data-raw '{"identifiers":[{"application_ids":{"application_id":"admin-app"}}]}'
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 1885 (#0)
> POST /api/v3/events HTTP/1.1
> Host: localhost:1885
> User-Agent: curl/7.64.1
> Accept-Encoding: deflate, gzip
> Authorization: Bearer MFRWG.DVTINRZNJDORITWD64NUJRIYVIXWCKJ3Q6VYLQY.E4K63GZ3WWTZGCIFMD7XLN7A7ACA35YCQSMFCBVCTEOMATCYGG6Q
> Accept: text/event-stream
> Content-Type: application/json
> Content-Length: 68
> 
* upload completely sent off: 68 out of 68 bytes
^C

На master С разн.

htdvisser % curl -v 'http://localhost:1885/api/v3/events' --compressed -H 'Authorization: Bearer MFRWG.DVTINRZNJDORITWD64NUJRIYVIXWCKJ3Q6VYLQY.E4K63GZ3WWTZGCIFMD7XLN7A7ACA35YCQSMFCBVCTEOMATCYGG6Q' -H 'Accept: text/event-stream' -H 'Content-Type: application/json' --data-raw '{"identifiers":[{"application_ids":{"application_id":"admin-app"}}]}'
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 1885 (#0)
> POST /api/v3/events HTTP/1.1
> Host: localhost:1885
> User-Agent: curl/7.64.1
> Accept-Encoding: deflate, gzip
> Authorization: Bearer MFRWG.DVTINRZNJDORITWD64NUJRIYVIXWCKJ3Q6VYLQY.E4K63GZ3WWTZGCIFMD7XLN7A7ACA35YCQSMFCBVCTEOMATCYGG6Q
> Accept: text/event-stream
> Content-Type: application/json
> Content-Length: 68
> 
* upload completely sent off: 68 out of 68 bytes
< HTTP/1.1 200 OK
< Content-Type: text/event-stream
< Referrer-Policy: strict-origin-when-cross-origin
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< X-Request-Id: 01EDTX9RGKRGM02YZVWNB3RXJP
< X-Xss-Protection: 1; mode=block
< Date: Wed, 22 Jul 2020 09:22:32 GMT
< Transfer-Encoding: chunked
< 
{"result":{"time":"0001-01-01T00:00:00Z"}}
^C

Мы должны дифференцировать эту проблему:

  1. Если одновременно открыто шесть TCP-соединений для каждого домена и браузера, любой последующий запрос будет зависать. Это ограничение браузера, и способы решения этой проблемы IMO следует обсудить в другом выпуске. Это проблема, которую я вижу в вашем видео @rvolosatovs
  2. Когда конечная точка потока не отправляет заголовок ответа немедленно, запрос останавливается (до тех пор, пока заголовок не будет отправлен в первом сообщении). Это означает, что при использовании только одной вкладки консоль будет накапливать ожидающие потоковые соединения при многократном переходе к страницам, открывающим потоковые соединения. После открытия шести таких подключений консоль зависнет по той же причине, что и в (1).

Чтобы смягчить 2, необходимо немедленно отправить заголовок ответа.

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

@kschiffer, не могли бы вы дать шаги, чтобы воспроизвести проблему в 2.?
Я постоянно обновляю вкладку данных одного шлюза и не испытываю зависаний с последней версией master (без патча)

Самый простой способ - создать совершенно новый и неподключенный шлюз, поскольку он не будет отправлять никаких сообщений. Затем перейдите на страницу обзора и вернитесь к списку шлюзов шесть раз.

Это проблема не только для событий шлюза, но и для всех потоков событий.

Отмена назначения меня, поскольку проблема не в консоли.

Закрыл # 2989

Временное решение было представлено на https://github.com/TheThingsNetwork/lorawan-stack/pull/2989 - более надежного решения пока не найдено.

Так что это либо что-то в наших зависимостях (grpc-gateway не сбрасывает заголовки должным образом), либо в нашем общем коде (возможно, какое-то промежуточное ПО grpc или http не сбрасывает заголовки).

Удаление ярлыка bug потому что в настоящее время он не влияет на наших пользователей.

Пожалуйста, откройте новую проблему, если есть что-то, что нужно решить.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги