百度空间 | 百度首页 
               
 
查看文章
 
MINA ProtocolDecoder doDecode 调错
2008-10-21 18:52
Mina是一种Java中使用广泛的网络框架,Mina写一个Hello world可能5分钟就可以了(参看 Mina测试程序)。 其中最复杂的部分可能就是Decode解码。其作用是将网络的二进制数据流转换成业务逻辑的对象。我前面那个例子为了简化目的,codec用的是Mina中现成的 TextLineDecoder,有些朋友一字不改拿去之后说程序有问题。没错,肯定有问题,因为TextLineDecoder每次读一行, 如果服务器一直不给换行就一直等在那了。那怎么改啊,自己想去吧。

doDecode的返回参数是不太直观的,这两天碰到问题了。我们有个服务器之间通讯的程序,压力测试时候反应很慢,现象有:
  • size<1k的包每秒才传几百个左右。但是把包的大小改成8k又能发七八千个。
  • 直接在 doDecoder最前面打印,每秒也只有1-200个。
  • 怀疑是 send/recv buffer不够大,设成16-64M,没有明显改善。
  • tcpdump 查看网络流量,因为信息量太大,也无法得到精确的数字,只是初略>判断包都投递到目标,不是发送方的问题。
    /**
     * Implement this method to consume the specified cumulative buffer and
     * decode its content into message(s).
     *
     * @param in the cumulative buffer
     * @return true if and only if there's more to decode in the buffer
     *         and you want to have doDecode method invoked again.
     *         Return false if remaining data is not enough to decode,
     *         then this method will be invoked again when more data is cumulated.
     * @throws Exception if cannot decode in.
     */
    protected abstract boolean doDecode(IoSession session, ByteBuffer in,
            ProtocolDecoderOutput out) throws Exception;

按上面的意思我是这样实现的,核心片断:
int pos = in.position();
try {
    Object obj = in.getObject();
    out.write(obj);
    return !in.hasRemaining();
} catch (Exception e) {
    in.position(pos);
    return false;
}
问题就在 return !in.hasRemaining(); 上面。这里是应该返回true的。
  • 如果你能够解析一次,那就需要返回 true; position 移到解析了的这个末尾
  • 如果1个不够解析,position移到最初的位置,返回false
  • 解析了一个,后面还有内容,可能是半个,也返回 true
Mina的结构可以参看这里 Openfire (Wildfire) 的最新特性, 基于 Mina 的 Connection Manager

如果你对 ProtocolDecoder 感兴趣,我建议新手去看 ObjectSerializationDecoder / ObjectSerializationEncoder 的代码,特别简洁。不要看 TextLineDecoder, 无关细节太多。

类别:高性能服务器 | 添加到搜藏 | 浏览() | 评论 (1)
 
最近读者:
 
网友评论:
1
2008-10-24 11:06 | 回复
这里应该反一下的吧, in 里面还有数据的时候应该要返回 true 让他再次调用 doDecode 方法才对的啊。in 没有足够的数据解码,需要等待 buffer 填充新数据才需要返回 false 的啊。
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu