coding……
但行好事 莫问前程

Spring Boot整合dubbo

随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。简单了解一下,网站架构的发展历程:

  • 单一应用架构

当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。

  • 垂直应用架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。

  • 分布式服务架构

当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。这种架构也就是所说的面向服务的架构,一般方法为把工程拆分成服务层、表现层。服务层中包含业务逻辑,真正对外提供服务。表现层只需要定义服务协议(接口),业务逻辑都是调用服务层的服务来实现,这样不光开发效率快,而且在扩展和升级相关服务的时候更加灵活。

  • 流动计算架构

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

在大规模服务化之前,应用可能只是通过RMI或Hessia 等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过 F5 等硬件进行负载均衡。当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。 此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。其实Dubbo就是SOA服务治理的一个优秀的实现方案。

Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的RPC实现服务的输出和输入功能,可以和Spring框架无缝集成。

介绍完Dubbo的基本概念,本篇文章讲述一下,Spring Boot与Dubbo集成的实现方案。Dubbo现在已经成为Apache社区优秀开源项目,在Maven中心仓库现在最新的版本是2.6.3。在开源后,Dubbo很长一段时间处官方未支持状态,直至2017年才重启了官方的维护。期间很多公司在Dubbo的基础上,根据自身的需求,为Dubbo实现了一些新的功能,比如当当的Dubbox,现在最新版本是2.8.4。因为之前用Maven中心仓库的2.6.3版本存在一些bug,比如使用telnet invoke测试时,如果dubbo服务的request是对象,会报no such method异常,所以本文使用的是2.8.4版本。2.8.4在Maven中心仓库拉不到,需要手动下载dubbox源码进行编译获取jar包,如果不想手动打包,可以到我的网盘下载,链接: https://pan.baidu.com/s/1yL_lcyS2nfFABG5hiv_lZw 密码: 752f。可以通过maven中心仓库拉取2.6.3的Dubbo依赖,然后手动将com.alibaba:dubbo手动替换成2.8.4版本,注意同时要添加com.alibaba:fastjson依赖,否则telnet invoke测试依然报错。

在测试dubbo之前,要安装dubbo注册中心——Zookeeper(其实也可以不适用Zookeeper作为注册中心,Redis也可以),安装方法windows、Linux直接通过apt安装即可。

1. 项目结构

|   .gitignore
|   pom.xml
|   springboot-11-dubbo.iml
+---dubbo-consumer
|   |   dubbo-consumer.iml
|   |   pom.xml
|   |
|   +---src
|   |   +---main
|   |   |   +---java
|   |   |   |   \---com
|   |   |   |       \---zhuoli
|   |   |   |           \---service
|   |   |   |               \---springboot
|   |   |   |                   \---dubbo
|   |   |   |                       \---consumer
|   |   |   |                           |   DubboConsumerApplicationContext.java
|   |   |   |                           |
|   |   |   |                           +---common
|   |   |   |                           |   +---request
|   |   |   |                           |   |       SayHelloConsumerRequest.java
|   |   |   |                           |   |
|   |   |   |                           |   \---vo
|   |   |   |                           |           SayHelloConsumerVo.java
|   |   |   |                           |
|   |   |   |                           +---controller
|   |   |   |                           |       HelloController.java
|   |   |   |                           |
|   |   |   |                           \---core
|   |   |   |                               |   HelloControllerService.java
|   |   |   |                               |
|   |   |   |                               \---impl
|   |   |   |                                       HelloControllerServiceImpl.java
|   |   |   |
|   |   |   \---resources
|   |   |           dubbo-consumer.xml
|   |   |
|   |   \---test
|   |       \---java
+---dubbo-contract
|   |   dubbo-contract.iml
|   |   pom.xml
|   |
|   +---src
|   |   +---main
|   |   |   +---java
|   |   |   |   \---com
|   |   |   |       \---zhuoli
|   |   |   |           \---service
|   |   |   |               \---springboot
|   |   |   |                   \---dubbo
|   |   |   |                       \---contract
|   |   |   |                           +---request
|   |   |   |                           |       SayHelloRequest.java
|   |   |   |                           |
|   |   |   |                           +---service
|   |   |   |                           |       DubboTestService.java
|   |   |   |                           |
|   |   |   |                           \---vo
|   |   |   |                                   SayHelloVo.java
|   |   |   |
|   |   |   \---resources
|   |   \---test
|   |       \---java
\---dubbo-provider
    |   dubbo-provider.iml
    |   pom.xml
    |
    +---src
    |   +---main
    |   |   +---java
    |   |   |   \---com
    |   |   |       \---zhuoli
    |   |   |           \---service
    |   |   |               \---springboot
    |   |   |                   \---dubbo
    |   |   |                       \---provider
    |   |   |                           |   DubboProviderApplicationContext.java
    |   |   |                           |
    |   |   |                           \---core
    |   |   |                               \---rpc
    |   |   |                                       DubboTestServiceImpl.java
    |   |   |
    |   |   \---resources
    |   |           dubbo-provider.xml
    |   |           logback.xml
    |   |
    |   \---test
    |       \---java

该项目跟以往的示例代码有所不同,该项目是个多module项目,可以理解为每个module都是一个独立的项目。

  • dubbo-provider:dubbo服务提供方
  • dubbo-consumer:dubbo服务消费放
  • dubbo-contract:之前讲的面向服务架构的协议,提供方通过协议暴露服务,消费方通过协议消费服务

2. 父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.zhuoli.service</groupId>
    <artifactId>springboot-11-dubbo</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>dubbo-provider</module>
        <module>dubbo-consumer</module>
        <module>dubbo-contract</module>
    </modules>

    <!-- 继承说明:这里继承SpringBoot提供的父工程 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.7.RELEASE</version>
        <relativePath/>
    </parent>

    <!-- 版本说明:这里统一管理依赖的版本号 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.zhuoli.service</groupId>
                <artifactId>dubbo-provider</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <dependency>
                <groupId>com.zhuoli.service</groupId>
                <artifactId>dubbo-consumer</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

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

        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba/dubbo -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.9</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>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.44</version>
        </dependency>
        
    </dependencies>

</project>

注意如果要使用2.8.4版本的Dubbo,通过Maven获取依赖后,要手动替换com.alibaba:dubbo jar包。其实不替换也可以,我测试了一下,2.6.3版本只是在使用telnet invoke消费时会报”no such method”异常,除此之外,都是正常的。

3. Dubbo Contract

@Getter
@Setter
public class SayHelloRequest implements Serializable {
    private String content;
}

@Getter
@Setter
public class SayHelloVo implements Serializable {
    private String result;
}

public interface DubboTestService {
    SayHelloVo sayHello(SayHelloRequest request);
}

contract的意义在于dubbo服务提供方暴露服务,而服务消费方通过协议消费提供方的服务。实际开发中通常将contract作为提供方的一个子module,通过maven/gradle集成自动打包工具,将contract发布到公司私服上,消费方通过maven/gradle引用这个包就可以了。但是在本项目中,不具备这些条件,所以我将contract单独作为一个module,然后通过provider和consumer的pom.xml添加对dubbo-contract的依赖,达到同样的效果。

4. Dubbo Provider

4.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">
    <parent>
        <artifactId>springboot-11-dubbo</artifactId>
        <groupId>com.zhuoli.service</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>dubbo-provider</artifactId>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!--添加dubbo-contract依赖-->
        <dependency>
            <groupId>com.zhuoli.service</groupId>
            <artifactId>dubbo-contract</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

4.2 服务暴露

在src/main/resources目录下定义dubbo-provider.xml文件,暴露dubbo服务,如下:

<?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-2.5.xsd
	    http://code.alibabatech.com/schema/dubbo
	 http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!--dubbo服务名称-->
    <dubbo:application name="springboot-dubbo-provider" />
    <!--dubbo注册地址-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
    <!--dubbo服务端口-->
    <dubbo:protocol name="dubbo" port="10001" />

    <!--服务实现-->
    <bean id="dubboTestService" class="com.zhuoli.service.springboot.dubbo.provider.core.rpc.DubboTestServiceImpl"/>
    <!--dubbo服务暴露-->
    <dubbo:service interface="com.zhuoli.service.springboot.dubbo.contract.service.DubboTestService"
                   protocol="dubbo"
                   ref="dubboTestService"
                   timeout="5000"/>
</beans>

4.3 服务实现

@Service
public class DubboTestServiceImpl implements DubboTestService {
    @Override
    public SayHelloVo sayHello(SayHelloRequest request) {
        SayHelloVo sayHelloVo = new SayHelloVo();
        sayHelloVo.setResult("Hello: " + request.getContent());
        return sayHelloVo;
    }
}

4.4 dubbo-provider web服务启动入口

@SpringBootApplication
@ImportResource(value = "dubbo-provider.xml")
public class DubboProviderApplicationContext {
    public static void main(String[] args) {
        SpringApplication.run(DubboProviderApplicationContext.class, args);
    }
    
    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        /*http端口*/
        return container -> container.setPort(9898);
    }
}

4.5 配置web服务启动Configuration

配置方法见Spring Boot入门Intellij Idea配置Edit Configurations启动程序章节。

5. Dubbo Consumer

5.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">
    <parent>
        <artifactId>springboot-11-dubbo</artifactId>
        <groupId>com.zhuoli.service</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>dubbo-consumer</artifactId>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!--dubbo contract依赖-->
        <dependency>
            <groupId>com.zhuoli.service</groupId>
            <artifactId>dubbo-contract</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

5.2 dubbo consumer注册服务

在src/main/resources目录下定义dubbo-consumer.xml文件,引用dubbo服务,如下:

<?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-2.5.xsd
	    http://code.alibabatech.com/schema/dubbo
	 http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:application name="springboot-dubbo-consumer"/>
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <dubbo:reference id="dubboTestService"
                     interface="com.zhuoli.service.springboot.dubbo.contract.service.DubboTestService"
                     check="false"
                     validation="true"
                     timeout="5000"/>
</beans>

5.3 dubbo-consumer web服务启动入口

@SpringBootApplication
@ImportResource(value = "dubbo-consumer.xml")
public class DubboConsumerApplicationContext {
    public static void main(String[] args) {
        SpringApplication.run(DubboConsumerApplicationContext.class, args);
    }

    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        return container -> container.setPort(9899);
    }
}

定义之后,也要配置web服务启动Configuration,配置方法跟4.5节一致。

5.4 controller web接口

@RestController
@RequestMapping(value = "/consumer/hello")
@AllArgsConstructor
public class HelloController {
    private HelloControllerService helloControllerService;

    @RequestMapping(value = "/say_hello", method = RequestMethod.POST)
    public ResponseEntity<SayHelloConsumerVo> sayHello(@Valid @RequestBody SayHelloConsumerRequest request){
        return ResponseEntity.status(HttpStatus.OK).body(helloControllerService.sayHello(request));
    }
}

5.5 service层服务

public interface HelloControllerService {
    SayHelloConsumerVo sayHello(SayHelloConsumerRequest request);
}

@Service
@AllArgsConstructor
public class HelloControllerServiceImpl implements HelloControllerService {

    private DubboTestService dubboTestService;

    @Override
    public SayHelloConsumerVo sayHello(SayHelloConsumerRequest request) {
        SayHelloRequest sayHelloRequest = new SayHelloRequest();
        sayHelloRequest.setContent(request.getContent());
        SayHelloVo sayHelloVo = dubboTestService.sayHello(sayHelloRequest);

        SayHelloConsumerVo sayHelloConsumerVo = new SayHelloConsumerVo();
        sayHelloConsumerVo.setResult(sayHelloVo.getResult());
        return sayHelloConsumerVo;
    }
}

可以看到,对dubbo服务的引用就是通过contract接口实现的。

5.6 测试

将provider、consumer web服务启动,通过postman发送请求,查看结果,如下: 以上,就是一次dubbo的简单调用过程,只是讲述一下简单的使用方法,对于dubbo来讲仅仅是皮毛,dubbo作为优秀的SOA服务治理框架,比如负载均衡,服务分组等高级应用,我的了解也是比较少少,以后有机会希望可以研究一下dubbo源码,深入一下对Dubbo的了解

示例代码:码云 – 卓立 – Spring Boot + Dubbo示例

参考链接:

  1. Dubbo 官方文档
  2. 高性能优秀的服务框架-dubbo介绍

赞(0) 打赏
Zhuoli's Blog » Spring Boot整合dubbo
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址