dubbo

1、前言

1.1、Dubbo 简介

[Dubbo]是由阿里巴巴基于java开发的一个RPC框架,经历过了长时间的停止维护后又重新开始维护,现在(2018年04月17日)已经划入了Apache孵化项目中,github地址:https://github.com/apache/incubator-dubbo,在国内属于一个应用广泛的RPC框架,接下来就一起来学习Dubbo是如何使用的,其原理又是如何。
TODO 提个问题那么Dubbo和Spring Cloud又有什么同异呢?

1.2、RPC 简介

RPC全称Remote Procedure Call,中文名叫远程过程调用,通过网络利用TCP或者UDP协议实现的不同机器之间的数据传输协议,A机器想调取B机器提供的服务,A机器拼接好自身请求的参数之后由RPC框架包装成为特定格式的数字,序列化后后通过网络发送到B机器上,B机器的RPC框架反解析出参数数据后去invoke调用自身机器的服务,最后按照原路返回到A机器上。

RPC是C/S模式,而且屏蔽了传输层和应用层,再基于特定的协议,使得用户只需要关注自身的业务即可。

1.3、SOA 简介

SOA全称Service-Oriented Architecture,中文名叫面向服务编程,另一个常用的名称是服务发现。业务繁多而且复杂就需要有一种统一的管理服务的机制,在分布式架构中,新加入的机器或者宕掉的机器后系统如何自动调整,一方面使得流量分发均衡,另一方面能够及时发现出现异常的服务;控制服务与服务的调用关系等,确保服务合理正常的运行,例如zookeeper可以统一管理各机器以及机器上的服务运行情况。

在我们介绍的dubbo也会使用zookeeper作为其服务注册中心

1.4、Zookeeper 简介&安装

zookeeper是为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

进入到http://mirrors.hust.edu.cn/apache/zookeeper/页面选择一个合适的版本,进入下载其tar.gz包,随便解压到一个本地目录,如下图

image

进入到conf文件夹,可以看到zoo_sample.cfg文件,直接cp一个名字为zoo.cfg的文件,可以把内容修改为如下内容

$ cat zoo.cfg
tickTime=2000
dataDir=../data      // 工作路径,表示为conf的上一级目录的data文件夹
dataLogDir=../logs  // 日志的路径
clientPort=2182  // zk启动的端口

现在就可以启动zk了,进入到bin目录,Windows环境选择zkServer.cmd,Unix类环境选择zkServer.sh

$ ./zkServer.sh
JMX enabled by default
Using config: ./../conf/zoo.cfg
Usage: ./zkServer.sh {start|start-foreground|stop|restart|status|upgrade|print-cmd}

如上述执行结果,很明显已经确实加载了之前配置的zoo.cfg文件,但是需要加上启动参数,其中有{start|start-foreground|stop|restart|status|upgrade|print-cmd}

  • start-foreground 前台启动,可以看到实时日志
  • start 后台启动

在这遇到一个,当前台启动之后,执行stop命令时,会提示没有发现对应的服务pid,可是如果以start方式启动,就可以正常使用stop关闭zk服务

image

zk服务已经正常启动了,如下图,1896端口的服务就是zk启动的java进程服务

image

2、Dubbo 服务提供方

整个的文件目录结构

image

spring-product.xml

<context:property-placeholder location="pro.properties" />

<!-- 消费方应用名 -->
<dubbo:application name="${dubbo.application.name}" owner="${dubbo.application.owner}" />
<dubbo:provider loadbalance="random" default="true"/>
<dubbo:registry protocol="zookeeper" address="${dubbo.zk.servers}" client="zkclient" group="${dubbo.zk.group}"/>
<dubbo:protocol name="${dubbo.application.protocol.name}" port="${dubbo.application.protocol.port}"/>
<!--<dubbo:monitor address="${dubbo.monitor.address}" />-->
<dubbo:consumer check="false" />

<bean class="com.jwfy.dubbo.product.ProductServiceImpl" id="productService" />
<!--  基础的bean 配置-->

<dubbo:service interface="com.jwfy.dubbo.product.ProductService" ref="productService" />
<!-- dubbo 对外暴露的接口,映射到的实体bean是productService-->

pro.properties

# dubbo
dubbo.application.name=dubbo-demo
dubbo.application.owner=jwfy
dubbo.application.protocol.name=dubbo
dubbo.application.protocol.port=20880

# dubbo.monitor.address=dubbo://127.0.0.1:20888
dubbo.zk.servers=127.0.0.1:2182
dubbo.zk.group=dubbo-demo

dubbo的相关配置,包含了使用的协议以及端口还有zk的配置情况,这里就使用了2182端口,到时候就会连上上文启动的zk服务

ProductService 接口

public interface ProductService {
    void print();
    String getStr();
}

dubbo对外暴露的时候都是通过动态代理反射的,必须存在相关接口

ProductServiceImpl 实现类

public class ProductServiceImpl implements ProductService {

    public void print() {
        System.out.println("print");
    }

    public String getStr() {
        return "Hello World Product";
    }
}

ProductBootstrap 启动类

public class ProductBootstrap {

    /**
    * 其实这个函数是用硬编码的形式代替xml配置,xml配置最后都会变成如下的数据以及参数进行处理
    */
    public static void runProduct(){
        ProductService demo = new ProductServiceImpl();
        ApplicationConfig config=new ApplicationConfig("simple-spring-dubbo");

        RegistryConfig reg=new RegistryConfig("127.0.0.1:2182");
        reg.setProtocol("zookeeper");

        ProtocolConfig protocol = new ProtocolConfig();
        protocol.setName("dubbo");
        protocol.setPort(20880);

        ServiceConfig<ProductService> service=new ServiceConfig<ProductService>();
        service.setApplication(config);
        service.setRegistry(reg);
        service.setProtocol(protocol);
        service.setInterface(ProductService.class);
        service.setRef(demo);
        service.setVersion("1.0");
        service.export();
        // export是最关键的函数,对外暴露服务
        // 包括了向zk注册以及启动netty服务等待接受调用

        try {
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void runDubboProduct(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                new String[]{"spring-product.xml"});

        while (true){
       // 为了让服务不会自己终止,加个死循环
        }
    }

    public static void main(String[] args){
        //runProduct();
        runDubboProduct();
    }

}

如下图dubbo-admin显示的数据,服务提供方已经正常启动,同时可以看到该服务的具体情况

image
image
image

可以通过Telnet查看当前机器上dubbo服务提供方的一些数据,当线上服务提供方添加了新的接口就可以通过该方法确认

3、Dubbo 服务调用方

调用方文件目录结构

image

spring-consume.xml 文件

<context:property-placeholder location="application.properties" />

<!-- 消费方应用名 -->
<dubbo:application name="${dubbo.application.name}" owner="${dubbo.application.owner}" />
<dubbo:provider loadbalance="random" default="true"/>
<dubbo:registry protocol="zookeeper" address="${dubbo.zk.servers}" client="zkclient" group="${dubbo.zk.group}"/>
<dubbo:protocol name="${dubbo.application.protocol.name}" port="${dubbo.application.protocol.port}"/>
<!--<dubbo:monitor address="${dubbo.monitor.address}" />-->
<dubbo:consumer check="false" />

<dubbo:reference interface="com.jwfy.dubbo.product.ProductService" id="productService"  />

application.proerties 文件

# dubbo
dubbo.application.name=dubbo-consume
dubbo.application.owner=jwfy
dubbo.application.protocol.name=dubbo
dubbo.application.protocol.port=20880

dubbo.monitor.address=dubbo://127.0.0.1:20888
dubbo.zk.servers=127.0.0.1:2182
dubbo.zk.group=dubbo-consumer-demo

public class ConsumeBootstrap {

    private static final Logger logger = LoggerFactory.getLogger(ConsumeBootstrap.class);

    public static void runDubboConsume(){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                new String[]{ "spring-consume.xml" });

        ProductService productService = (ProductService)applicationContext.getBean("productService");

        System.out.println(productService.getStr());

        while (true){

        }
    }

    public static void main(String[] args){
        runDubboConsume();

    }

}

直接启动,显示连接拒绝错误

Exception in thread "main" com.alibaba.dubbo.rpc.RpcException: Forbid consumer 192.168.10.123 access service com.jwfy.dubbo.product.ProductService from registry 127.0.0.1:2182 use dubbo version 2.5.3, Please check registry access list (whitelist/blacklist).
    at com.alibaba.dubbo.registry.integration.RegistryDirectory.doList(RegistryDirectory.java:579)
    at com.alibaba.dubbo.rpc.cluster.directory.AbstractDirectory.list(AbstractDirectory.java:73)
    at com.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.list(AbstractClusterInvoker.java:260)
    at com.alibaba.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:219)
    at com.alibaba.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:72)
    at com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:52)
    at com.alibaba.dubbo.common.bytecode.proxy0.getStr(proxy0.java)
    at com.jwfy.dubbo.consume.ConsumeBootstrap.runDubboConsume(ConsumeBootstrap.java:22)
    at com.jwfy.dubbo.consume.ConsumeBootstrap.main(ConsumeBootstrap.java:30)

拒绝链接到远程服务,这时候需要核对服务提供方以及服务调用方的配置是否不同

经过观察发现是服务调用方的zk组写错了,调用方在使用不存在的zk注册的时候,会被禁止掉,从而提示该错误

把application.proerties 中的dubbo.zk.group=dubbo-consumer-demo修改为dubbo.zk.group=dubbo-demo,再启动,就恢复正常了,再看看dubbo-admin的显示

image
image
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352