Dubbo学习

  • 一、传统应用架构到分布式架构的演化
  • 1、单体式应用架构
  • 2、多个垂直应用架构
  • 3、分布式服务架构
  • 4、流动计算机架构(SOA服务化)
  • 二、Dubbo技术架构
  • 三、Dubbo的核心配置
  • 1、映射规则
  • 2、属性配置优先级
  • 3、启动时检查
  • 4、集群容错
  • 5、负载均衡策略
  • 6、多协议配置
  • 7、多版本配置
  • 8、服务分组
  • 四、小例子
  • 生产者代码
  • 消费者代码


一、传统应用架构到分布式架构的演化

dubbo微内核 dubbo核心配置_dubbo微内核

1、单体式应用架构

当网站流量很小时,只需要一个应用,将所有功能部署在一起。此时,用于简化增删改查工作量的数据库访问框架(ORM)是关键,例如SSM,Spring MVC,配合Nginx做负载均衡已足够使用。

2、多个垂直应用架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆分成几个互不相干的应用。此时,用于加速前端页面开发的web框架(MVC)是关键。但是不同应用之间无法高效的利用。

3、分布式服务架构

当垂直架构越来越多,应用之间的交互不可避免。将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复合及整合的分布式服务框架(RPC)是关键,实现不同的应用之间的互相调用。

4、流动计算机架构(SOA服务化)

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐出现,此时需要一个调度中心基于访问压力实时管理集群容量,动态更新调度策略,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

二、Dubbo技术架构

dubbo微内核 dubbo核心配置_Dubbo_02


各个节点角色说明:

节点

角色说明

Provider

暴露服务的提供方

Consumer

调用远程服务的服务消费方

Registry

服务注册与发现的注册中心

Monitor

统计服务的调用次数和调用时间的监控中心

Container

服务运行容器

上图可以看出,Dubbo的架构很像生产者-消费者模型,只是在这个模型上加了注册中心和监控中心。

那么,整个过程大概就分为以下几步:

  • 1、启动容器,加载,运行服务提供方
  • 2、服务提供方在启动时,在注册中心发布自己提供的服务
  • 3、注册中心通知服务消费方可以进行消费了
  • 4、服务消费方通过注册中心订阅自己所需要的服务

三、Dubbo的核心配置

标签

作用

延伸

dubbo:service

服务配置

用于暴露一个服务,定义服务的元信息,一个服务可以用多个协议暴露,一个服务也可以注册到多个注册中心

dubbo:reference

引用配置

用于创建一个远程服务代理,一个引用可以指向多个注册中心

dubbo:protocol

协议配置

用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受

dubbo:application

应用配置

用于配置当前应用信息,不管该应用是提供者还是消费者

dubbo:module

模块配置

用于配置当前模块信息,可选

dubbo:registry

注册中心配置

用于配置连接注册中心相关信息

dubbo:monitor

监控中心配置

用于配置连接监控中心相关信息,可选

dubbo:provider

提供方配置

当 ProtocolConfig 和 ServiceConfig 某属性没有配置时,采用此缺省值,可选

dubbo:consumer

消费方配置

当 ReferenceConfig 某属性没有配置时,采用此缺省值,可选

dubbo:method

方法配置

用于 ServiceConfig 和 ReferenceConfig 指定方法级的配置信息

dubbo:argument

参数配置

用于指定方法参数配置

Dubbo 将自动加载 classpath 根目录下的 dubbo.properties,可以通过JVM启动参数 -Ddubbo.properties.file=xxx.properties 改变缺省配置位置。

1、映射规则

将XML配置的标签名,加属性名,用点分割,多个属性拆成多行。

  • 比如:dubbo.registry.address=10.20.153.10:9090等价于<dubbo:registry address=“10.20.153.10:9090” />

多协议配置示例:

#dubbo\u652F\u6301\u7684dubbo\u534F\u8BAE\u914D\u7F6E
dubbo.protocol.name=dubbo
dubbo.protocol.dubbo.port=20903

#dubbo\u652F\u6301\u7684http rest api\u7684\u914D\u7F6E
dubbo.protocol.name=rest
dubbo.protocol.rest.port=9013
dubbo.protocol.rest.server=tomcat
2、属性配置优先级

dubbo微内核 dubbo核心配置_spring_03


如果虚拟机传入参数优先级最高,如果虚拟机没有传入,Dubbo的XML和SpringBoot的Application.properties优先,如果上面两个都没有传,则dubbo.properties优先,dubbo.properties一般是公共的配置。

3、启动时检查

Dubbo默认会在启动时检查依赖的服务是否可用,不可用时会抛异常,阻止Spring初始化完成,以便上线时,能及早发现问题,默认check=“true”

可以通过设置check=“false”关闭检查,比如测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。
如果设置check=“false”,总是会返回引用,当服务恢复时,会自动连接上。

问题:如果Dubbo的生产者端没有启动,消费者端能启动吗?

答案是可以的,可以关闭消费者端服务的启动检查:(没有提供者时也不报错)

<dubbo:reference interface="com.foo.BarService" check="false" />

关闭注册中心启动检查:(没有配置中心也不报错)

<dubbo:registry check="false" />
4、集群容错

失败自动切换,当出现失败,重试其他服务器。通常用来读操作,但重试会带来更长延迟,可以通过设置retries=“2”来设置重试次数(不包含第一次)。
配置如下:

<dubbo:service retries="2" />

<dubbo:reference retries="2" />

设置容错机制:

<dubbo:service cluster="failsafe" />
5、负载均衡策略
  • Random LoadBalance :随机,按权重设置随机概率(默认)
  • RoundRobin LoadBalance:轮询,按公约后的权重设置轮询比率。
  • LeastActive LoadBalance :最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
  • ConsistentHash LoadBalance:一致性 Hash,相同参数的请求总是发到同一提供者。

可以在dubbo.properties中设置:

dubbo.service.loadbalance=roundrobin
6、多协议配置
<!-- 多协议配置 -->
    <dubbo:protocol name="dubbo" port="20904" />
    <dubbo:protocol name="rest" port="9014" />

或者

#dubbo\u652F\u6301\u7684dubbo\u534F\u8BAE\u914D\u7F6E
dubbo.protocol.name=dubbo
dubbo.protocol.dubbo.port=20904

#dubbo\u652F\u6301\u7684http rest api\u7684\u914D\u7F6E
dubbo.protocol.name=rest
dubbo.protocol.rest.port=9014
dubbo.protocol.rest.server=tomcat
7、多版本配置

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务之间相互不引用。

老版本服务提供者:

<dubbo:service interface="com.foo.BarService" version="1.0.0" />

新版本服务提供者:

<dubbo:service interface="com.foo.BarService" version="2.0.0" />

老版本服务消费者:

<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" />

新版本服务消费者:

<dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />
8、服务分组

当一个接口有多个实现时,可以用group名区分。

服务:

<dubbo:service group="feedback" interface="com.xxx.IndexService" />
<dubbo:service group="member" interface="com.xxx.IndexService" />

引用:

<dubbo:reference id="feedbackIndexService" group="feedback" interface="com.xxx.IndexService" />
<dubbo:reference id="memberIndexService" group="member" interface="com.xxx.IndexService" />

任意组:

<dubbo:reference id="barService" interface="com.foo.BarService" group="*" />

四、小例子

生产者代码

生产者配置Spring-dubbo.xml:

<?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服务类所在包的注解-->
    <dubbo:annotation package="com.debug.mooc.dubbo.one.server.service.dubbo" />

    <!--注册中心zookeeper配置信息-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <!--支持两种协议的调用:rpc-dubbo协议;http协议-rest api-url调用-->
    <dubbo:protocol name="rest" threads="500" contextpath="v1" server="tomcat" accepts="500"/>
    <dubbo:protocol name="dubbo" />

    <!--消费方信息配置-->
	<dubbo:application name="dubboOne-consume" owner="debug" organization="dubbox"/>


</beans>

生产者配置dubbo.properties:

##
dubbo.container=log4j,spring
dubbo.reference.check=false
dubbo.registry.client=curator
dubbo.application.name=dubboOne-provider
dubbo.application.owner=debug

#dubbo\u652F\u6301\u7684dubbo\u534F\u8BAE\u914D\u7F6E
dubbo.protocol.name=dubbo
dubbo.protocol.dubbo.port=20903

#dubbo\u652F\u6301\u7684http rest api\u7684\u914D\u7F6E
dubbo.protocol.name=rest
dubbo.protocol.rest.port=9013
dubbo.protocol.rest.server=tomcat

dubbo.service.loadbalance=roundrobin

生产者提供Service:

public interface IDubboItemService {

    BaseResponse listItems();
}

生产者提供Service实现类:

// 支持Dubbo协议和HTTP协议
@Service(protocol = {"dubbo","rest"},validation = "true",version = "1.0",timeout = 3000)
@Path("moocOne")
public class DubboItemService implements IDubboItemService{

    private static final Logger log= LoggerFactory.getLogger(DubboItemService.class);

    @Autowired
    private ItemInfoMapper itemInfoMapper;

    /**
     * 列表查询服务-实际的业务实现逻辑
     * @return
     */
    @Path("item/list")
    public BaseResponse listItems() {
        BaseResponse response=new BaseResponse(StatusCode.Success);
        try {
            List<ItemInfo> infos=itemInfoMapper.selectAll();
            log.info("查询到的商品列表数据:{} ",infos);
            response.setData(infos);

        }catch (Exception e){
            log.error("列表查询服务-实际的业务实现逻辑-发生异常:",e.fillInStackTrace());
            response=new BaseResponse(StatusCode.Fail);
        }
        return response;
    }
}
消费者代码

消费者配置Spring-dubbo.xml:

<?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服务类所在包的注解-->
    <dubbo:annotation package="com.debug.mooc.dubbo.two.server.service.dubbo" />

    <!--注册中心zookeeper配置信息-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <!--支持两种协议的调用:rpc-dubbo协议;http协议-rest api-url调用-->
    <dubbo:protocol name="rest" threads="500" contextpath="v1" server="tomcat" accepts="500"/>
    <dubbo:protocol name="dubbo" />

    <!--消费方信息配置-->
	<dubbo:application name="dubboTwo-consume" owner="debug" organization="dubbox"/>

    <!--引入服务提供方提供的dubbo服务-url="dubbo://127.0.0.1:20903" -->
    <dubbo:reference interface="com.debug.mooc.dubbo.one.api.service.IDubboItemService" id="dubboItemService"
                     url="dubbo://127.0.0.1:20903" protocol="dubbo" version="1.0" timeout="20000">
    </dubbo:reference>

</beans>

消费者配置dubbo.properties:

##
dubbo.container=log4j,spring
dubbo.reference.check=false
dubbo.registry.client=curator
dubbo.application.name=dubboTwo-provider
dubbo.application.owner=debug

#dubbo\u652F\u6301\u7684dubbo\u534F\u8BAE\u914D\u7F6E
dubbo.protocol.name=dubbo
dubbo.protocol.dubbo.port=20904

#dubbo\u652F\u6301\u7684http rest api\u7684\u914D\u7F6E
dubbo.protocol.name=rest
dubbo.protocol.rest.port=9014
dubbo.protocol.rest.server=tomcat

dubbo.service.loadbalance=roundrobin

消费者调用:

/**
 * @Author:debug (SteadyJack)
 * @Date: 2019/1/13 15:35
 **/
@RestController
public class ItemController {

    private static final Logger log= LoggerFactory.getLogger(ItemController.class);

    private static final String prefix="item";

    @Autowired
    private IDubboItemService dubboItemService;

    /**
     * 用户商城列表查询
     * @return
     */
    @RequestMapping(value = prefix+"/list",method = RequestMethod.GET)
    public Map<String,Object> list(){
        Map<String,Object> resMap= Maps.newHashMap();
        resMap.put("code","0");
        resMap.put("msg","成功");

        //TODO:调用服务提供方dubboOne提供的列表查询功能
        try {
            BaseResponse response=dubboItemService.listItems();
	            if (response!=null && response.getCode().equals(0)){
                resMap.put("data",response.getData());

            }
        }catch (Exception e){
            e.printStackTrace();
            resMap.put("code","-1");
            resMap.put("msg","失败");
        }
        return resMap;
    }
}