Dubbo学习笔记2:Dubbo服务提供端与消费端应用的搭建

摘要:
基于Spring配置的服务提供者和使用者将provider模块构建为服务提供者,用于向Zookeeper提供服务,并使用Netty服务监控服务使用者的链接。基于Spring配置的服务使用者将consumer模块构建为服务使用者。服务消费者主要从Zookeeper获取所需服务提供商的IP列表,然后根据路由规则选择远程呼叫的IP。

Demo结构介绍

Demo使用Maven聚合功能,里面有三个模块,目录如下:

Dubbo学习笔记2:Dubbo服务提供端与消费端应用的搭建第1张

  • 其中Consumer模块为服务消费者,里面TestConsumer和consumer.xml组成了基于Spring配置方式的服务调用,TestConsumerApi是基于Dubbo API方式的服务调用,TestConsumerApiGeneric是泛化方式的服务调用,TestConsumerAsync是异步调用的方式。
  • 其中Provider模块为服务提供者,里面TestProvider和provider.xml组成了基于Spring配置方式的服务提供,TestProviderApi是基于Dubbo API的服务提供,UserServiceImpl为服务实现类。
  • 其中SDK模块是一个二方包,用来存放服务提供者所有的接口,是为了代码复用使用,在服务提供者和消费者的模块里面都需要引入这个二方包。

其中SDK里面的接口定义源码如下:

public interface UserServiceBo {
    String sayHello(String name);  
    String testPojo(Person person);
}
public interface Person {
}

在SDK模块执行 mvn clean install 命令会安装该模块的jar到本地仓库,要想在其他模块引入该jar,必须要先执行这个安装步骤。

基于Spring配置的服务提供方与消费方搭建

Provider模块为服务提供者,作用是提供的服务到Zookeeper,并使用Netty服务监听服务消费端的链接。里面TestProvider和provider.xml组成了基于XML方式的服务提供,UserServiceImpl为服务实现类。

首先需要在Provider模块里面引入SDK模块,因为Provider模块需要用到UserServiceBo接口(需要在SDK模块执行 mvn clean install 命令,会安装该模块的jar到本地仓库)。

然后实现UserServiceBo接口为UserServiceImpl,代码如下:

public class UserServiceImpl implements UserServiceBo{

    @Override
    public String sayHello(String name) {
        //让当前当前线程休眠2s
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return name; 
    }

    @Override
    public String sayHello2(String name) {
        //让当前当前线程休眠2s
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return name;
    }
        @Override
    public String testPojo(Person person) {
        return JSON.toJSONString(person);
    }  
}

provider.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:context="http://www.springframework.org/schema/context"
    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://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.0.xsd 
    http://code.alibabatech.com/schema/dubbo
    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="dubboProvider" />

    <!-- 使用zookeeper注册中心暴露服务地址 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <!-- 启用monitor模块 -->
    <dubbo:monitor protocol="registry" />

    <bean id="userService" class="com.test.UserServiceImpl" />

    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.test.UserServiceBo" ref="userService"
        group="dubbo"  version="1.0.0" timeout="3000"/>

</beans>

日志文件log4j.properties内容如下:

log4j.rootLogger=INFO,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout

然后,编写服务发布测试类TestProvider,代码如下:

public class TestProvider {   

    public static void main(String[] arg) throws InterruptedException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:provider.xml");

        //挂起当前线程,如果没有改行代码,服务提供者进程会消亡,服务消费者就发现不了提供者了
        Thread.currentThread().join();
    }
}

最后,运行TestProvider类,输出如下:

Dubbo学习笔记2:Dubbo服务提供端与消费端应用的搭建第2张

说明当前服务已经注册了Zookeeper。

基于Spring配置的服务消费方搭建

Consumer模块为服务消费方,服务消费端主要是从Zookeeper获取自己需要的服务提供者的ip列表,然后根据路由规则选择一个ip进行远程调用。里面TestConsumer和consumer.xml组成了基于xml方式的服务调用。

首先需要在Consumer模块中引入SDK模块,因为Consumer模块需要用到UserServiceBo接口(泛化调用时候不需要这个步骤)。

consumer.xml内容如下:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
     xmlns:context="http://www.springframework.org/schema/context"
     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://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.0.xsd 
    http://code.alibabatech.com/schema/dubbo
    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

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

      <!-- 使用multicast广播注册中心暴露发现服务地址 -->    
    <dubbo:registry  protocol="zookeeper" address="zookeeper://127.0.0.1:2181" />  
       <!-- 启动monitor-->
    <dubbo:monitor protocol="registry" />        
      <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->    
    <dubbo:reference id="userService" interface="com.test.UserServiceBo" group="dubbo" version="1.0.0" timeout="3000"/>    

</beans>

测试服务消费类TestConsumer代码如下:

public class TestConsumer {

    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] { "classpath:consumer.xml" });

        final UserServiceBo demoService = (UserServiceBo) context.getBean("userService");

        System.out.println(demoService.sayHello("哈哈哈"));
    }
}

最后运行TestConsumer,会输出:

Dubbo学习笔记2:Dubbo服务提供端与消费端应用的搭建第3张

说明服务消费端已经正常调用了服务提供方的服务了。

注:至此一个经典的含有服务提供者/服务消费者/服务注册中心的简单分布式系统搭建完毕了。

基于Dubbo API方式的服务提供方与消费方搭建

基于Dubbo API方式的服务提供方搭建

其中Provider模块为服务提供者,里面TestProviderApi是基于Dubbo Api的服务提供,UserServiceImpl为服务实现类。

首先需要在Provider模块里面引入SDK模块,这个不变。

然后实现UserServiceBo接口为UserServiceImpl,这个也不变。

再接着编写Dubbo Api服务提供测试代码TestProviderApi,代码如下:

public class TestProviderApi {

    public static void main(String[] arg) throws InterruptedException {

        //(4.3.1-1)等价于  <bean     />
        UserServiceBo userService = new UserServiceImpl();
        //(4.3.1-2)等价于  <dubbo:application name="dubboProvider" />
        ApplicationConfig application = new ApplicationConfig();
        application.setName("dubboProvider");

        //(4.3.1-3)等价于  <dubbo:registry address="zookeeper://127.0.0.1:2181" />
        RegistryConfig registry = new RegistryConfig();
        registry.setAddress("127.0.0.1:2181");
        registry.setProtocol("zookeeper");

        // (4.3.1-4)等价于 <dubbo:protocol name="dubbo" port="20880" />
        ProtocolConfig protocol = new ProtocolConfig();
        protocol.setName("dubbo");
        protocol.setPort(20880);

        //4.3.1-5)等价于     <dubbo:monitor protocol="registry" />
        MonitorConfig monitorConfig = new MonitorConfig();
        monitorConfig.setProtocol("registry");

        //4.3.1-6)等价于 <dubbo:service interface="com.test.UserServiceBo" ref="userService"
        //group="dubbo"  version="1.0.0" timeout="3000"/>
        ServiceConfig<UserServiceBo> service = new ServiceConfig<UserServiceBo>(); // 此实例很重,封装了与注册中心的连接,请自行缓存,否则可能造成内存和连接泄漏
        service.setApplication(application);
        service.setMonitor(monitorConfig);
        service.setRegistry(registry); // 多个注册中心可以用setRegistries()
        service.setProtocol(protocol); // 多个协议可以用setProtocols()
        service.setInterface(UserServiceBo.class);
        service.setRef(userService);
        service.setVersion("1.0.0");
        service.setGroup("dubbo");
        service.setTimeout(3000);
        service.export();

       //4.3.1-8) 挂起当前线程
        Thread.currentThread().join();
    }
}

基于dubbo-spring-boot-starter使用SpringBoot搭建一个简单的服务提供者服务应用,这里重新打包一个SDK,内容如下:

Dubbo学习笔记2:Dubbo服务提供端与消费端应用的搭建第4张

服务提供方搭建

服务提供方应用结构如下:

Dubbo学习笔记2:Dubbo服务提供端与消费端应用的搭建第5张

其中ProviderApp为SpringBoot的启动类,代码如下:

@SpringBootApplication
@EnableDubboConfiguration
@RestController 
@ComponentScan(basePackages = { "com.gitchat.demo.provider.service" })  
public class ProviderApp {


    @RequestMapping("/")
    String home() {
        return "Hello Demo!";
    }
    public static void main(String[] args) {   
        SpringApplication.run(ProviderApp.class, args);
    }
}

@ComponentScan(basePackages={"com.gitchat.demo.provider.service"})说明扫描com.gitchat.demo.provider.service包下的@Component注解的类到Spring容器。

UserServiceImpl为服务实现类,代码如下:

@Service(interfaceClass = UserServiceBo.class,group="dubbo",version="1.0.0")
@Component
public class UserServiceBoImpl implements UserServiceBo{

    @Override
    public String sayHello(String name) {
        return "hello:" + name;
    }

    @Override
    public String testPojo(Person person) {
        return person.toString();
    }

}

@Service(interfaceClass=UserServiceBo.class,group="dubbo",version="1.0.0")标示UserServiceBoImpl会作为服务提供出去,dubbo-start会扫描到这个注解,并创建一个ServiceConfig对象,然后调用ServiceConfig的export方法发布服务到Zookeeper。使用dubbo-starter后,你只需要在需要发布的服务的实现类上添加@Service注解就可以了,无须在显示创建ServiceConfig对象。

配置文件application.properties内容如下:

server.port=7003
management.port=7004
spring.application.name=demo-provider

spring.dubbo.server=true
spring.dubbo.registry=zookeeper://127.0.0.1:2181

其中server.port为内嵌Tomcat容器监听端口,management.port为健康检查端口,spring.application.name为应用的名称,spring.dubbo.server=true说明开启Dubbo服务,spring.dubbo.registry为服务注册中心地址。

日志配置文件log4j.properties内容如下:

log4j.rootLogger=INFO,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout

pom.xml里面需要配置内容如下,首先由于是SpringBoot应用所以需要如下引入:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
</parent>
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
</dependency>

还需要引入dubbo-spring-boot-starter,这个starter里面包含了Dubbo需要的东西:

    <dependency>
            <groupId>com.alibaba.spring.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.0.0</version>
    </dependency>

然后引入Zookeeper包,和依赖的SDK:

        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-log4j12</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>

最后需要引入spring-boot-maven插件,以便打包为可执行的jar文件:

<build>
        <finalName>demo-provider</finalName>

        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <executable>false</executable>
                    <excludeDevtools>true</excludeDevtools>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            </plugins>
    </build>

上面配置完毕后,执行ProviderApp的main函数输出如下,可知服务注册到Zookeeper了:

Dubbo学习笔记2:Dubbo服务提供端与消费端应用的搭建第6张

服务消费方搭建

服务消费方应用结构如下:

Dubbo学习笔记2:Dubbo服务提供端与消费端应用的搭建第7张

其中ConsumerApp为SpringBoot启动的入口,代码如下:

@SpringBootApplication
@EnableDubboConfiguration 
@RestController
@ComponentScan(basePackages = { "com.gitchat.demo.consumer.service" })
public class ConsumerApp {

    @Autowired 
    private ConsumerService  consumerService; 

    @RequestMapping(value = "/testSayHello", method = RequestMethod.GET)
    String testSayHello(@RequestParam(value = "name", required = true) String name) {
        return  consumerService.sayHello(name);
    }

    @RequestMapping("/")
    String home() {
        return "Hello Demo!";
    }

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApp.class, args);

    }
}

可知注入了ConsumerService的一个实例到Spring容器,然后testSayHello方法内部调用了ConsumerService实例的sayHello方法,这个controller是为了测试服务消费的,下面我们看看ConsumerService的实现:

@Component
public class ConsumerService {

    @Reference(group="dubbo",interfaceClass=UserServiceBo.class,version="1.0.0")
    private UserServiceBo userServiceBo;

    public String sayHello(String name){
        return userServiceBo.sayHello(name);
    }
}

注解@Reference标示当前要消费UserServiceBo接口的服务,并通过注解说明要消费服务的接口,版本和分组信息,dubbo-starter会自动扫描这个注解然后生成一个ReferenceConfig对象,然后调用ReferenceConfig的get()方法获取远程调用实例的代理类,并设置到userServiceBo变量。ConsumerService的sayHello方法则是调用远程服务userServiceBo的sayHello方法。

配置文件application.properties内容如下:

server.port=7001
management.port=7002
spring.application.name=demo-consumer

spring.dubbo.server=true
spring.dubbo.registry=zookeeper://127.0.0.1:2181

pom文件和日志文件与服务提供者类似,不再赘述。

免责声明:文章转载自《Dubbo学习笔记2:Dubbo服务提供端与消费端应用的搭建》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇PHP stream_context_create()作用和用法分析Flask-爱家租房项目ihome-01-项目框架的搭建下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Dubbo多版本

当服务提供者提供的服务接口出现不兼容升级时,可以设置版本号,使用多个版本号(version)进行过渡。 1)、服务提供者配置文件 1 <dubbo:service ref="userService"interface="cn.coreqi.service.UserService"version="1.0.0"/> 2 3...

分布式项目报错及解决

dubbo分布式项目 1.在注册中心找不到对应的服务 java.lang.IllegalStateException: Failed to check the status of the service com.pinyougou.sellergoods.service.BrandService. No provider available for the...

SpringCloud入门

1.什么是微服务 官网: https://www.martinfowler.com/articles/microservices.html In short, the microservice architectural style is an approach to developing a single application as a suite...

开发规约(一)接口统一返回值格式

一、前言 上篇在介绍 Spring Boot 集成 Dubbo 时,埋下了有关返回值格式的一个小小伏笔。本篇将主要介绍一种常用的返回值格式以及通过什么手段去达成这个目的。 二、Dubbo 接口统一返回值格式 我们在应用中经常会涉及到 server 和 client 的交互,目前比较流行的是基于 json 格式的数据交互。但是 json 只是消息的格式,其...

Dubbo自定义Filter统一处理异常

Dubbo版本:2.7 使用自定义Filter注意事项 1、自定义名称不能和默认Filter相同,否则可能不生效 2、只用定义Filter类和META-INF下的文本文件,不用添加配置,@Activate注解会自动激活 3、业务最好抛RpcException异常,抛其它RuntimeException子类,方法中的exception会识别为RuntimeE...

Dubbo端口占用错误信息

SEVERE: Exception sending context initialized event to listener instance of class com.common.SysContextLoaderListener com.alibaba.dubbo.rpc.RpcException: Fail to start server(url...