作者:looloSam | 来源:互联网 | 2023-09-17 13:30
一、简介基于Zookeeper、Netty和Spring写了一个轻量级的分布式RPC框架。RPC,即RemoteProcedureCall(远程过程调用),调用远程计算机上的服务,
一、简介
基于Zookeeper、Netty和Spring写了一个轻量级的分布式RPC框架。
RPC,即 Remote Procedure Call(远程过程调用),调用远程计算机上的服务,就像调用本地服务一样。RPC可以很好的解耦系统,如WebService就是一种基于Http协议的RPC。
使用的一些技术所解决的问题:
服务发布与订阅:服务端使用Zookeeper注册服务地址,客户端从Zookeeper获取可用的服务地址。
通信:使用Netty作为通信框架。
Spring:使用Spring配置服务,加载Bean,扫描注解。
动态代理:客户端使用代理模式透明化服务调用。
消息编解码:使用Protostuff序列化和反序列化消息。
整体项目结构:
二、编写服务接口
一般会把该接口放在独立的项目中,打包的时候生成独立的jar 包,以供调用者使用。
三、编写服务接口的实现类
使用RpcService注解定义在服务接口的实现类上,需要对该实现类指定远程接口,因为实现类可能会实现多个接口,一定要告诉框架哪个才是远程接口。
该注解具备 Spring 的Component注解的特性,可被 Spring 扫描。
该实现类放在服务端的项目中,打包的时候独立生成 jar 包,该jar包还提供了一些服务端的配置文件与启动服务的引导程序。
RpcService代码如下:
四、实现RPC 服务器
使用 Netty 可实现一个支持 NIO 的 RPC 服务器,需要使用ServiceRegistry注册服务地址,RpcServer代码如下:
使用RpcRequest封装 RPC 请求,代码如下:
使用RpcResponse封装 RPC 响应,代码如下:
使用RpcDecoder提供 RPC 解码,只需扩展 Netty 的ByteToMessageDecoder抽象类的decode方法即可,代码如下:
使用RpcEncoder提供 RPC 编码,只需扩展 Netty 的MessageToByteEncoder抽象类的encode方法即可,代码如下:
编写一个SerializationUtil工具类,使用Protostuff实现序列化:
使用 Objenesis 来实例化对象,它是比 Java 反射更加强大。
注意:如需要替换其它序列化框架,只需修改SerializationUtil即可。当然,更好的实现方式是提供配置项来决定使用哪种序列化方式。
使用RpcHandler中处理 RPC 请求,只需扩展 Netty 的SimpleChannelInboundHandler抽象类即可,代码如下:
为了避免使用 Java 反射带来的性能问题,我们可以使用 CGLib 提供的反射 API,如上面用到的FastClass与FastMethod。
五、实现服务注册
其中,通过Constant配置了所有的常量:
config.properties:
# ZooKeeper 服务器
registry.address=127.0.0.1:2181
# RPC 服务器
server.address=127.0.0.1:8000
服务端 Spring 配置文件名为spring.xml,内容如下:
六、启动服务器并发布服务
为了加载 Spring 配置文件来发布服务,只需编写一个引导程序即可:
运行RpcBootstrap类的main方法即可启动服务端。
七、实现服务发现
同样使用 ZooKeeper 实现服务发现功能,见如下代码:
八、实现 RPC 代理
这里使用 Java 提供的动态代理技术实现 RPC 代理(当然也可以使用 CGLib 来实现),具体代码如下:
使用RpcClient类实现 RPC 客户端,只需扩展 Netty 提供的SimpleChannelInboundHandler抽象类即可,代码如下:
九、最后发送 RPC 请求
十、总结
通过 Spring + Netty + Protostuff + ZooKeeper 实现了一个轻量级 RPC 框架,使用 Spring 提供依赖注入与参数配置,使用 Netty 实现 NIO 方式的数据传输,使用 Protostuff 实现对象序列化,使用 ZooKeeper 实现服务注册与发现。使用该框架,可将服务部署到分布式环境中的任意节点上,客户端通过远程接口来调用服务端的具体实现,让服务端与客户端的开发完全分离,为实现大规模分布式应用提供了基础支持。
参考:http://www.importnew.com/24689.html