See in-line. On 26 April 2015 at 05:37, Tim Bain <tb...@alumni.duke.edu> wrote:
> James, > > The prefetch buffer is a buffer of messages in the ActiveMQ code in the > client process that holds messages that have been dispatched from the > broker to the client but that haven't yet been handed over to the client. > To clarify the location of this pre-fetch buffer, is it inside the broker itself? Allocated to the client that is connected but not to individual consumers? > The purpose is to keep some number of messages in memory and available for > the consumer to handle, to ensure that the consumer never has to wait for a > message to be pulled from the broker. This lets the consumer consume as > quickly as possible. The broker will continue dispatching messages to the > client until the client has a full prefetch buffer, after which point it > will dispatch one message for every ack it gets back from the consumer. > Where "client" is in fact inside the broker at the network edge listening to the socket where the client with consumers is connected. > When you have multiple concurrent consumers, the broker will round-robin > messages between consumer that don't have full prefetch buffers; it won't > batch up a full prefetch buffer's worth for Consumer 1 before sending any > messages to Consumers 2-4, which is what I think you were worried about. > I was more conceptually thinking of a pre-fetch buffer being inside the client that is connected to the broker - i.e. the messages have already gone across the network and are therefore instant delivery into consumers. But I think when you talk of "client" you actually mean a resource within the broker marshalling messages out to a session within which multiple consumers are present. > > If there are a non-zero number of messages in the client's prefetch buffer > and receive() is called, the thread should simply go grab the first message > in the buffer and return it, so the timeout should not elapse unless the > broker's host is HEAVILY loaded or locking somehow delays thread execution > or you get unlucky enough to catch a full GC right then. If there are no > messages in the buffer, the thread should wait for the timeout period to > see if a message shows up, and either return that message when it does or > return with no message after the timeout elapses. In both scenarios, I > would expect that the consumer would remain connected and so no redelivery > would apply; receive() should just be looking to see whether a message came > across the pre-existing connection, but it should not be making connections > nor disconnecting if the timeout interval elapses without a message. (If > you're disconnecting after each message, that's an anti-pattern as I > understand it, and you should probably rethink your approach.) > I think our machine itself gets busy. We know that connecting and sending to ActiveMQ via STOMP sometimes ends up with a socket wait over 10 seconds. Identifying why could be interesting. > All of that is to say, I don't think that the elapsing of a receive() > timeout without receiving a message should do anything that would cause a > message redelivery, so I wonder if that's a red herring and the problem is > actually something else. Do you see any messages in your client or broker > logs indicating that the client disconnected and reconnected, that the > connection's inactivity monitor detected the connection to be inactive, or > that the consumer was aborted as a slow consumer? > I have not received any indications that the client is reconnecting. We have updated the receive time-out from 1000ms to 10000ms retaining the default 6 delivery attempts and so far nothing new has appeared in the DLQ. > > BTW, for your update of that page on the wiki, what client connection > timeout did you have in mind? (I can think of at least three things that > match that phrase: timeout on establishing the initial connection to the > broker, inactivity on the connection that leads to a disconnect, and the > receive() timeout you referenced above.) I think that a disconnect due to > connection inactivity where the inactivity monitor was in use would indeed > produce a redelivery, but if you meant the elapsing of a receive() timeout > as described above, I'm not convinced that that's accurate (and if it turns > out not to be, we should pull that edit back off the wiki page to avoid > confusing people). But one thing that I believe is missing from that list > is when a consumer disconnects from the broker (for any reason) where > messages have been dispatched to the consumer but not acknowledged (i.e. > they're in the consumer's prefetch buffer or they're the message the > consumer was processing at the time of the disconnect under certain > acknowledgement modes). > Surely if a client takes more than the receive time-out to process a message, a re-delivery will occur? If not, what does happen? That was the documentation update I had intended under what I thought was a very safe interpretation so far. > > Tim > > On Fri, Apr 24, 2015 at 8:10 AM, James Green <james.mk.gr...@gmail.com> > wrote: > > > I'm need to understand pre-fetch limit and receive time-out interaction. > > > > We have four concurrent consumers in our route. Do each receive the > > messages in batches of the pre-fetch limit? > > > > At what point does the receive time-out start and end? > > > > In our case each client performs a number of db queries then fires a new > > message at the broker before the route is complete. Typically this may > take > > more than 1 second under load. A 10s time-out only makes sense if the > > pre-fetching is not included but then that suggests client-calculated > > time-outs communicated back to the broker which also makes no sense. > > > > So, am clear we need to better understand what's under the hood here! > > > > James > > > > On 24 April 2015 at 14:39, Gary Tully <gary.tu...@gmail.com> wrote: > > > > > Tim, steady, I suggested it *may* be relevant :-) > > > With camel and transactions - ie: spring dmlc, connection pools and > > > cache levels - anything is possible w.r.t consumer/sessions/connection > > > state, because there are so many variables in the mix. > > > > > > With activemq and prefetch, every consumer disconnect will result in > > > redeliveries. The trick is figuring out whether > > > the prefetched messages were actually delivered to the consumer so the > > > delivery count can reflect the applications view > > > of the world, that is not an exact science. > > > > > > > > > On 24 April 2015 at 13:51, Tim Bain <tb...@alumni.duke.edu> wrote: > > > > Gary, > > > > > > > > If I understood that JIRA correctly, the bug only occurs when the > > client > > > > disconnects, which doesn't sound like what James is doing (nothing in > > his > > > > description indicated to me that his client wasn't staying up and > > > connected > > > > the whole time), so it doesn't sound like your fix would resolve (nor > > > > explain) his problem. And although I'm all about workarounds when I > > know > > > > there's a fix in a future version, I'm not sure that's the case here > > and > > > I > > > > don't want to give him a workaround at the expense of actually > finding > > > and > > > > fixing a bug. > > > > > > > > The two things I know of that can cause message redelivery are 1) > > client > > > > disconnection with queues and durable topic subscriptions and 2) > > > unhandled > > > > exceptions in the client message handler code. James, might #2 be > > going > > > on > > > > here? And Gary (or anyone else), are there any other possible causes > > of > > > > redelivery that I don't know about? > > > > > > > > Tim > > > > On Apr 24, 2015 4:59 AM, "Gary Tully" <gary.tu...@gmail.com> wrote: > > > > > > > >> to avoid the redelivered messages getting sent to the DLQ, changing > > > >> the default redelivery policy max from 6 to infinite will help. > > > >> > > > >> You can do this in the brokerurl passed to the jms connection > factory, > > > >> it may also make sense to reduce the prefetch if consumers come and > go > > > >> without consuming the prefetch, which seems to be the case. > > > >> > > > >> > > > >> > > > > > > tcp://..:61616?jms.prefetchPolicy.all=100&jms.redeliveryPolicy.maximumRedeliveries=-1 > > > >> > > > >> On 23 April 2015 at 17:14, James Green <james.mk.gr...@gmail.com> > > > wrote: > > > >> > Hi, > > > >> > > > > >> > We are not overriding so the defaults of 1s timeout on the > receive() > > > and > > > >> > 1,000 prefetch are in play. > > > >> > > > > >> > We are updating the connection URI to set a much higher timeout. > > > >> > > > > >> > Interestingly, PHP sending to the very same broker via STOMP gets > > > send() > > > >> > fail with a 2 second timeout specified. With a 10 second timeout > the > > > >> > frequency of this is reduced. > > > >> > > > > >> > I have fired up the latest hawt.io jar and connected to this > > broker, > > > >> > however the Health and Threads parts are entirely blank. The > queues > > > are > > > >> all > > > >> > visible yet "browse" of ActiveMQ.DLQ shows none of the 3,000+ > > > accumulated > > > >> > messages. Wondering where to go next? > > > >> > > > > >> > Thanks, > > > >> > > > > >> > James > > > >> > > > > >> > > > > >> > On 23 April 2015 at 13:35, Gary Tully <gary.tu...@gmail.com> > wrote: > > > >> > > > > >> >> what sort of timeout is on the receive(...) from spring dmlc, and > > > what > > > >> >> is the prefetch for that consumer. It appears that the message is > > > >> >> getting dispatched but not consumed, the connection/consumer dies > > and > > > >> >> the message is flagged as a redelivery. then the before delivery > > > check > > > >> >> on the delivery counter kicks the message to the dlq. So this > must > > be > > > >> >> happening 6 times. > > > >> >> > > > >> >> I just pushed a tidy up of some of the redelivery semantics - > there > > > >> >> was a bug there that would cause the redelivery counter to > > increment > > > >> >> in error... so that may be relevant[1]. > > > >> >> A short term solution would be to ensure infinite or a very large > > > >> >> number of redeliveries, up from the default 6. That can be > provided > > > in > > > >> >> the broker url. > > > >> >> > > > >> >> [1] https://issues.apache.org/jira/browse/AMQ-5735 > > > >> >> > > > >> >> On 23 April 2015 at 13:08, James Green <james.mk.gr...@gmail.com > > > > > >> wrote: > > > >> >> > We have a camel route consuming from ActiveMQ (5.10.0 with > > KahaDB) > > > and > > > >> >> > frequently get a DLQ entry without anything logged through our > > > >> >> errorHandler. > > > >> >> > > > > >> >> > The only thing we have to go on is a dlqFailureCause header > which > > > >> says: > > > >> >> > > > > >> >> > java.lang.Throwable: Exceeded redelivery policy > > > limit:RedeliveryPolicy > > > >> >> > {destination = null, collisionAvoidanceFactor = 0.15, > > > >> >> maximumRedeliveries = > > > >> >> > 6, maximumRedeliveryDelay = -1, initialRedeliveryDelay = 1000, > > > >> >> > useCollisionAvoidance = false, useExponentialBackOff = false, > > > >> >> > backOffMultiplier = 5.0, redeliveryDelay = 1000}, cause:null > > > >> >> > > > > >> >> > These are happening apparently at random. The route is marked > > > >> transacted, > > > >> >> > and is backed by Spring Transactions itself backed by Narayana. > > > >> >> > > > > >> >> > Our debugging indicates that our route never receives the > message > > > from > > > >> >> AMQ > > > >> >> > prior to it hitting the DLQ. We have switched on DEBUG logging > > for > > > >> >> > org.apache.activemq but other than being swamped with even more > > > logs > > > >> >> we've > > > >> >> > observed nothing notable. > > > >> >> > > > > >> >> > Any ideas where to go from here? Impossible to say which of the > > > >> several > > > >> >> > thousand messages per day will go this way so an attached > > debugger > > > is > > > >> out > > > >> >> > of the question. > > > >> >> > > > > >> >> > Our log4j config fragment: > > > >> >> > > > > >> >> > <Logger name="com" level="WARN"/> > > > >> >> > <Logger name="org" level="WARN"/> > > > >> >> > <Logger name="org.apache.camel" level="DEBUG"/> > > > >> >> > <Logger name="org.apache.activemq" level="DEBUG"/> > > > >> >> > <Logger name="org.springframework.orm.jpa" > > level="DEBUG"/> > > > >> >> > <Logger name="org.springframework.transaction" > > > level="DEBUG"/> > > > >> >> > > > > >> >> > Thanks, > > > >> >> > > > > >> >> > James > > > >> >> > > > >> > > > > > >