官方文档: https://dubbo.apache.org/zh/docs/v2.7/user/configuration/

1.XML配置

拿前面的配置来示例
provider.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
  5. 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">
  6. <!--当前项目在整个分布式架构里面的唯一名称,计算依赖关系的标签-->
  7. <dubbo:application name="provider" owner="yuanzi">
  8. <dubbo:parameter key="qos.enable" value="true"/>
  9. <dubbo:parameter key="qos.accept.foreign.ip" value="false"/>
  10. <dubbo:parameter key="qos.port" value="55555"/>
  11. </dubbo:application>
  12. <dubbo:monitor protocol="registry"/>
  13. <!--dubbo这个服务所要暴露的服务地址所对应的注册中心-->
  14. <!--<dubbo:registry address="N/A"/>-->
  15. <dubbo:registry address="zookeeper://10.58.11.13:2131" check="false"/>
  16. <!--当前服务发布所依赖的协议;webserovice、Thrift、Hessain、http-->
  17. <dubbo:protocol name="dubbo" port="20880"/>
  18. <!--服务发布的配置,需要暴露的服务接口-->
  19. <dubbo:service
  20. interface="com.yuanzi.dubbo.ProviderService"
  21. ref="providerService"/>
  22. <!--Bean bean定义-->
  23. <bean id="providerService" class="com.yuanzi.dubbo.ProviderServiceImpl"/>
  24. </beans>


consumer.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:application name="consumer" owner="yuanzi"/>

    <!--dubbo这个服务所要暴露的服务地址所对应的注册中心-->
    <!--点对点的方式-->
    <dubbo:registry address="zookeeper://10.58.11.13:2131" check="false"/>
    <!--<dubbo:registry address="zookeeper://localhost:2181" check="false"/>-->

    <!--生成一个远程服务的调用代理-->
    <!--点对点方式-->
    <dubbo:reference id="providerService"
                     interface="com.yuanzi.dubbo.ProviderService"/>
<!--                     url="dubbo://10.57.242.17:20880/com.yuanzi.dubbo.ProviderService"/>-->

</beans>

1.1 配置之间的关系

image.png

标签 用途 解释
服务配置 用于暴露一个服务,定义服务的元信息,一个服务可以用多个协议暴露,一个服务也可以注册到多个注册中心
引用配置 用于创建一个远程服务代理,一个引用可以指向多个注册中心
协议配置 用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受
应用配置 用于配置当前应用信息,不管该应用是提供者还是消费者
模块配置 用于配置当前模块信息,可选
注册中心配置 用于配置连接注册中心相关信息
监控中心配置 用于配置连接监控中心相关信息,可选
提供方配置 当 ProtocolConfig 和 ServiceConfig 某属性没有配置时,采用此缺省值,可选
消费方配置 当 ReferenceConfig 某属性没有配置时,采用此缺省值,可选
方法配置 用于 ServiceConfig 和 ReferenceConfig 指定方法级的配置信息
参数配置 用于指定方法参数配置

1.2 不同粒度配置的覆盖关系

以 timeout 为例,下图显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似:

  • 方法级优先,接口级次之,全局配置再次之。
  • 如果级别一样,则消费方优先,提供方次之。

其中,服务提供方配置,通过 URL 经由注册中心传递给消费方。
image.png
(建议由服务提供方设置超时,因为一个方法需要执行多长时间,服务提供方更清楚,如果一个消费方同时引用多个服务,就不需要关心每个服务的超时设置)。
理论上 ReferenceConfig 中除了interface 这一项,其他所有配置项都可以缺省不配置,
框架会自动使用ConsumerConfig,ServiceConfig, ProviderConfig等提供的缺省配置。

  1. 2.1.0 开始支持,注意声明:xmlns:p=”http://www.springframework.org/schema/p
  2. 引用缺省是延迟初始化的,只有引用被注入到其它 Bean,或被 getBean() 获取,才会初始化。如果需要饥饿加载,即没有人引用也立即生成动态代理,可以配置:

2.API(不推荐)


3.注解配置

注解配置方式还是需要了解一下的,现在微服务都倾向于这种方式,这也是以后发展的趋势,0 配置应该是这几年的趋势。
那么如何对 dubbo 使用注解的方式呢?我们先看服务端。

服务端

image.png

第一步:定义接口及实现类

在上面的截图中的 annotation 包下

package com.yuanzi.dubbo.provider.service.annotation;

public interface ProviderServiceAnnotation {

    String SayHelloAnnotation(String word);
}
package com.yuanzi.dubbo.provider.service.annotation;

import com.alibaba.dubbo.config.annotation.Service;

@Service(timeout= 5000)
public class ProviderServiceAnnotationImpl implements ProviderServiceAnnotation{

    public String SayHelloAnnotation(String word) {
        return word;
    }
}

@Service
@Service 用来配置 Dubbo 的服务提供方。

第二步:组装服务提供方

通过 Spring 中 Java Config 的技术(@Configuration)和 annotation 扫描(@EnableDubbo)来发现、组装、并向外提供 Dubbo 的服务。

package com.yuanzi.dubbo.provider.configuration;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * 注解方式配置
 */
@Configuration
@EnableDubbo(scanBasePackages = "com.yuanzi.dubbo.provider.service.annotation")
public class DubboConfiguration {
    @Bean // #1 服务提供者信息配置
    public ProviderConfig providerConfig() {
        ProviderConfig providerConfig = new ProviderConfig();
        providerConfig.setTimeout(1000);
        return providerConfig;
    }

    @Bean // #2 分布式应用信息配置
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-annotation-provider");
        return applicationConfig;
    }

    @Bean // #3 注册中心信息配置
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol("zookeeper");
        registryConfig.setAddress("10.58.11.13");
        registryConfig.setPort(2131);
        return registryConfig;
    }

    @Bean // #4 使用协议配置,这里使用 dubbo
    public ProtocolConfig protocolConfig() {
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(20881);
        return protocolConfig;
    }
}

分析

  • 通过 @EnableDubbo 指定在com.yuanzi.dubbo.provider.service.annotation下扫描所有标注有 @Service 的类
  • 通过 @Configuration 将 DubboConfiguration 中所有的 @Bean 通过 Java Config 的方式组装出来并注入给 Dubbo 服务,也就是标注有 @Service 的类。这其中就包括了:
    • ProviderConfig:服务提供方配置
    • ApplicationConfig:应用配置
    • RegistryConfig:注册中心配置
    • ProtocolConfig:协议配置

第三步:启动服务

package com.yuanzi.dubbo;

import com.yuanzi.dubbo.provider.configuration.DubboConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.io.IOException;

/**
 * 注解启动方式
 */
public class AppAnnotation {
    public static void main(String[] args) throws IOException {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DubboConfiguration.class);
        context.start();
        System.in.read();
    }
}


发现输出下面信息就表示 success 了。
image.png

pom.xml升级一下版本,从1.0-SNAPSHOT 改成 1.1-SNAPSHOT,然后执行 mvn instanll
image.png

消费端
image.png

第一步:引用服务

升级pom中服务端的版本到1.1
image.png

package com.yuanzi.dubbo.consumer.Annotation;
import com.alibaba.dubbo.config.annotation.Reference;
import com.yuanzi.dubbo.provider.service.annotation.ProviderServiceAnnotation;
import org.springframework.stereotype.Component;

/**
 * 注解方式的service
 */
@Component("annotatedConsumer")
public class ConsumerAnnotationService {
    @Reference
    private ProviderServiceAnnotation providerServiceAnnotation;

    public String doSayHello(String name) {
        return providerServiceAnnotation.SayHelloAnnotation(name);
    }
}

在 ConsumerAnnotationService 类中,通过 @Reference 引用服务端提供的类,然后通过方法调用这个类的方式,给消费端提供接口。

第二步:组装服务消费者

这一步和服务端是类似的,这里就不在重复了。

package com.yuanzi.dubbo.consumer.configuration;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;

/**
 * 注解配置类
 */
@Configuration
@EnableDubbo(scanBasePackages = "com.yuanzi.dubbo.consumer.Annotation")
@ComponentScan(value = {"com.yuanzi.dubbo.consumer.Annotation"})
public class ConsumerConfiguration {

    @Bean // 应用配置
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-annotation-consumer");
        Map<String, String> stringStringMap = new HashMap<String, String>();
        stringStringMap.put("qos.enable","true");
        stringStringMap.put("qos.accept.foreign.ip","false");
        stringStringMap.put("qos.port","33333");
        applicationConfig.setParameters(stringStringMap);
        return applicationConfig;
    }

    @Bean // 服务消费者配置
    public ConsumerConfig consumerConfig() {
        ConsumerConfig consumerConfig = new ConsumerConfig();
        consumerConfig.setTimeout(3000);
        return consumerConfig;
    }

    @Bean // 配置注册中心
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol("zookeeper");
        registryConfig.setAddress("10.58.11.13");
        registryConfig.setPort(2131);
        return registryConfig;
    }

}

第三步:发起远程调用
在 main 方法中通过启动一个 Spring Context,从其中查找到组装好的 Dubbo 的服务消费者,并发起一次远程调用。

package com.yuanzi.dubbo.consumer;

import com.yuanzi.dubbo.consumer.Annotation.ConsumerAnnotationService;
import com.yuanzi.dubbo.consumer.configuration.ConsumerConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * 注解方式启动
 *
 */
public class AppAnnotation {
    public static void main(String[] args) {

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
        context.start(); // 启动
    ConsumerAnnotationService consumerAnnotationService = context.getBean(ConsumerAnnotationService.class);
    String hello = consumerAnnotationService.doSayHello("annotation"); // 调用方法
        System.out.println("result: " + hello); // 输出结果

    }
}

结果
image.png