netty实现远程调用RPC功能

PRC的功能一句话说白了,就是远程调用其他电脑的api

依赖

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.31.Final</version>
</dependency>

服务端功能模块编写

  1. 项目结构

  2. ClassInfo

    package test;
    
    import java.io.Serializable;
    
    public class ClassInfo implements Serializable {
    
        private static final long serialVersionUID = -8970942815543515064L;
    
        private String className;//类名
    private String methodName;//函数名称
    private Class<?>[] types;//参数类型
    private Object[] objects;//参数列表
    public String getClassName() {
    return className;
    }
    public void setClassName(String className) {
    this.className = className;
    }
    public String getMethodName() {
    return methodName;
    }
    public void setMethodName(String methodName) {
    this.methodName = methodName;
    }
    public Class<?>[] getTypes() {
    return types;
    }
    public void setTypes(Class<?>[] types) {
    this.types = types;
    }
    public Object[] getObjects() {
    return objects;
    }
    public void setObjects(Object[] objects) {
    this.objects = objects;
    }
    }
  3. InvokerHandler

    package test;
    
    import java.lang.reflect.Method;
    import java.util.concurrent.ConcurrentHashMap; import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInboundHandlerAdapter; public class InvokerHandler extends ChannelInboundHandlerAdapter {
    public static ConcurrentHashMap<String, Object> classMap = new ConcurrentHashMap<String,Object>();
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    ClassInfo classInfo = (ClassInfo)msg;
    Object claszz = null;
    if(!classMap.containsKey(classInfo.getClassName())){
    try {
    claszz = Class.forName(classInfo.getClassName()).getDeclaredConstructor().newInstance();
    classMap.put(classInfo.getClassName(), claszz);
    } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
    e.printStackTrace();
    }
    }else {
    claszz = classMap.get(classInfo.getClassName());
    }
    Method method = claszz.getClass().getMethod(classInfo.getMethodName(), classInfo.getTypes());
    Object result = method.invoke(claszz, classInfo.getObjects());
    System.out.println("服务器接受客户端的数据" + result);
    ctx.write("SeverSendData");
    ctx.flush();
    ctx.close();
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    cause.printStackTrace();
    ctx.close();
    } }
  4. RPCServer

    package test;
    
    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelOption;
    import io.netty.channel.ChannelPipeline;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
    import io.netty.handler.codec.LengthFieldPrepender;
    import io.netty.handler.codec.serialization.ClassResolvers;
    import io.netty.handler.codec.serialization.ObjectDecoder;
    import io.netty.handler.codec.serialization.ObjectEncoder; public class RPCServer {
    private int port; public RPCServer(int port) {
    this.port = port;
    } public void start() {
    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup(); try {
    ServerBootstrap serverBootstrap =
    new ServerBootstrap()
    .group(bossGroup, workerGroup)
    .channel(NioServerSocketChannel.class).localAddress(port)
    .childHandler(new ChannelInitializer<SocketChannel>() { @Override
    protected void initChannel(SocketChannel ch) throws Exception {
    ChannelPipeline pipeline = ch.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 InvokerHandler());
    }
    })
    .option(ChannelOption.SO_BACKLOG, 128)
    .childOption(ChannelOption.SO_KEEPALIVE, true);
    ChannelFuture future = serverBootstrap.bind(port).sync();
    System.out.println("Server start listen at " + port);
    future.channel().closeFuture().sync();
    } catch (Exception e) {
    bossGroup.shutdownGracefully();
    workerGroup.shutdownGracefully();
    }
    } public static void main(String[] args) throws Exception {
    int port;
    if (args.length > 0) {
    port = Integer.parseInt(args[0]);
    } else {
    port = 8080;
    }
    new RPCServer(port).start();
    }
    }
  5. SeverClass

    package test;
    
    public class SeverClass implements SeverInterface {
    
        @Override
    public String fn(String data) {
    return data;
    } }
  6. SeverInterface

    package test;
    
    public interface SeverInterface {
    String fn(String data);
    }

客户端功能模块编写

  1. 目录结构

  2. App

    package test;
    
    import io.netty.bootstrap.Bootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelOption;
    import io.netty.channel.ChannelPipeline;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioSocketChannel;
    import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
    import io.netty.handler.codec.LengthFieldPrepender;
    import io.netty.handler.codec.serialization.ClassResolvers;
    import io.netty.handler.codec.serialization.ObjectDecoder;
    import io.netty.handler.codec.serialization.ObjectEncoder; public class App
    {
    public static void main(String [] args) throws Throwable{ ClassInfo classInfo = new ClassInfo();
    classInfo.setClassName("test.SeverClass");
    classInfo.setMethodName("fn");
    classInfo.setObjects(new Object[]{"ClientSendData"});
    classInfo.setTypes(new Class[]{String.class}); ResultHandler resultHandler = new ResultHandler();
    EventLoopGroup group = new NioEventLoopGroup();
    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",resultHandler);
    }
    }); ChannelFuture future = b.connect("localhost", 8080).sync();
    future.channel().writeAndFlush(classInfo).sync();
    future.channel().closeFuture().sync();
    } finally {
    group.shutdownGracefully();
    } System.out.println("调用服务器数据返回回来的数据:" + resultHandler.getResponse());
    }
    }
  3. ResultHandler

    package test;
    
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInboundHandlerAdapter; public class ResultHandler extends ChannelInboundHandlerAdapter { private Object response; public Object getResponse() {
    return response;
    } @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    response = msg;
    System.out.println("调用服务器数据返回回来的数据:" + response);
    } @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    System.out.println("client exception is general");
    }
    }

netty实现远程调用RPC功能的更多相关文章

  1. Atitit.分布式远程调用  rpc  rmi  CORBA的关系

    Atitit.分布式远程调用  rpc  rmi  CORBA的关系 1. 远程调用(包括rpc,rmi,rest)1 2. 分布式调用大体上就分为两类,RPC式的,REST式的1 3. RPC(远程 ...

  2. java 远程调用 RPC

    1. 概念 RPC,全称为Remote Procedure Call,即远程过程调用,它是一个计算机通信协议.它允许像调用本地服务一样调用远程服务.它可以有不同的实现方式.如RMI(远程方法调用).H ...

  3. 远程调用RPC

    一.简介 RPC,就是Remote Procedure Call的简称呀,翻译成中文就是远程过程调用. 本地调用,就好比你现在在家里,你要想洗碗,那你直接把碗放进洗碗机,打开洗碗机开关就可以洗了.这就 ...

  4. (转)RabbitMQ消息队列(七):适用于云计算集群的远程调用(RPC)

    在云计算环境中,很多时候需要用它其他机器的计算资源,我们有可能会在接收到Message进行处理时,会把一部分计算任务分配到其他节点来完成.那么,RabbitMQ如何使用RPC呢?在本篇文章中,我们将会 ...

  5. RabbitMQ消息队列(七):适用于云计算集群的远程调用(RPC)

            在云计算环境中,很多时候需要用它其他机器的计算资源,我们有可能会在接收到Message进行处理时,会把一部分计算任务分配到其他节点来完成.那么,RabbitMQ如何使用RPC呢?在本篇 ...

  6. RabbitMQ 适用于云计算集群的远程调用(RPC)

    在云计算环境中,很多时候需要用它其他机器的计算资源,我们有可能会在接收到Message进行处理时,会把一部分计算任务分配到其他节点来完成.那么,RabbitMQ如何使用RPC呢?在本篇文章中,我们将会 ...

  7. RabbitMQ入门学习系列(七) 远程调用RPC

    快速阅读 生产者和消费者启动以后,都有一个接收事件,消费者是接收事件是处理调用方法以后等待生产者的返回,生产者的接收事件是处理接收生产者发送的消息,进行处理.消费者发送的时候要在回调队列中加入一个标识 ...

  8. go程序添加远程调用tcpdump功能

    最近开发的telemetry采集系统上线了.听起来高大上,简单来说就是一个grpc/udp服务端,用户的机器(路由器.交换机)将它们的各种统计数据上报采集.整理后交后端的各类AI分析系统分析.目前华为 ...

  9. goroute应用-模拟远程调用RPC

    go语言简单模拟RPC,详见个人新博客:blog.dlgde.cn 代码如下: package main import ( "errors" "fmt" &qu ...

随机推荐

  1. UVALive 4270 Discrete Square Roots

    题目描述: 在已知一个离散平方根的情况下,按照从小到大的顺序输出其他所有的离散平方根. 在模n意义下,非负整数x的离散平方根是满足0<=r<n且r2=x(mod n)的整数r. 解题思路: ...

  2. python----异常处理(二)

    格式如下: try:     pass except Exception as e:#如果上面出错,执行下面代码     pass else:#try如果没出错执行此下面代码     pass fin ...

  3. HTML 中 id与name 区别

    一个name可以同时对应多个控件,比如checkbox和radio而id必须是全文档中唯一的 id的用途1) id是HTML元素的Identity,主要是在客户端脚本里用.2) label与form控 ...

  4. html5新增语义化标签

    注意:body.section.nav 需要h1-h6. div.header则不需要. 1):<article> 显示一个独立的文章内容. 例如一篇完整的论坛帖子,一则网站新闻,一篇博客 ...

  5. LeetCode OJ:Merge Sorted Array(合并排序的数组)

    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note:Yo ...

  6. HAWQ取代传统数仓实践(九)——维度表技术之退化维度

    退化维度技术减少维度的数量,简化维度数据仓库模式.简单的模式比复杂的更容易理解,也有更好的查询性能.        有时,维度表中除了业务主键外没有其它内容.例如,在本销售订单示例中,订单维度表除了订 ...

  7. js 下获取子元素的方法

    笔记核心: firstElementChild只会获取元素节点对象,从名称就可以看出来,firstChild则可以获取文本节点对象(当然也可以获取元素节点对象),比如空格和换行都被当做文本节点. js ...

  8. C++中继承关系中的同名隐藏和对策

    在C++及其面向对象的理论中,有这样的场景:一个类继承自另外一个类,如果这两个类都有一个函数名和参数及其返回值一样的成员函数,那么子类的函数会自动将父类对应的函数隐藏.即同名隐藏.在有时的开发过程中, ...

  9. Python之namedtuple源码分析

    namedtuple()函数根据提供的参数创建一个新类,这个类会有一个类名,一些字段名和一个可选的用于定义类行为的关键字,具体实现如下 namedtuple函数源码 from keyword impo ...

  10. 生动有趣地讲解Map/Reduce基本原理

    Hadoop简介 Hadoop就是一个实现了Google云计算系统的开源系统,包括并行计算模型Map/Reduce,分布式文件系统HDFS,以及分布式数据库Hbase,同时Hadoop的相关项目也很丰 ...