سؤال

أنا في محاولة للحد من بلدي التطبيق إرسال معدل 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;
}

الدلالي سوف تكون مختلفة قليلا ، ولكن في المتوسط على مدى فترة طويلة من الوقت يجب أن تحصل على ما يقرب من معدل كنت تبحث عن.بالطبع, إذا كنت ترسل 125K في رسالة واحدة على 1gbps الرابط, بالكاد يمكن للمرء الحديث عن 900kbps معدل - سوف تكون كاملة 1gbps انفجر من الحزم ، وأنها سوف تحتاج إلى أن تكون في قائمة الانتظار في مكان ما في حالة وجود أقل-السرعة الروابط - ومن ثم تكون على استعداد لتفقد بعض من الحزم في هذه الحالة.

ولكن اعتمادا على التطبيق الخاص بك وشبكة النقل البروتوكول الذي تستخدمه (TCP/UDP/SCTP/...?) قد ترغب في نقل تشكيل الرمز أسفل المكدس - لأن الحزم على الشبكة عادة فقط كحد أقصى 1500 بايت على أي حال (التي تشمل مختلف شبكة/بروتوكول نقل رؤوس)

شيء واحد التي قد تكون مثيرة للاهتمام بالنسبة الاختبار http://www.linuxfoundation.org/en/Net:Netem - إذا الهدف الخاص بك هو محاولة لمعالجة أصغر سعة الروابط.أو الاستيلاء على اثنين من كبار السن من أجهزة التوجيه مع 1mbps المنافذ التسلسلية متصل العودة إلى الوراء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top