首页 > 其他分享 >用netty实现dubboRPC

用netty实现dubboRPC

时间:2023-03-27 16:47:57浏览次数:43  
标签:netty pipeline String 实现 request public dubboRPC new port

Dubbo是一种基于Java的高性能RPC框架,使用Netty作为底层网络通信库。下面是使用Netty实现Dubbo RPC的示例代码:

服务端代码:

public class DubboRpcServer {
    private final int port;

    public DubboRpcServer(int port) {
        this.port = port;
    }

    public void run() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 protected void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline pipeline = ch.pipeline();
                     pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4));
                     pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
                     pipeline.addLast("handler", new DubboRpcServerHandler());
                 }
             })
             .option(ChannelOption.SO_BACKLOG, 128)
             .childOption(ChannelOption.SO_KEEPALIVE, true);

            ChannelFuture f = b.bind(port).sync();

            System.out.println("DubboRpcServer started on port " + port);

            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        new DubboRpcServer(8080).run();
    }
}

在这个示例中,服务端使用Netty的LengthFieldBasedFrameDecoder和LengthFieldPrepender来处理消息的编码和解码。Dubbo协议使用Hessian来序列化Java对象,因此需要添加一个Hessian解码器和编码器来将ByteBuf转换为Java对象以及反向转换。

public class DubboRpcServerHandler extends SimpleChannelInboundHandler<Object> {
    private final Map<String, Object> services = new ConcurrentHashMap<>();

    public DubboRpcServerHandler() {
        services.put(DemoService.class.getName(), new DemoServiceImpl());
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof Request) {
            Request request = (Request) msg;
            String serviceName = request.getInterfaceName();
            Object service = services.get(serviceName);
            if (service == null) {
                throw new ClassNotFoundException(serviceName);
            }
            Method method = service.getClass().getMethod(request.getMethodName(), request.getParameterTypes());
            Object result = method.invoke(service, request.getArguments());

            Response response = new Response();
            response.setRequestId(request.getRequestId());
            response.setResult(result);

            ctx.writeAndFlush(response);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

在这个示例中,服务端实现了Dubbo的请求处理程序,从接收到的Request对象中提取出服务名、方法名和参数,并调用相应的方法。然后,服务端将结果封装到一个Response对象中并发送回客户端。

客户端代码:

public class DubboRpcClient {
    private final String host;
    private final int port;

    public DubboRpcClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public Object call(String serviceName, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        final DubboRpcClientHandler handler = new DubboRpcClientHandler();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(NioSocketChannel.class)
             .option(ChannelOption.TCP_NODELAY, true)
             .handler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 protected void initChannel(SocketChannel ch) throws Exception {
                     ChannelPipeline pipeline = ch.pipeline();
                     pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4));
                     pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
                     pipeline.addLast("hessianDecoder", new HessianDecoder());
                     pipeline.addLast("hessianEncoder", new HessianEncoder());
                     pipeline.addLast("handler", handler);
                 }
             });

            ChannelFuture f = b.connect(host, port).sync();

            Requestrequest = new Request();
            request.setRequestId(UUID.randomUUID().toString());
            request.setInterfaceName(serviceName);
            request.setMethodName(methodName);
            request.setParameterTypes(parameterTypes);
            request.setArguments(arguments);

            f.channel().writeAndFlush(request).sync();

            return handler.getResponse(request.getRequestId()).getResult();
        } finally {
            group.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        DubboRpcClient client = new DubboRpcClient("localhost", 8080);
        DemoService service = (DemoService) client.call(DemoService.class.getName(), "hello", new Class<?>[]{String.class}, new Object[]{"Dubbo RPC"});
        System.out.println(service.sayHello());
    }
}

在这个示例中,客户端使用Netty的Bootstrap来建立与服务端的连接,并通过一个请求对象向服务端发送请求。然后,DubboRpcClientHandler从响应对象中提取出结果并返回给调用方。

总之,这是一个简单的示例,仅用于演示如何使用Netty实现Dubbo RPC。在实际使用中,需要考虑更多的细节和异常情况,并根据需要进行调整。

标签:netty,pipeline,String,实现,request,public,dubboRPC,new,port
From: https://www.cnblogs.com/15078480385zyc/p/17262036.html

相关文章