< Previous by Date Date Index Next by Date >
  Thread Index Next in Thread >

[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;
   }

....