}
至此API 模块就定义完成了,非常简单的两个接口。接下来,我们要确定传输规则,也就是传输协议,协议内容当然要自定义,才能体现出Netty 的优势。
设计一个InvokerMessage类,里面包含了服务名称、调用方法、参数列表、参数值,这就是我们自定义协议的协议包:
@Data
public class InvokerMessage implements Serializable {
private String className; // 服务名称
private String methodName; // 调用哪个方法
private Class<?>[] params; // 参数列表
private Object[] values; // 参数值
}
通过定义这样的协议类,就能知道我们需要调用哪个服务,服务中的哪个方法,方法需要传递的参数列表(参数类型+参数值),这些信息正确传递过去了才能拿到正确的调用返回值。
接下来创建这两个服务的具体实现类,IRpcHello的实现类如下:
public class RpcHelloProvider implements IRpcHello {
public String hello(String name) {
return "Hello, " + name + “!”;
}
}
IRpcCalc的实现类如下:
public class RpcCalcProvider implements IRpcCalc {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int sub(int a, int b) {
return a - b;
}
@Override
public int mul(int a, int b) {
return a * b;
}
@Override
public int div(int a, int b) {
return a / b;
}
}
Registry 注册中心主要功能就是负责将所有Provider的服务名称和服务引用地址注册到一个容器中(这里为了方便直接使用接口类名作为服务名称,前提是假定我们每个服务只有一个实现类),并对外发布。Registry 应该要启动一个对外的服务,很显然应该作为服务端,并提供一个对外可以访问的端口。先启动一个Netty服务,创建RpcRegistry 类,RpcRegistry.java的具体代码如下:
public class RpcRegistry {
private final int port;
public RpcRegistry(int port){
this.port = port;
}
public void start(){
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
NioEventLoopGroup workGroup = new NioEventLoopGroup();
try{
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer() {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
// 处理拆包、粘包的编解码器
pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
pipeline.addLast(new LengthFieldPrepender(4));
// 处理序列化的编解码器
pipeline.addLast(“encoder”, new ObjectEncoder());
pipeline.addLast(“decoder”, new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
// 自己的业务逻辑
pipeline.addLast(new MyRegistryHandler());
}
})
.option(ChannelO