Desde https://github.com/TheThingsNetwork/lorawan-stack/pull/2565 os eventos são transmitidos no bloco do console depois de clicar no console.
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 console deve permanecer responsivo.
Compilar com base no atual master
branch 3df51cd750f57b37c3acffc28b417441babdbf30 (não preste atenção ao 3.8.5 mostrado pelo console)
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:
Experimente as etapas de reprodução
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 parawww.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:
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.
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.