文档章节

dubbo中的那些“坑”(1) - 关于MINA传输协议的bug定位及修复

阿阮
 阿阮
发布于 2014/12/02 21:04
字数 573
阅读 13539
收藏 5

同事刘阳使用dubbo服务器中配置mina作为网络传输层,发现大并发情况下,解码发生如下异常

014-12-01 18:00:44,652 [DubboServerHandler-10.1.19.13:20880-thread-164] WARN  alibaba.dubbo.remoting.exchange.codec.ExchangeCodec (ExchangeCodec.java:596) -  [DUBBO] Fail to encode response: Response [id=8119, version=2.0.0, status=40, event=false, error=Fail to decode request due to: RpcInvocation [methodName=null, parameterTypes=null, arguments=null, attachments={input=242}, headers=null], result=null], send bad_response info instead, cause: null, dubbo version: 2.5.5, current host: 127.0.0.1
java.lang.NullPointerException
    at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec.encodeResponseData(DubboCodec.java:301)
    at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.encodeResponse(ExchangeCodec.java:560)
    at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.encode(ExchangeCodec.java:104)
    at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCountCodec.encode(DubboCountCodec.java:39)
    at com.alibaba.dubbo.remoting.transport.mina.MinaCodecAdapter$InternalEncoder.encode(MinaCodecAdapter.java:79)
    at org.apache.mina.filter.codec.ProtocolCodecFilter.filterWrite(ProtocolCodecFilter.java:214)
    at org.apache.mina.common.support.AbstractIoFilterChain.callPreviousFilterWrite(AbstractIoFilterChain.java:361)
    at org.apache.mina.common.support.AbstractIoFilterChain.access$1300(AbstractIoFilterChain.java:53)
    at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.filterWrite(AbstractIoFilterChain.java:659)
    at org.apache.mina.common.support.AbstractIoFilterChain$TailFilter.filterWrite(AbstractIoFilterChain.java:587)
    at org.apache.mina.common.support.AbstractIoFilterChain.callPreviousFilterWrite(AbstractIoFilterChain.java:361)
    at org.apache.mina.common.support.AbstractIoFilterChain.fireFilterWrite(AbstractIoFilterChain.java:355)
    at org.apache.mina.transport.socket.nio.SocketSessionImpl.write0(SocketSessionImpl.java:166)
    at org.apache.mina.common.support.BaseIoSession.write(BaseIoSession.java:177)
    at org.apache.mina.common.support.BaseIoSession.write(BaseIoSession.java:168)
    at com.alibaba.dubbo.remoting.transport.mina.MinaChannel.send(MinaChannel.java:95)
    at com.alibaba.dubbo.remoting.transport.AbstractPeer.send(AbstractPeer.java:51)
    at

经过对比netty3和netty4作为传输层,却都没有发现类似的问题。

首先排除不是mina本身的问题,mina也没有爆出有这个问题,初步判断dubbo在使用mina时机制有问题

经过对比发现

1.netty是为每一个channel分配了一个NettyCodecAdapter, mina确实在服务器监听前配置了MinaCodecAdapter

2.也就是说,netty的每一个独立的通道的Codec(encoder/decoder)是通道安全的

3.mina的所有通道是共享相同的codec(encoder/decoder)的,因此,解码器中的实例数据时非channel安全的

因此解码器中与netty相同的解码器的缓冲数据算法在并发情况下将会产生数据覆盖问题。

4.解决方案

        1.配置acceptor的监听器

codecAdapter = new MinaCodecAdapter(getCodec(), getUrl(), this);
        acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(codecAdapter));

    acceptor.addListener(new IoServiceListener(){
            @Override
            public void serviceActivated(IoService service,
                    SocketAddress serviceAddress, IoHandler handler,
                    IoServiceConfig config) {
            }

            @Override
            public void serviceDeactivated(IoService service,
                    SocketAddress serviceAddress, IoHandler handler,
                    IoServiceConfig config) {
            }

            @Override
            public void sessionCreated(IoSession session) {
                codecAdapter.sessionCreated(session);
            }

            @Override
            public void sessionDestroyed(IoSession session) {
                codecAdapter.sessionDestroyed(session);
            }
        });

    2.监听session的create和destroy事件,传递到decoder中,decoder中,通过session和buffer的键值对保存对不同通道的数据的缓存,

private Map<IoSession, ChannelBuffer> buffers = new ConcurrentHashMap<IoSession, ChannelBuffer>();

        // ChannelBuffers.EMPTY_BUFFER;

        public void sessionCreated(IoSession session) {
            buffers.put(session, ChannelBuffers.EMPTY_BUFFER);
        }

        public void sessionDestroyed(IoSession session) {
            buffers.remove(session);
        }

    3.解码时通过session获得当前channel的数据

ChannelBuffer buffer = buffers.get(session);
            if(buffer == null) return;


经过测试,问题得以解决




© 著作权归作者所有

阿阮
粉丝 36
博文 11
码字总数 3987
作品 0
海淀
架构师
私信 提问
Dubbo底层采用Socket进行通信详解(转)

由于Dubbo底层采用Socket进行通信,自己对通信理理论也不是很清楚,所以顺便把通信的知识也学习一下。 n 通信理论 计算机与外界的信息交换称为通信。基本的通信方法有并行通信和串行通信两种...

鈈哓锝
2018/01/11
42
0
dubbo典型协议、传输组件、序列化方式组合性能对比测试

前言 Dubbo作为一个扩展能力极强的分布式服务框架,在实现rpc特性的时候,给传输协议、传输框架和序列化方式提供了多种扩展实现,供开发者根据实际场景进行选择。 1、支持常见的传输协议:R...

杨武兵
2016/06/13
3.6K
6
Dubbo面试20问!这些题你都遇到过吗?

作者:Dean Wang https://deanwang1943.github.io/bugs/2018/10/05/面试/饿了么/dubbo 面试题/ 1、dubbo是什么 dubbo是一个分布式框架,远程服务调用的分布式框架,其核心部分包含: 集群容错...

安小乐
06/10
67
0
dubbo 面试18问 JAVA葵花宝典 今天

dubbo 面试18问 dubbo是什么 dubbo是一个分布式框架,远程服务调用的分布式框架,其核心部分包含: 集群容错:提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容...

DemonsI
02/28
46
0
dubbo剖析:七 网络通信总结

注:文章中使用的dubbo源码版本为2.5.4 零、文章目录 Dubbo的网络分层抽象 Dubbo如何保证Client端与Server端的连通性 Dubbo的请求响应模式,如何将异步IO变为同步RPC Dubbo线程模型总结 一、...

益文的圈
2018/05/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

springboot2.0 maven打包分离lib,resources

springboot将工程打包成jar包后,会出现获取classpath下的文件出现测试环境正常而生产环境文件找不到的问题,这是因为 1、在调试过程中,文件是真实存在于磁盘的某个目录。此时通过获取文件路...

陈俊凯
今天
6
0
BootStrap

一、BootStrap 简洁、直观、强悍的前端开发框架,让web开发更加迅速、简单 中文镜像网站:http://www.bootcss.com 用于开发响应式布局、移动设备优先的WEB项目 1、使用boot 创建文件夹,在文...

wytao1995
今天
10
0
小知识:讲述Linux命令别名与资源文件的区别

别名 别名是命令的快捷方式。为那些需要经常执行,但需要很长时间输入的长命令创建快捷方式很有用。语法是: alias ppp='ping www.baidu.com' 它们并不总是用来缩短长命令。重要的是,你将它...

老孟的Linux私房菜
今天
8
0
《JAVA核心知识》学习笔记(6. Spring 原理)-5

它是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是 Spring 仍然可以和其他的框架无缝整合。 6.1.1. Spring 特点 6.1.1.1. 轻量级 6.1.1.2. 控制反转 6.1.1....

Shingfi
今天
8
0
Excel导入数据库数据+Excel导入网页数据【实时追踪】

1.Excel导入数据库数据:数据选项卡------>导入数据 2.Excel导入网页数据【实时追踪】:

东方墨天
今天
11
1

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部