我已经在这个问题上工作了一段时间,并决定寻求帮助。
我有以下情况。 ActiveMQ服务器在端口61614上侦听。两个WebSocketStompClient正在连接到以下队列;
Client1: / queue / request / server1-/ queue / replyto / server1
Client2: / queue / request / server2-/ queue / replyto / server2
2个服务器相互通信并请求信息。 这些情况我都没问题。 从服务器1向服务器2队列发送请求,并在服务器1响应队列上接收响应。
类似这样的:I don't have 10 reputations...
Sending SEND {destination=[/queue/request/server2], session=[0d2573e2-079e-ad9c-71df-9274eeba2519], receipt=[3]} etc..
Received MESSAGE {destination=[/queue/request/server2], session=[0d2573e2-079e-ad9c-71df-9274eeba2519] etc...
在此处执行随机应用逻辑...
Sending SEND {destination=[/queue/replyto/server1] ,session=[0d2573e2-079e-ad9c-71df-9274eeba2519], etc...
Received MESSAGE {destination=[/queue/replyto/server1], session=[0d2573e2-079e-ad9c-71df-9274eeba2519], etc...
但是,如果您尝试在响应第一个请求之前将另一条消息发送到服务器1的请求队列,则会出现问题。该响应被发送到服务器2的响应队列,但从未收到。
此处的图片:Never receive the response( 3. RESPONSE) to the request (2. REQUEST)
Sending SEND { destination=[/queue/replyto/server2], session=[c504b2fe-ae63-1bc2-87ce-651682b7c98e], receipt=[4], etc.
Received RECEIPT {receipt-id=[4]} session=c256762b-ddef-4109-8a3e-04bde832ed85
我希望已经足够清楚,如果需要更多说明,请告诉我。
其他信息是,我确定该消息是按写在队列中的方式发送的,我可以看到它。
您还可以看到,所有消息均已出队/确认。
值得一提的是,所有这些操作都是通过docker ActiveMQ服务器在本地完成的,并进行了模拟开发服务器上发生的事情的单元测试。
使用Wireshark,我可以看到该消息已被server2确认。
最后:
这是设置,两台服务器都相同:
客户:
WebSocketClient transport = new StandardWebSocketClient();
WebSocketStompClient server1 = new WebSocketStompClient(transport);
server1.setMessageConverter(new MappingJackson2MessageConverter());
server1.setTaskScheduler(taskScheduler);
server1.setDefaultHeartbeat(heartbeat);
server1.connect(bindAddress, Server1SessionHandler);
处理程序:
public class Server1SessionHandler extends StompSessionHandlerAdapter {
@Override
public void afterConnected(final StompSession session, final StompHeaders connectedHeaders) {
logger.debug("Entering RemoteSessionHandler after connected method");
this.stompSession = session;
if (session.isConnected()) {
session.setAutoReceipt(true);
logger.trace("Attempting to subscribe to channel {} using the RequestFrameHandler ", this.subscribeChannel);
session.subscribe(this.subscribeChannel, new Server1RequestFrameHandler(session, null, brokerMessageTtl, logicService, guid));
logger.trace("Attempting to subscribe to channel {} using the ResponseFrameHandler ", this.replyQueue);
session.subscribe(this.replyQueue, new Server1ResponseFrameHandler(this.cache));
publisher.publishEvent(new ConnectionSuccessEvent(Server1SessionHandler.class, "RemoteSessionHandler"));
}
else {
logger.error("Could not connect to stomp Session {}", session.toString());
}
}
}
请求帧处理程序:
public class Server1RequestFrameHandler implements StompFrameHandler {
private StompSession session;
public Server1RequestFrameHandler(final StompSession session) {
this.session = session;
}
@Override
@SuppressWarnings("static-access")
public void handleFrame(final StompHeaders headers, final Object payload) {
...... BUSINESS LOGIC ......
if (session.isConnected()) {
session.send(header, response);
logger.debug("Successfully connected using the stompsession {}, ", session.toString());
}
}
@Override
public Type getPayloadType(final StompHeaders headers) {
return Request.class;
}
}
响应帧处理程序:
public class Server1ResponseFrameHandler implements StompFrameHandler {
private Server1Cache cache;
public Server1ResponseFrameHandler(final Server1Cache cache) {
this.cache = cache;
}
public void handleFrame(final StompHeaders headers, final Object payload) {
Response response = (Response) payload;
logger.debug("response: {}", response);
cache.cacheMessage(id, response);
}
public Type getPayloadType(final StompHeaders headers) {
return Response.class;
}
}
如果您需要更多信息,请告诉我。
答案 0 :(得分:0)
我能够通过使用2种不同的WebSocket连接设置订阅主题来绕过此操作。如: 创建一个请求客户端
WebSocketClient requestTransport = new StandardWebSocketClient();
WebSocketStompClient requestClient = new WebSocketStompClient(requestTransport);
requestClient.setMessageConverter(new MappingJackson2MessageConverter());
requestClient.setTaskScheduler(taskScheduler);
requestClient.setDefaultHeartbeat(heartbeat);
requestClient.connect(bindAddress, RequestSessionHandler);
创建一个单独的响应客户端
WebSocketClient responseTransport = new StandardWebSocketClient();
WebSocketStompClient responseClient = new WebSocketStompClient(responseTransport);
responseClient.setMessageConverter(new MappingJackson2MessageConverter());
responseClient.setTaskScheduler(taskScheduler);
responseClient.setDefaultHeartbeat(heartbeat);
responseClient.connect(bindAddress, ResponseSessionHandler);
其中请求和响应会话处理程序仅订阅1个队列,而不是两个。
public class RequestSessionHandler extends StompSessionHandlerAdapter {
@Override
public void afterConnected(final StompSession session, final StompHeaders connectedHeaders) {
...
if (session.isConnected()) {
session.subscribe("requestChannel", new Server1RequestFrameHandler(session, null, brokerMessageTtl, logicService, guid));
....
}
}
}
如果有人对仅使用1个WebSocket客户端订阅两个队列时为什么会发生这种情况的解释,我很想听听。
我的理论是,为Websocket连接服务的线程忙于请求,并且没有空余的时间来处理已发送的响应。