5

Dubbo的几种配置方式总结

 1 year ago
source link: https://jasonkayzk.github.io/2023/03/23/Dubbo%E7%9A%84%E5%87%A0%E7%A7%8D%E9%85%8D%E7%BD%AE%E6%96%B9%E5%BC%8F%E6%80%BB%E7%BB%93/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本文讲解了Dubbo的几种配置方式,包括XML、API以及Annotation的方式;Dubbo版本基于2.x;

Dubbo的几种配置方式总结

XML方式

XML 方式和 Spring 框架中的 XML 配置方式一模一样;

接口实现

io/github/jasonkayzk/impl/BasicHelloServiceImpl.java

public class BasicHelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date())
                + "] Hello " + name + ", request from consumer: "
                + RpcContext.getContext().getRemoteAddress());
        return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
    }
}

Provider实现

io/github/jasonkayzk/XmlProviderBootstrap.java

public class XmlProviderBootstrap {

    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[]{"spring/dubbo-demo-provider.xml"});
        context.start();

        System.in.read(); // press any key to exit
    }

}

上面的代码读取了 resources 下的配置:

spring/dubbo-demo-provider.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- provider's application name, used for tracing dependency relationship -->
    <dubbo:application name="demo-provider"/>

    <!-- use multicast registry center to export service -->
    <dubbo:registry group="aaa" address="zookeeper://127.0.0.1:2181"/>
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
    <!--<dubbo:registry address="zookeeper://11.163.250.27:2181"/>-->

    <!-- use dubbo protocol to export service on port 20880 -->
    <dubbo:protocol name="dubbo" port="20890"/>

    <!-- service implementation, as same as regular local bean -->
    <bean id="helloService" class="io.github.jasonkayzk.impl.BasicHelloServiceImpl"/>

    <!-- declare the service interface to be exported -->
    <dubbo:service interface="io.github.jasonkayzk.HelloService" ref="helloService"/>

</beans>

Consumer配置

Consumer实现:

io/github/jasonkayzk/XmlConsumerBootstrap.java

public class XmlConsumerBootstrap {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[]{"spring/dubbo-demo-consumer.xml"});
        context.start();

        // get remote service proxy
        HelloService helloService = (HelloService) context.getBean("demoService");

        while (true) {
            try {
                Thread.sleep(1000);
                String hello = helloService.sayHello("world"); // call remote method
                System.out.println(hello); // get result
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    }
}

spring/dubbo-demo-consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- consumer's application name, used for tracing dependency relationship (not a matching criterion),
    don't set it same as provider -->
    <dubbo:application name="demo-consumer"/>

    <!-- use multicast registry center to discover service -->
    <dubbo:registry group="aaa" address="zookeeper://127.0.0.1:2181"/>

    <!-- generate proxy for the remote service, then demoService can be used in the same way as the
    local regular interface -->
    <dubbo:reference id="demoService" check="false" interface="io.github.jasonkayzk.HelloService"/>

</beans>

API方式

如果不想编写 XML,可以使用API的方式进行配置:

Provider实现

Provider实现如下:

dubbo2/b-hello-dubbo-api/src/main/java/io/github/jasonkayzk/ApiProviderBootstrap.java

public class ApiProviderBootstrap {

    public static void main(String[] args) throws Exception {
        // 服务实现
        HelloService helloService = new ApiHelloServiceImpl();

        // 当前应用配置
        ApplicationConfig application = new ApplicationConfig();
        application.setName("api-hello-provider");

        // 连接注册中心配置
        RegistryConfig registry = new RegistryConfig();
        registry.setAddress("zookeeper://127.0.0.1:2181");

        // 服务提供者协议配置
        ProtocolConfig protocol = new ProtocolConfig();
        protocol.setName("dubbo");
        protocol.setPort(12345);
        protocol.setThreads(20);

        // 注意:ServiceConfig为重对象,内部封装了与注册中心的连接,以及开启服务端口

        // 服务提供者暴露服务配置
        // 此实例很重,封装了与注册中心的连接,请自行缓存,否则可能造成内存和连接泄漏
        ServiceConfig<HelloService> service = new ServiceConfig<>();
        service.setApplication(application);
        service.setRegistry(registry); // 多个注册中心可以用setRegistries()
        service.setProtocol(protocol); // 多个协议可以用setProtocols()
        service.setInterface(HelloService.class);
        service.setRef(helloService);
        service.setVersion("1.0.0");

        // 暴露及注册服务
        service.export();

        System.in.read(); // press any key to exit
    }
}

Consumer实现

dubbo2/b-hello-dubbo-api/src/main/java/io/github/jasonkayzk/ApiConsumerBootstrap.java

public class ApiConsumerBootstrap {

    public static void main(String[] args) {
        // 当前应用配置
        ApplicationConfig application = new ApplicationConfig();
        application.setName("api-hello-consumer");

        // 连接注册中心配置
        RegistryConfig registry = new RegistryConfig();
        registry.setAddress("zookeeper://127.0.0.1:2181");

        // 注意:ReferenceConfig为重对象,内部封装了与注册中心的连接,以及与服务提供方的连接

        // 引用远程服务
        // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
        ReferenceConfig<HelloService> reference = new ReferenceConfig<>();
        reference.setApplication(application);
        reference.setRegistry(registry); // 多个注册中心可以用setRegistries()
        reference.setInterface(HelloService.class);
        reference.setVersion("1.0.0");

        // 和本地bean一样使用xxxService
        // 注意:此代理对象内部封装了所有通讯细节,对象较重,请缓存复用
        HelloService helloService = reference.get();

        // get remote service proxy
//        HelloService helloService = (HelloService) context.getBean("helloService");

        while (true) {
            try {
                Thread.sleep(1000);
                String hello = helloService.sayHello("world"); // call remote method
                System.out.println(hello); // get result
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    }
}

Annotation方式

接口实现

Provider中接口实现:

dubbo2/c-hello-dubbo-annotation/src/main/java/io/github/jasonkayzk/provider/impl/AnnotationHelloServiceImpl.java

@Service
public class AnnotationHelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String name) {
        System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date())
                + "] Hello " + name + ", request from consumer: "
                + RpcContext.getContext().getRemoteAddress());
        return "Hello " + name + ", response from annotation-provider: " + RpcContext.getContext().getLocalAddress();
    }
}

使用了 @Service 注解;

Consumer中Action声明

使用注解方式需要在 Consumer 中声明接口,从而将具体的实现注入;:

dubbo2/c-hello-dubbo-annotation/src/main/java/io/github/jasonkayzk/consumer/action/AnnotationHelloAction.java

@Component("annotationHelloAction")
public class AnnotationHelloAction {

    @Reference
    private HelloService helloService;

    public String doSayHello(String name) {
        return helloService.sayHello(name);
    }

}

Annotation中使用Property配置

Provider的配置及启动

Property配置如下:

dubbo2/c-hello-dubbo-annotation/src/main/resources/spring/dubbo-provider.properties

dubbo.application.name=annotation-configuration-provider
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

启动实现:

dubbo2/c-hello-dubbo-annotation/src/main/java/io/github/jasonkayzk/provider/AnnotationPropertyProviderBootstrap.java

@Configuration
@EnableDubbo(scanBasePackages = "io.github.jasonkayzk.consumer.action")
@ComponentScan(value = {"io.github.jasonkayzk.consumer.action"})
@PropertySource("classpath:/spring/dubbo-consumer.properties")
class AnnotationPropertyConsumerConfiguration {
}

public class AnnotationPropertyConsumerBootstrap {

    public static void main(String[] args) throws InterruptedException {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(AnnotationPropertyConsumerConfiguration.class);
        context.start();

        AnnotationHelloAction helloService = context.getBean(AnnotationHelloAction.class);

        for (int i = 0; i < 10; i++) {
            String hello = helloService.doSayHello("annotation-config");
            System.out.println("result: " + hello);
            Thread.sleep(1000);
        }
    }

}

Consumer的配置及启动

Property配置如下:

dubbo2/c-hello-dubbo-annotation/src/main/resources/spring/dubbo-consumer.properties

dubbo.application.name=annotation-configuration-consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.consumer.timeout=3000

启动如下:

dubbo2/c-hello-dubbo-annotation/src/main/java/io/github/jasonkayzk/consumer/AnnotationPropertyConsumerBootstrap.java

@Configuration
@EnableDubbo(scanBasePackages = "io.github.jasonkayzk.consumer.action")
@ComponentScan(value = {"io.github.jasonkayzk.consumer.action"})
@PropertySource("classpath:/spring/dubbo-consumer.properties")
class AnnotationPropertyConsumerConfiguration {
}

public class AnnotationPropertyConsumerBootstrap {

    public static void main(String[] args) throws InterruptedException {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(AnnotationPropertyConsumerConfiguration.class);
        context.start();

        AnnotationHelloAction helloService = context.getBean(AnnotationHelloAction.class);

        for (int i = 0; i < 10; i++) {
            String hello = helloService.doSayHello("annotation-config");
            System.out.println("result: " + hello);
            Thread.sleep(1000);
        }
    }
}

使用SpringBean注入

除了从 Property 中配置,还可以使用 Spring Bean 注入的方式来进行配置;

Provider配置

dubbo2/c-hello-dubbo-annotation/src/main/java/io/github/jasonkayzk/AnnotationProviderBootstrap.java

@Configuration
@EnableDubbo(scanBasePackages = "io.github.jasonkayzk.provider.impl")
class ProviderConfiguration {
    @Bean
    public ProviderConfig providerConfig() {
        ProviderConfig providerConfig = new ProviderConfig();
        providerConfig.setTimeout(1000);
        return providerConfig;
    }

    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-annotation-provider");
        return applicationConfig;
    }

    @Bean
    public RegistryConfig registryConfig() {
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol("zookeeper");
        registryConfig.setAddress("localhost");
        registryConfig.setPort(2181);
        return registryConfig;
    }

    @Bean
    public ProtocolConfig protocolConfig() {
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(20880);
        return protocolConfig;
    }
}

public class AnnotationProviderBootstrap {

    public static void main(String[] args) throws IOException {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderConfiguration.class);
        context.start();
        System.in.read();
    }

}

Consumer配置

dubbo2/c-hello-dubbo-annotation/src/main/java/io/github/jasonkayzk/AnnotationConsumerBootstrap.java

@Configuration
@EnableDubbo(scanBasePackages = "io.github.jasonkayzk.consumer.action")
@ComponentScan(value = {"io.github.jasonkayzk.consumer.action"})
class ConsumerConfiguration {
    @Bean
    public ApplicationConfig applicationConfig() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("dubbo-annotation");
        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("localhost");
        registryConfig.setPort(2181);
        return registryConfig;
    }
}
public class AnnotationConsumerBootstrap {

    public static void main(String[] args) throws InterruptedException {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
        ctx.start();
        AnnotationHelloAction greetingServiceConsumer = ctx.getBean(AnnotationHelloAction.class);

        for (int i = 0; i < 10; i++) {
            String hello = greetingServiceConsumer.doSayHello("annotation-config");
            System.out.println("result: " + hello);
            Thread.sleep(1000);
        }
    }
}

使用YAML配置

上面的配置主要是通过 XML 或者 Property 的方式,实际上阅读起来并没有那么容易;

比较高版本的 SpringBoot 中可以使用 YAML 的方式进行配置;

YAML配置转换工厂类

创建一个工厂类用于将YAML配置转为Property配置:

dubbo2/d-hello-dubbo-yaml/src/main/java/io/github/jasonkayzk/utils/YamlPropertySourceFactory.java

public class YamlPropertySourceFactory extends DefaultPropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        List<PropertySource<?>> sources = new YamlPropertySourceLoader().load(resource.getResource().getFilename(),resource.getResource());
        return sources.get(0);
    }
}

Provider配置

使用 YAML 配置 Provider:

dubbo2/d-hello-dubbo-yaml/src/main/resources/dubbo-provider.yml

dubbo:
  application:
    name: "yaml-configuration-provider"
  registry:
    address: "zookeeper://127.0.0.1:2181"
  protocol:
    name: "dubbo"
    port: "20880"

配置 Bean 代码:

dubbo2/d-hello-dubbo-yaml/src/main/java/io/github/jasonkayzk/provider/config/YamlConfigProviderConfig.java

@Configuration
@EnableDubbo(scanBasePackages = "io.github.jasonkayzk.provider.impl")
@PropertySource(value = "classpath:dubbo-provider.yml", factory = YamlPropertySourceFactory.class)
public class YamlConfigProviderConfig {
}

Consumer配置

YAML 配置:

dubbo2/d-hello-dubbo-yaml/src/main/resources/dubbo-consumer.yml

dubbo:
  application:
    name: "yaml-configuration-consumer"
  registry:
    address: "zookeeper://127.0.0.1:2181"
  consumer:
    timeout: 3000

配置 Bean 代码:

dubbo2/d-hello-dubbo-yaml/src/main/java/io/github/jasonkayzk/consumer/config/YamlConfigConsumerConfig.java

@Configuration
@EnableDubbo(scanBasePackages = "io.github.jasonkayzk.consumer.action")
@ComponentScan(value = {"io.github.jasonkayzk.consumer.action"})
@PropertySource(value = "classpath:dubbo-consumer.yml", factory = YamlPropertySourceFactory.class)
public class YamlConfigConsumerConfig {
}

附录

参考文章:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK