springboot 整合 dubbox

本贴最后更新于 2909 天前,其中的信息可能已经沧海桑田

简介

今天咱们来看看怎么利用 Spring Boot 整合 Dubbox 来开发去中心化的微服务。

系统环境

本文基于 Jdk1.8/Maven 3.3.9/Spring Boot 1.4.2.RELEASE/Dubbo 2.8.5.SNAPSHOT(Dubbox 后续开源版本)/ZooKeeper3.4.8

Zookeeper 环境搭建

下载并安装启动

下载

  wget http://mirrors.hust.edu.cn/apache/zookeeper/zookeeper-3.4.8/

解压

  tar -zxf zookeeper-3.4.8.tar.gz

修改配置文件

  cd zookeeper-3.4.8/conf

  cp zoo_sample.cfg zoo.cfg # zookeeper 默认是用../conf/zoo.cfg 如果没有这个文件则报错

  vim zoo.cfg

好吧 我们不改了,我们使用默认的配置.哈!

启动

  cd zookeeper-3.4.8/bin

  ./start.sh start #启动zookeeper 关闭: ./start.sh stop

Dubbox 环境准备

zookeeper 准备好了,先放着 一会再用.下面我们来准备下 Dubbox.

dubbox 是当当网基于 dubbo 开源的组件

为什么使用 dubbox?

因为 dubbox 支持更新的 spring 版本...

Dubbox 在 maven 中央仓库并没有对应的依赖,所以我们需要自己动手将其发布到我们的本地仓库来使用.

下载

我们这次从码云下载

  git clone https://git.oschina.net/wuyu15255872976/dubbox.git

编译安装

  cd dubbox

  mvn clean install -Dmaven.test.skip

等待 ... 等待...

之后我们在我们的 maven 本地仓库/com/alibaba/dubbo/2.8.5-SNAPSHOT 中会发现这么一个东西:

dubbo-2.8.5-SNAPSHOT.jar

这个玩意就是我们需要的 Dubbx 的 jar 包...

Spring Boot Dubbo 引导

dubbox 的 jar 包准备好了,行,咱先放着.一会再用.

下面来介绍下 spring-boot-starter-dubbo 项目的准备.

我们可能以前在使用 dubbo 的时候都是用的 xml 配置.在整合 Spring Boot 的时候呢是用的 @ImportResource 注解来引入的 dubbo 的 xml 配置.

但是 Spring Boot 本身并不推荐 xml 配置.怎么解决这个矛盾,我们可以自己准备一个 Spring Boot Starter dubbo 的项目来引导 Spring Boot 对 Dubbo 的自动化配置.

下载

  git clone https://git.oschina.net/wuyu15255872976/spring-boot-starter-dubbo.git

感谢这位悲伤的大神的开源贡献!. 顶一个,赞两个.

修改 pom.xml

  • 在环境准备的时候我们说过,我们的项目基于 Spring Boot 1.4.2.RELEASE ,但是我们 down 下来 spring-boot-starter-dubbo 的时候发现它用的是 1.3.6 的版本.我们动手自己改下 parent 的依赖吧.
  • 我们发现在 pom.xml 中基本所有的依赖的 option 都是 true,我懒所以我想在其他项目依赖这个项目的时候不要再写一遍,所以我把 <option>true</option> 都给干掉了...... 干不干掉这个倒是随意哈.
  • 刚上一个环节我们打包并安装到本地库的 Dubbox 在这个地方需要用上了. 我们修改 dubbo 的版本为 2.8.5-SNAPSHOT
  • 修改 java 版本为 1.8

完整 pom.xml 文件如下:

  <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>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.4.2.RELEASE</version>
    </parent>
    <artifactId>spring-boot-starter-dubbo</artifactId>
    <version>1.4.2.RELEASE</version>
    <name>Spring Boot Dubbo Rpc</name>
    <description>Spring Boot Dubbo Rpc</description>
    <url>http://projects.spring.io/spring-boot/</url>
    <organization>
      <name>Pivotal Software, Inc.</name>
      <url>http://www.spring.io</url>
    </organization>

    <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <java.version>1.8</java.version>
    </properties>

    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
      </dependency>
      <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>2.8.5-SNAPSHOT</version>
        <exclusions>
          <exclusion>
            <artifactId>spring</artifactId>
            <groupId>org.springframework</groupId>
          </exclusion>
        </exclusions>
      </dependency>
      <!-- zookeeper 客户端 -->
      <dependency>
        <groupId>com.github.sgroschupf</groupId>
        <artifactId>zkclient</artifactId>
        <version>0.1</version>
      </dependency>
    </dependencies>
    <dependencyManagement>
      <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-dependencies</artifactId>
          <version>1.4.2.RELEASE</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
      </dependencies>
    </dependencyManagement>

    <build>
      <plugins>
        <plugin>
          <artifactId>maven-source-plugin</artifactId>
          <configuration>
            <attach>true</attach>
          </configuration>
          <executions>
            <execution>
              <phase>compile</phase>
              <goals>
                <goal>jar</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
  </project>

编译打包

上面我们对于 spring-boot-starter-dubbo 的准备工作完成,我们现在打包编译

  mvn clean install -Dmaven.test.skip

然后我们去 maven 本地仓库中找到它:

xxx/org/springframework/boot/spring-boot-starter-dubbo/1.4.2.RELEASE/spring-boot-starter-dubbo-1.4.2.RELEASE.jar

dubbo 系统监控工具

这里我们使用韩都衣舍马老师提供的 dubbo-monitor

下载

  git clone https://git.oschina.net/handu/dubbo-monitor.git

运行

根据项目 README.MD 我们先创建一个叫 monitor 的数据库,然后 maven 打包运行,我们也可以导入到 IDE 中直接运行,当然生产环境我们不能这么干.

我们的 home 页面:

我们的 home 页面

一会儿我们需要在这里验证我们的 provider 和 consumer 是否已经成功.

基本工作已经准备妥当,我们来看下我们怎么使用它.

目录结构

首先我们来看一下整个 maven 项目的目录结构:

目录结构

  business
  --consumer
  ----pom.xml
  ----src/main/java
  --provier
  ----pom.xml
  ----src/main/java
  --service
  ----src/main/java
  --pom.xml

说明

  • business 作为父项目

  • consumer 是我们的服务消费者

  • provider 是我们的服务提供者

  • service 是提供 domain 和接口 service 的项目

    为什么要单独把 servicemodule 呢?

    因为我们写的 service(java interface)domain(java bean) 是需要在 consumer和provider 端共享的.

    单独打成 jar 包有利用我们的 代码重用和序列化反序列化.

基本结构介绍完成,下面我们分每一个模块来详细探讨.

business 父项目

既然 business 作为 maven 父项目,就做点它应该干的事.

pom.xml

  <?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>

    <groupId>cn.veryjava</groupId>
    <artifactId>business</artifactId>
    <packaging>pom</packaging>
    <version>1.0</version>

    <name>business</name>
    <description>business</description>

    <organization>
      <name>veryjava</name>
      <url>http://blog.veryjava.cn</url>
    </organization>

    <developers>
      <developer>
        <name>sunshineasbefore</name>
        <email>work_wjj@163.com</email>
      </developer>
    </developers>

    <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <spring-boot.version>1.4.2.RELEASE</spring-boot.version>
      <spring-boot-dubbo.version>1.4.2.RELEASE</spring-boot-dubbo.version>
    </properties>

    <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.4.2.RELEASE</version>
      <relativePath/>
    </parent>

    <modules>
      <module>service</module>
      <module>provider</module>
      <module>consumer</module>
    </modules>

    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>${spring-boot.version}</version>
        <optional>true</optional>
      </dependency>

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
      </dependency>

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-dubbo</artifactId>
        <version>${spring-boot-dubbo.version}</version>
        <optional>true</optional>
      </dependency>
    </dependencies>
  </project>

在其中我们引入 spring-boot-starter-parent spring-boot-starter-web spring-boot-starter-test spring-boot-starter-dubbo,其中除了 spring-boot-starter-parent 我们定义其他依赖都可选.

没了...

service 子项目

service 子项目提供 domain 和 service 接口.

pom.xml

  <?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">
    <parent>
      <artifactId>business</artifactId>
      <groupId>cn.veryjava</groupId>
      <version>1.0</version>
    </parent>

    <packaging>jar</packaging>

    <modelVersion>4.0.0</modelVersion>

    <artifactId>service</artifactId>

  </project>

定义一下 parentartifactId 完事.

BusinessDomain.java

  package cn.veryjava.business.domain;

  import java.io.Serializable;

  public class BusinessDomain implements Serializable{

    private int id;

    private String name;

    public BusinessDomain(int id, String name) {
      this.id = id;
      this.name = name;
    }

    public int getId() {
      return id;
    }

    public void setId(int id) {
      this.id = id;
    }

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }
  }

定义我们需要在 provider 和 consumer 中使用的 domain,实现 java.io.Serializable 来进行序列化.

dubbo 支持的序列化方式很多,这个可以参考 dubbo.io 里关于协议和序列化的介绍,我们使用默认的协议 dubbo.

BusinessService.java

  package cn.veryjava.business.service;

  import cn.veryjava.business.domain.BusinessDomain;

  public interface BusinessService {
    BusinessDomain findBusiness(int id, String name);
  }

定义我们需要在 provider 和 consumer 中使用的接口方法.

provider 子项目

我们的服务提供者.

pom.xml

  <?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">
    <parent>
      <artifactId>business</artifactId>
      <groupId>cn.veryjava</groupId>
      <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>provider</artifactId>

    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-dubbo</artifactId>
        <version>${spring-boot-dubbo.version}</version>
      </dependency>
      <dependency>
        <groupId>cn.veryjava</groupId>
        <artifactId>service</artifactId>
        <version>1.0</version>
      </dependency>
    </dependencies>

  </project>

定义 parentartifactId 并引入 spring-boot-starter-web spring-boot-starter-dubbo service 依赖.

application.yml

  server:
    port: 8081
  spring:
    dubbo:
      application:
        name: business-provider
      registry:
        protocol: zookeeper
        address: localhost:2181,192.168.2.23:2181
      protocol:
        name: dubbo
        port: 20880
        host: localhost
      scan: cn.veryjava.business.provider

定义我们的 dubbo 配置.

服务注册发现使用 zookeeper.协议使用 dubbo,包扫描路径写 cn.veryjava.business.provider

ProviderApplication.java

  package cn.veryjava.business.provider;

  import com.alibaba.boot.dubbo.EnableDubboAutoConfiguration;
  import org.springframework.boot.SpringApplication;
  import org.springframework.boot.autoconfigure.SpringBootApplication;

  @SpringBootApplication
  @EnableDubboAutoConfiguration
  public class ProviderApplication {
    public static void main(String[] args) {
      SpringApplication.run(ProviderApplication.class, args);
    }
  }

这是我们服务提供者的引导类.重点是 @EnableDubboAutoConfiguration 这个注解将引导我们自动化配置 dubbox

BusinessServiceImpl.java

  package cn.veryjava.business.provider;

  import cn.veryjava.business.domain.BusinessDomain;
  import cn.veryjava.business.service.BusinessService;
  import com.alibaba.dubbo.config.annotation.Service;

  @Service(version = "1.0.0")
  public class BusinessServiceImpl implements BusinessService {
    @Override
    public BusinessDomain findBusiness(int id, String name) {
      return new BusinessDomain(id,name);
    }
  }

这个是我们需要提供的服务,重点是 @Service 这个注解,需要注意的是此 @Service 非彼 @Service.

我们在这个地方使用的 @Service 是 dubbo 提供的,注意看 import 部分.然后,dubbo 的 springBoot 自动化配置会自动发现这个类并将其注册到 zookeeper.

当然我们使用 spring 提供的 @Service 也是可以的,不过这种方式比较麻烦.这个地方我们就不介绍了,有想了解的同学可以去 dubbo.io 去详细了解

编译运行

代码写好了,服务提供了,我们来验证下我们提供的服务是否能够成功注册并被发现.

启动后我们打开 dubbo-monitorServices 页面,如果看到如下情况,则证明我们的服务已经注册成功:

dubbo-monitor-services

注意观察其中 cn.veryjava.business.service.BusinessService 我们发现这个时候的 BusinessService 已经被提供但是还没有相应的消费者来使用.那么我们接下来看一下消费者怎么去使用.

consumer 子项目

这个是我们的服务消费者

pom.xml

  <?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">
    <parent>
      <artifactId>business</artifactId>
      <groupId>cn.veryjava</groupId>
      <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>consumer</artifactId>
    <dependencies>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-dubbo</artifactId>
        <version>${spring-boot-dubbo.version}</version>
      </dependency>
      <dependency>
        <groupId>cn.veryjava</groupId>
        <artifactId>service</artifactId>
        <version>1.0</version>
      </dependency>
    </dependencies>

  </project>

定义 parent artifactId 并引入 spring-boot-starter-web spring-boot-starter-dubbo service 依赖.

application.yml

  server:
    port: 8777
  spring:
    dubbo:
      application:
        name: business-consumer
      registry:
        protocol: zookeeper
        address: localhost:2181,192.168.2.23:2181
      protocol:
        name: dubbo
        port: 20880
        host: localhost
      scan: cn.veryjava.business.consumer.controller

实测 不写 scan 不行,可能是我刚开始理解有问题....我刚开始以为 scan 只是用来进行服务发现的,结果跟消费者进行消费也有关系...

ConsumerApplication.java

  package cn.veryjava.business.consumer;

  import com.alibaba.boot.dubbo.EnableDubboAutoConfiguration;
  import org.springframework.boot.SpringApplication;
  import org.springframework.boot.autoconfigure.SpringBootApplication;

  @SpringBootApplication
  @EnableDubboAutoConfiguration
  public class ConsumerApplication {
    public static void main(String[] args) {
      SpringApplication.run(ConsumerApplication.class, args);
    }
  }

服务消费者引导类,@EnableDubboAutoConfiguration 注解也得写,原因同上.

BusinessConsumerController.java

  package cn.veryjava.business.consumer.controller;

  import cn.veryjava.business.domain.BusinessDomain;
  import cn.veryjava.business.service.BusinessService;
  import com.alibaba.dubbo.config.annotation.Reference;
  import org.springframework.stereotype.Controller;
  import org.springframework.web.bind.annotation.RequestMapping;
  import org.springframework.web.bind.annotation.ResponseBody;

  @Controller
  public class BusinessConsumerController {

    @Reference(version = "1.0.0")
    public BusinessService businessService;


    @RequestMapping("/business")
    @ResponseBody
    public BusinessDomain getBusiness() {
      return businessService.findBusiness(1, "businessaaa");
    }
  }

我们的 BusinessService 服务是怎么被消费的,怎么被依赖的.其实就是使用了 dubbo 提供的 @Reference 注解... 告诉 dubbo 我要使用哪个版本服务,就是这么简单....

编译运行

我们来测一下 dubbo-monitor 能否监控到服务的消费者吧.

启动后我们打开 dubbo-monitorServices 页面,如果看到如下情况,则证明我们的服务已经注册成功并且消费者已经能够发现:

consumers

然后我们调用一下这个接口,看看到底是不是我们想要的数据.

  curl -L http://localhost:8777/business

输出如下:

  {"id":1,"name":"businessaaa"}

好吧,到这一步,我们的服务发现和服务消费都可以成功了.

总结

我们发现,dubbo 的使用还是很简单的,几乎没有任何的侵入性,也非常符合 Spring 的 IOC/DI 的理论概念.可以说跟 spring 的结合非常完美!

我们的这个小项目,仅仅只是用来学习的小项目,不过我们可以在此基础上对 zookeeper,对各个 provider/consumer 进行集群配置.这样我们就可以慢慢实现后台服务的去中心化,很大程度上提高了我们架构的可用性.

希望各位在 Java 的路上越走越好.!

代码

springboot 整合 dubbox 的实例一枚

原文地址

springboot 整合 dubbox 的实例一枚

  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 595 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    944 引用 • 1459 回帖 • 17 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3187 引用 • 8213 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • mainlove

    我们的这个小项目,仅仅只是用来学习的小项目,不过我们可以在此基础上对 zookeeper,对各个 provider/consumer 进行集群配置.这样我们就可以慢慢实现后台服务的去中心化,很大程度上提高了我们架构的可用性.

    然后你发现项目根本没有什么并发

    1 回复
  • 其他回帖
  • freerambo

    耐着性子才看完,太复杂啊

    1 回复
  • 27186129

    步骤不少,不过楼主很用心,帖子很详细,有空我照着来一遍,学习下。

    1 回复
  • alanfans

    👍

  • 查看全部回帖