dubbo相关

画的图不错,http://study.163.com/course/introduction/1003828012.htm

Dubbo缺省协议采用单一长连接和NIO异步通讯。当然客户端可配置对每个提供者建立长连接数(默认配置0,即共享一个长连接,详情查询DubboProtocol.java),另外在Transporters.java中可看到建立连接通过Netty、Mina、Grizzly。

单一长连接:其实就是只有一个长连接做所有操作。那么如何处理发送端client多线程并发请求呢?其实每个线程将请求方法、参数、唯一ID等封装一个object,然后放到ConcurentHashMap中,将object放到request对象通过单一连接发送到服务端后,加锁wait,即done.await(timeout, TimeUnit.MILLISECONDS)。一个连接数可以支持70Mbype的网络流量。

协议:缺省协议,使用基于netty3.2.2+hessian3.2.1交互

java扩展实现:跟SPI机制很像,比如扩展Filter等。实现原理比如接口AService,有默认实现DefaultAService,要想实现自定义,可先写个MyAService,在META-INF下放一个com.alibaba.dubbo.xxx.A命名的文件,文件内容为xxxAService=com.xxx.MyAService即可。然后实例获取实现类可以简单理解为读取配置指定的class即可。

Container实现:使用了@SPI阿里自定义注解,其子类SpringContainer是含有ClassPathXmlApplicationContext的ioc容器,通过ExtensionLoader来生成对象。其中有JettyContainer、Log4jContainer。

源码:

dubbo底层嵌套使用了jetty,用于汇报状态。

dubbo-common 公共逻辑模块,包括Util类和通用模型。

dubbo-remoting 远程通讯模块,相当于Dubbo协议的实现,如果RPC用RMI协议则不需要使用此包。

dubbo-rpc 远程调用模块,抽象各种协议,以及动态代理,只包含一对一的调用,不关心集群的管理。

dubbo-cluster 集群模块,将多个服务提供方伪装为一个提供方,包括:负载均衡, 容错,路由等,集群的地址列表可以是静态配置的,也可以是由注册中心下发。

dubbo-registry 注册中心模块,基于注册中心下发地址的集群方式,以及对各种注册中心的抽象。

dubbo-monitor 监控模块,统计服务调用次数,调用时间的,调用链跟踪的服务。

dubbo-config 配置模块,是Dubbo对外的API,用户通过Config使用Dubbo,隐藏Dubbo所有细节。

dubbo-container 容器模块,是一个Standlone的容器,以简单的Main加载Spring启动,因为服务通常不需要Tomcat/JBoss等Web容器的特性,没必要用Web容器去加载服务

关系说明:

Protocol:在RPC中,Protocol是核心层,也就是只要有Protocol + Invoker + Exporter就可以完成非透明的RPC调用,然后在Invoker的主过程上Filter拦截点。Protocol是远程服务协议接口,具体实现有多个,比如DubboPrptpcpl、HttpProtocol等,其中Dubbo和RMI协议基于TCP实现,Hessian和WebService基于HTTP实现。

remoting-http中:remoting-netty同理,有一个Map<Integer, HttpHandler>,端口号对应处理器,HttpHandler有三种(HessianProtocol、WebServiceProtocol、HttpProtocol)。Remoting实现是Dubbo协议的实现,如果你选择RMI协议,整个Remoting都不会用上,Remoting内部再划为Transport传输层和Exchange信息交换层,Transport层只负责单向消息传输,是对Mina,Netty,Grizzly的抽象,它也可以扩展UDP传输,而Exchange层是在传输层之上封装了Request-Response语义。

Cluster:外围概念,所以Cluster的目的是将多个Invoker伪装成一个Invoker,这样其它人只要关注Protocol层Invoker即可,加上Cluster或者去掉Cluster对其它层都不会造成影响,因为只有一个提供者时,是不需要Cluster的。

Proxy层:封装了所有接口的透明化代理,而在其它层都以Invoker为中心,只有到了暴露给用户使用时,才用Proxy将Invoker转成接口,或将接口实现转成Invoker,也就是去掉Proxy层RPC是可以Run的,只是不那么透明,不那么看起来像调本地服务一样调远程服务。Javassist和jdk动态代理:JavassistProxyFactory、JdkProxyFactory两个类很简单。生成服务的客户端Stub和服务器端Skeleton。

模型:

Protocol是服务域,它是Invoker暴露和引用的主功能入口,它负责Invoker的生命周期管理

Invoker是实体域,它是Dubbo的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起invoke调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现

Invocation是会话域,它持有调用过程中的变量,比如方法名,参数等

另外:

dubbo处理TCP拆包粘包问题:由于TCP包的缓存大小限制,每次请求数据有可能不在一个TCP包里面,或者也可能多个请求的数据在一个TCP包里面。NettyCodecAdapter是对dubbo协议解析的入口,里面包含decoder和encoder两部分,而TCP的拆包和粘包主要是decoder部分。在NettyCodecAdapter中的decoder是由InternalDecoder来实现,它的父类是Netty的SimpleChannelUpstreamHandler可以接受所有inbound消息,那么就可以对接受的消息进行decode。这里需要说明一下对于某一个Channel都有一个私有的InternalDecoder对象,并不是和其他的

Channel共享,这里就避免了并发问题。

粘包拆包问题解决:http://blog.csdn.net/scythe666/article/details/51996268

1、发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。

2、发送端将每个数据包封装为固定长度(不够的可以通过补0填充),这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。

3、可以在数据包之间设置边界,如添加特殊符号,这样,接收端通过这个边界就可以将不同的数据包拆分开。

题外话:dubbo.jar包

迁移数据工具kettle:

猜你喜欢

转载自1181731633.iteye.com/blog/2398052