28

5分钟实现SpringBoot整合Dubbo构建分布式服务

 4 years ago
source link: http://developer.51cto.com/art/202005/616813.htm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

概述:

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

ZRru2yE.png!web

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

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

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

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

一、项目构建

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

  •  Spring-boot
  •  JDK 8
  •  Dubbo
  •  Zookeeper

项目构建通过: http://start.spring.io/ 快速构建web 项目,具体操作可以参考

http://www.cnblogs.com/jaycekon/p/7562688.html

由于Dubbo 中需要使用到服务注册中心,我们这里将使用Zookeeper 作为服务注册中心,具体安装配置,可以参考

http://www.cnblogs.com/jaycekon/p/7553909.html

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

Ub6Jfy2.png!web

上图所示,我们项目主要分为了两个模块,一部分是生产者: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 注解。更多springboot实战内容,Java知音公众号内回复“springboot聚合”

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 的服务提供端,已经总体开发完成,非常简单,总体的目录结构如下:

QZJn2uE.png!web

三、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地址

https://github.com/jaycekon/SpringBoot

【责任编辑:庞桂玉 TEL:(010)68476606】


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK