如何编写 Netty 的集成测试?

2018 年 12 月 6 日
 zjp

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 的连接

2607 次点击
所在节点    Java
7 条回复
zjp
2018 年 12 月 6 日
mm163
2018 年 12 月 6 日
ConcurrentSet 虽然时线程安全的,但是
if (connected.contains(remoteIp)) {
return false;
} else {
connected.add(remoteIp);
这几行没有原子化,有可能造成同一个 IP 的两个请求同时 false。
BBCCBB
2018 年 12 月 6 日
netty 一般是用 EmbeddedChannel 做测试, 你这个不知道用哪个
zjp
2018 年 12 月 6 日
@BBCCBB EmbeddedChannel 只表征一条通道,这里需要一个服务器下的两个连接

@mm163 是的,但是测试代码 我就只会不断同时建立两个连接,过一段时间看两个是不是都没有被 UniqueIpFilter 掐掉连接...这样测试可能永远结束不了......
q263397478
2018 年 12 月 7 日
不是,accept 处理是单线程的啊,不用担心线程安全问题
zjp
2018 年 12 月 7 日
@BBCCBB 重新看了下 EmbeddedChannel,确实可以用


@q263397478 UniqueIpFilter 是在 Channel 中共享的
BBCCBB
2018 年 12 月 7 日
我猜开多线程用多个 EmbeddedChannel 就可以, 只是这个 uniqueIpFilter 得用同一个

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://study.congcong.us/t/515154

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX