简单的rpc实现

1.什么是rpc?

RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。

                               

client functions:客户端,请求发送端

client stub:客户端句柄,主要是获取请求的相关数据信息,比如调用的接口名,参数名,参数类型,以及对信息进行序列化,通过socket发送到服务端;

server stub:服务端句柄,主要将client发来的请求信息进行读取并反序列化,然后通过这些信息调用具体的实现类,并将结果序列化后通过sock发送到client。


2.rpc用到什么技术?

(1)JAVA 动态代理(cglib或jdk的proxy类)

(2)socket通信,涉及到IO(io,NIO)

  (3) JAVA序列化

3 rpc架构

RPC架构分为三部分:

(1)服务提供者,运行在服务器端,提供服务接口定义与服务实现类。

(2)服务中心,运行在服务器端,负责将本地服务发布成远程服务,管理远程服务,提供给服务消费者使用。

(3)服务消费者,运行在客户端,通过远程代理对象调用远程服务。


4简单rpc实现代码

====================================================================

                                                                服务端

====================================================================

服务端业务处理类:

package com.axj.server;

import java.io.*;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.HashMap;

/**
 * \* Created with IntelliJ IDEA.
 * \* User: axj
 * \* Date: 2018/6/14
 * \* Time: 14:46
 * \* Description:
 * \
 */
public class ServerTask implements Runnable {
    private Socket socket = null;
    private  HashMap<String,Class> serviceRegistry;

    public ServerTask(Socket socket, HashMap<String, Class> serviceRegistry) {
        this.socket=socket;
        this.serviceRegistry=serviceRegistry;
    }

    @Override
    public void run() {
        ObjectOutputStream outputStream =null;
        ObjectInputStream  inputStream=null;
        try {
            inputStream = new ObjectInputStream(socket.getInputStream());
            String serviceName=inputStream.readUTF();
            String serviceMethod=inputStream.readUTF();
            Class<?>[] parameterTypes = (Class<?>[]) inputStream.readObject();
            Object[] arguments = (Object[]) inputStream.readObject();

            Class serviceClass=serviceRegistry.get(serviceName);
            if (serviceClass == null) {
                throw new ClassNotFoundException(serviceName + " not found");
            }
            Method method=serviceClass.getMethod(serviceMethod,parameterTypes);
            Object object=method.invoke(serviceClass.newInstance(),arguments);
            //
            // 3.将执行结果反序列化,通过socket发送给客户端
            outputStream = new ObjectOutputStream(socket.getOutputStream());
            outputStream.writeObject(object);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

服务端类ServerSocket:

package com.axj.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * \* Created with IntelliJ IDEA.
 * \* User: xxx
 * \* Date: 2018/6/14
 * \* Time: 14:40
 * \* Description:
 * \
 */
public  class RpcServer {
    private static ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    private  int port;
    private  String ip;
    public  RpcServer(String ip,int port){
         this.port=port;
         this.ip=ip;
    }

    private static final HashMap<String, Class> serviceRegistry = new HashMap<String, Class>();

    public void register(Class serviceInterface, Class impl) {
        serviceRegistry.put(serviceInterface.getName(), impl);
    }
    //
    public void start() throws IOException {
        ServerSocket serverSocket= new ServerSocket();

        serverSocket.bind(new InetSocketAddress(ip,port));
        
        // 1.监听客户端的TCP连接,接到TCP连接后将其封装成task,由线程池执行
        while (true){
            Socket socket=serverSocket.accept();
            executor.execute(new ServerTask(socket,serviceRegistry));
        }
    }
}

服务端启动类:

public class RpcServerTest {
    public static void main(String[] args) {
        try {
            RpcServer rpcServer=new RpcServer("localhost",8088);
            rpcServer.register(HelloService.class, HelloServiceImpl.class);
            rpcServer.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

=====================================================================

                                                                客户端

=====================================================================

客户端动态代理类:

package com.axj.client;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
 * \* Created with IntelliJ IDEA.
 * \* User: axj
 * \* Date: 2018/6/14
 * \* Time: 14:28
 * \* Description:
 * \
 */
public class RpcClientPoxy {

    public static Object getRemoteProxyObj(final Class<?> serviceInterface,final  InetSocketAddress addr) {
        return Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class[]{serviceInterface}, new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] args) throws Throwable {
                Socket socket=null;
                ObjectOutputStream outputStream=null;
                ObjectInputStream inputStream=null;
                Object object=null;
                try {
                     socket=new Socket();
                     socket.connect(addr);

                     outputStream=new ObjectOutputStream(socket.getOutputStream());
                     outputStream.writeUTF(serviceInterface.getName());
                     outputStream.writeUTF(method.getName());
                     outputStream.writeObject(method.getParameterTypes());
                     outputStream.writeObject(args);

                     inputStream=new ObjectInputStream(socket.getInputStream());
                     object=inputStream.readObject();
                }catch (Exception e){
                     e.printStackTrace();
                } finally {
                    if (socket != null) socket.close();
                    if (outputStream != null) outputStream.close();
                    if (inputStream != null) inputStream.close();
                }
                return  object;
            }
        });
    }
}

客户端Socket

package com.axj;

import com.axj.client.RpcClientPoxy;
import com.axj.service.HelloService;

import java.net.InetSocketAddress;

/**
 * \* Created with IntelliJ IDEA.
 * \* User: axj
 * \* Date: 2018/6/14
 * \* Time: 15:38
 * \* Description:
 * \
 */
public class RpcClientTest {
    public static void main(String[] args) {
        HelloService helloService= (HelloService) RpcClientPoxy.getRemoteProxyObj(HelloService.class, new InetSocketAddress("localhost",8088));
        System.out.println(helloService.sayHeelo("xxxxxxx"));

        System.out.println(helloService.sayBye());
    }
}

远程service接口

public interface HelloService {
    String  sayHeelo(String string);

    String  sayBye();
}

远程service接口实现类

public class HelloServiceImpl implements  HelloService {
    @Override
    public String sayHeelo(String string) {
        System.out.println(string);
        return string;
    }

    @Override
    public String sayBye() {
        System.out.println("bye bye");
        return "bye bye" ;
    }
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
介绍RCP的实现原理 目录 1. 前言 2 2. 基本概念 3 2.1. IDL 3 2.2. 代理(Proxy) 3 2.3. 存根(Stub) 4 3. 三要素 4 3.1. 网络通讯 4 3.2. 消息编解码 5 3.3. IDL编译器 5 4. flex和bison 5 4.1. 准备概念 5 4.1.1. 正则表达式(regex/regexp) 6 4.1.2. 符号∈ 6 4.1.3. 终结符/非终结符/产生式 6 4.1.4. 记号(Token) 6 4.1.5. 形式文法 7 4.1.6. 上下文无关文法(CFG) 7 4.1.7. BNF 8 4.1.8. 推导 8 4.1.9. 语法树 8 4.1.10. LL(k) 9 4.1.11. LR(k) 9 4.1.12. LALR(k) 9 4.1.13. GLR 9 4.1.14. 移进/归约 9 4.2. flex和bison文件格式 9 4.2.1. 定义部分 10 4.2.2. 规则部分 10 4.2.3. 用户子例程部分 10 4.3. flex基础 10 4.3.1. flex文件格式 11 4.3.2. 选项 11 4.3.3. 名字定义 11 4.3.4. 词法规则 12 4.3.5. 匹配规则 12 4.3.6. %option 13 4.3.7. 全局变量yytext 13 4.3.8. 全局变量yyval 13 4.3.9. 全局变量yyleng 13 4.3.10. 全局函数yylex 13 4.3.11. 全局函数yywrap 13 4.4. bison基础 14 4.4.1. bison文件格式 14 4.4.2. %union 14 4.4.3. %token 15 4.4.4. 全局函数yyerror() 15 4.4.5. 全局函数yyparse() 15 4.5. 例1:单词计数 15 4.5.1. 目的 15 4.5.2. flex词法文件wc.l 16 4.5.3. Makefile 16 4.6. 例2:表达式 17 4.6.1. 目的 17 4.6.2. flex词法exp.l 17 4.6.3. bison语法exp.y 17 4.6.4. Makefile 19 4.6.5. 代码集成 19 4.7. 例3:函数 20 4.7.1. 目的 20 4.7.2. func.h 20 4.7.3. func.c 21 4.7.4. IDL代码func.idl 22 4.7.5. flex词法func.l 22 4.7.6. bison语法func.y 24 4.7.7. Makefile 27 5. 进阶 27 5.1. 客户端函数实现 27 5.2. 服务端函数实现 28 5.2.1. Stub部分实现 28 5.2.2. 用户部分实现 29 6. 参考资料 29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值