Jetty Websockets-处理不可靠的连接时正确发送异步消息 [英] Jetty Websockets - Correctly sending async messages when handling unreliable connections

查看:160
本文介绍了Jetty Websockets-处理不可靠的连接时正确发送异步消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Jetty 9.3.5,我想知道在发送websocket消息时处理不可靠连接的正确方法是什么,特别是:我注意到即使客户端在正常情况下,websocket连接也无法正常关闭的情况侧面朝下时,要花很多时间才能在服务器上触发onClose()(例如,用户合上笔记本电脑盖并将其置于待机状态-可能需要1-2个小时才能在服务器上收到close事件服务器端).

I'm using Jetty 9.3.5 and I would like to know what is the proper way to handle unreliable connections when sending websocket messages, specifically: I noticed cases when a websocket connection does not close normally so, even though the client side is down, it takes a lot of time until onClose() is triggered on the server (for ex. a user closes the laptop lid and puts it in standby - it can take 1-2 hours until the close event is received on the server side).

因此,由于客户端仍处于注册状态,因此服务器不断发送开始建立的消息.发送大量邮件时,这成为一个问题.

Thus, because the client is still registered, the server keeps sending messages that begin to build up. This becomes an issue when sending a large number of messages.

我已经测试过使用以下方式发送字节消息:

I've tested sending byte messages with:

Session.getRemote().sendBytes(ByteBuffer, WriteCallback)
Session.getRemote().sendBytesByFuture(ByteBuffer);

为模拟一侧的连接(即用户将笔记本电脑置于待机状态),在Linux上,我为eth0接口分配了IP地址,开始发送消息,然后将其断开:

To simulate the connection down on one side (ie. user puts laptop in standby), on Linux, I assigned an IP address to eth0 interface, started sending the messages and then brought it down:

ifconfig eth0 192.168.1.1
ifconfig eth0 up
--- start sending messages (simple incremented numbers) and connect using Chrome browser and print them ---
ifconfig eth0 down

这种方式:邮件仍由Jetty发送,Chrome客户端未接收到,服务器端未触发onCllose或onError

This way: the messages were still being sent by Jetty, the Chrome client did not receive them, the onCllose or onError was not triggered on server-side

关于码头的我的问题是:

My questions regarding Jetty are:

  1. 是否可以清除未传递的排队消息? 我已经尝试过,但是没有运气:

  1. Is there a way to clear queued messages that were not delivered? I've tried, but with no luck:

Session.getRemote().flush();

Session.getRemote().flush();

可以设置最大数量的排队消息吗? 我尝试过:

Can a max number of queued messages be set? I've tried:

WebSocketServletFactory.getPolicy().setMaxBinaryMessageBufferSize(1)

WebSocketServletFactory.getPolicy().setMaxBinaryMessageBufferSize(1)

我可以检测客户端是否未收到消息? (或者说如果连接处于异常状态) 我已经尝试过:

Can I detect if the client does not receive the message? (or if the connection is in abnormal state let's say) I've tried:

session.getRemote().sendBytes(bb, new WriteCallback() {

                @Override
                public void writeSuccess() {
                    //print success                     }

                @Override
                public void writeFailed(Throwable arg0) {
                    //print fail
                }
            });

但这即使没有收到消息也能成功打印.

But this prints success even though the messages are not received.

我也尝试使用,但找不到解决方案:

I also tried to use, but couldn't find a solution:

factory.getPolicy().setIdleTimeout(...);
factory.getPolicy().setAsyncWriteTimeout(3000);
sendPing()

提前谢谢!

推荐答案

不幸的是,作为消息传递协议的WebSocket协议并不是真正针对消息之间的这种细微差别而设计的.

Unfortunately, the WebSocket protocol, being a message passing protocol isn't really designed for this level of nuance between messages.

第一条消息必须完成,您甚至可以考虑发送下一条消息.因此,如果您正在处理一条消息,则无法安全地取消该消息.

The first message MUST complete before you can even think of sending the next message. So if you have a message in process, then there is no way to safely cancel that message.

充其量,可以存在一个API来用CONTINUATION/空有效载荷/fin = true截断该消息.

At best, an API could exist to truncate that message with a CONTINUATION / empty payload / fin=true.

但是即使那样,远程端点也不会知道您已取消了该消息,它只会看到部分消息.

But even then the remote endpoint wouldn't know that you canceled the message, it would just see a partial message.

检测连接问题最好通过操作系统级别的事件(例如Android的连接意图)或通过定期的websocket PING(将其自身插入行外的websocket框架)来解决.

Detecting connectivity issues is best handled with either OS level events (like Android's Connectivity intents), or via periodic websocket PING (which inserts itself in front of the line for outgoing websocket frames.

但是,即使使用PING,如果您正在发送的websocket框架正在进行中,则即使在该websocket框架发送完毕之前,也无法发送PING.

However, even with PING, if your outgoing websocket frame is in-progress, even the PING cannot be sent until that websocket frame is done sending.

RemoteEndpoint.flush()将尝试刷新任何待处理的消息(和框架),而不是清除待处理的消息(或框架).

RemoteEndpoint.flush() will attempt to flush any pending messages (and frames), not clear out pending messages (or frames).

关于检测客户端是否收到消息,您需要在自己的层中实现某种消息ACK以验证该协议没有这样的概念. (一些构建在websocket之上的lib/api在该层中实现了消息ACK.

As for detecting if client got the message, you'll need to implement some sort of message ACK into your own layer to verify that, the protocol has no such concept. (Some libs/apis built on top of websocket have implemented message ACK in that layer. The cometd message ack extension comes to mind as a real world example)

您要解决哪种情况?

也许使用

Perhaps using the RemoteEndpoint.sendPartialString(String, boolean) or RemoteEndpoint.sendPartialBytes(ByteBuffer, boolean) to send smaller frames of the whole message could be useful to you. However, the other side might not have an API that can read those partial frames (eg: Javascript in a browser).

这篇关于Jetty Websockets-处理不可靠的连接时正确发送异步消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆