第一部分,设计分析
远程调用要解决的主要问题:
1,序列化 : 如何将对象转化为二进制数据进行传输,如何将二进制数据转化对象
2,数据的传输(协议,第三方框架)
3,服务的注册/发现,单点故障,分布式服务
4,服务的监控和管理
序列化的选择:
可以使用java自带的序列化,Hessian,protobuff,json,xml等
性能比较高的是protobuff和hessian,protobuff使用的时候需要编写proto文件,有侵入性,比较麻烦,而Hessian
性能比protobuff稍差
不过近来出现了一个基于protobuff的框架:protostuff--不用编写proto文件,基于注解,性能可以,推荐使用。
数据的传输:
出于并发性能的考虑,传统的阻塞式 IO 显然不太合适,因此我们需要异步的 IO,即 NIO。Java 提供了 NIO 的解决方案,Java 7 也提供了更优秀的 NIO.2 支持。可以选择Netty或者mina来解决NIO数据传输的问题
使用ZooKeeper提供服务注册与发现功能,解决单点故障以及分布式部署的问题(注册中心)
需要单独开发一个应用对服务进行监控和管理。
详细的细节可以参看dubbo的文档。
第二部分,设计样例:
一,包设计。
![](https://images2017.cnblogs.com/blog/388326/201709/388326-20170907092258554-588341276.png)
1,common包用于封装服务请求对象,服务响应对象以及基于protostuff的序列化工具
2,client包封装服务的请求,开发服务消费者的时候需要依赖此包
3,registry包封装服务的注册以及发现
4,server包封装请求的实际调用以及服务的发布
client和server均依赖common,registry
二,类设计
1,common包:
![](https://images2017.cnblogs.com/blog/388326/201709/388326-20170907092248835-1497379045.png)
RpcRequest与RpcResponse为简单javaBean,封装RPC调用的请求和响应
SerializationUtil使用protostuff进行对象序列化操作,
RpcDecoder与RpcEncoder使用SerializationUtil和netty执行数据流的读取和写入(NIO传输)。
2,registry包
![](https://images2017.cnblogs.com/blog/388326/201709/388326-20170907092238304-1409027866.png)
ServiceDiscovery负责服务的查找,返回
host:port
格式的服务提供地址数据
ServiceRegistry负责服务的注册,以
host:port
的格式将服务的提供地址写入到zookeeper
3,client包
![](https://images2017.cnblogs.com/blog/388326/201709/388326-20170907092228085-755711378.png)
RpcClient通过netty的NIO发起RPC请求并获取服务的响应数据
RpcProxy负责:
封装RPC请求对象
从服务注册中心查找服务
代理RpcClient发起请求(使用java动态代理)
4,server包
![](https://images2017.cnblogs.com/blog/388326/201709/388326-20170907092219054-1893438189.png)
RpcHandler实现io.netty.channel.SimpleChannelInboundHandler
完成Rpc请求的实际调用,通过反射调用方法(java reflect或者cglib)
RpcServer实现ApplicationContextAware, InitializingBean
通过读取classpath中的spring-context文件依赖ServiceRegistry执行服务的注册,当客户端请求的时候
依赖RpcHandler完成调用。
第三部分,rpc服务的开发流程
1,分离接口与实现,api接口包为服务端和客户端都必须依赖的接口,常量,javabean
2,服务端provider编写实现类实现api包中的接口,依赖rpc-server包,classpath中放置spring配置文件,用于服务的注册
3,客户端consumer依赖rpc-client包,使用RpcProxy 创建接口实例执行调用