分布式Web应用----基于Socket+动态代理实现简单RPC 生产者消费者模型

10 篇文章 0 订阅

原文连接:https://ksfmaster.com/article/9
##写在前面
前面一文主要简单介绍了JAVA动态代理基本原理,这也是实现RPC的基本知识,这里我们运用Socket简单实现一个远程过程调用,方便大家理解RPC的基本原理,希望对大家有所帮助。

##新建People接口类与Man实现类
接口类

public interface People {
    public  String sayHello(String name);
}

实现类

public class Man implements People {
    public String sayHello(String name) {
        System.out.println("call Man sayHello ");
        return "Hello "+name;
    }
}

这两个类都比较简单,没什么好说的了。

##新建生产者线程类ProducerTask 和处理Socket服务类RPCProducer

生产者处理连接线程类

public class ProducerTask implements  Runnable {

    Socket client=null;
    public  ProducerTask(Socket client){
        this.client=client;
    }
    public void run() {
        ObjectInputStream input=null;
        ObjectOutputStream output=null;
        try {
            input=new ObjectInputStream(client.getInputStream());
            String interFaceName=input.readUTF();
            Class<?> service=Class.forName(interFaceName);
            String methodName=input.readUTF();
            Class<?> [] paramterTypes= (Class<?>[]) input.readObject();
            Object [] arguments= (Object[]) input.readObject();
            Method method=service.getMethod(methodName,paramterTypes);
            Object result=method.invoke(service.newInstance(),arguments);
            System.out.println("远程调用对象名为:"+service.getName());
            System.out.println("远程调用方法名为:"+methodName);
            for (Object obj:arguments){
                System.out.println("远程调用参数为:"+obj);
            }
            output=new ObjectOutputStream(client.getOutputStream());
            output.writeObject(result);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
              output.close();
               input.close();
               client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

ProducerTask 类主要是处理请求子线程,在该类中通过Socket连接获取消费者发送过来的 对象名、方法名、方法参数、参数列表,再利用反射机制,完成方法的调用,并向消费者返回调用的结果。

处理Socket服务类

public class RPCProducer {
    static Executor executor= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    public static void exproter(String hostName,int port) throws Exception {
        ServerSocket server=new ServerSocket();
        server.bind(new InetSocketAddress(hostName,port));
        try {
            while (true){
                System.out.println("get client call");
                executor.execute(new ProducerTask(server.accept()));
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            server.close();
        }
    }
}

该类是生产者监听连接类,这里面主要使用了线程池,每当一个连接过来时,将线程池中增加一个线程,并让子线程去处理连接请求。

##新建消费者动态代理类和消费者类
消费者动态代理类

public class ConsumerHandler<T> implements InvocationHandler {
    private Class<?> object;
    private InetSocketAddress address;
    public ConsumerHandler(Class<?> object, InetSocketAddress address){
        this.object=object;
        this.address=address;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(" call peopleProxyHandler invoke ");
        System.out.println("调用对象为:"+object.getClass().getName());
        System.out.println("调用方法为:"+method.getName());
        for (Object obj:args){
            System.out.println("参数为:"+obj.toString());
        }

        Class cl=Class.forName(object.getClass().getName());

        Socket socket=null;
        ObjectOutputStream output=null;
        ObjectInputStream  input=null;

        socket=new Socket();
        socket.connect(address);
        output=new ObjectOutputStream(socket.getOutputStream());
        output.writeUTF(object.getName());
        output.writeUTF(method.getName());
        output.writeObject(method.getParameterTypes());
        output.writeObject(args);
        input =new ObjectInputStream(socket.getInputStream());

        return  input.readObject();
    }
}

该类实现了InvocationHandler 接口,主要将对本地方法的调用,代理到此类中,在invoke方法中,获取调用方法的对象名、方法名、参数类型及参数列表,再通过连接生产者的Socket服务,将这些参数传送给生产者,并返回生产者返回的结果。

消费者类

public class RPCConsumer<T> {
    public T improter(Class<?> serviceClass, InetSocketAddress address){
        ConsumerHandler<T> consumerHandler=new ConsumerHandler<T>(serviceClass,address);
        Class<?> intf=serviceClass.getInterfaces()[0];
        Class<?> [] interfaces=new Class<?>[]{intf};
        return (T) Proxy.newProxyInstance(serviceClass.getClassLoader(),interfaces,consumerHandler);
    }
}

该类主要是返回一个代理对象,完成动态代理功能

##新建生产者和服务者测试类

生产者测试类

public class ProducerTest {
    public  static  void  main(String [] rags){
        new Thread(new Runnable() {
            public void run() {
                try {
                    RPCProducer.exproter("localhost",8080);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

这是生产者测试类,主要在开启生产者服务,监听端口为8080

消费者测试类

    public static void main(String [] rags){
        RPCConsumer<People> peopleRPCConsumer=new RPCConsumer<People>();
        People people=peopleRPCConsumer.improter(Man.class,new InetSocketAddress("localhost",8080));
        System.out.println(people.sayHello("zhaochao"));

    }

消费者测试类,通过peopleRPCConsumer 生成代理对象people,调用people的方法,完成远程调用

##结果

生产者输出

get client call
get client call
call Man sayHello 
远程调用对象名为:com.zhaocaho.proxy.Man
远程调用方法名为:sayHello
远程调用参数为:zhaochao

消费者输出

 call peopleProxyHandler invoke 
调用对象为:java.lang.Class
调用方法为:sayHello
参数为:zhaochao
Hello zhaochao
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵侠客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值