SpringBoot + Dubbo + zookeeper Demo

1.1 什么是 Duboo?

Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。简单来说 Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。

1.2 Dubbo 架构

Dubbo 架构

上述节点简单说明:

  • Provider 暴露服务的服务提供方
  • Consumer 调用远程服务的服务消费方
  • Registry 服务注册与发现的注册中心
  • Monitor 统计服务的调用次数和调用时间的监控中心
  • Container 服务运行容器

调用关系说明:

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

1.3 什么是 RPC?

RPC(Remote Procedure Call Protocol)远程过程调用协议。一个通俗的描述是:客户端在不知道调用细节的情况下,调用存在于远程计算机上的某个对象,就像调用本地应用程序中的对象一样。比较正式的描述是:一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。

1.4 环境搭建

1.4.1 zookeeper搭建

我这里选择的是Docker Desktop上面进行搭建zookeeper,因为只是做个Demo,所以选择最简单的搭建方式。
想在Windows上搭建的可以参考:windows环境下安装zookeeper教程详解(单机版)
想在Linux上搭建的可以参考:linux安装zookeeper及使用

执行下面的Docker命令

docker run --privileged=true -d --name zookeeper --publish 2181:2181 -d zookeeper:latest

等待安装完成后,执行下面的命令,进入zookeeper容器内部

docker exec -it container-id /bin/bash

进入容器后,输入一下命令进行校验

bin/zkCli.sh -server 127.0.0.1:2181

image-20210303204102559

1.4.2 项目结构

image-20210303211223440

  • dubbo-demo:父项目

    • interfaces:提供接口的子项目
    • provider:服务的提供者
    • consumer:服务的消费者
  • JDK11

1.4.3 interfaces项目

主要用于提供接口

pom.xml

<properties>
    <java.version>11</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Student.java

@Getter
@Setter
@Builder
@ToString
@EqualsAndHashCode
public class Student implements Serializable {
    private Integer id;
    private String studentName;
    private String classRoom;
    private String phoneNumber;
}

StudentService.java

package com.wifi.dubbo.interfaces.service;

import com.wifi.dubbo.interfaces.dto.Student;

public interface StudentService {
    Student getStudentInfo(Integer id);
}

1.4.4 provider项目

实现接口,提供服务

pom.xml

<properties>
    <java.version>11</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    <spring-cloud-alibaba.version>2.2.2.RELEASE</spring-cloud-alibaba.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>2.7.8</version>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-dependencies-zookeeper</artifactId>
        <version>2.7.8</version>
        <type>pom</type>
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>com.wifi.dubbo</groupId>
        <artifactId>interfaces</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

遇到的问题:

  1. 启动有警告

    image-20210303212855949

    1. 通过提示可以得知是:logback-classicslf4-log4j12冲突了

    2. 查看maven依赖

      image-20210303213021321

      image-20210303215900693

    3. 找到是dubbo-dependencies-zookeeper包中引入的slf4j-log4j12

    4. 从dependency中exclusions掉

      <dependency>
          <groupId>org.apache.dubbo</groupId>
          <artifactId>dubbo-dependencies-zookeeper</artifactId>
          <version>2.7.8</version>
          <type>pom</type>
          <exclusions>
              <exclusion>
                  <groupId>org.slf4j</groupId>
                  <artifactId>slf4j-log4j12</artifactId>
              </exclusion>
          </exclusions>
      </dependency>
      

StudentServiceImpl.java

package com.wifi.dubbo.provider.serviceImpl;

import com.wifi.dubbo.interfaces.dto.Student;
import com.wifi.dubbo.interfaces.service.StudentService;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService
public class StudentServiceImpl implements StudentService {
    @Override
    public Student getStudentInfo(Integer id) {
        return Student.builder()
                .id(id)
                .studentName("wifi")
                .classRoom("Room one")
                .phoneNumber("123456")
                .build();
    }
}

Alibaba和Apache的@Service都不建议使用了,这里换成Apache的@DubboService

application.properties

# 应用名称
spring.application.name=provider
#如果指定了spring应用名称,可以缺省dubbo的应用名称,这2个至少要配置1个。缺省dubbo的应用名称时默认值是spring的应用名称
#dubbo.application.name=user-service

# dubbo 协议
dubbo.protocol.id=dubbo
dubbo.protocol.name=dubbo

# dubbo 协议端口( -1 表示自增端口,从 20880 开始)
dubbo.protocol.port=-1

# Dubbo 消费端订阅服务端的应用名,多个服务提供者用逗号分隔
# 这里订阅"自己",会被忽略掉,请根据实际情况添加
#dubbo.cloud.subscribed-services=provider

# dubbo 服务扫描基准包
dubbo.scan.base-packages=com.wifi.dubbo.provider

# 应用服务 WEB 访问端口
server.port=8181

#注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
#端口号可以写在address中,也可以单独写。实质是从address中获取的port是null,后面设置的port覆盖了null
#dubbo.registry.port=2181

#指定注册到zk上超时时间,ms
dubbo.registry.timeout=10000

1.4.5 consumer项目

pom.xml

<properties>
    <java.version>11</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>2.7.8</version>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-dependencies-zookeeper</artifactId>
        <version>2.7.8</version>
        <type>pom</type>
        <exclusions>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>com.wifi.dubbo</groupId>
        <artifactId>interfaces</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

这里引入的依赖与Provider是一样的

StudentConsumerServiceImpl.java

@Service
public class StudentConsumerServiceImpl {

    @DubboReference
    private StudentService studentService;

    public Student getStudentInfo() {
        return studentService.getStudentInfo(1);
    }
}
  1. Alibaba和Apache的@Reference也不建议使用了,所以用Apache的@DubboReference
  2. 用Spring的@Service,将StudentConsumerServiceImpl注入到Bean容器中

application.properties

# 应用名称
spring.application.name=consumer

# 应用服务 WEB 访问端口
server.port=8282

#注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
#dubbo.registry.port=2181

#协议、端口
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

#连接zk的超时时间,ms
dubbo.registry.timeout=10000

#启动应用时是否检查注册中心上有没有依赖的服务,默认true
#dubbo.consumer.check=false

1.4.6 测试

  1. 启动Provider项目

    在这里插入图片描述

  2. consumer中写个测试

    package com.wifi.dubbo.consumer.service;
    
    import com.wifi.dubbo.interfaces.dto.Student;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    @SpringBootTest
    class StudentConsumerServiceImplTest {
    
        @Autowired
        private StudentConsumerServiceImpl studentConsumerService;
    
        @Test
        public void should_return_student_dto_when_getStudentInfo_given_id_is_1() {
            Student expectStudentResult = Student.builder()
                    .id(1)
                    .studentName("wifi")
                    .classRoom("Room one")
                    .phoneNumber("123456")
                    .build();
    
            Student actualStudentResult = studentConsumerService.getStudentInfo();
    
            assertEquals(expectStudentResult, actualStudentResult);
        }
    }
    
  3. 结果

    在这里插入图片描述

1.5 小结

因为只是想要体验/了解一下搭建SpringBoot + Dubbo 的过程,所以没有包含其他深入的知识点。
源代码地址

1.6 参考

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值