Dubbo框架介绍与手写模拟Dubbo

dubbo:被称作开源 Java RPC框架
RPC:对于java程序员而言,RPC就是远程的方法调用;
远程方法调用:我们经常使用的是本地方法调用,相对的远程方法调用性质上差不多,也是方法调用。但是是通过网络去连接,两个不同线程之间的调用。
往泛了说像http网络协议传输数据,TCP协议输出数据都算的上是RPC。
Dubbo:
1、dubbo协议 数据格式 netty
2、http协议 数据格式 tomcat,jetty
手写Dubbo
概念
在java程序中,远程调用方法;
服务提供者:
1、提供服务的接口
2、提供实现类
3、注册服务(注册中心,本地注册)
4、暴露服务(tomcat,nettyServer接受及处理请求)
代码实现
服务提供者主要功能就是方法的提供者
(远程方法的提供者)
需要暴露方法出去,就需要启动tomcat暴露我们的方法,
tomcat是个Servlet容器,我们还需要写一个Servlet来接受请求。
public class DispatcherServlet extends HttpServlet {

定义一个HttpServlet,handler(req, resp);就是处理请求的方法。

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        new HttpServerHandler().handler(req, resp);
    }
}

那我们怎么才能访问一个服务呢?
需要给定以下四个东西才能指定服务,并且有效的调用
1、接口名
2、方法名
3、方法参数类型列表
4、方法值列表
我们把这四个必要的东西构建成一个对象,
Invocation对象

 private String interfaceName;
    private String methodName;
    private Class[] paramTypes;
    private Object[] params;
    //和上面一一对应

handler要处理请求肯定是要得到上面这四个值,我们要怎么获得Invocation对象呢?
现在我们想提供HelloService这个服务

public interface HelloService {
    String sayHello(String userName);
}

假设我们这个服务只有一个实现

public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String userName) {
        return "Hello: " + userName;
    }
}

在我们的提供者中是需要注册服务的,我们这边先把服务注册到本地
这就要使用到注册相关的类

public class LocalRegister {
private static Map<String, Class> map = new HashMap<>();
public static void regist(String interfaceName, Class implClass) {
        map.put(interfaceName, implClass);
    }
    //传我一个接口名和实现类,保存到map中
public static Class get(String interfaceName) {
       return map.get(interfaceName);
    }
    //通过接口名获得对应实现类
}

本地注册
有了这个注册类;
使用这行代码,就可以把Invocation存起来了。
LocalRegister.regist(HelloService.class.getName(), HelloServiceImpl.class);
再之后就可以再handler中使用get方法获得Invocation类了。
获得了invocation方法就可以执行请求了
Method method = implClass.getMethod(invocation.getMethodName(), invocation.getParamTypes());
var result = (String) method.invoke(implClass.newInstance(), invocation.getParams());
到此我们就得到结果了
然后返回结果
System.out.println(“tomcat:” + result);
IOUtils.write(result, resp.getOutputStream());

如果需要不通服务的实现类,可以通过添加多个版本实现。
服务消费者
发送数据方法,
发送的地址,哪个端口,发送的数据是什么
地址:hostname
端口:port
要发送的数据就是我们的:Invocation
利用jdk自带的http方式发送数据即可。

   public String send(String hostname, Integer port, Invocation invocation) {
        try {
            URL url = new URL("http", hostname, port, "/");
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setDoOutput(true);
            OutputStream outputStream = httpURLConnection.getOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(outputStream);
            oos.writeObject(invocation);
            oos.flush();
            oos.close();
            InputStream inputStream = httpURLConnection.getInputStream();
            String result = IOUtils.toString(inputStream);
            return result;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

我们消费者去调用这个方法

 HttpClient httpClient=new HttpClient();
        Invocation invocation=new Invocation(HelloService.class,"sayhello",new Class[]{String.class},new Object[]{"方法"});
       String result =httpClient.send("localhost",8080,invocation);

这就完成了远程的方法调用,但是这种调用方式对于消费者而言非常不友好。
这里我们利用jdk的动态代理

HelloService helloService = ProxyFactory.getProxy(HelloService.class);
        String xxx = helloService.sayHello("xxx");
 @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String mock = System.getProperty("mock");
                if (mock != null && mock.startsWith("return:")) {
                    String result = mock.replace("return:", "");
                    return result;
                }

                Invocation invocation = new Invocation(interfaceClass.getName(), method.getName(), method.getParameterTypes(), args);
                List<URL> urlList = RemoteMapRegister.get(interfaceClass.getName());
                URL url = LoadBalance.random(urlList);
                Protocol protocol = ProtocolFactory.getProtocol();
                String result = protocol.send(url, invocation);
                return result;
            }

把方法写活,只利用HelloService helloService = ProxyFactory.getProxy(HelloService.class);方法,然后再传入String xxx = helloService.sayHello(“xxx”);值就可以实现调用了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值