[ 
https://issues.apache.org/jira/browse/AMQ-4710?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16519686#comment-16519686
 ] 

Brett Elliott commented on AMQ-4710:
------------------------------------

Admittedly I haven't looked at the code or thought about this very long. 
However having said that: since then problem is that the heartbeat interval may 
be 2x as long as desired, couldn't you set the timer to half the desired 
interval? Then each time the timer expires, check to see if the last heartbeat 
went out on timer expiration, and if not send a heart beat message? I believe 
such an approach would allow you to have a reasonable timer interrupt interval, 
avoid the resetting in a busy system, and ensure that heartbeats are sent out 
on time.

> The first heart-beat after a connection becomes idle isn't sent as quickly as 
> it should be
> ------------------------------------------------------------------------------------------
>
>                 Key: AMQ-4710
>                 URL: https://issues.apache.org/jira/browse/AMQ-4710
>             Project: ActiveMQ
>          Issue Type: Bug
>          Components: stomp
>    Affects Versions: 5.8.0
>            Reporter: Andy Wilkinson
>            Assignee: Timothy Bish
>            Priority: Major
>             Fix For: 5.x
>
>         Attachments: amq-4710.diff
>
>
> After ActiveMQ sends a stomp frame, it may not send a heart-beat for up to 
> almost 2x the negotiated interval.
> The following test should illustrate the problem:
> {code}
> import org.junit.Test;
> import static org.junit.Assert.*;
> public class ActiveMqHeartbeatTests {
>       @Test
>       public void heartbeats() throws Exception {
>               BrokerService broker = createAndStartBroker();
>               Socket socket = null;
>               try {
>                       socket = new Socket("localhost", 61613);
>                       byte[] connectFrame = 
> "CONNECT\nheart-beat:0,10000\naccept-version:1.2\n\n\0".getBytes();
>                       socket.getOutputStream().write(connectFrame);
>                       byte[] buffer = new byte[4096];
>                       long lastReadTime = System.currentTimeMillis();
>                       while (true) {
>                               int read = socket.getInputStream().read(buffer);
>                               byte[] frame = Arrays.copyOf(buffer, read);
>                               long now = System.currentTimeMillis();
>                               long timeSinceLastRead = now - lastReadTime;
>                               lastReadTime = now;
>                               System.out.println(new String(frame));
>                               System.out.println("Time since last read: " + 
> timeSinceLastRead + "ms");
>                               if (timeSinceLastRead > 15000) {
>                                       fail("Data not received for " + 
> timeSinceLastRead + "ms");
>                               }
>                       }
>               } finally {
>                       if (socket != null) {
>                               socket.close();
>                       }
>                       broker.stop();
>               }
>       }
>       private BrokerService createAndStartBroker() throws Exception {
>               BrokerService broker = new BrokerService();
>               broker.addConnector("stomp://localhost:61613");
>               broker.setStartAsync(false);
>               broker.setDeleteAllMessagesOnStartup(true);
>               broker.start();
>               return broker;
>       }
> }
> {code}
> For the initial read of the CONNECTED frame I see:
> {noformat}
> Time since last read: 49ms
> {noformat}
> However, it's then almost 20 seconds before a heart-beat's sent:
> {noformat}
> Time since last read: 19994ms
> {noformat}
> If I comment out the fail(…) line in the test, after the first heartbeat 
> taking almost 20000ms to be sent, things settle down and a heartbeat's 
> received every 10000ms.
> It looks like the write checker wakes up every 10000ms. The first time it 
> wakes up, it notices that the CONNECTED frame was sent and does nothing. It 
> then sleeps for a further 10000ms before checking again. As the CONNECTED 
> frame was sent very early in the first 10000ms window, this leads to it 
> taking almost 20000ms for the first heart-beat to be sent. From this point, 
> as no further data frames are sent, the write checker wakes up and sends a 
> heart-beat every 10000ms.
> In short, I don't think ActiveMQ is adhering to the requirement that "the 
> sender MUST send new data over the network connection at least every <n> 
> milliseconds".



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to