dubbo简介

文档

https://github.com/apache/dubbo

https://www.iteye.com/blog/javatar-1123915(dubbo的作者梁飞的博客,用一个例子描述了什么是rpc框架)

示例分析

定义服务接口

package com.alibaba.study.rpc.test;  
  
public interface HelloService {  
    String hello(String name);    
}

实现服务

package com.alibaba.study.rpc.test;  
  
public class HelloServiceImpl implements HelloService {  
    public String hello(String name) {  
        return "Hello " + name;  
    }  
}  

RPC框架

package com.alibaba.study.rpc.framework;  
  
import java.io.ObjectInputStream;  
import java.io.ObjectOutputStream;  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
import java.net.ServerSocket;  
import java.net.Socket;  
  
/** 
 * RpcFramework 
 *  
 * @author william.liangf 
 */  
public class RpcFramework {  
  
    /** 
     * 暴露服务 
     *  
     * @param service 服务实现 
     * @param port 服务端口 
     * @throws Exception 
     */  
    public static void export(final Object service, int port) throws Exception {  
        if (service == null)  
            throw new IllegalArgumentException("service instance == null");  
        if (port <= 0 || port > 65535)  
            throw new IllegalArgumentException("Invalid port " + port);  
        System.out.println("Export service " + service.getClass().getName() + " on port " + port);  
        ServerSocket server = new ServerSocket(port);  
        for(;;) {  
            try {  
                final Socket socket = server.accept();  
                new Thread(new Runnable() {  
                    @Override  
                    public void run() {  
                        try {  
                            try {  
                                ObjectInputStream input = new ObjectInputStream(socket.getInputStream());  
                                try {  
                                    String methodName = input.readUTF();  
                                    Class<?>[] parameterTypes = (Class<?>[])input.readObject();  
                                    Object[] arguments = (Object[])input.readObject();  
                                    ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());  
                                    try {  
                                        Method method = service.getClass().getMethod(methodName, parameterTypes);  
                                        Object result = method.invoke(service, arguments);  
                                        output.writeObject(result);  
                                    } catch (Throwable t) {  
                                        output.writeObject(t);  
                                    } finally {  
                                        output.close();  
                                    }  
                                } finally {  
                                    input.close();  
                                }  
                            } finally {  
                                socket.close();  
                            }  
                        } catch (Exception e) {  
                            e.printStackTrace();  
                        }  
                    }  
                }).start();  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
    /** 
     * 引用服务 
     *  
     * @param <T> 接口泛型 
     * @param interfaceClass 接口类型 
     * @param host 服务器主机名 
     * @param port 服务器端口 
     * @return 远程服务 
     * @throws Exception 
     */  
    @SuppressWarnings("unchecked")  
    public static <T> T refer(final Class<T> interfaceClass, final String host, final int port) throws Exception {  
        if (interfaceClass == null)  
            throw new IllegalArgumentException("Interface class == null");  
        if (! interfaceClass.isInterface())  
            throw new IllegalArgumentException("The " + interfaceClass.getName() + " must be interface class!");  
        if (host == null || host.length() == 0)  
            throw new IllegalArgumentException("Host == null!");  
        if (port <= 0 || port > 65535)  
            throw new IllegalArgumentException("Invalid port " + port);  
        System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port);  
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] {interfaceClass}, new InvocationHandler() {  
            public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {  
                Socket socket = new Socket(host, port);  
                try {  
                    ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());  
                    try {  
                        output.writeUTF(method.getName());  
                        output.writeObject(method.getParameterTypes());  
                        output.writeObject(arguments);  
                        ObjectInputStream input = new ObjectInputStream(socket.getInputStream());  
                        try {  
                            Object result = input.readObject();  
                            if (result instanceof Throwable) {  
                                throw (Throwable) result;  
                            }  
                            return result;  
                        } finally {  
                            input.close();  
                        }  
                    } finally {  
                        output.close();  
                    }  
                } finally {  
                    socket.close();  
                }  
            }  
        });  
    }  
  
}  

暴露服务

package com.alibaba.study.rpc.test;  
  
import com.alibaba.study.rpc.framework.RpcFramework;  
  
public class RpcProvider {    
    public static void main(String[] args) throws Exception {  
        HelloService service = new HelloServiceImpl();  
        RpcFramework.export(service, 1234);  
    }  
}  

服务消费

package com.alibaba.study.rpc.test;  
  
import com.alibaba.study.rpc.framework.RpcFramework;  
   
public class RpcConsumer {    
    public static void main(String[] args) throws Exception {  
        HelloService service = RpcFramework.refer(HelloService.class, "127.0.0.1", 1234);  
        for (int i = 0; i < Integer.MAX_VALUE; i ++) {  
            String hello = service.hello("World" + i);  
            System.out.println(hello);  
            Thread.sleep(1000);  
        }  
    }    
}  

在这里插入图片描述
首先第一个是provider,将要暴露的服务进行暴露,通过端口1234,服务消费者去调用服务提供者,怎么样去调用呢?第一个告诉的是调用哪个服务的那个方法,第二个是参数是什么,这样provider接收到后就能知道我要执行哪个服务的哪个方法,将执行结果返回给调用方,其实,dubbo做的就是这么一件事情。

dubbo设计简介

通过示例我们知道了rpc就是远程方法调用,我们接着看下dubbo的设计简介,看下dubbo是如何封装dubbo这个过程的。
在dubbo的设计原则里有这么一句话,dubbo是采用微内核+插件的设计原理进行封装的。微内核是说它的核心逻辑是非常少的,它的主要逻辑主要是通过插件的逻辑来封装,微内核的作用就是来组装这一个个插件

dubbo架构图

在这里插入图片描述
在dubbo的官网有上面这张图,consumer表示消费者,Provider表示服务提供者,Register表示注册中心,Monitor表示监视器,主要做服务治理用的,紫色的虚线表示初始化,蓝色的虚线表示异步,蓝色的实线表示同步,0步表示Provider会随着容器启动,1步会去注册要暴露的服务,2步consumer会去注册中心订阅服务,3步表示注册中心有服务变更的话去通知服务消费者,4步表示服务消费者去调用服务提供者
在这里插入图片描述
在dubbo的官网还有一张图,就是这个复杂一点的图,是dubbo的整体设计图,要怎么看呢?图分了左右两半边,浅蓝色表示Consumer,浅绿色右半边表示Provider,橙色表示的服务启动开始的地方,绿色的方块表示的接口,蓝色的方块表示具体的类,紫色的实线箭头表示的是继承,蓝色的虚线表示初始化,红色的实线箭头表示调用过程,黑色的箭头表示依赖关系。
最上一层表示business层,就是业务接口和业务接口的实现,中间表示的是RPC层,就是远程过程调用的封装,最下面一层Remoting层,就是数据交换层,黑色箭头表示上层依赖下层
接下来,看下左边,从start开始看起,consumer一般会引用一个接口,假设这个接口是ServiceA,我要消费的是ServiceA这个接口,这个接口会有一个ReferenceConfig(服务引用的配置),ReferenceConfig会通过ProxyFactory生成一个Proxy代理类,Proxy代理类是实现了我们需要引用的业务接口,ReferenceConfig还会初始化一个Protocol,默认是DubboProtocol,通过DubboProtocol去初始化一个DubboInvoke,还会初始化Exchange、Transport、Codec、Serialization 做数据交换用,这就是Consumer端的初始化大致过程
再看下,右边Provider端,也从start开始,首先会有一个服务暴露的接口,还有服务接口的实现,也就是业务接口会有一个Implemant,通过ServiceConfig去将服务暴露的配置进行初始化,再通过初试化的DubboProtocol去export一个DubboExproter,最后再初始化一个DubboHandler,还会初始化Exchange、Transport、Codec、Serialization 做数据交换用
最后,看下服务调用的过程,服务调用是从consumer端调用到Provider,用户会通过Interface接口调用到生成的Proxy,Proxy调用到Invoker,Invoker会做一个LoadBalance(负载均衡,服务端会有多个),再去调用Dubbo的Filter,经过一系列Filter后,去调用Dubbo的Invoker,再通过ExchangeClient做数据交换的,最后通过Codec做dubbo协议的数据编码,编码后写到输出流里,写到输出流之后,服务提供者这一端会读到我们的数据,再去通过codec做数据解码,之后通过ChannelHandler调到DubboHandler,再调到DubboExporter,最后调用到Dubbo的Filter,最后通过Invoker调用到Interface的实现Implement

核心领域模型

  • Protocol:服务域
  • Invoker:实体域
  • Invocation:会话域,主要封装了方法调用所需要的关键信息,比如方法名、参数类型、参数
    Invoker+Invocation -> 是dubbo对方法调用的抽象,Invoker.invoke(Invocation)

在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值