由于https://github.com/TheThingsNetwork/lorawan-stack/pull/2565事件在控制台中单击后在控制台块中流动。
在某些时候,控制台会不断加载。 这似乎是由“打开的连接过多”引起的,因为/api/v3/events
请求没有关闭。
控制台应该保持响应。
基于当前的master
分支构建3df51cd750f57b37c3acffc28b417441babdbf30(不要关注控制台显示的3.8.5)
我怀疑这是由于标题仅在流中的第一条消息之前写入这一事实造成的。 如果没有消息,则没有标题,浏览器会一直等待。
所以为了调查,我建议:
尝试复制步骤
如果有 6 个打开的选项卡,Firefox 控制台将永远加载 - 例如,如果刷新了工作选项卡之一 - 加载选项卡之一会解除阻塞,但有时似乎会失败。
无论如何,我尝试发送开始/结束消息,但这并没有改变任何东西 - 在有 6 个选项卡后它仍然挂起。
注意:所有选项卡都在网关的数据视图中(2 个不同的)
@kschiffer 有什么想法吗?
如果有 6 个打开的选项卡,Firefox 控制台将永远加载 - 例如,如果刷新了工作选项卡之一 - 加载选项卡之一会解除阻塞,但有时似乎会失败。
这是预期的,并且在不使用 HTTP/2 时取消事件流的限制:
当不通过 HTTP/2 使用时,SSE 会受到最大打开连接数的限制,这在打开各种选项卡时会特别痛苦,因为限制是 _per browser_ 并且设置为非常低的数字 (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
我们必须区分这个问题:
为了缓解 2,需要立即发送响应头。
就控制台而言,这里需要注意的一件事是,我们还应该考虑取消挂起的请求。 目前只有在建立流连接后才能取消请求。
@kschiffer你能给出在 2. 中重现问题的步骤吗?
我不断刷新单个网关数据选项卡,并且在使用最新的master
(无补丁)时没有遇到任何挂起
最简单的方法是创建一个全新且未连接的网关,因为它不会发送任何消息。 然后导航到其概览页面并返回网关列表六次。
顺便说一下,这不是网关事件特有的问题,而是所有事件流的问题。
取消分配我,因为这不是源自控制台的问题。
关闭 #2989
https://github.com/TheThingsNetwork/lorawan-stack/pull/2989中引入了一个临时解决方案 - 尚未找到更强大的解决方案。
所以这要么是在我们的依赖项中(grpc-gateway 没有正确刷新标头),要么是在我们的共享代码中(可能是一些 grpc 或 http 中间件没有刷新标头)。
删除bug
标签,因为它目前不会影响我们的用户。
如果还有需要解决的问题,请打开一个新问题。
最有用的评论
所以这要么是在我们的依赖项中(grpc-gateway 没有正确刷新标头),要么是在我们的共享代码中(可能是一些 grpc 或 http 中间件没有刷新标头)。
删除
bug
标签,因为它目前不会影响我们的用户。