Domanda

Sto cercando di limitare la mia applicazione inviare tasso di 900Kbps ma il problema è che il protocollo che uso è orientato ai messaggi ei messaggi hanno dimensioni molto diverse. Posso avere messaggi da 40 byte tutta la strada fino a 125000 byte e tutti i messaggi vengono inviati come unità atomiche.

Ho provato attuare un buffer token bucket ma se regolo una bassa dimensione secchio grandi pacchetti mai ad inviare e un secchio maggiore si tradurrà in un grande scoppio senza limitante affatto.

Questa è la mia piccola implementazione in C:

typedef struct token_buffer {
  size_t capacity;
  size_t tokens;
  double rate;
  uint64_t timestamp;

} token_buffer;


static uint64_t time_now()
{
  struct timeval ts;
  gettimeofday(&ts, NULL);
  return (uint64_t)(ts.tv_sec * 1000 + ts.tv_usec/1000);
}

static int token_buffer_init(token_buffer *tbf, size_t max_burst, double rate)
{
  tbf->capacity = max_burst;
  tbf->tokens   = max_burst;
  tbf->rate = rate;
  tbf->timestamp = time_now();
}

static size_t token_buffer_consume(token_buffer *tbf, size_t bytes)
{
  // Update the tokens
  uint64_t now = time_now();
  size_t delta = (size_t)(tbf->rate * (now - tbf->timestamp));
  tbf->tokens = (tbf->capacity < tbf->tokens+delta)?tbf->capacity:tbf->tokens+delta;
  tbf->timestamp = now;

  fprintf(stdout, "TOKENS %d  bytes: %d\n", tbf->tokens, bytes);

  if(bytes <= tbf->tokens) {
    tbf->tokens -= bytes;
  } else {
    return -1;
  }

  return 0;
}

Poi, da qualche parte nel main ():

while(1) {
  len = read_msg(&msg, file);

  // Loop until we have enough tokens.
  // if len is larger than the bucket capacity the loop never ends.
  // if the capacity is too large then no rate limit occurs.
  while(token_buffer_consume(&tbf,msg, len) != 0) {}

  send_to_net(&msg, len);
}
È stato utile?

Soluzione

Si stanno limitando la dimensione massima dei messaggi da max_burst (che viene assegnato a tbf-> capacità in principio) - dal momento che la tbf-> Gettoni non incrementa di là di questo valore, i messaggi più grandi potranno mai ottenere inviato a causa di questo controllo:

if(bytes <= tbf->tokens) {
    tbf->tokens -= bytes;
  } else {
    return -1;
  }

Quindi, il codice imposta effettivamente un limite rigido sulla raffica da max_burst -. Così si dovrebbe frammentare i messaggi se si desidera che questo formato scoppio

Supponendo che questo è l'unico posto nel codice in cui è possibile inserire il limitatore, si potrebbe ottenere un risultato migliore se si sostituisce il pezzo di cui sopra con:

if(tbf->tokens > 0) {
  tbf->tokens -= bytes;
} else {
  return -1;
}

La semantica sarà leggermente diversa, ma in media per un lungo periodo di tempo che dovrebbe arrivare a circa il tasso che si sta cercando. Naturalmente, se si invia 125K in un unico messaggio su un collegamento a 1 Gbps, difficilmente si può parlare di tasso di 900Kbps - sarà 1Gbps pieni burst di pacchetti, ed essi dovranno essere in coda da qualche parte nel caso in cui non ci sono collegamenti a bassa velocità - da qui essere disposti a perdere un po 'dei pacchetti in quel caso.

Ma, a seconda dell'applicazione in uso e il protocollo di rete di trasporto che si sta utilizzando (TCP / UDP / SCTP / ...?) Si potrebbe desiderare di spostare il codice sagomatura in fondo alla pila - perché i pacchetti sulla rete di solito sono solo massimo 1500 byte comunque (che include varie intestazioni di protocollo di rete / trasporto)

Una cosa che potrebbe essere interessante per il test è http://www.linuxfoundation.org/ it / Net: Netem - se il vostro obiettivo sta cercando di affrontare i collegamenti di capacità minore. Oppure, prendere un paio di router più anziani con le porte seriali 1Mbps collegati back to back.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top