Lorawan-stack: Secuencias de eventos que bloquean la consola cuando los eventos de inicio no se envían

Creado en 21 jul. 2020  ·  14Comentarios  ·  Fuente: TheThingsNetwork/lorawan-stack

Resumen

Desde https://github.com/TheThingsNetwork/lorawan-stack/pull/2565, los eventos se transmiten en el bloque de la consola después de hacer clic en la consola.

Pasos para reproducir

  1. Vaya a https://tti.staging1.cloud.thethings.industries/console/gateways
  2. En una sola pestaña, abra una puerta de enlace y use las migas de pan para volver
  3. Repita para cada puerta de enlace

¿Qué ves ahora?

En algún momento, la consola sigue cargándose. Esto parece deberse a "demasiadas conexiones abiertas" porque las solicitudes /api/v3/events no están cerradas.

¿Qué quieres ver en su lugar?

La consola debe seguir respondiendo.

Medio ambiente

Construya sobre la base de la actual master branch 3df51cd750f57b37c3acffc28b417441babdbf30 (no preste atención al 3.8.5 que se muestra en la consola)

¿Cómo se propone implementar esto?

Sospecho que esto se debe al hecho de que los encabezados solo se escriben justo antes del primer mensaje en la transmisión. Si no hay mensaje, no hay encabezado y el navegador sigue esperando.

Entonces, para investigar, sugiero:

  • Comprueba si escribimos el encabezado correctamente
  • Compruebe si la puerta de enlace gRPC escribe y vacía el encabezado correctamente
  • Compruebe si las cosas de Echo / Mux no interfieren

¿Cómo propones probar esto?

Prueba los pasos de reproducción

shared dependencies

Comentario más útil

Entonces, esto es algo en nuestras dependencias (grpc-gateway no descarga correctamente los encabezados) o en nuestro código compartido (tal vez algún middleware grpc o http no vacía los encabezados).

Eliminando la etiqueta bug porque actualmente no es algo que afecte a nuestros usuarios.

Todos 14 comentarios

En la consola de Firefox se está cargando para siempre si hay 6 pestañas abiertas, si, por ejemplo, una de las pestañas de trabajo se actualiza, una de las pestañas de carga se desbloquea, pero a veces parece fallar.

En cualquier caso, intenté enviar los mensajes de inicio / finalización, pero eso no cambió nada; todavía se cuelga después de que haya 6 pestañas.

Nota: todas las pestañas están en la vista de datos de una puerta de enlace (2 diferentes)

@kschiffer ¿ alguna idea?

En la consola de Firefox se está cargando para siempre si hay 6 pestañas abiertas, si, por ejemplo, una de las pestañas de trabajo se actualiza, una de las pestañas de carga se desbloquea, pero a veces parece fallar.

Eso es lo esperado y una limitación al no utilizar los flujos de eventos mientras no se usa HTTP / 2 :

Cuando no se usa a través de HTTP / 2 , SSE sufre una limitación en el número máximo de conexiones abiertas, lo que puede ser especialmente doloroso al abrir varias pestañas, ya que el límite es _por navegador_ y se establece en un número muy bajo (6). El problema se ha marcado como "No se solucionará" en Chrome y Firefox . Este límite es por navegador + dominio, lo que significa que puede abrir 6 conexiones SSE en todas las pestañas a www.example1.com y otras 6 conexiones SSE a www.example2.com. (de Stackoverflow ). Cuando se utiliza HTTP / 2, el número máximo de _HTTP streams_ simultáneos se negocia entre el servidor y el cliente (el valor predeterminado es 100).

Tengo problemas para reproducir el problema original porque solo tengo acceso a dos puertas de enlace conectadas en el entorno de ensayo.

Sospecho que esto se debe al hecho de que los encabezados solo se escriben justo antes del primer mensaje en la transmisión. Si no hay mensaje, no hay encabezado y el navegador sigue esperando.

Puedo confirmar esto. Las solicitudes se detendrán si no reciben un encabezado de respuesta. Después de que se abran seis de estas conexiones, todos los XHR posteriores también se detendrán.

Antes del # 2565 esto no era un problema ya que el flujo de eventos siempre enviaba un "mensaje de inicio de flujo" inmediatamente, lo que resultaba en el envío de los encabezados.

Como tal, no lo veo como un problema de interfaz. Lo único que tendría sentido cambiar en la interfaz es asegurarse de que las conexiones de transmisión detenidas se eliminen después de un tiempo determinado.

Entonces, el problema ocurre cuando los flujos de eventos no envían ningún dato. El XHR que realiza la conexión de flujo de eventos solo se resolverá después de que se haya recibido el primer mensaje; de ​​lo contrario, se colgará en el estado pending . Una vez que se abren 6 de esas conexiones, todas las demás conexiones también se bloquearán, ya que se ha alcanzado la cantidad máxima de conexiones TCP simultáneas. Entonces, parece que XHR espera algún tipo de reconocimiento del servidor de que se estableció la transmisión.

Antes del # 2565 esto no era un problema ya que el flujo de eventos siempre enviaba un "mensaje de inicio de flujo".

Actualmente estoy tratando de averiguar si esto se puede solucionar en el lado de la interfaz y cómo.

En mi experiencia, enviar un "mensaje inicial" no ayuda con este problema. Pruebe usted mismo con la siguiente diferencia:

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 {

Aquí hay un video:
https://youtu.be/0Ir0lakV-Mc

Veo una diferencia.

En master SIN la diferencia:

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

En master CON el diff.

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

Tenemos que diferenciar este tema:

  1. Siempre que haya seis conexiones TCP abiertas simultáneamente por dominio y navegador, cualquier solicitud posterior se bloqueará. Esta es una limitación del navegador y las formas de la OMI para lidiar con esto deberían discutirse en otro número. Este es el problema que veo en tu video @rvolosatovs
  2. Cuando un punto final de transmisión no envía un encabezado de respuesta inmediatamente, la solicitud se detendrá (hasta que el encabezado se envíe finalmente en el primer mensaje). Esto significa que, aunque use solo una pestaña, la consola acumulará conexiones de transmisión pendientes cuando navegue repetidamente a páginas que abren conexiones de transmisión. Después de que se abran seis de estas conexiones, la consola se bloqueará, por la misma razón que en (1).

Para mitigar 2, el encabezado de respuesta debe enviarse inmediatamente.

Una cosa a tener en cuenta aquí en lo que respecta a la consola, deberíamos considerar también cancelar las solicitudes pendientes. Actualmente, las solicitudes solo se pueden cancelar una vez que se haya establecido la conexión de transmisión.

@kschiffer, ¿ puede darnos pasos para reproducir el problema en 2.?
Actualizo constantemente una sola pestaña de datos de la puerta de enlace y no experimento bloqueos con el último master (sin parche)

La forma más sencilla es crear una puerta de enlace completamente nueva y desconectada, ya que no enviará ningún mensaje. Luego, navegue a su página de descripción general y regrese a la lista de puertas de enlace seis veces.

Este no es un problema específico de los eventos de la puerta de enlace, sino de todos los flujos de eventos.

Desasignándome ya que este no es un problema que se origina en la Consola.

Cerrado por # 2989

Se introdujo una solución temporal en https://github.com/TheThingsNetwork/lorawan-stack/pull/2989 ; aún no se ha encontrado una solución más sólida.

Entonces, esto es algo en nuestras dependencias (grpc-gateway no descarga correctamente los encabezados) o en nuestro código compartido (tal vez algún middleware grpc o http no vacía los encabezados).

Eliminando la etiqueta bug porque actualmente no es algo que afecte a nuestros usuarios.

Abra un nuevo problema si todavía hay algo que debe solucionarse.

¿Fue útil esta página
0 / 5 - 0 calificaciones