Pregunta

Estoy tratando de limitar mi solicitud tasa de 900Kbps a enviar pero el problema es que el protocolo que utilizo es orientado a mensajes y los mensajes tienen tamaños muy diferentes. Puedo tener mensajes de 40 bytes todo el camino hasta 125000 bytes y todos los mensajes son enviados como unidades atómicas.

He intentado implementar una memoria intermedia de cubetas de fichas, pero si me puse un bajo tamaño de cubo de los grandes paquetes nunca me mando y un cubo grande dará lugar a una gran explosión sin limitación de velocidad en absoluto.

Esta es mi pequeña aplicación en 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;
}

A continuación, en algún lugar de 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);
}
¿Fue útil?

Solución

Se está limitando su tamaño máximo de mensaje por max_burst (que se asigna a tbf-> capacidad en el comienzo) - ya que el tbf-> Fichas nunca se incrementa más allá de ese valor, los mensajes más grandes nunca conseguirá enviado debido a esta comprobación:

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

Por lo tanto, el código de hecho establezca un límite físico en la explosión que se max_burst -. Por lo que debe fragmentar sus mensajes si desea que este tamaño de ráfaga

Asumiendo que este es el único lugar en el código donde se puede insertar el limitador, es posible obtener un mejor resultado si se reemplaza la pieza anterior con:

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

La semántica será un poco diferente, pero en promedio durante un largo período de tiempo que se debe obtener aproximadamente la velocidad que busca. Por supuesto, si usted envía 125 K en un mensaje a través de un enlace de 1 Gbps, difícilmente se puede hablar de velocidad de 900Kbps - será de 1 Gbps completos ráfaga de paquetes, y que tendrá que ser puesto en cola en algún lugar en caso de que haya enlaces de baja velocidad - por lo tanto estar preparado para perder algunos de los paquetes en ese caso.

Sin embargo, dependiendo de su aplicación y el protocolo de red de transporte que está utilizando (TCP / UDP / SCTP / ...?) Es posible que desee mover el código de conformación abajo de la pila - porque los paquetes en la red normalmente sólo están máximo 1500 bytes de todos modos (que incluye varias cabeceras de protocolo de red / transporte)

Una cosa que podría ser interesante para las pruebas es http://www.linuxfoundation.org/ es / neto: NetEm - si su objetivo está tratando de hacer frente a los enlaces de menor capacidad. O bien, tomar un par de routers antiguos con puertos serie 1Mbps conectados espalda con espalda.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top