[Standards-JIG] The Ack Hack.

Pavel Šimerda pavel.simerda.lists at centrum.cz
Sat May 6 14:42:23 UTC 2006


On 2006-05-04 00:43, Dave Cridland wrote:

> 1) The Sequence Number: Stanzas MAY have an attribute attached to
> their top-level element indicating their "sequence number". This has
> a strictly increasing interger value, meaning that it's higher than
> any previously sent stanza in the same connection.
>
> 	Rationale: This is expected to be on all stanzas or none. It's used
> to acknowledge receipt of stanzas, both implicitly and explicitly.
>
> 	Wire cost: Around 20 octets.
>

I believe sequence numbers are good. It seems that remembering last stanza's 
sequence number is better than confirming the exact number of stanzas 
recieved. Sequence numbers only add octets to existing stanzas/packets.

> 2) Implicit Acks: Stanzas MAY have an attribute attached to their
> top-level element indicating the highest sequence number seen by
> stanzas the transmitting entity has received.
>
> 	Rationale: Whenever you're sending a stanza, you can ACK all the
> stanzas you've received if you need to.
>
> 	Wire Cost: Again, 20 octets.
>

Implicit acks included in stanzas let you know the connection is still alive. 
Again, they're not adding more stanzas/packets.

What about high-load s2s connections? Is it better to use implicit acks in 
stanzas... or time-by-time explicit acking?

I'd personally prefer implicit acks on all connections, it's easier. But I'm 
not a high-load jabber server administrator

> 3) Explicit Acks: A Sender MAY require the Receiver to transmit the
> highest sequence number it has received at any time. (This can be
> implemented as a Ping, or NOOP, because the response indicates that
> all stanzas have been received to this point).
>
> 	Rationale: When the connection's quiet, this can both test the
> connection and eliminate a build-up of potentially unreceived stanzas.
> 	Note: Unlike JEP-ACK's ping, the receiving entity processes pings
> after accepting prior stanzas.

When server/client doesn't recieve an implicit ack in some reasonable time, it 
asks for it. If even that fails, client tries to reconnect. If reconnection 
fails, user gets an error message.

Both client and server could use the same (or similar) values for timeouts. 
They would be implementation specific, I'll just throw some examples. Feel 
free to improve them.

When client/server sends a stanza, it expects an implicit ack in 25 seconds. 
If it doesn't arrive, it asks for an explicit one and expects the response in 
5 seconds.

When client/server hasn't sent any new staza, it expects no implicit ack. 
After 120 secends it asks for an explicit one.

This would mean that... during a conversation, you'd know about connection 
errors in half a minute. And when idle, you'd know it in two minutes.

Rationale: Both client and server would realize the connection is lost. Server 
would close the connection and it SHOULD include a descriptive message in the 
broadcasted presence:unavailable stanza so that your friend knows you've lost 
the connection (and not left deliberately). Messages undelivered to you would 
be stored offline (if supported and allowed).


> 4) Reconnection: A Receiver MAY store the highest sequence number it
> has received when the connection fails, and present it to the Sender
> upon reconnection. (Server in a stream feature, and Client in an iq?
> That would eliminate a round-trip.)

Good idea. This optianal feature would eliminate duplicate messages.

> 5) Hop only: The sequence number attribute and any Implicit Ack
> attribute MUST be removed prior to further processing - they are
> semantically purely a stream feature, and not part of the stanza per
> se.
>
> So that's the protocol description. Namespace URIs, attribute names,
> etc all up for grabs.
>
> Now how to use it:
>
> First, note that this is not symmetric - a client may send sequence
> numbered stanzas without offering the same service to a server -
> assuming the server offers the feature anyway.
>
> As a receiver:
>
> a) When sending a stanza, you need to add a sequence number
> attribute, and store the stanza in an "unacknowledged" collection.
>
> b) Every time you receive any stanza, check to see if it has the
> Implicit Ack attribute. If it does, you can delete all stanzas in the
> "unacknowledged" collection with a sequence number equal to or lower
> than the one you've received.
>
> c) If the connection goes suspiciously quiet for long enough, or the
> number of stanzas (or size of them) is large, you can ping the
> connection, thus causing an Explicit Ack. If you receive a return,
> then that's an incoming packet, so see (b).

I offered an alternative to this above, ensuring reasonably short time before 
broken connection is detected.

> d) If you receive no response to a ping, or you get an explicit TCP
> fatal error, then reconnect. On reconnection, obtain the highest
> sequence value for the now defunct session. Treat this value as an
> Ack value, then retransmit all stanzas in your "unacknowledged"
> collection. Note these may have to use new sequence numbers.
>
> Receiver side:
>
> For the receiver, you have to store one sequence value per active
> connection, the highest received sequence value.
>
> The receiver also should store persistently the highest received
> sequence store for each resource, for a minimum of around an hour
> after the connection is lost. I'll call this the last highest
> sequence value.
>
> a) Whenever you receive a stanza, note the sequence value, and store
> it as the highest received sequence value.
>
> b) Whenever you send a stanza, see if you have acknowledged the
> current highest received sequence value. If not, add the Implicit Ack
> attribute. You can always add the Implicit Ack attribute, but you're
> wasting data.

So... send implicit acks only if the "last recieved" sequence number changed. 
Acking the same one again is useless.

> c) When a new connection is made, transmit the last highest sequence
> value.
>
> Pros: Many fewer packets, reliable connections are less costly,
> unreliable connections are made much more reliable.
>
> Cons:
> - Bandwidth is increased, although by 40 octets or so worst case
> (usually much less) - a TCP packet empty of data is around 40 octets,
> for comparison.
> - Complexity is increased, however this is only an issue during
> reconnection, not during more normal operation.
> - Servers need to rewrite stanzas when forwarding. On the plus side,
> at least it's only the outer element.

Allright, it seems the cons are not bad... and we're getting reliable :-)

> With the Implicit Acks, we've put a lot more acking back in. This is
> now, roughly, JEP-ACK, but with Acks made more lazy, compensated for
> by having connection failure itself made non-fatal.

It would be nice to hear Justin's view. Since he was trying to solve this too. 
He might know something we have missed.

Pavel

-- 
Keep it simple... http://www.pavlix.net/



More information about the Standards mailing list