我试图限制我的应用程序发送速率900kbps,但问题是,我使用的协议是面向消息和消息具有非常不同的尺寸。我可以具有从40个字节消息一路高达125000个字节,并且所有消息都被发送以原子单位。

我想实现一个令牌桶缓冲区,但如果我设置一个较低的桶大小的大包永远不会发送和更大的铲斗将导致爆出大,没有限速的。

这是我的用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;
}

然后某处在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);
}
有帮助吗?

解决方案

您是限制由max_burst最大邮件大小(被分配到tbf->在开始时能力) - 因为>令牌从来没有tbf-递增超过该值,更大的消息将不会被发送,由于这个检查:

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

因此,该代码确实设置猝发的硬性限制被max_burst - 所以你如果希望此突发大小应分段邮件

假设这是在代码中唯一的地方,你可以插入限幅器,你可以,如果你将其替换上面这段获得更好的结果:

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

在语义会略有不同,但平均在一段长时间它应该让你约你正在寻找的速度。当然,如果你在一个消息在1Gbps的链路上发送125K,人们很难谈论900kbps速率 - 这将是全1Gbps的突发的数据,他们将需要有较低的高速链路的情况下,地方排队 - 因此准备丢失一些分组在这种情况下。

不过,这取决于你的应用程序和您正在使用(TCP / UDP / SCTP / ...?),你可能要移动的整形代码在堆栈中向下传输网络协议 - 因为网络上的数据包通常只最大1500个字节反正(包括各种网络/传输协议报头)

这可能是测试有趣的一件事是 http://www.linuxfoundation.org/ EN /网:Netem - 如果你的目标是设法解决这个容量较小的链接。或者,抓住一对夫妇旧的路由器与连接背对背1Mbps的串行端口。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top