在 java (IRC) 中避免速率限制(节流)
Avoiding rate-limiting (throttling) in java (IRC)
所以我一直在写一个基于 java 的 irc-bot,它相当简单。与服务器建立套接字连接,将缓冲的读取器/写入器附加到套接字,然后使用这些缓冲区进行读取/写入。
我没有 运行 遇到过问题,除了当我打印出一个 json 对象并因过度泛滥而被踢出网络时。我不确定网络的消息速率限制,但我确实通过相同的简单函数传递我的所有消息。
我希望为其添加某种 x 字节/时间范围限制。有人建议我研究一下 NIO,但这似乎有点过度设计了这个问题。
这是我当前的写入 irc 通道的方法:
public static void writeMsg(BufferedWriter writer, String Channel, String Message) {
try {
System.out.println("Bot Command: PRIVMSG " + Channel + Message); //diagnostic
writer.write("PRIVMSG " + Channel + Message);
writer.flush();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
可能传入/传出该函数的示例:
输入:
writer (my BufferedWriter object), "#Testing1234: ", "!wiki China";
输出:
PRIVMSG #BeginnersProgramming :http://en.wikipedia.org/wiki/China
我会在你的方法开始时随机休眠。这样,您就可以模拟人类打字。
非线程安全版本
private static SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
public static void writeMsg(BufferedWriter writer, String Channel, String Message){
try {
// Sleep randomly between 2 (inclusive) and 5 (exclusive) seconds.
int duration = 2000 + sr.nextInt(3000);
System.out.println("Pausing execution for " + duration + " ms...");
TimeUnit.MILLISECONDS.sleep(duration);
System.out.println("Bot Command: PRIVMSG " + Channel + Message); //diagnostic
writer.write("PRIVMSG " + Channel + Message);
writer.flush();
} catch(IOException ioe){
ioe.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
线程安全版本
如果您的方法将被多个线程调用,请考虑此代码使用锁。锁在发送消息时增加了一些随机性。
private static final Lock writeLock = new ReentrantLock();
private static SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
public static void writeMsg(BufferedWriter writer, String Channel, String Message){
writeLock.lock();
try {
// Sleep randomly between 2 (inclusive) and 5 (exclusive) seconds.
int duration = 2000 + sr.nextInt(3000);
System.out.println("Pausing execution for " + duration + " ms...");
TimeUnit.MILLISECONDS.sleep(duration);
System.out.println("Bot Command: PRIVMSG " + Channel + Message); //diagnostic
writer.write("PRIVMSG " + Channel + Message);
writer.flush();
} catch(IOException ioe){
ioe.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
writeLock.unlock();
}
}
I'm hoping to add some kind of x bytes / timeframe limit to it
最简单的方法是
final int rateLimit = 50; // Bytes per second
final float msPerByte = 1000.0f / rateLimit;
writer.write(message);
int numBytes = message.length();
Thread.sleep((int)(msPerByte * numBytes + 1));
但是,根据消息的长度,一条消息的单次突发可能已经触发了服务器的速率限制。在这种情况下,您必须将消息拆分为更小的部分,并在适当的延迟之间一个接一个地发送。
如果仅在每个时间段的消息基础上实施速率限制,您需要做的就是sleep()
每条消息后的固定时间。
我相信有更复杂的算法在起作用,其中可能包括更多基于时间的参数来决定。
所以我一直在写一个基于 java 的 irc-bot,它相当简单。与服务器建立套接字连接,将缓冲的读取器/写入器附加到套接字,然后使用这些缓冲区进行读取/写入。
我没有 运行 遇到过问题,除了当我打印出一个 json 对象并因过度泛滥而被踢出网络时。我不确定网络的消息速率限制,但我确实通过相同的简单函数传递我的所有消息。
我希望为其添加某种 x 字节/时间范围限制。有人建议我研究一下 NIO,但这似乎有点过度设计了这个问题。
这是我当前的写入 irc 通道的方法:
public static void writeMsg(BufferedWriter writer, String Channel, String Message) {
try {
System.out.println("Bot Command: PRIVMSG " + Channel + Message); //diagnostic
writer.write("PRIVMSG " + Channel + Message);
writer.flush();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
可能传入/传出该函数的示例:
输入:
writer (my BufferedWriter object), "#Testing1234: ", "!wiki China";
输出:
PRIVMSG #BeginnersProgramming :http://en.wikipedia.org/wiki/China
我会在你的方法开始时随机休眠。这样,您就可以模拟人类打字。
非线程安全版本
private static SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
public static void writeMsg(BufferedWriter writer, String Channel, String Message){
try {
// Sleep randomly between 2 (inclusive) and 5 (exclusive) seconds.
int duration = 2000 + sr.nextInt(3000);
System.out.println("Pausing execution for " + duration + " ms...");
TimeUnit.MILLISECONDS.sleep(duration);
System.out.println("Bot Command: PRIVMSG " + Channel + Message); //diagnostic
writer.write("PRIVMSG " + Channel + Message);
writer.flush();
} catch(IOException ioe){
ioe.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
线程安全版本
如果您的方法将被多个线程调用,请考虑此代码使用锁。锁在发送消息时增加了一些随机性。
private static final Lock writeLock = new ReentrantLock();
private static SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
public static void writeMsg(BufferedWriter writer, String Channel, String Message){
writeLock.lock();
try {
// Sleep randomly between 2 (inclusive) and 5 (exclusive) seconds.
int duration = 2000 + sr.nextInt(3000);
System.out.println("Pausing execution for " + duration + " ms...");
TimeUnit.MILLISECONDS.sleep(duration);
System.out.println("Bot Command: PRIVMSG " + Channel + Message); //diagnostic
writer.write("PRIVMSG " + Channel + Message);
writer.flush();
} catch(IOException ioe){
ioe.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
writeLock.unlock();
}
}
I'm hoping to add some kind of x bytes / timeframe limit to it
最简单的方法是
final int rateLimit = 50; // Bytes per second
final float msPerByte = 1000.0f / rateLimit;
writer.write(message);
int numBytes = message.length();
Thread.sleep((int)(msPerByte * numBytes + 1));
但是,根据消息的长度,一条消息的单次突发可能已经触发了服务器的速率限制。在这种情况下,您必须将消息拆分为更小的部分,并在适当的延迟之间一个接一个地发送。
如果仅在每个时间段的消息基础上实施速率限制,您需要做的就是sleep()
每条消息后的固定时间。
我相信有更复杂的算法在起作用,其中可能包括更多基于时间的参数来决定。