RPC服务框架(二) 简单RPC实现

来源:互联网 发布:兔展软件下载 编辑:程序博客网 时间:2024/05/22 06:20

1. 设计思路


基于socket通信:
服务启动时,RPCServer类开启ServerSocket,监听指定端口;接收到连接请求时,开启SocketThread线程处理IO
客户端启动时,ProxyServer连接指定ServerSocket(无服务路由)
编码协议基于json:
请求格式为{"serviceName":,"method":,"param":{}};返回格式为{"code":,"result":{}}
服务定义:
通过接口暴露服务,服务通过集成接口,完成功能实现,同时添加RpcServer注解
服务发布:
服务启动时,加载所有类,扫描类是否包含注解RpcServer,若包含则实例化对象,并放入Map中;
接口调用:
客户端调用服务时,Proxy2Server通过socket发起调用请求,同时接收返回参数;
服务调用:
服务器接收到调用请求时,根据“serviceName”查找服务实现类,“mehod”获得方法,通过反射调用

2.代码实现

RpcServer注解

@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface RpcServer {}

Classutil加载并扫描包含RpcServer注解的类
public class ClassUtil {    private static Map<String,Class<?>>  serviceMap=new HashMap<String,Class<?>>();    private static Map<String,Object>  serviceInstanceMap=new HashMap<String,Object>();    static{        initClassMap();    }    public static Map<String,Class<?>> getClassMap(){        return serviceMap;    }    public static Map<String, Object> getServiceInstanceMap() {        return serviceInstanceMap;    }    private static void initClassMap(){        Set<Class<?>> classSet=new HashSet<Class<?>>();        //扫描获得所有类        getAllClass(classSet);        for(Class<?> cls : classSet){            Annotation anno=cls.getAnnotation(RpcServer.class);            if(anno != null){                Class<?> [] sc=cls.getInterfaces();                if(sc!=null && sc.length==1){                    serviceMap.put(sc[0].getSimpleName(),cls);                    try {                        serviceInstanceMap.put(sc[0].getSimpleName(),cls.newInstance());                    } catch (InstantiationException e) {                        e.printStackTrace();                    } catch (IllegalAccessException e) {                        e.printStackTrace();                    }                }            }        }    }}
RpcServer开启ServerSocket监听
public class RPCServer {public  void start(){        try {            Class.forName("com.luoyu.srpc.util.ClassUtil");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        startServer();}    private void startServer(){        try {            ServerSocket server=new ServerSocket(5555);            while(true){                Socket socket=server.accept();                new SocketThread(socket).start();            }        } catch (IOException e) {            System.out.println("server start fail");        }    }}
SocketThread处理调用请求
public class SocketThread extends Thread{    private boolean flag=true;    private Socket socket;    private static BufferedWriter writer;    private static BufferedReader reader;    public SocketThread(Socket socket) {        this.socket = socket;        try {            writer=new BufferedWriter(new OutputStreamWriter(this.socket.getOutputStream()));            reader=new BufferedReader(new InputStreamReader(this.socket.getInputStream()));        } catch (IOException e) {            e.printStackTrace();        }    }    @Override    public void run() {        System.out.println("rcv connect---->"+socket.getRemoteSocketAddress().toString());        while(flag){            JSONObject json=readJson();            if(json.isEmpty()){                continue;            }            System.out.println("rcv---->"+json.toString());            String serviceName=json.getString("serviceName");            String methodName=json.getString("method");            JSONObject param=json.getJSONObject("param");            JSONObject resp=new JSONObject();            Class<?> cls=ClassUtil.getClassMap().get(serviceName);            if(cls==null){                resp.put("code", CodeConstants.NOSERVICE);                writeResp(resp);                continue;            }            Method method=null;            try {                method=cls.getMethod(methodName, JSONObject.class);            } catch (NoSuchMethodException e) {                resp.put("code",CodeConstants.NOMETHOD);                writeResp(resp);                continue;            }            Object instance=ClassUtil.getServiceInstanceMap().get(serviceName);            if(instance==null){                resp.put("code", CodeConstants.NOSERVICE);                writeResp(resp);                continue;            }            if(method!=null){                try {                    resp= (JSONObject) method.invoke(instance, param);                    if(resp==null){                        resp=new JSONObject();                    }                    resp.put("code", CodeConstants.OK);                    writeResp(resp);                } catch(Exception e){                    resp.put("code",CodeConstants.ERR);                    writeResp(resp);                }            }        }        try {            reader.close();            writer.close();            socket.close();        } catch (IOException e1) {        }        System.out.println("server close socket");
    }
}
ProxyServer客户端发起socket连接,发送调用请求
public class Proxy2Sevcer {    private static Socket socket;    private static BufferedWriter writer;    private static BufferedReader reader;    public static void connect2Server(){        try {            socket=new Socket("127.0.0.1",5555);            writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));            reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));        } catch (IOException e) {            System.out.println("connect to server fail");        }    }    public static void callProxy(String serviceName, String methodName, JSONObject json){        JSONObject req=new JSONObject();        req.put("serviceName",serviceName);        req.put("method",methodName);        req.put("param",json);        JSONObject result=new JSONObject();        try {            writer.write(req.toString());            writer.flush();            System.out.println("send---->"+req.toString());            char buf[]=new char[1024];            reader.read(buf);            String str=new String(buf);            result=JSONObject.parseObject(str);            System.out.println("result---->"+str);        } catch (IOException e) {            System.out.println("client socket close");            try {                reader.close();                writer.close();                socket.close();            } catch (IOException e1) {            }        }    }}

3. 测试代码

服务接口
public interface Test {    void hello(JSONObject json);}
服务实现类
@RpcServerpublic class TestImpl implements Test{    @Override    public void hello(JSONObject json) {        System.out.println("hello method invoke---->"+json.toString());    }}
服务调用
public class ClientTest implements Test{    @Override    public void hello(JSONObject json) {        Proxy2Sevcer.callProxy(Test.class.getSimpleName(),Thread.currentThread().getStackTrace()[1].getMethodName(),json);    }}
* 服务调用时,可以通过代理实现,不用在ClientTest写死代码;动态获得serviceName和method

阅读全文
0 0
原创粉丝点击