1、SOA模式
首先简单介绍一下SOA模式,这对咱们后面理解Dubbo颇有帮助。数据库
SOA模式是什么?编程
SQA(Service-Oriented Architecture)即面向服务架构,它将应用程序的不一样功能单元(这里就理解为服务)进行了拆分。在这种架构下项目不会直接和数据库进行交互,而是经过调用不一样服务的接口来访问数据库。设计模式
模式优势在哪?架构
这样最直接的好处就是解决代码冗余,若是多个项目同时都要访问数据库同一张表。好比用户表的访问。咱们能够直接调用用户服务里面的接口进行开发,而不须要每一个项目都去写一遍用户表的增删改查。除了这个,SOA能带给咱们的好处就是可以让开发者以更迅速、更可靠、更具重用性架构整个业务系统。较之以往MVC开发模式,以SOA架构的系统可以更加从容地面对业务的急剧变化。框架
SOA示意图:ide
2、Dubbo基本组成
聊完了SOA,如今来看看Dubbo内部架构,相信你们多多少少看过下面这幅图:源码分析
@Override protected void doSubscribe(final URL url, final NotifyListener listener) { try { if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {//根据URL获得服务接口为*,也就是全部 String root = toRootPath(); ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);//拿取URL下的监听器 if (listeners == null) {//不存在则进行建立 zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>()); listeners = zkListeners.get(url); } ChildListener zkListener = listeners.get(listener);//获得子目录的监听器 if (zkListener == null) {//没法获得子目录监听器,则会新建一个。 listeners.putIfAbsent(listener, new ChildListener() { @Override public void childChanged(String parentPath, List<String> currentChilds) { for (String child : currentChilds) { child = URL.decode(child); if (!anyServices.contains(child)) { anyServices.add(child); //若是consumer的interface为*,会订阅每个url,会触发另外一个分支的逻辑 //这里是用来对/dubbo下面提供者新增时的回调,至关于增量 subscribe(url.setPath(child).addParameters(Constants.INTERFACE_KEY, child, Constants.CHECK_KEY, String.valueOf(false)), listener); } } } }); zkListener = listeners.get(listener); } zkClient.create(root, false); //添加监听器会返回子节点集合 List<String> services = zkClient.addChildListener(root, zkListener);//订阅root目录下的子元素,好比:/dubbo/com.learnDubbo.demo.DemoService/providers if (services != null && !services.isEmpty()) { for (String service : services) { service = URL.decode(service); anyServices.add(service); subscribe(url.setPath(service).addParameters(Constants.INTERFACE_KEY, service, Constants.CHECK_KEY, String.valueOf(false)), listener); } } } else { //这边是针对明确interface的订阅逻辑 List<URL> urls = new ArrayList<URL>(); //针对每种category路径进行监听 for (String path : toCategoriesPath(url)) { ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url); if (listeners == null) { zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>()); listeners = zkListeners.get(url); } ChildListener zkListener = listeners.get(listener); if (zkListener == null) { //封装回调逻辑 listeners.putIfAbsent(listener, new ChildListener() { @Override public void childChanged(String parentPath, List<String> currentChilds) { ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds)); } }); zkListener = listeners.get(listener); } //建立节点 zkClient.create(path, false); //增长回调 List<String> children = zkClient.addChildListener(path, zkListener); if (children != null) { urls.addAll(toUrlsWithEmpty(url, path, children)); } } //而且会对订阅的URL下的服务进行监听,并会实时的更新Consumer中的invoke列表,使得可以进行调用。这个方法不展开讲 notify(url, listener, urls); } } catch (Throwable e) { throw new RpcException("Failed to subscribe " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e); } }
四、invoke:根据获取到的Provider地址,真实调用Provider中功能。这里就是惟一一个同步的方法,由于消费者要获得生产者传来的数据才能进行下一步操做,可是Dubbo是一个RPC框架,RPC的核心就在于只能知道接口不能知道内部具体实现。因此在Consumer方使用了代理设计模式,建立一个Provider方类的一个代理对象,经过代理对象获取Provider中真实功能,起到保护Provider真实功能的做用。学习
invoke部分源码分析this
有兴趣的能够看看invoke调用过程url
五、Monitor:Consumer和Provider每隔1分钟向Monitor发送统计信息,统计信息包含,访问次数,频率等
4、总结 这里只是稍微对Dubbo的原理作了一下分析,想要弄懂Dubbo还须要结合源码来看。尽管不少时候咱们只是一个使用者,可是可以理解内部运行原理不但可以让咱们更好的使用,同时里面的编程思路,设计模式也是咱们须要学习的。后面还会作更多关于Dubbo的原理解析。