Spring-boot:5分钟整合Dubbo构建分布式服务

概述:

  Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看,Dubbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。

  我们来看一下Dubbo 的RPC 调用流程,这里主要涉及到4个模块:

  • Registry:服务注册,我们一般会采取Zookeeper 作为我们的注册中心
  • Provider:服务提供者(生产者),提供具体的服务实现
  • Consumer:消费者,从注册中心中订阅服务
  • Monitor:监控中心,RPC调用次数和调用时间监控

      从上图中我们可以了解到整个RPC 服务调用的过程主要为:

  1. 生产者发布服务到服务注册中心中
  2. 消费者在服务注册中心中订阅服务
  3. 消费者调用已经注册的服务

一、项目构建

 开发环境主要涉及以下几个方面:

  • Spring-boot
  • JDK 8
  • Dubbo
  • Zookeeper

 项目构建通过: http://start.spring.io/ 快速构建web 项目,具体操作可以参考《Spring-Boot:6分钟掌握SpringBoot开发》

 由于Dubbo 中需要使用到服务注册中心,我们这里将使用Zookeeper 作为服务注册中心,具体安装配置,可以参考《Zookeeper-5分钟快速掌握分布式应用程序协调服》

 在基础环境确定好了之后,我们项目的目录结构如下:

    上图所示,我们项目主要分为了两个模块,一部分是生产者:spring-boot-dubbo ,一部分是:spring-boot-consumer。

    整个项目的结构非常简单,这很符合Spring-Boot 的特性,简单便捷,下面我们开始一步步的剖析整个项目的结构

二、Productor

 2.1、Pom.xml

   项目依赖这一块主要使用到了基本的Spring-Boot-Web 依赖,然后我们需要额外引入Dubbo 与Zookeeper的依赖(详细依赖可参考源码,博文底部会有项目Github 地址):

    <dependency>
            <groupId>io.dubbo.springboot</groupId>
            <artifactId>spring-boot-starter-dubbo</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

 2.2、配置文件

   由于我们底层使用的是Spring-Boot 进行开发,那么我们就应该善于利用Spring-Boot 给我们带来的优势,因此我们可以直接在Application.properties 文件中配置Dubbo 服务:

## Dubbo 服务提供者配置
spring.dubbo.application.name=provider    --服务名称
spring.dubbo.registry.address=zookeeper://127.0.0.1:2181   -- 注册中心地址
spring.dubbo.protocol.name=dubbo     -- dubbo 协议
spring.dubbo.protocol.port=20880
spring.dubbo.scan=com.jaycekon.dubbo.service     --声明需要暴露的服务接口

   如果不采用Spring-Boot 进行自动配置,大家可以参考一下的配置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: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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!-- 提供方应用信息 -->
    <dubbo:application name="provider"  />
    <!-- 注册中心服务地址 -->
    <dubbo:registry  protocol="zookeeper" address="127.0.0.1"  check="false" />
    <!-- 用dubbo协议-->
    <dubbo:protocol name="dubbo" port="-1" dispather="all" check="false" />
    <dubbo:provider timeout="10000"  threads="10" threadpool="fixed"   loadbalance="roundrobin"/>
    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.jaycekon.dubbo.service" ref="userService"/> </beans>

2.3、服务提供

  在服务提供主要包括两部分,一个是暴露服务,一个是服务实现

  暴露服务:即我们平常开发中所使用的的接口,这里我们创建一个 UserService 的接口,主要包括一个保存用户的方法。

import com.jaycekon.dubbo.domain.User;

/**
 * Created by Jaycekon on 2017/9/19.
 */
public interface UserService {

    User saveUser(User user);
}

  服务实现:服务实现,与我们平常的服务一样,对接口进行实现,比较特别的是,我们这里需要使用到Dubbo 的 @Service 注解

import com.alibaba.dubbo.config.annotation.Service;
import com.jaycekon.dubbo.domain.User;
import com.jaycekon.dubbo.service.UserService;

/**
 * Created by Jaycekon on 2017/9/19.
 */
@Service
public class UserServiceImpl implements UserService {

    @Override
    public User saveUser(User user) {
        user.setId(1);
        System.out.println(user.toString());
        return user;
    }
}

2.4、总体结构

  Dubbo 的服务提供端,已经总体开发完成,非常简单,总体的目录结构如下:

三、Consumer

3.1、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>com.jaycekon</groupId>
    <artifactId>spring-boot-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-boot-consumer</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

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

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

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

        <!-- Spring Boot Dubbo 依赖 -->
        <dependency>
            <groupId>io.dubbo.springboot</groupId>
            <artifactId>spring-boot-starter-dubbo</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


        <!-- mvn spring-boot:run 热部署启动 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>springloaded</artifactId>
            <version>1.2.3.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

3.2、配置文件

  配置文件与生产者稍有区别:

## 避免和 server 工程端口冲突
server.port=8081

## Dubbo 服务消费者配置
spring.dubbo.application.name=consumer
spring.dubbo.registry.address=zookeeper://127.0.0.1:2181
spring.dubbo.scan=com.jaycekon.dubbo.service

      基于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: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://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!-- 提供方应用信息 -->
    <dubbo:application name="provider"  />
    <!-- 注册中心服务地址 -->
    <dubbo:registry  protocol="zookeeper" address="${dubbo.registry.address}"  check="false" />
    <!-- 用dubbo协议-->
    <dubbo:protocol name="dubbo" port="-1" dispather="all" check="false" />
    <dubbo:provider timeout="10000"  threads="10" threadpool="fixed"   loadbalance="roundrobin"/>
    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.jaycekon.dubbo.service" ref="userService"/>
</beans>

3.3、服务实现

  在这里,如果我们需要调用注册服务中的相关服务,则需要实现相关的接口。

import com.jaycekon.dubbo.domain.User;

/**
 * Created by Jaycekon on 2017/9/19.
 */
public interface UserService {
    User saveUser(User user);
}

  例如,在这里我们需要使用到生产者中的 saveUser(User user) 方法,则需要创建一个接口,然后再调用时,使用 @Reference 注解进行引用:

import com.alibaba.dubbo.config.annotation.Reference;
import com.jaycekon.dubbo.domain.City;
import com.jaycekon.dubbo.domain.User;
import org.springframework.stereotype.Component;

/**
 * 城市 Dubbo 服务消费者
 * <p>
 * Created by Jaycekon on 20/09/2017.
 */
@Component
public class CityDubboConsumerService {

    @Reference
    CityDubboService cityDubboService;

    @Reference
    UserService userService;

    public void printCity() {
        String cityName = "广州";
        City city = cityDubboService.findCityByName(cityName);
        System.out.println(city.toString());
    }


    public User saveUser() {
        User user = new User();
        user.setUsername("jaycekon")
                .setPassword("jaycekong824");
        return userService.saveUser(user);
    }
}

3.4、服务调用

  最后,我们需要实现一个RESTful 接口,提供给用户调用:

import com.jaycekon.dubbo.service.CityDubboConsumerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by Jaycekon on 2017/9/19.
 */
@RestController
public class UserController {

    @Autowired
    private CityDubboConsumerService service;


    @RequestMapping("/save")
    public Object saveUser() {

        return service.saveUser();
    }
}

3.5、目录结构

四、总结

  本篇博客主要是博主在学习Spring-boot 的时候,总结下来的。在经过一些列的对比后,感觉Dubbo 与Spring-Cloud 还是有点差距的,不管是从服务提供,还是社区活跃来说,Spring-Cloud 还是会强一点。但是由于公司内部使用的是Dubbo,因此还是需要学习一下,后续的话,会对Spring-Cloud 进行学习以及分项。

  本文中出现的代码,大家可以到我的 GitHub 多啦A梦 的传送门-https://github.com/jaycekon/SpringBoot

       希望大家不要吝啬自己的Star 和 Fork ,谢谢。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JackieZheng

RabbitMQ入门-从HelloWorld开始

从读者的反馈谈RabbitMQ 昨天发完《RabbitMQ入门-初识RabbitMQ》,我陆陆续续收到一些反馈。鉴于部分读者希望结合实例来讲 期待下篇详细,最好...

1869
来自专栏玩转JavaEE

Spring Cloud中的API网关服务Zuul

到目前为止,我们Spring Cloud中的内容已经介绍了很多了,Ribbon、Hystrix、Feign这些知识点大家都耳熟能详了,我们在前文也提到过微服务就...

3235
来自专栏酷玩时刻

t-io 集群解决方案以及源码解析

本博客是基于谭总 t-io showcase中的tio-websocket-showcase 示例来实现集群。看showcase 入门还是挺容易的,入坑(入门)...

532
来自专栏Java技术栈

两年摸爬滚打 Spring Boot,总结了这 16 条最佳实践

Spring Boot是最流行的用于开发微服务的Java框架。在本文中,我将与你分享自2016年以来我在专业开发中使用Spring Boot所采用的最佳实践。这...

743
来自专栏一枝花算不算浪漫

Dubbo的使用及原理浅析.

43813
来自专栏Kirito的技术分享

使用Spring Cloud Sleuth实现链路监控

在服务比较少的年代,一个系统的接口响应缓慢通常能够迅速被发现,但如今的微服务模块,大多具有规模大,依赖关系复杂等特性,错综复杂的网状结构使得我们不容易定位到某一...

3518
来自专栏java一日一条

Java管理扩展指南之JMX技术总览

JMX(Java管理扩展)系列旨在介绍包含于Java基础版本(Java SE)中的JMX技术。本系列提供了如何使用JMX重要技术特性的诸多示例。

854
来自专栏情情说

《深入实践Spring Boot》阅读笔记之三:核心技术源代码分析

上篇文章总结了《深入实践Spring Boot》的第二部分,本篇文章总结第三部分,也是最后一部分。这部分主要讲解核心技术的源代码分析,因为篇幅和能力原因,分析的...

4738
来自专栏Spark学习技巧

基于zookeeper leader选举方式一

一,基本介绍 Curator Framework是一个针对zookeeper做的搞层次的API,极大地简化了zookeeper的使用。它基于zookeeper构...

2035
来自专栏冷冷

扩展Zuul实现敏捷开发的小小技巧

重写网关的转发规则,其实就是重写ribbon的路由规则,根据客户端不同的用户请求(可以根据入参不同区分)路由到对应的微服务上,所以对应的微服务上要打上标签。b...

1131

扫码关注云+社区