Bir Token Kova'nın uygulanması oldukça basittir.
5 jetonlu bir kova ile başlayın.
Her 5/8 saniyede bir: Kepçede 5'ten az jeton varsa bir tane ekleyin.
Her mesaj göndermek istediğinizde: Grupta ≥1 jeton varsa, bir jeton alın ve mesajı gönderin. Aksi takdirde, mesajı bekleyin / bırakın.
(açıkçası, gerçek kodda, gerçek jetonlar yerine bir tamsayı sayacı kullanırsınız ve her 5 / 8s adımını zaman damgalarını kaydederek optimize edebilirsiniz)
Soruyu tekrar okumak, hız limiti her 8 saniyede bir tamamen sıfırlanırsa, işte bir değişiklik:
Bir zaman damgası ile başlayın, last_send
uzun zaman önce (örneğin, çağda). Ayrıca, aynı 5 jetonlu kova ile başlayın.
Her 5/8 saniyede bir kuralı vurun.
Her mesaj gönderdiğinizde: İlk olarak, last_send
≥ 8 saniye önce olup olmadığını kontrol edin . Öyleyse, kovayı doldurun (5 jetona ayarlayın). İkincisi, kovada jetonlar varsa, mesajı gönderin (aksi takdirde bırakın / bekleyin / vb.). Üçüncü olarak, last_send
şimdi ayarlayın .
Bu senaryo için işe yarayacak.
Aslında böyle bir stratejiyi kullanarak bir IRC bot yazdım (ilk yaklaşım). Perl'de, Python'da değil, ancak göstermek için bazı kodlar:
Buradaki ilk bölüm, kovaya jeton eklemeyi ele alır. Jeton ekleme optimizasyonunu zamana göre (2'den son satıra) ve son satırda kova içeriğini maksimuma (MESSAGE_BURST)
my $start_time = time;
...
# Bucket handling
my $bucket = $conn->{fujiko_limit_bucket};
my $lasttx = $conn->{fujiko_limit_lasttx};
$bucket += ($start_time-$lasttx)/MESSAGE_INTERVAL;
($bucket <= MESSAGE_BURST) or $bucket = MESSAGE_BURST;
$ conn aktarılan bir veri yapısıdır. Bu, rutin olarak çalışan bir yöntemin içindedir (bir dahaki sefere yapacak bir şey olduğunda ne zaman hesaplar ve bu kadar uzun süre veya ağ trafiği alana kadar uyur). Yöntemin bir sonraki bölümü gönderme işlemini gerçekleştirir. Oldukça karmaşıktır, çünkü mesajların kendileriyle ilişkili öncelikleri vardır.
# Queue handling. Start with the ultimate queue.
my $queues = $conn->{fujiko_queues};
foreach my $entry (@{$queues->[PRIORITY_ULTIMATE]}) {
# Ultimate is special. We run ultimate no matter what. Even if
# it sends the bucket negative.
--$bucket;
$entry->{code}(@{$entry->{args}});
}
$queues->[PRIORITY_ULTIMATE] = [];
Bu ne olursa olsun çalıştırılan ilk kuyruk. Sel bağlantımız yüzünden bağlantımız kesilse bile. Sunucunun PING'ine yanıt vermek gibi son derece önemli şeyler için kullanılır. Sonra, sıraların geri kalanı:
# Continue to the other queues, in order of priority.
QRUN: for (my $pri = PRIORITY_HIGH; $pri >= PRIORITY_JUNK; --$pri) {
my $queue = $queues->[$pri];
while (scalar(@$queue)) {
if ($bucket < 1) {
# continue later.
$need_more_time = 1;
last QRUN;
} else {
--$bucket;
my $entry = shift @$queue;
$entry->{code}(@{$entry->{args}});
}
}
}
Son olarak, grup durumu $ conn veri yapısına geri kaydedilir (aslında yöntemde biraz sonra; önce ne kadar süre daha fazla çalışma yapacağını hesaplar)
# Save status.
$conn->{fujiko_limit_bucket} = $bucket;
$conn->{fujiko_limit_lasttx} = $start_time;
Gördüğünüz gibi, gerçek kova işleme kodu çok küçük - yaklaşık dört satır. Kodun geri kalanı öncelik sırası işlemedir. Botun öncelik sıraları vardır, böylece onunla sohbet eden biri önemli vuruş / yasak görevlerini yapmasını engelleyemez.