dubbox

相信有很多小伙伴都知道,dubbo是一个分布式、高性能、透明化的RPC服务框架,提供服务自动注册、自动发现等高效服务治理方案,dubbo的中文文档也是非常全的,中文文档可以参考这里dubbo.io。由于官网的介绍比较简洁,我这里打算通过Maven多模块工程再给小伙伴们演示一下用法。


 


节点角色说明
节点角色说明
Provider暴露服务的服务提供方
Consumer调用远程服务的服务消费方
Registry服务注册与发现的注册中心
Monitor统计服务的调用次数和调用时间的监控中心
Container服务运行容器
调用关系说明
  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

Dubbo 架构具有以下几个特点,分别是连通性、健壮性、伸缩性、以及向未来架构的升级性。


集群容错模式

可以自行扩展集群容错策略,参见:集群扩展

Failover Cluster

失败自动切换,当出现失败,重试其它服务器 1。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。

重试次数配置如下:

<dubbo:service retries="2" />

<dubbo:reference retries="2" />

<dubbo:reference>
    <dubbo:method name="findFoo" retries="2" />
</dubbo:reference>

Failfast Cluster

快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

Failsafe Cluster

失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

Failback Cluster

失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

Forking Cluster

并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。

Broadcast Cluster

广播调用所有提供者,逐个调用,任意一台报错则报错 2。通常用于通知所有提供者更新缓存或日志等本地资源信息。

集群模式配置

按照以下示例在服务提供方和消费方配置集群模式

<dubbo:service cluster="failsafe" />

<dubbo:reference cluster="failsafe" />


 
这里我还是以dubbo官方文档中的例子作为基准,我们来详细的看看运行过程。

创建一个Maven工程

IntelliJ中创建Maven工程的方式我这里就不再多说了,这里只说一点,工程创建成功之后,将src目录删除,因为我们不需要在这个工程下面写代码,我们将以这个工程为父工程,然后给它创建多个模块。

向创建好的工程中添加模块

当我们第一步成功创建了要给Maven工程之后,第二步我们就向这个Maven工程中添加三个模块,分别是common,provider和consumer三个模块,添加完成之后效果如下:
这里写图片描述

provider将作为我们的服务提供者,consumer将作为服务消费者,这两个好理解,除了这两个之外我们还需要要给common模块,common模块主要是提供公共接口,供服务提供者和服务消费者使用。

向common模块中添加接口

在common模块中,添加一个SayHello接口,如下:

这里写图片描述

provider模块依赖common并提供服务

1.首先打开provider的pom.xml文件,在其中添加依赖,要添加的依赖有如下四个小类:

1.添加对common模块的依赖
2.添加对spring的依赖
3.添加对dubbo的依赖
4.添加对zookeeper的依赖

如下:

<dependencies>
        <dependency>
            <groupId>org.sang</groupId>
            <artifactId>common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
                <exclusion>
                    <artifactId>netty</artifactId>
                    <groupId>org.jboss.netty</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.10</version>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>
    </dependencies>


然后在provider中实现common模块的接口,如下:

public class SayHelloImpl implements SayHello {
    public String sayHello(String name) {
        return "Hello "+name;
    }
}


然后我们需要在provider的spring配置文件中暴露服务,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="hello-world-app"></dubbo:application>
    <!--<dubbo:registry address="multicast://224.5.6.7:2181"/>-->
    <dubbo:registry address="zookeeper://192.168.248.128:2181"/>
    <dubbo:protocol name="dubbo" port="20880"/>
    <dubbo:service interface="org.sang.SayHello" ref="sayHelloImpl"/>
    <bean id="sayHelloImpl" class="org.sang.SayHelloImpl"/>
</beans>


这里我采用了dubbo推荐的注册中心zookeeper,关于Linux上zookeeper的安装小伙伴们可以参考Linux上安装Zookeeper以及一些注意事项。
注册地址就是你安装zookeeper的服务器地址,然后将服务的接口暴露出来即可。

最后我们采用一个main方法将provider跑起来,如下:

public class Main {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        ctx.start();
        System.in.read();
    }
}


OK,如此之后我们的provider模块就算开发完成了。

在consumer模块中消费服务

首先在consumer模块中添加相关依赖,要依赖的东西和provider的依赖一样,这里我就不再重复贴出代码。
然后我们在consumer的spring配置文件中订阅服务,订阅方式如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <dubbo:application name="consumer-of-helloworld-app"/>
    <!--<dubbo:registry address="multicast://224.5.6.7:2181" check="false"/>-->
    <dubbo:registry address="zookeeper://192.168.248.128:2181" check="false"/>
    <dubbo:reference id="sayHello" interface="org.sang.SayHello" check="false"/>
</beans>


首先订阅地址依然是zookeeper的地址,然后注册一个SayHello的bean,这个bean可以直接在我们的工程中使用。
一样,我们还是通过一个main方法来启动服务消费端:

public class Main {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        SayHello sayHello = (SayHello) ctx.getBean("sayHello");
        String s = sayHello.sayHello("张三");
        System.out.println(s);
    }
}


运行结果如下:
这里写图片描述

Ok,至此,一个简单的案例就完成了,有问题欢迎小伙伴留言讨论。

 如果测试和开发公用一个zookeeper,。dubbo这边配置不同的group就好了


  • 连接个数:单连接
  • 连接方式:长连接
  • 传输协议:TCP
  • 传输方式:NIO异步传输
  • 序列化:Hessian二进制序列化
  • 适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用dubbo协议传输大文件或超大字符串
  • 适用场景:常规远程服务方法调用
为什么采用异步单一长连接:
因为服务的现状大都是服务提供者少,通常只有几台机器,
而服务的消费者多,可能整个网站都在访问该服务,
比如Morgan的提供者只有6台提供者,却有上百台消费者,每天有1.5亿次调用,
如果采用常规的hessian服务,服务提供者很容易就被压跨,
通过单一连接,保证单一消费者不会压死提供者,
长连接,减少连接握手验证等,

并使用异步IO,复用线程池,防止C10K问题。


在dubbo RPC中,同时支持多种序列化方式,例如:

  1. dubbo序列化:阿里尚未开发成熟的高效java序列化实现,阿里不建议在生产环境使用它
  2. hessian2序列化:hessian是一种跨语言的高效二进制序列化方式。但这里实际不是原生的hessian2序列化,而是阿里修改过的hessian lite,它是dubbo RPC默认启用的序列化方式
  3. json序列化:目前有两种实现,一种是采用的阿里的fastjson库,另一种是采用dubbo中自己实现的简单json库,但其实现都不是特别成熟,而且json这种文本序列化性能一般不如上面两种二进制序列化。
  4. java序列化:主要是采用JDK自带的Java序列化实现,性能很不理想。

在通常情况下,这四种主要序列化方式的性能从上到下依次递减。对于dubbo RPC这种追求高性能的远程调用方式来说,实际上只有1、2两种高效序列化方式比较般配,而第1个dubbo序列化由于还不成熟,所以实际只剩下2可用,所以dubbo RPC默认采用hessian2序列化。

但hessian是一个比较老的序列化实现了,而且它是跨语言的,所以不是单独针对java进行优化的。而dubbo RPC实际上完全是一种Java to Java的远程调用,其实没有必要采用跨语言的序列化方式(当然肯定也不排斥跨语言的序列化)。

最近几年,各种新的高效序列化方式层出不穷,不断刷新序列化性能的上限,最典型的包括:

  • 专门针对Java语言的:Kryo,FST等等
  • 跨语言的:Protostuff,ProtoBuf,Thrift,Avro,MsgPack等等

这些序列化方式的性能多数都显著优于hessian2(甚至包括尚未成熟的dubbo序列化)。

有鉴于此,我们为dubbo引入Kryo和FST这两种高效Java序列化实现,来逐步取代hessian2。

其中,Kryo是一种非常成熟的序列化实现,已经在Twitter、Groupon、Yahoo以及多个著名开源项目(如Hive、Storm)中广泛的使用。而FST是一种较新的序列化实现,目前还缺乏足够多的成熟使用案例,但我认为它还是非常有前途的。

在面向生产环境的应用中,我建议目前更优先选择Kryo。

启用Kryo和FST

使用Kryo和FST非常简单,只需要在dubbo RPC的XML配置中添加一个属性即可:

<dubbo:protocol name="dubbo" serialization="kryo"/>
<dubbo:protocol name="dubbo" serialization="fst"/>

参考资料:http://dubbo.io

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值