简单的Dubbo实验环境搭建


在这里插入图片描述

Dubbo-api中定义的UserQueryFacade接口可以发布在私服上,这样子dubbo-consumer和dubbo-provider就可以以maven依赖的形式导入使用。dubbo-provider需要提供接口的实现类,dubbo-consumer需要订阅该实现类,他们的元数据都通过zk进行记录。

许多教程都通过Spring XML的形式进行dubbo服务注册的,其实还有很多种方式,参考配置加载流程 | Apache Dubbo

  1. Spring XML

参见示例

  <!-- dubbo-provier.xml -->
  
  <dubbo:application name="demo-provider"/>
  <dubbo:config-center address="zookeeper://127.0.0.1:2181"/>
  
  <dubbo:registry address="zookeeper://127.0.0.1:2181" simplified="true"/>
  <dubbo:metadata-report address="redis://127.0.0.1:6379"/>
  <dubbo:protocol name="dubbo" port="20880"/>
  
  <bean id="demoService" class="org.apache.dubbo.samples.basic.impl.DemoServiceImpl"/>
  <dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService" ref="demoService"/>
  1. Spring Annotation

参见示例

  // AnnotationService服务实现
  
  @Service
  public class AnnotationServiceImpl implements AnnotationService {
      @Override
      public String sayHello(String name) {
          System.out.println("async provider received: " + name);
          return "annotation: hello, " + name;
      }
  }
## dubbo.properties

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

参见示例

  ## application.properties
  
  # Spring boot application
  spring.application.name=dubbo-externalized-configuration-provider-sample
  
  # Base packages to scan Dubbo Component: @com.alibaba.dubbo.config.annotation.Service
  dubbo.scan.base-packages=com.alibaba.boot.dubbo.demo.provider.service
  
  # Dubbo Application
  ## The default value of dubbo.application.name is ${spring.application.name}
  ## dubbo.application.name=${spring.application.name}
  
  # Dubbo Protocol
  dubbo.protocol.name=dubbo
  dubbo.protocol.port=12345
  
  ## Dubbo Registry
  dubbo.registry.address=N/A
  
  ## DemoService version
  demo.service.version=1.0.0
  1. Java API

参考示例

public static void main(String[] args) throws IOException {
    ServiceConfig<GreetingsService> service = new ServiceConfig<>();
    service.setApplication(new ApplicationConfig("first-dubbo-provider"));
    service.setRegistry(new RegistryConfig("multicast://224.5.6.7:1234"));
    service.setInterface(GreetingsService.class);
    service.setRef(new GreetingsServiceImpl());
    service.export();
    System.out.println("first-dubbo-provider is running.");
    System.in.read();
}

Spring XML配置发布与服务调用

创建了三个模块,整体结构如下:
在这里插入图片描述

  1. 在dubbo-api模块中定义接口,并生成别的模块可以依赖的maven jar包,那我这里其实是provider,consumer,api都在localhost上,因此直接本地install生成maven jar.

    package com.jxz.dubbo.api;
    
    /**
     * @Author jiangxuzhao
     * @Description
     * @Date 2023/6/4
     */
    public interface UserQueryFacade {
        String query(String name);
    }
    
  2. 在dubbo-provider模块中定义服务提供者,实现前面发布的接口

    2.1 先提供pom依赖:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>com.jxz.dubbo</groupId>
            <artifactId>DubboLearning</artifactId>
            <version>1.0-SNAPSHOT</version>
        </parent>
    
        <artifactId>dubbo-provider</artifactId>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
        <dependencies>
    <!--        引用自定义接口maven jar依赖-->
            <dependency>
                <groupId>com.jxz.dubbo</groupId>
                <artifactId>dubbo-api</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
    <!--    引用dubbo依赖-->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo</artifactId>
                <version>2.7.1</version>
            </dependency>
        </dependencies>
    </project>
    

    2.2 服务提供者提供实现接口的服务提供类

    package com.jxz.dubbo.provider.impl;
    
    import com.jxz.dubbo.api.UserQueryFacade;
    
    /**
     * @Author jiangxuzhao
     * @Description
     * @Date 2023/6/4
     */
    public class UserQueryFacadeImpl implements UserQueryFacade {
    
        @Override
        public String query(String name) {
            return "query name is "+name;
        }
    }
    

    2.3 dubbo provider配置文件放在resources/META-INF/spring

    参考快速开始 | Apache Dubbo,其中各个配置含义参考XML 配置 | Apache Dubbo

    <?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://dubbo.apache.org/schema/dubbo"
           xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd        http://dubbo.apache.org/schema/dubbo        http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
    
        <!-- 提供方的应用服务名,最好是当前应用归属的系统名称,用于计算依赖关系 -->
        <dubbo:application name="dubbo-provider"  />
    
        <!-- 注册中心的地址名,这里可以先注册到本地,到时用url注册到ZK中 -->
        <dubbo:registry address="N/A" />
    
        <!-- 服务提供方需要暴露的服务接口,采用dubbo协议,端口号为20880 -->
        <dubbo:protocol name="dubbo" port="20880" />
    
        <!-- 服务提供方需要暴露的服务功能,也就是对应接口和实现类 -->
        <dubbo:service interface="com.jxz.dubbo.api.UserQueryFacade" ref="UserQueryFacadeImpl" />
        <!-- 和本地bean一样注册服务实现类,id对应上面ref -->
        <bean id="UserQueryFacadeImpl" class="com.jxz.dubbo.provider.impl.UserQueryFacadeImpl" />
    </beans>
    

    其中详细的含义可以看参考手册,比如各种XML配置的详细含义Schema 配置参考手册 | Apache Dubbo,以及<dubbo:protocol指定的服务提供协议,缺省为dubbo,这我理解起来每个协议就是对rpc传输中各种配置的规范,看协议参考手册 | Apache Dubbo,其中Dubbo协议为默认的单一长链接。
    在这里插入图片描述

    2.4 Dubbo-provider服务提供者启动类中,启动spring容器

    package com.jxz.dubbo.provider;
    
    import org.apache.dubbo.container.Main;
    
    /**
     * @Author jiangxuzhao
     * @Description 服务提供者启动类中,启动spring容器
     * @Date 2023/6/4
     */
    public class ProviderApplication {
        public static void main(String[] args) {
            Main.main(new String[]{"spring"});
        }
    }
    

    其中SpringContainer会去读取相关的配置文件,参考源码:默认读取DEFAULT_SPRING_CONFIG,即 “classpath*:META-INF/spring/*.xml”,因此我们的dubbo provider配置文件写在这个目录下

    public class SpringContainer implements Container {
    
        public static final String SPRING_CONFIG = "dubbo.spring.config";
        public static final String DEFAULT_SPRING_CONFIG = "classpath*:META-INF/spring/*.xml";
        private static final Logger logger = LoggerFactory.getLogger(SpringContainer.class);
        static ClassPathXmlApplicationContext context;
    
        public static ClassPathXmlApplicationContext getContext() {
            return context;
        }
    
        @Override
        public void start() {
          
            String configPath = ConfigUtils.getProperty(SPRING_CONFIG);
            if (StringUtils.isEmpty(configPath)) {
                configPath = DEFAULT_SPRING_CONFIG;
            }
          	// 内部也是通过ClassPathXmlApplicationContext
            context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"), false);
            context.refresh();
            context.start();
        }
    

    2.5 provider服务提供者注册测试
    在这里插入图片描述

  3. 在dubbo-consumer模块中定义服务消费者

​ 3.1 先提供pom依赖:

<dependencies>
<!--        引用自定义接口maven jar依赖-->
    <dependency>
        <groupId>com.jxz.dubbo</groupId>
        <artifactId>dubbo-api</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
<!--    引用dubbo依赖-->
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.7.1</version>
    </dependency>
</dependencies>

​ 3.2 dubbo consumer配置文件放在resources/META-INF/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://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd        http://dubbo.apache.org/schema/dubbo        http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:application name="dubbo-consumer"  />

    <!-- 注册中心的地址名,这里可以先注册到本地,到时用url注册到ZK中 -->
    <dubbo:registry address="N/A" />

    <!-- 引用服务提供者的接口,生成远程服务代理,可以和本地bean一样使UserQueryFacade,其中url为服务提供者export的url -->
    <dubbo:reference id="UserQueryFacade" interface="com.jxz.dubbo.api.UserQueryFacade" url="dubbo://127.0.0.1:20880"/>
</beans>

其中指定了想调用的接口名以及对应的服务提供端口,id就是本地调用的对象

​ 3.3 dubbo-consumer服务消费者启动类

​ 加载Spring配置,并调用远程服务

package com.jxz.dubbo.consumer;

import com.jxz.dubbo.api.UserQueryFacade;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2023/6/5
 */
public class ConsumerApplication {
    public static void main(String[] args) {
        String configPath = "classpath*:META-INF/spring/*.xml";

        // 加载Spring配置
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(configPath);
        context.start();

        // 获取远程代理对象
        UserQueryFacade userQueryFacade = (UserQueryFacade)context.getBean(UserQueryFacade.class);
        String str = userQueryFacade.query("jiangxuzhao"); // 执行远程方法
        System.out.println( str ); // 显示调用结果
    }
}

​ 3.4 consumer服务消费者测试
在这里插入图片描述

碰到bug: No qualifying bean of type ‘com.jxz.dubbo.api.UserQueryFacade’ available

那是因为我在创建META-INF/spring目录的时候,直接META-INF.spring创建了一个层级目录,导致xml配置不上,因此没法找到相关服务。

  1. 集成ZK

    上面的服务调用都是在本地直接写死的,现在想从ZK中获取服务调用提供方的地址,首先去Index of /zookeeper (apache.org)下载zk安装包

​ 4.1 修改dubbo provider配置文件放在resources/META-INF/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://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd        http://dubbo.apache.org/schema/dubbo        http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 提供方的应用服务名,最好是当前应用归属的系统名称,用于计算依赖关系 -->
    <dubbo:application name="dubbo-provider"  />

    <!-- 注册中心的地址名,用url注册到ZK中 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <!-- 服务提供方需要暴露的服务接口,采用dubbo协议,端口号为20880 -->
    <dubbo:protocol name="dubbo" port="20880" />

    <!-- 服务提供方需要暴露的服务功能,也就是对应接口和实现类 -->
    <dubbo:service interface="com.jxz.dubbo.api.UserQueryFacade" ref="UserQueryFacadeImpl" />
    <!-- 和本地bean一样注册服务实现类,id对应上面ref -->
    <bean id="UserQueryFacadeImpl" class="com.jxz.dubbo.provider.impl.UserQueryFacadeImpl" />
</beans>

​ 4.2 修改dubbo consumer配置文件放在resources/META-INF/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://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd        http://dubbo.apache.org/schema/dubbo        http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:application name="dubbo-consumer"  />

    <!-- 注册中心的地址名,用url注册到ZK中 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <!-- 引用服务提供者的接口,生成远程服务代理,可以和本地bean一样使UserQueryFacade,其中不需要指定url了 -->
    <dubbo:reference id="UserQueryFacade666666" interface="com.jxz.dubbo.api.UserQueryFacade"/>
</beans>

服务方和消费方都修改pom依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.jxz.dubbo</groupId>
        <artifactId>DubboLearning</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>dubbo-provider</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
<!--        引用自定义接口maven jar依赖-->
        <dependency>
            <groupId>com.jxz.dubbo</groupId>
            <artifactId>dubbo-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
<!--    引用dubbo依赖-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.7.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.3.0</version>
        </dependency>
    </dependencies>
</project>

其中控制台一直报log4j和slf相关的错误,继续添加依赖:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-nop</artifactId>
    <version>1.7.2</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

同时配置log4j.properties

log4j.rootLogger=debug, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log

log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=5

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

本来以为配置日志没什么用的,同时这时候provider我在idea控制台只是能运行,但是每次都是过一会就exit with code 1,却没有一点查错信息。配完日志以后,发现控制台打印的东西就多了,同时在provider端打印出了20880端口被占用,这不就是我为服务提供者的UserQueryFacadeImpl指定的端口嘛,之前并没有将其关闭,遂kill -9然后重新启动。Dubbo service server started!成功启动。

依次启动provider和consumer,发现consumer输出“query name is jiangxuzhao”,同时zk中注册上了两者的信息:
在这里插入图片描述

小小的修改了一下consumer,看它获取bean是根据class还是id获取

package com.jxz.dubbo.consumer;

import com.jxz.dubbo.api.UserQueryFacade;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2023/6/5
 */
public class ConsumerApplication {
    public static void main(String[] args) throws IOException {
        String configPath = "classpath*:META-INF/spring/*.xml";

        // 加载Spring配置
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(configPath);
        context.start();

        // 获取远程代理对象,这是通过<dubbo:reference>中定义的class获取
        // UserQueryFacade userQueryFacade = (UserQueryFacade)context.getBean(UserQueryFacade.class);
        // 也支持通过bean id获取
        UserQueryFacade userQueryFacade = (UserQueryFacade)context.getBean("UserQueryFacade666666");
        String str = userQueryFacade.query("jiangxuzhao"); // 执行远程方法
        System.out.println( str ); // 显示调用结果

        System.in.read(); // 阻塞等待
    }
}

又尝试着加上个dubbo-provider2,直接就复制模块改下provider.xml中的port

<?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://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd        http://dubbo.apache.org/schema/dubbo        http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 提供方的应用服务名,最好是当前应用归属的系统名称,用于计算依赖关系 -->
    <dubbo:application name="dubbo-provider"  />

    <!-- 注册中心的地址名,用url注册到ZK中 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <!-- 服务提供方需要暴露的服务接口,采用dubbo协议,端口号为20880 -->
    <dubbo:protocol name="dubbo" port="20881" />

    <!-- 服务提供方需要暴露的服务功能,也就是对应接口和实现类 -->
    <dubbo:service interface="com.jxz.dubbo.api.UserQueryFacade" ref="UserQueryFacadeImpl" />
    <!-- 和本地bean一样注册服务实现类,id对应上面ref -->
    <bean id="UserQueryFacadeImpl" class="com.jxz.dubbo.provider.impl.UserQueryFacadeImpl" />
</beans>

Java API配置发布与服务调用

  1. Dubbo-api中定义新的接口
package com.jxz.dubbo.api;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2023/6/17
 */
public interface UserUpdateFacade {
    String updateUser(String name);
}
  1. Dubbo-provider中实现接口并注册
package com.jxz.dubbo.provider.impl;

import com.jxz.dubbo.api.UserUpdateFacade;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2023/6/17
 */
public class UserUpdateFacadeImpl implements UserUpdateFacade {
    @Override
    public String updateUser(String name) {
        return "Update your name is "+name;
    }
}

服务暴露

package com.jxz.dubbo.provider;

import com.jxz.dubbo.api.UserUpdateFacade;
import com.jxz.dubbo.provider.impl.UserUpdateFacadeImpl;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;

import java.io.IOException;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2023/6/17
 */
public class JavaApiProviderApplication {
    public static void main(String[] args) throws IOException {
        // 创建暴露UserUpdateFacade接口的对象
        ServiceConfig<UserUpdateFacade> service = new ServiceConfig<>();
        service.setApplication(new ApplicationConfig("dubbo-provider-javaapi"));
        service.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
        service.setInterface(UserUpdateFacade.class);
        // 设置实现类并暴露服务
        service.setRef(new UserUpdateFacadeImpl());
        service.export();

        System.out.println("UserUpdateFacade-dubbo-provider is running...");
        // 阻塞等待
        System.in.read();
    }
}
  1. Dubbo-consumer中调用服务
package com.jxz.dubbo.consumer;

import com.jxz.dubbo.api.UserUpdateFacade;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;

import java.io.IOException;

/**
 * @Author jiangxuzhao
 * @Description
 * @Date 2023/6/17
 */
public class JavaApiConsumerApplication {
    public static void main(String[] args) throws IOException {
        // 创建UserUpdateFacade接口的引用对象
        ReferenceConfig<UserUpdateFacade> reference = new ReferenceConfig<>();
        reference.setApplication(new ApplicationConfig("dubbo-consumer-javaapi"));
        reference.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
        reference.setInterface(UserUpdateFacade.class);
        // 直接拿到代理对象并进行远程调用
        UserUpdateFacade userUpdateFacade = reference.get();
        System.out.println(userUpdateFacade.updateUser("jiangxuzhao"));

        // 阻塞等待
        System.in.read();
    }
}

消费者输出:

Update your name is jiangxuzhao

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

互联网民工蒋大钊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值