Akka的RoundRobinRouting
实现存在bug,当累计执行超过Long最大值之后(变为负数),会导致分散不均,最后一个节点永远分配不上,直到累计值再次变为正数才恢复均匀。代码如下(2.4.9版本):
final class RoundRobinRoutingLogic extends RoutingLogic {
val next = new AtomicLong
override def select(message: Any, routees: immutable.IndexedSeq[Routee]): Routee =
if (routees.nonEmpty) {
val size = routees.size
val index = (next.getAndIncrement % size).asInstanceOf[Int]
routees(if (index < 0) size + index - 1 else index)
} else NoRoutee
}
上面select
函数里当index
为负数时,返回size + index - 1
存在问题,用一段java代码验证一下:
import java.util.concurrent.atomic.AtomicLong;
public class Test {
static final AtomicLong next = new AtomicLong(-2003);
static final int size = 4;
static int getNext() {
int index = (int) (next.getAndIncrement() % size);
if (index < 0)
return size + index - 1;
else
return index;
}
public static void main(String[] args) {
for (int n = 0; n < 8; n++) {
System.out.println(getNext());
}
}
}
// 运行后输出:
0
1
2
0
0
1
2
0
上面的代码假设有4个节点,当next
为负数后,一直在"0,1,2"这三个节点上分配,不会分配给最后一个节点(即索引为3的),修正的方式是当index
为负数后,返回其绝对值(即 -index)即可。