[reSIProcate] back pressure
Here is my proposed code for applying back pressure from the TU. It is a
very simple approach. If the TU fifo gets above a certain size, start
sending 503 messages with Retry-After header in them. TU back pressure only
applies to incoming requests from the wire (excluding ACK).
Topics for discussion:
- will it work at all?
- how big should the fifo be before backpressure is applied?
- how long should Retry-After be? currently random between 32 and 64 seconds
Additional places to add backpressure:
- Transports should reject with 503 if the mStateMachineFifo is above a
certain size
- If they get really behind, they should drop the request on the floor
- Transport backpressure probably needs to apply to all incoming messages
(not just requests)
- SipStack will also reject application send with 503 if the
mStateMachineFifo is above certain size. Note: this is the same fifo that
the transports use.
- what do we do if the Transports are behind on transmitting messages? Could
just drop them on the floor and signal a failure to the transaction. Need to
think about the impact on a proxy.
void
TransactionState::process(TransactionController& controller)
{
Message* msg = controller.mStateMacFifo.getNext();
assert(msg);
TransactionMessage* message = dynamic_cast<TransactionMessage*>(msg);
SipMessage* sip = dynamic_cast<SipMessage*>(message);
RESIP_STATISTICS(sip && sip->isExternal() &&
controller.getStatisticsManager().received(sip));
// !jf! this is a first cut at elementary back pressure. hope it works :)
if (sip && sip->isExternal() && sip->isRequest() &&
sip->header(h_RequestLine).getMethod() != ACK &&
controller.isTUOverloaded())
{
SipMessage* tryLater = Helper::makeResponse(*sip, 503);
tryLater->header(h_RetryAfter).value() = 32 + (Random::getRandom() %
32);
tryLater->header(h_RetryAfter).comment() = "Server busy";
Tuple target(sip->getSource());
delete sip;
controller.mTransportSelector.transmit(tryLater, target);
return;
}
....