Lorawan-stack: 開始イベントが送信されない場合のイベントストリームブロッキングコンソール

作成日 2020年07月21日  ·  14コメント  ·  ソース: TheThingsNetwork/lorawan-stack

概要

https://github.com/TheThingsNetwork/lorawan-stack/pull/2565以降、コンソールでクリックした後、イベントはコンソールブロックでストリーミングされます。

再現する手順

  1. https://tti.staging1.cloud.thethings.industries/console/gatewaysにアクセス
  2. 1つのタブで、ゲートウェイを開き、ブレッドクラムを使用して戻ります
  3. ゲートウェイごとに繰り返します

あなたは今何を見ていますか?

ある時点で、コンソールはロードを続けます。 これは、 /api/v3/eventsリクエストが閉じられていないため、「開いている接続が多すぎる」ことが原因のようです。

代わりに何を見たいですか?

コンソールは応答性を維持する必要があります。

環境

現在のmasterブランチ3df51cd750f57b37c3acffc28b417441babdbf30に基づいてビルドします(コンソールに表示される3.8.5には注意を払わないでください)

これをどのように実装することを提案しますか?

これは、ヘッダーがストリームの最初のメッセージの直前にのみ書き込まれるという事実が原因であると思われます。 メッセージがない場合、ヘッダーはなく、ブラウザは待機し続けます。

したがって、調査するために、次のことをお勧めします。

  • ヘッダーが正しく書き込まれているかどうかを確認します
  • gRPCゲートウェイがヘッダーを正しく書き込んでフラッシュするかどうかを確認します
  • Echo / Muxのものが干渉しないかどうかを確認します

これをどのようにテストすることを提案しますか?

複製手順を試してください

shared dependencies

最も参考になるコメント

したがって、これは依存関係(grpc-gatewayがヘッダーを適切にフラッシュしない)または共有コード(おそらく一部のgrpcまたはhttpミドルウェアがヘッダーをフラッシュしない)のいずれかにあります。

bugラベルは現在ユーザーに影響を与えるものではないため、削除します。

全てのコメント14件

Firefoxコンソールでは、開いているタブが6つある場合(たとえば、作業中のタブの1つが更新された場合)、読み込み中のタブの1つがブロック解除されますが、失敗することがあります。

いずれにせよ、私は開始/終了メッセージを送信しようとしましたが、それは何も変わりませんでした-6つのタブがある後もハングします。

注:すべてのタブはゲートウェイのデータビューにあります(2つの異なるタブ)

@kschiffer何かアイデアはありますか?

Firefoxコンソールでは、開いているタブが6つある場合(たとえば、作業中のタブの1つが更新された場合)、読み込み中のタブの1つがブロック解除されますが、失敗することがあります。

これは予想されることであり、HTTP / 2を使用していないときにイベントストリームをアンシングするという制限があります

HTTP / 2ChromeFirefoxで「修正されません」とマークされています。 この制限はブラウザ+ドメインごとであるため、すべてのタブで6つのSSE接続をwww.example1.com開き、さらに6つのSSE接続をwww.example2.com.開くことができます

ステージング環境で接続されている2つのゲートウェイにしかアクセスできないため、元の問題を再現するのに問題があります。

これは、ヘッダーがストリームの最初のメッセージの直前にのみ書き込まれるという事実が原因であると思われます。 メッセージがない場合、ヘッダーはなく、ブラウザは待機し続けます。

確認できます。 応答ヘッダーを取得しない場合、要求は停止します。 このような接続が6つ開かれると、後続のすべての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. ドメインおよびブラウザごとに同時に6つのTCP接続が開いている場合は常に、後続の要求はすべてハングします。 これはブラウザの制限であり、これに対処するIMOの方法については別の問題で説明する必要があります。 これは私があなたのビデオ@rvolosatovsで見る問題です
  2. ストリームエンドポイントが応答ヘッダーをすぐに送信しない場合、要求は停止します(ヘッダーが最終的に最初のメッセージで送信されるまで)。 つまり、1つのタブだけを使用していても、ストリーム接続を開くページに繰り返し移動すると、コンソールは保留中のストリーム接続を蓄積します。 このような接続が6つ開かれると、(1)と同じ理由で、コンソールがハングします。

2を軽減するには、応答ヘッダーをすぐに送信する必要があります。

コンソールに関する限り、ここで注意すべきことの1つは、保留中のリクエストのキャンセルも検討する必要があります。 現在、リクエストは、ストリーム接続が確立された後でのみキャンセルできます。

@ kschiffer2で問題を再現する手順を教えてください。
私は常に単一のゲートウェイデータタブを更新しており、最新のmaster (パッチなし)でハングすることはありません

最も簡単な方法は、メッセージを送信しないため、完全に新しい未接続のゲートウェイを作成することです。 次に、概要ページに移動し、ゲートウェイリストに6回戻ります。

これはゲートウェイイベントに固有の問題ではありませんが、ちなみにすべてのイベントストリームです。

これはコンソールに起因する問題ではないため、割り当てを解除します。

#2989で閉鎖

一時的な解決策がhttps://github.com/TheThingsNetwork/lorawan-stack/pull/2989で紹介されました-より堅牢な解決策はまだ見つかりません。

したがって、これは依存関係(grpc-gatewayがヘッダーを適切にフラッシュしない)または共有コード(おそらく一部のgrpcまたはhttpミドルウェアがヘッダーをフラッシュしない)のいずれかにあります。

bugラベルは現在ユーザーに影響を与えるものではないため、削除します。

対処する必要のあることがまだある場合は、新しい問題を開いてください。

このページは役に立ちましたか?
0 / 5 - 0 評価