Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >基于Netty实现的简单RPC调用

基于Netty实现的简单RPC调用

作者头像
用户1215919
发布于 2021-12-28 04:43:27
发布于 2021-12-28 04:43:27
40500
代码可运行
举报
文章被收录于专栏:大大的微笑大大的微笑
运行总次数:0
代码可运行

模块

rpc-api

rpc-consumer

rpc-provider

依赖:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
	<groupId>io.netty</groupId>
	<artifactId>netty-all</artifactId>
	<version>4.1.25.Final</version>
 </dependency>
rpc-api代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 接口, consumer和provider分别添加api的依赖
public interface ISayHelloService {
    String say(String name);
}

// 请求参数封装
public class Request{
     private String methodName; // 方法名
    private String className;  // 全类名
    private Object[] values; // 实参列表
}
rpc-provider代码:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Server {
    private void start() throws InterruptedException {
       // 初始化
        ServerHandler h = new ServerHandler();
        h.init();
        
        EventLoopGroup boosGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.channel(NioServerSocketChannel.class)
                    .group(boosGroup, workGroup)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel sc) throws Exception {
                            sc.pipeline()
                                    .addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4,
                                            0, 4))
                                    .addLast(new LengthFieldPrepender(4))
                                    .addLast("encoder", new ObjectEncoder())
                                    .addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)))
                                    .addLast(h);
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 10)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);
            ChannelFuture future = bootstrap.bind(8080).sync();
            future.channel()
                    .closeFuture()
                    .sync();
            System.out.println("server running, listener port : 8080 !");
        } finally {
            boosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        try {
            new Server().start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
   // 具体业务处理
    
    public class ServerHandler extends ChannelInboundHandlerAdapter {
    private static String bashScanPackage = "com.data.service.impl";
    private ClassLoader classLoader = this.getClass().getClassLoader();
    private static final Map<String, Mapping> SERVICES = new HashMap<>();


    /**
     * 初始化
     *
     * @throws ClassNotFoundException
     */
    public void init() {
        URL url = classLoader.getResource(bashScanPackage.replaceAll("\\.", "/"));
        String filePath = url.getFile();
        File file = new File(filePath);
        for (String s : file.list()) {
            s = s.substring(0, s.indexOf("."));
            Class clazz = null;
            try {
                clazz = Class.forName(bashScanPackage + "." + s);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            Method[] methods = clazz.getDeclaredMethods();
            String interfaceName = clazz.getInterfaces()[0].getName();
            for (Method m : methods) {
                Mapping mapping = new Mapping();
                mapping.setMethod(m);
                mapping.setParameters(m.getParameterTypes());
                try {
                    mapping.setTarget(clazz.newInstance());
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                SERVICES.putIfAbsent(interfaceName + "." + m.getName(), mapping);
            }

        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Request request = (Request) msg;
        Object result;
        String key = request.getClassName() + "." + request.getMethodName();
        if (!SERVICES.containsKey(key)) {
            return;
        }
        Mapping clazz = SERVICES.get(key);
        result = clazz.getMethod().invoke(clazz.getTarget(), request.getValues());
        ctx.write(result);
        ctx.flush();
        ctx.close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
    }
}

// 业务提供方封装的参数
public class Mapping {
    private Object target;
    private Method method;
    private Class[] parameters;
}
rpc-consumer代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 动态代理类
public class ProxyHandler {
    public static <T> T create(Class<?> clazz) {
        MethodProxy proxy = new MethodProxy(clazz);
        Class<?>[] interfaces = clazz.isInterface() ?
                new Class[]{clazz} :
                clazz.getInterfaces();
        T result = (T) Proxy.newProxyInstance(clazz.getClassLoader(), interfaces, proxy);
        return result;
    }

    private static class MethodProxy implements InvocationHandler {
        private Class<?> clazz;

        public MethodProxy(Class<?> clazz) {
            this.clazz = clazz;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return invoke(method, args);
        }

        public Object invoke(Method method, Object[] args) {

            Request msg = new Request();
            msg.setClassName(this.clazz.getName());
            msg.setMethodName(method.getName());
            msg.setValues(args);
            msg.setParameters(method.getParameterTypes());
            EventLoopGroup group = new NioEventLoopGroup();
            RPCBusinessHandler handler = new RPCBusinessHandler();
            try {
                Bootstrap b = new Bootstrap();
                b.group(group)
                        .channel(NioSocketChannel.class)
                        .option(ChannelOption.TCP_NODELAY, true)
                        .handler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            public void initChannel(SocketChannel ch) throws Exception {
                                ChannelPipeline pipeline = ch.pipeline();
                                pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0,
                                        4, 0, 4));
                                pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
                                pipeline.addLast("encoder", new ObjectEncoder());
                                pipeline.addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
                                pipeline.addLast("handler", handler);
                            }
                        });

                ChannelFuture future = b.connect("localhost", 8080).sync();
                future.channel().writeAndFlush(msg).sync();
                future.channel().closeFuture().sync();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                group.shutdownGracefully();
            }
            return handler.getResult();
        }
    }
    
// 客户端逻辑处理
public class RPCBusinessHandler extends ChannelInboundHandlerAdapter {
    private Object result;
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        this.result = msg;
    }



    public Object getResult(){
        return this.result;
    }    
    
    
// 测试
 ISayHelloService service = new ProxyHandler().create(ISayHelloService.class);
 System.out.println(service.say("tony"));    
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
基于netty实现rpc远程调用
Netty中的HTTP处理要Netty内置的HTTP的编解码器来完成解析。现在我们来看自定义协议如何设定。在Netty中完成一个自定义协议其实非常简单,只需要定义一个普通的Java类即可。我们现在手写RPC主要是为了完成对Java代码的远程调用,类似于RMI(Remote Method Invocation,远程方法调用),大家应该都很熟悉了吧。在远程调用Java代码时,哪些内容是必须由网络来传输的呢?譬如,服务名称?需要调用该服务的哪个方法?方法的实参是什么?这些信息都需要通过客户端传送到服务端。
周杰伦本人
2022/10/25
6250
基于netty实现rpc远程调用
手写dubbo 10-基于netty实现RPC
博客中代码地址:https://github.com/farliu/farpc.git
并发笔记
2020/11/09
1.2K0
真的够可以的,基于Netty实现了PRC框架
RPC全称Remote Procedure Call,即远程过程调用,对于调用者无感知这是一个远程调用功能。目前流行的开源RPC 框架有阿里的Dubbo、Google 的 gRPC、Twitter 的Finagle 等。本次RPC框架的设计主要参考的是阿里的Dubbo,这里Netty 基本上是作为架构的技术底层而存在的,主要完成高性能的网络通信,从而实现高效的远程调用。
Java程序猿阿谷
2021/04/09
8310
真的够可以的,基于Netty实现了PRC框架
RPC框架原理与实现
RPC,全称 Remote Procedure Call(远程过程调用),即调用远程计算机上的服务,就像调用本地服务一样。那么RPC的原理是什么呢?了解一个技术最好的思路就是寻找一个该类型麻雀虽小五脏俱全的开源项目,不负所期,找到一个轻量级分布式 RPC 框架,本文从这个项目入手来解读RPC的原理及其实现。 其实说到RPC,大家应该不会陌生才是,以往流行的Web Service就是一种RPC,一般来说RPC 可基于 HTTP 或 TCP 协议,因为Web Service 基于HTTP,所以具有良好的跨平台性
JadePeng
2018/03/12
2.3K0
RPC框架原理与实现
【详解】轻量级分布式RPC框架实战
随着互联网的飞速发展,分布式系统逐渐成为构建大型应用的首选方案。在分布式系统中,远程过程调用(Remote Procedure Call,简称RPC)是一种常用的通信方式,它允许程序通过网络请求其他机器上的服务,就像调用本地函数一样方便。本文将介绍如何构建一个轻量级的分布式RPC框架,并通过实战案例展示其具体应用。
大盘鸡拌面
2025/07/06
940
基于Netty和SpringBoot实现一个轻量级RPC框架-Client篇
前一篇文章相对简略地介绍了RPC服务端的编写,而这篇博文最要介绍服务端(Client)的实现。RPC调用一般是面向契约编程的,而Client的核心功能就是:把契约接口方法的调用抽象为使用Netty向RPC服务端通过私有协议发送一个请求。这里最底层的实现依赖于动态代理,因此动态代理是动态实现接口的最简单方式(如果字节码研究得比较深入,可以通过字节码编程实现接口)。需要的依赖如下:
Throwable
2020/06/23
5400
Netty实现简单RPC调用
我们知道Dubbo是一个RPC框架,那RPC框架需要实现什么?需要实现的是调用远程服务和本地服务一样方便,同时提高调用远程服务的性能。而服务端和客户端之间的关系,其实就是一个生产和消费的关系。
路行的亚洲
2020/07/16
5940
通过 Netty、ZooKeeper 手撸一个 RPC 服务
使用 Netty、ZooKeeper 和 Spring Boot 手撸一个微服务框架。
Yano_nankai
2021/05/08
1.2K0
通过 Netty、ZooKeeper 手撸一个 RPC 服务
Netty实现一个简单的 RPC
众所周知,dubbo 底层使用了 Netty 作为网络通讯框架,而 Netty 的高性能我们之前也分析过源码,对他也算还是比较了解了。今天我们就自己用 Netty 实现一个简单的 RPC 框架。
用户5224393
2019/08/12
4150
Netty实现一个简单的 RPC
徒手撸框架--实现 RPC 远程调用
微服务已经是每个互联网开发者必须掌握的一项技术。而 RPC 框架,是构成微服务最重要的组成部分之一。趁最近有时间。又看了看 dubbo 的源码。dubbo 为了做到灵活和解耦,使用了大量的设计模式和 SPI机制,要看懂 dubbo 的代码也不太容易。
用户2060079
2018/10/11
7900
Netty之Protobuf​编解码框架
Protobuf是一个灵活、高效、结构化的数据序列化框架,相比于传统的XML序列化工具,它更小、更快、更简单。支持结构化数据一次可以到处使用,包括跨语言,通过代码生成工具可以自动生成不同语言版本的源代码,可以在使用不同版本的数据结构进程间进行数据传递,实现数据结构的前向兼容。
Liusy
2020/08/31
7410
教你用 Netty 实现一个简单的 RPC!
众所周知,dubbo 底层使用了 Netty 作为网络通讯框架,而 Netty 的高性能我们之前也分析过源码,对他也算还是比较了解了。今天我们就自己用 Netty 实现一个简单的 RPC 框架。
Java技术栈
2019/11/14
5060
史诗级最强教科书式“NIO与Netty编程”
java.nio全称java non-blocking IO,是指JDK1.4开始提供的新API。从JDK1.4开始,Java提供了一系列改进的输入/输出的新特性,也被称为NIO(既New IO),新增了许多用于处理输入输出的类,这些类都被放在java.nio包及子包下,并且对原java.io包中的很多类进行改写,新增类满足NIO的功能。 NIO和BIO有着相同的目的和作用,但是它们的实现方式完全不同,BIO以流的方式处理数据,而NIO以块的方式处理数据,块I/O的效率比流I/O高很多。另外,NIO是非阻塞式的,这一点跟BIO也很不相同,使用它可以提供非阻塞式的高伸缩性网络。 NIO主要有三大核心部分 :Channel(通道),Buffer(缓冲区),Selector(选择器)。传统的BIO基于字节流和字符流进行操作,而NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如 :连接打开,数据到达)。因此使用单个线程就可以监听多个数据管道。
海仔
2019/08/26
9890
史诗级最强教科书式“NIO与Netty编程”
Netty 中的心跳机制,还有谁不会?
作者:rickiyang 出处:www.cnblogs.com/rickiyang/p/11074231.html
Java技术栈
2021/06/16
5500
Netty基础—6.Netty实现RPC服务
本地只有一个方法的接口,需要在本地对这个方法进行远程调用,而对这个方法进行调用其实就是对该接口的动态代理进行调用。
东阳马生架构
2025/05/21
770
Netty 实现简单的RPC远程调用 原
RPC又称远程过程调用,我们所知的远程调用分为两种,现在在服务间通信的方式也太多已这两种为主
chinotan
2019/04/03
2K0
Netty 实现简单的RPC远程调用
                                                                            原
Netty 如何实现心跳机制与断线重连?
所谓心跳, 即在 TCP 长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, 通知对方自己还在线, 以确保 TCP 连接的有效性.
Java技术栈
2019/07/12
4.7K0
Netty 如何实现心跳机制与断线重连?
Netty 是如何解决 TCP 粘包拆包的?
那么数据在通信层传播其实就像河水一样并没有明显的分界线,而数据具体表示什么意思什么地方有句号什么地方有分号这个对于TCP底层来说并不清楚。应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段,之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。
Java技术栈
2021/07/16
8660
Netty 是如何解决 TCP 粘包拆包的?
Netty高级篇
RPC,远程调用,就是A程序部署在1号机器上,B程序部署在2号机器上,A可以像调本地方法一样地去调用B程序,而不需要程序员额外地编写这个交互过程,这就叫RPC远程调用。dubbo、Ribbon、openfeign都是RPC框架。
贪挽懒月
2020/08/25
4720
nio与netty编程(二)
Netty 是由 JBOSS 提供的一个 Java 开源框架。Netty 提供异步的、基于事件驱动的网络应用程序框架,用以快速开发高性能、高可靠性的网络 IO 程序。 Netty 是一个基于 NIO 的网络编程框架,使用 Netty 可以帮助你快速、简单的开发出一个网络应用,相当于简化和流程化了 NIO 的开发过程。 作为当前最流行的 NIO 框架,Netty 在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,知名的 Elasticsearch 、Dubbo 框架内部都采用了 Netty。
周杰伦本人
2022/10/25
5360
nio与netty编程(二)
相关推荐
基于netty实现rpc远程调用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验