博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自己动手实现RPC服务调用框架
阅读量:7074 次
发布时间:2019-06-28

本文共 6625 字,大约阅读时间需要 22 分钟。

hot3.png

引言

本文利用java自带的socket编程实现了一个简单的rpc调用框架,由两个工程组成分别名为battercake-provider(服务提供者)、battercake-consumer(服务调用者)。

设计思路如下: 1、在battercake-provider中,写一个服务叫BatterCakeService

2、在battercake-provider中,启动RpcProvider,发布该服务

3、在battercake-consumer中,启动测试类RpcTest

4、在battercake-consumer中,利用jdk动态代理,获得BatterCakeService的动态代理类BatterCakeService$Proxy0

5、在battercake-consumer中,动态代理类BatterCakeService$Proxy0,与battercake-provider建立socket连接,battercake-provider针对每一个连接,都会启动一个ServerThread处理请求,代理类则发送服务参数等相关信息

6、在battercake-consumer中,接收battercake-provider的ServerThread请求返回的结果。

上述过程时序图如下所示

image

接下来上代码!! 服务提供者

本部分的工程为battercake-provider,项目结构图如下图所示

先上使用的部分的代码 先创建一个微服务,接口如下

package com.rjzheng.service;public interface BatterCakeService {    /**     * 卖煎饼的服务     * @param name     * @return     */    public String sellBatterCake(String name);}
package com.rjzheng.service.impl;import com.rjzheng.service.BatterCakeService;public class BatterCakeServiceImpl implements BatterCakeService {    @Override    public String sellBatterCake(String name) {        // TODO Auto-generated method stub        return name+"煎饼,卖的特别好";    }}
package com.rjzheng.start;import com.rjzheng.rpc.RpcProvider;import com.rjzheng.service.BatterCakeService;import com.rjzheng.service.impl.BatterCakeServiceImpl;public class RpcBootStrap {    public static void main(String[] args) throws Exception {        BatterCakeService batterCakeService =new BatterCakeServiceImpl();        //发布卖煎饼的服务,注册在20006端口        RpcProvider.export(20006,batterCakeService);    }}
package com.rjzheng.rpc;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;import java.util.Arrays;import java.util.List;/** * RPC服务提供器 * @author zhengrongjun * */public class RpcProvider {        //存储注册的服务列表    private static List serviceList;        /**     * 发布rpc服务     * @param object     * @param port     * @throws Exception     */    public static void export(int port,Object... services) throws Exception {        serviceList=Arrays.asList(services);        ServerSocket server = new ServerSocket(port);        Socket client = null;        while (true) {            //阻塞等待输入            client = server.accept();            //每一个请求,启动一个线程处理            new Thread(new ServerThread(client,serviceList)).start();        }    }}
package com.rjzheng.rpc;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Method;import java.net.Socket;import java.util.List;public class ServerThread implements Runnable {    private Socket client = null;    private List serviceList = null;    public ServerThread(Socket client, List service) {        this.client = client;        this.serviceList = service;    }    @Override    public void run() {        ObjectInputStream input = null;        ObjectOutputStream output = null;        try {            input = new ObjectInputStream(client.getInputStream());            output = new ObjectOutputStream(client.getOutputStream());            // 读取客户端要访问那个service            Class serviceClass = (Class) input.readObject();            // 找到该服务类            Object obj = findService(serviceClass);            if (obj == null) {                output.writeObject(serviceClass.getName() + "服务未发现");            } else {                //利用反射调用该方法,返回结果                try {                    String methodName = input.readUTF();                    Class
[] parameterTypes = (Class
[]) input.readObject(); Object[] arguments = (Object[]) input.readObject(); Method method = obj.getClass().getMethod(methodName, parameterTypes); Object result = method.invoke(obj, arguments); output.writeObject(result); } catch (Throwable t) { output.writeObject(t); } } } catch (Exception e) { e.printStackTrace(); } finally { try { client.close(); input.close(); output.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private Object findService(Class serviceClass) { // TODO Auto-generated method stub for (Object obj : serviceList) { boolean isFather = serviceClass.isAssignableFrom(obj.getClass()); if (isFather) { return obj; } } return null; }}
package com.rjzheng.rpc;import java.lang.reflect.Proxy;public class RpcConsumer {        public static 
T getService(Class
clazz,String ip,int port) { ProxyHandler proxyHandler =new ProxyHandler(ip,port); return (T)Proxy.newProxyInstance(RpcConsumer.class.getClassLoader(), new Class
[] {clazz}, proxyHandler); }}
package com.rjzheng.rpc;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.net.Socket;import com.rjzheng.service.BatterCakeService;public class ProxyHandler implements InvocationHandler {    private String ip;    private int port;    public ProxyHandler(String ip, int port) {        // TODO Auto-generated constructor stub        this.ip = ip;        this.port = port;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        // TODO Auto-generated method stub        Socket socket = new Socket(this.ip, this.port);        ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());        ObjectInputStream input = new ObjectInputStream(socket.getInputStream());        try {            output.writeObject(proxy.getClass().getInterfaces()[0]);            output.writeUTF(method.getName());            output.writeObject(method.getParameterTypes());            output.writeObject(args);            output.flush();            Object result = input.readObject();            if(result instanceof Throwable) {                throw (Throwable) result;            }                return result;        } finally {            socket.shutdownOutput();        }    }}
package com.rjzheng.start;import com.rjzheng.rpc.RpcConsumer;import com.rjzheng.service.BatterCakeService;public class RpcTest {    public static void main(String[] args) {        BatterCakeService batterCakeService=RpcConsumer.getService(BatterCakeService.class, "127.0.0.1", 20006);        String result=batterCakeService.sellBatterCake("双蛋");        System.out.println(result);    }}

转载于:https://my.oschina.net/findurl/blog/1928590

你可能感兴趣的文章
Windows Server 2012的服务管理自动化 -启动类型设置,手动启动还是自动启动
查看>>
Chrome浏览器调用摄像头拍照
查看>>
表空间在dba_tablespaces中存在,删除时却提示无法删除
查看>>
secure shell(SSH)
查看>>
我的友情链接
查看>>
探秘varian:优雅的发布部署程序
查看>>
shell脚本(1)
查看>>
perl中的sig问题
查看>>
Ubuntu下ssh登陆出现host can not be established解决
查看>>
华为3700 WEB管理配置
查看>>
我的友情链接
查看>>
CentOS6.x安装memcached-1.5.x
查看>>
mysql搭建主从数据库及测试(ubuntu)
查看>>
Linux常用命令集合
查看>>
Oracle中的copy from导数
查看>>
MySQL多实例安装部署
查看>>
fastdfs添加新group注意事项
查看>>
Java 程序编译运行
查看>>
PyTorch快速入门教程三(神经网络)
查看>>
网规:第1章 计算机网络原理-1.10服务质量控制技术
查看>>