Netty 里 UniqueIpFilter 的代码
public class UniqueIpFilter extends AbstractRemoteAddressFilter<InetSocketAddress> {
private final Set<InetAddress> connected = new ConcurrentSet<InetAddress>();
@Override
protected boolean accept(ChannelHandlerContext ctx, InetSocketAddress remoteAddress) throws Exception {
final InetAddress remoteIp = remoteAddress.getAddress();
if (connected.contains(remoteIp)) {
return false;
} else {
connected.add(remoteIp);
ctx.channel().closeFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
connected.remove(remoteIp);
}
});
return true;
}
}
}
逻辑很简单,就是每次连接建立时判断 set 里是否已经有新连接的远程地址。但多线程下同一个 IP 的两个请求在执行connected.contains(remoteIp)
时可能出现同时为false
的情况。似乎是个典型的 Test and Set 问题...
但我现在问题是不知道怎么写测试,搞了大半天了,官方也没有对这个类的测试...不管从客户端还是服务端入手,都找不到合适的时间点验证存在两个相同 IP 的连接
1
zjp OP |
2
mm163 2018-12-06 23:04:09 +08:00
ConcurrentSet 虽然时线程安全的,但是
if (connected.contains(remoteIp)) { return false; } else { connected.add(remoteIp); 这几行没有原子化,有可能造成同一个 IP 的两个请求同时 false。 |
3
BBCCBB 2018-12-06 23:07:16 +08:00 1
netty 一般是用 EmbeddedChannel 做测试, 你这个不知道用哪个
|
4
zjp OP |
5
q263397478 2018-12-07 10:37:45 +08:00
不是,accept 处理是单线程的啊,不用担心线程安全问题
|
6
zjp OP |
7
BBCCBB 2018-12-07 14:25:36 +08:00
我猜开多线程用多个 EmbeddedChannel 就可以, 只是这个 uniqueIpFilter 得用同一个
|