使用 permessage-deflate 启用时,Undertow 似乎会发送损坏的消息

问题描述 投票:0回答:1

我正在使用 undertow 运行发送光标位置的 websocket 服务器。我在

2.3.5.Final
下,在
openjdk 11.0.22 2024-01-16
上奔跑。

问题:如果我打开两个选项卡,最终我会收到一条损坏的消息。

成功的消息如下所示:

{"op":"refresh-presence","room-id":"123","data":{"5c494daf-3c68-4ef6-b649-69177cc10105":{"peer-id":"5c494daf-3c68-4ef6-b649-69177cc10105","user":null,"data":{}},"b4eb6d8a-562a-4b8c-8e44-ecd43cba3621":{"peer-id":"b4eb6d8a-562a-4b8c-8e44-ecd43cba3621","user":null,"data":{}},"88f03150-696d-4e09-afbd-1381a2fa2f7e":{"peer-id":"88f03150-696d-4e09-afbd-1381a2fa2f7e","user":null,"data":{"cursors-space-default--main-123":{"x":723,"y":345,"xPercent":56.484375,"yPercent":52.43161094224924}}}}}                                                                                                                                                                                                                                                                                                                                                                                  

这是一个失败:

ors-space-default--main-123":{"x":562,"y":12,"xPercent":43.9ab521,"r56nt":1b3273a68bf-fefe7d735"}   

^ 这看起来乞讨部分被“切断”了。

xPercent
看起来也很奇怪:
43.9ab521
,就像某些 uuid 污染了值。

另一个例子:

这是一条成功的消息:

{"op":"set-presence-ok","room-id":"123","client-event-id":"9093a7cc-96ea-42e5-943e-e7c7962bbfcc"}

这是一个失败

{"op":"set-presence-ok","room-id":"123","client-event-id":"6186021","u44-45ser"265-211b8cu44315"}

看起来这里的

uuid
被切掉了

设置

这是我设置 websocket 连接的方法:

(defn ws-request [^HttpServerExchange exchange ^IPersistentMap headers ^WebSocketConnectionCallback callback]
  (let [handler (->  (WebSocketProtocolHandshakeHandler. callback)
                     (.addExtension (PerMessageDeflateHandshake.
                                     true ; client? 
                                     6    ; deflaterLevel: is a number from 0 (no compression) to 9 (maximum compression)
                                     )))]
    (when headers
      (set-headers (.getResponseHeaders exchange) headers))
    (.handleRequest handler exchange)))

这是我发送消息的方式:

(defn send-json!
  "Serializes `obj` to json, and sends over a websocket."
  [obj ws-conn]
  (let [obj-json (->json obj)
        p (promise)
        _ (WebSockets/sendText
           ^String obj-json
           ^WebSocketChannel ws-conn
           (proxy [WebSocketCallback] []
             (complete [ws-conn context]
               (deliver p nil))
             (onError [ws-conn context throwable]
               (deliver p throwable))))
        ret @p]
    (when (instance? Throwable ret)
      (throw ret))))

潜在的罪魁祸首:PerMessageDeflateHandshake

如果删除

PerMessageDeflateHandshake
扩展,我将无法再重现损坏的消息。

我不确定解决这个问题的最佳方法是什么。

java clojure undertow
1个回答
0
投票

问题在于

Websockets.sendText
是在多线程环境下使用的。

根据这篇文章

WebsocketChannel
应该是线程安全的。我的猜测是,当与
PermessageDeflate
结合使用时,它不再是线程安全的。

sendText
周围添加一把锁为我解决了这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.