Lorawan-stack: Console de bloqueio de fluxos de eventos ao iniciar eventos não enviados

Criado em 21 jul. 2020  ·  14Comentários  ·  Fonte: TheThingsNetwork/lorawan-stack

Resumo

Desde https://github.com/TheThingsNetwork/lorawan-stack/pull/2565 os eventos são transmitidos no bloco do console depois de clicar no console.

Passos para reproduzir

  1. Acesse https://tti.staging1.cloud.thethings.industries/console/gateways
  2. Em uma única guia, abra um gateway e use a localização atual para voltar
  3. Repita para cada gateway

O que você vê agora?

Em algum ponto, o console continua carregando. Isso parece ser causado por "muitas conexões abertas" porque /api/v3/events solicitações não foram fechadas.

O que você quer ver em vez disso?

O console deve permanecer responsivo.

Ambiente

Compilar com base no atual master branch 3df51cd750f57b37c3acffc28b417441babdbf30 (não preste atenção ao 3.8.5 mostrado pelo console)

Como você pretende implementar isso?

Suspeito que isso seja causado pelo fato de que os cabeçalhos são escritos apenas antes da primeira mensagem no fluxo. Se não houver mensagem, não há cabeçalho e o navegador fica esperando.

Então, para investigar, sugiro:

  • Verifique se escrevemos o cabeçalho corretamente
  • Verifique se o gRPC gateway grava e libera o cabeçalho corretamente
  • Verifique se o material Echo / Mux não interfere

Como você pretende testar isso?

Experimente as etapas de reprodução

shared dependencies

Comentários muito úteis

Portanto, isso é algo em nossas dependências (grpc-gateway não liberando cabeçalhos corretamente) ou em nosso código compartilhado (talvez algum middleware grpc ou http não liberando os cabeçalhos).

Removendo o rótulo bug porque atualmente não é algo que afeta nossos usuários.

Todos 14 comentários

No console do Firefox está carregando para sempre se houver 6 guias abertas - se, por exemplo, uma das guias de trabalho for atualizada - uma das guias de carregamento é desbloqueada, mas às vezes parece falhar.

Em qualquer caso, tentei enviar as mensagens de início / fim, mas isso não mudou nada - ainda trava depois de seis guias.

Observação: todas as guias estão na visualização de dados de um gateway (2 diferentes)

@kschiffer alguma ideia?

No console do Firefox está carregando para sempre se houver 6 guias abertas - se, por exemplo, uma das guias de trabalho for atualizada - uma das guias de carregamento é desbloqueada, mas às vezes parece falhar.

Isso é esperado e uma limitação dos fluxos de eventos de remoção sem usar HTTP / 2 :

Quando não é usado em HTTP / 2 , o SSE sofre de uma limitação ao número máximo de conexões abertas, o que pode ser especialmente doloroso ao abrir várias guias, pois o limite é _por navegador_ e definido para um número muito baixo (6). O problema foi marcado como "Não corrige" no Chrome e no Firefox . Este limite é por navegador + domínio, o que significa que você pode abrir 6 conexões SSE em todas as guias para www.example1.com e outras 6 conexões SSE para www.example2.com. (do Stackoverflow ). Ao usar HTTP / 2, o número máximo de fluxos _HTTP_ simultâneos é negociado entre o servidor e o cliente (o padrão é 100).

Tenho problemas para reproduzir o problema original, pois só tenho acesso a dois gateways conectados no ambiente de teste.

Suspeito que isso seja causado pelo fato de que os cabeçalhos são escritos apenas antes da primeira mensagem no fluxo. Se não houver mensagem, não há cabeçalho e o navegador fica esperando.

Eu posso confirmar isso. As solicitações serão paralisadas se não obtiverem um cabeçalho de resposta. Depois que seis dessas conexões forem abertas, todos os XHRs subsequentes também serão paralisados.

Antes do # 2565, isso não era um problema, pois o fluxo de eventos sempre enviava uma "mensagem de fluxo inicial" imediatamente, o que resultava no envio dos cabeçalhos.

Como tal, não vejo isso como um problema de front-end. A única coisa que faria sentido mudar no frontend é garantir que as conexões de stream travadas sejam eliminadas após um certo tempo.

Portanto, o problema ocorre quando os fluxos de eventos não enviam nenhum dado. O XHR que executa a conexão do fluxo de eventos só será resolvido após o recebimento da primeira mensagem, caso contrário, ele travará no estado pending . Assim que 6 dessas conexões forem abertas, todas as outras conexões também serão interrompidas, pois a quantidade máxima de conexões TCP simultâneas foi atingida. Portanto, parece que o XHR espera algum tipo de confirmação do servidor de que o fluxo foi estabelecido.

Antes do # 2565, isso não era um problema, pois o fluxo de eventos sempre enviava uma "mensagem de fluxo inicial".

No momento, estou tentando descobrir se e como isso pode ser corrigido no lado do front-end.

Na minha experiência, o envio de "mensagem inicial" não ajuda com esse problema. Por favor, tente você mesmo com a seguinte diferença:

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 {

Aqui está um vídeo:
https://youtu.be/0Ir0lakV-Mc

Eu vejo uma diferença.

Em master SEM a diferença:

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

Em master COM o 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

Precisamos diferenciar esse problema:

  1. Sempre que houver seis conexões TCP abertas simultaneamente por domínio e navegador, qualquer solicitação subsequente será interrompida. Esta é uma limitação do navegador e as maneiras da IMO de lidar com isso devem ser discutidas em outra edição. Este é o problema que vejo em seu vídeo @rvolosatovs
  2. Quando um endpoint de fluxo não envia um cabeçalho de resposta imediatamente, a solicitação fica paralisada (até que o cabeçalho seja enviado na primeira mensagem). Isso significa que, embora use apenas uma guia, o console acumulará conexões de fluxo pendentes ao navegar repetidamente para páginas que abrem conexões de fluxo. Após seis conexões sendo abertas, o console irá travar, pelo mesmo motivo que em (1).

Para mitigar 2, o cabeçalho da resposta precisa ser enviado imediatamente.

Uma coisa a ser observada aqui, no que diz respeito ao console, devemos analisar também o cancelamento de solicitações pendentes. Atualmente, as solicitações só podem ser canceladas depois que a conexão de fluxo for estabelecida.

@kschiffer você pode fornecer etapas para reproduzir o problema em 2.?
Estou constantemente atualizando uma única guia de dados do gateway e não tenho travamentos com os master mais recentes (sem patch)

A maneira mais fácil é criar um gateway completamente novo e desconectado, pois ele não enviará nenhuma mensagem. Em seguida, navegue até sua página de visão geral e volte para a lista de gateway seis vezes.

Este não é um problema específico para eventos de gateway, mas todos os fluxos de eventos, a propósito.

Cancelando minha atribuição, pois este não é um problema originado no Console.

Fechado por # 2989

Uma solução temporária foi introduzida em https://github.com/TheThingsNetwork/lorawan-stack/pull/2989 - uma solução mais robusta ainda não foi encontrada.

Portanto, isso é algo em nossas dependências (grpc-gateway não liberando cabeçalhos corretamente) ou em nosso código compartilhado (talvez algum middleware grpc ou http não liberando os cabeçalhos).

Removendo o rótulo bug porque atualmente não é algo que afeta nossos usuários.

Abra um novo problema se ainda houver algo que precise ser resolvido.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

johanstokking picture johanstokking  ·  5Comentários

w4tsn picture w4tsn  ·  6Comentários

ZeroSum24 picture ZeroSum24  ·  3Comentários

adriansmares picture adriansmares  ·  9Comentários

kschiffer picture kschiffer  ·  7Comentários