google-chrome - Chrome RSV 中的 Zeppelin 和 Netty 反向代理!= 0 并且没有协商扩展,RSV:4
问题描述
我们正在尝试将 Zeppelin 版本从 0.7.0 升级到 0.8.2,并且在 Chrome 中遇到 WebSockets 问题。我们的流程是 Zeppelin <- -> 用于身份验证的反向代理,基于 Netty。反向代理使用的是 netty 4.1.50。在我们尝试升级之前,我们通过反向代理使用 Zeppelin 没有任何问题。
该问题与 WebSockets 有关,并且在 Netty 中引发了异常-
io.netty.handler.codec.CorruptedFrameException: RSV != 0 and no extension negotiated, RSV:4
我们最初认为问题出在 Netty 中,因为我们没有在 Netty 中启用扩展
WebSocketServerHandshakerFactory(java.lang.String webSocketURL, java.lang.String subprotocols, boolean allowExtensions)
但是,当我们启用 allowExtensions = true 时,我们仍然看到完全相同的行为。
当我们进一步挖掘时,我们发现在用于连接 WebSocket 的 RFC 中:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
RSV1、RSV2、RSV3:各 1 位
MUST be 0 unless an extension is negotiated that defines meanings
for non-zero values. If a nonzero value is received and none of
the negotiated extensions defines the meaning of such a nonzero
value, the receiving endpoint MUST _Fail the WebSocket
Connection_.
因此,Netty 的行为似乎是正确的,并且 Zeppelin 以某种方式发送 RSV = 4。
看起来 Zeppelin 负责定义 RSV = 4 的含义:
8. 错误处理
8.1. Handling Errors in UTF-8-Encoded Data
When an endpoint is to interpret a byte stream as UTF-8 but finds
that the byte stream is not, in fact, a valid UTF-8 stream, that
endpoint MUST _Fail the WebSocket Connection_. This rule applies
both during the opening handshake and during subsequent data
exchange.
9. Extensions
WebSocket clients MAY request extensions to this specification, and
WebSocket servers MAY accept some or all extensions requested by the
client. A server MUST NOT respond with any extension not requested
by the client. If extension parameters are included in negotiations
between the client and the server, those parameters MUST be chosen in
accordance with the specification of the extension to which the
parameters apply.
最后,相关的堆栈跟踪如下。一旦反向代理成功验证并转发到 Zeppelin,就会触发此操作。
akka.actor.default-dispatcher-7] .o.p.WebSocketProxyNettyClient - Connecting to -97122421/servername:26698 /notebook/ws
akka.actor.default-dispatcher-7] .o.p.WebSocketProxyNettyClient - 97122421/servername:26698 handshakingWithFrontEnd>got UpgradedToWebSocket
akka.actor.default-dispatcher-7] .o.p.WebSocketProxyNettyClient - 97122421/servername:26698 connect>got BothHandshakesCompleted
akka.actor.default-dispatcher-4] .o.p.WebSocketProxyNettyClient - 97122421/servername:26698 front-end>send frame TextWebSocketFrame size=111
akka.actor.default-dispatcher-4] .o.p.WebSocketProxyNettyClient - 97122421/servername:26698 front-end>send frame TextWebSocketFrame size=102
akka.actor.default-dispatcher-4] .o.p.WebSocketProxyNettyClient - 97122421/servername:26698 front-end>send frame TextWebSocketFrame size=105
[nioEventLoopGroup-4-4] .p.WebSocketNettyClientHandler - ExceptionCaught for -97122421/servername:26698 /notebook/ws
io.netty.handler.codec.CorruptedFrameException: RSV != 0 and no extension negotiated, RSV:4
at io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.protocolViolation(WebSocket08FrameDecoder.java:412)
at io.netty.handler.codec.http.websocketx.WebSocket08FrameDecoder.decode(WebSocket08FrameDecoder.java:188)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1412)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:943)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:141)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
解决方案
推荐阅读
- javascript - 为什么firebase会自动关闭我的身份验证窗口?反应 - Firebase
- caching - Drupal 8 - 添加自定义缓存上下文
- reactjs - 自定义反应钩子的 Proptypes
- amazon-web-services - KMS 加密后无法从 S3 下载文件
- javascript - 在 JS 幻灯片中单击图像时转到其他 URL 和锚点
- c# - SQLite 插入带参数的字符串数据会导致无效的强制转换异常
- javascript - 查找对象中的所有日期类型属性,并将相同属性从字符串转换为克隆对象中的日期对象
- database-design - 暂存表以使用层次结构或平面
- typescript - 打字稿:如何为对象属性添加类型安全?
- ffmpeg - 如何将 .cap 隐藏式字幕编码为 MPEG 视频