Spring Boot 2+Dubbo 学习系列2:搭建Spring Boot 2+Dubbo+Zookeeper集群

本项目使用当前(2018年7月)最新的官方正式版本实践,SpringBoot 2.0.3+dubbo-spring-boot-starter 0.2.0(即dubbo2.6.2)+zookeeper集群

文章主要参考了Dubbo在Apache的项目主页的文档,还有Dubbo Spring Boot 工程在github的说明和例子

文章写得较繁琐,重点在后半部分

目录:

一 项目结构

项目结构

项目名为dubbo,其下分3个模块base-interface,provider和consumer

  • base-interface:基础接口模块,对应的即Dubbo服务
  • provider:提供者
  • consumer:消费者

模块功能

  • 相互关系
    主项目dubbo负责版本管理,provider和consumer都依赖base-interface接口,其中,provider提供了接口的具体实现,而consumer则调用了provider的实现,他们通过base-interface来确定使用规范(接口即契约)
  • 对应MVC关系
    对应到MVC的话,base-interface就是service(接口,为提供实现),provider就相当于serviceImpl(service的实现类),而concumer就是controller的角色.
  • 框架依赖
    所以base-interface是单纯的服务接口集,不需要额外的依赖,而provider只提供服务实现,并不对外开放,只需对内提供服务调用就好,不需要spring-web支持,真正对外开放接口的就只有consumer

二 项目搭建

新建dubbo项目,在dubbo项目下添加base-interface,provider和consumer 3个模块
修改各个模块pom文件,组成项目结构,具体如下

1 在主项目dubbo的pom引入子模块并进行依赖的版本管理

注意,这里的packing是pom,子模块为jar
而且,子模块不定义groupId和version,即跟随主项目的groupId和version
另外,这里的插件是maven-deploy-plugin,并没有spring-boot-maven-plugin,因为一些子模块不需要(如base-interface)

<?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.linshen.dubbo</groupId>
    <artifactId>dubbo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>dubbo</name>
    <description>Demo project for Spring Boot</description>

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

    <!--引入的子模块-->
    <modules>
        <module>base-interface</module>
        <module>provider</module>
        <module>consumer</module>
    </modules>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.boot</groupId>
                <artifactId>dubbo-spring-boot-starter</artifactId>
                <version>${dubbo-springboot.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba.boot</groupId>
                <artifactId>dubbo-spring-boot-actuator</artifactId>
                <version>${dubbo-springboot.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-deploy-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2 修改base-interface模块如下

注意,这里没有引入spring-boot-maven-plugin插件,因为base-interface并不是一个真正的SpringBoot项目,也没有启动类

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

    <artifactId>base-interface</artifactId>

    <name>base-interface</name>

    <parent>
        <groupId>com.linshen.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

</project>

3 在模块provider和consumer引入依赖

注意这里引入了actuator,非必须,也可以去掉的

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

    <artifactId>provider</artifactId>
    <packaging>jar</packaging>

    <name>provider</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>com.linshen.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <dependencies>
        <!-- 基础接口模块-->
        <dependency>
            <groupId>com.linshen.dubbo</groupId>
            <artifactId>base-interface</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>dubbo-spring-boot-actuator</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

4 在consumer模块中再引入web依赖

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

5 将base-interface的Application引导类删除,其他无用的文件夹也删去(如resource)

6 修改provider的Application引导类,使其按非web应用运行

@SpringBootApplication
public class ProviderApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(ProviderApplication.class)
                .web(WebApplicationType.NONE)
                .run(args);
    }
}

至此,项目搭建完毕

三 功能实现

按照前文讲的,我们来实现最基础的问候功能(hello和goodbye)

1 在base-interface模块定义接口

如下,是一个很单纯的接口

public interface HelloService {
    String sayHello(String name);
    String sayGoodbye(String name);
}

2 在provider模块实现接口

如下,重点在于@Service注解

@Service(
        version = "${hello.service.version}",
        application = "${dubbo.application.id}",
        protocol = "${dubbo.protocol.id}",
        registry = "${dubbo.registry.id}"
)
public class DefaultHelloService implements HelloService {
    @Override
    public String sayHello(String name) {
        return "Hello "+name+" !";
    }

    @Override
    public String sayGoodbye(String name) {
        return "Goodbye "+name+" !";
    }

application.yml文件如下:
注意,dubbo.registry.address请设置为真实zookeeper地址,我这里用的是zookeeper集群,具体可参考上一篇文章:SpringBoot2+Dubbo 学习系列1:使用Docker部署zookeeper
如果要简单的话可以像官方教程一样直接用广播,这样就不需要使用注册中心了(相应的,就不能指定dubbo.registry.protocol)

dubbo.registry.id = my-registry
dubbo.registry.address = N/A

另外注意这里给了dubbo.protocol的参数,因为provider是要通过dubbo协议来提供服务的(当然也可以用其他协议,这里不展开)

spring:
  application:
    name: linshen-dubbo-provider1
server:
  port: 9090
dubbo:
  registry:
    protocol: zookeeper
    address: ip:2181,ip:2182,ip:2183
    id: lin-registry-1
  protocol:
    port: 12345
    name: dubbo
    id: dubbo
    status: server
  application:
    name: linshen-dubbo-provider-name1
    id: linshen-dubbo-provider-id1
    qos-enable: true
    qos-port: 22222
  scan:
    basePackages: com.linshen.dubbo.provider.service
hello:
  service:
    version: 1.0.0

3 在consumer模块编写controller

如下,重点在于@Reference
注意,下面的注解中在官方给的例子中是把registry换成url,如url = “dubbo://localhost:12345”来指定dubbo服务地址,这样下面yml文件就可以不用写dubbo.registry板块了(毕竟官方给的例子没有真正的注册中心),但我还是觉得使用一开始就使用zookeeper会更加自然,更容易理解

@RestController
public class HelloController {

    @Reference(
            version = "${hello.service.version}",
            application = "${dubbo.application.id}",
            registry = "${dubbo.registry.id}"
    )
    private HelloService helloService;

    @GetMapping("hello/{name}")
    public String sayHello(@PathVariable String name){
        return helloService.sayHello(name);
    }

    @GetMapping("goodbye/{name}")
    public String sayGoodbye(@PathVariable String name){
        return helloService.sayGoodbye(name);
    }
}

application.yml文件如下:
注意,这里我开启了actuator

spring:
  application:
    name: linshen-dubbo-consumer1
server:
  port: 9091
hello:
  service:
    version: 1.0.0
dubbo:
  application:
    id: linshen-dubbo-consumer-id1
    name: linshen-dubbo-consumer-name1
  registry:
    protocol: zookeeper
    address: ip:2181,ip:2182,ip:2183
    id: lin-registry-1
management:
  endpoint:
    dubbo-configs:
      enabled: true
    dubbo:
      enabled: true
    dubbo-services:
      enabled: true
    dubbo-properties:
      enabled: true
    dubbo-shutdown:
      enabled: true
    dubbo-references:
      enabled: true
  health:
    dubbo:
      status:
        defaults: memory
        extras: load,threadpool
  endpoints:
    web:
      exposure:
        include: '*'

至此项目搭建结束

四 项目启动并测试

1 启动项目

启动provider,观察日志

这里写图片描述
如图是只是日志的一部分,其中红线为本机ip,蓝线为zookeeper所在主机ip,绿框为连接建立状态,从日志中也可以看出来,大概流程是先初始化客户端连接到zookeeper集群,在开通一个socket连接到一台zookeeper主机,,接着就注册当前客户端信息(包含dubbo协议地址,服务信息等等,如截图),然后与注册中心建立连接完成,会话建立,状态更改为CONNECTED,然后注册中心会订阅此provider信息并通知所有订阅此provider信息的url.(这个流程只是从日志上粗略地看的,并不一定准确)

启动consumer,观察日志

前面和provider差不多,也是要把自身注册到zookeeper上的,注册完后还会多一些步骤,如下图
这里写图片描述
可以很直观地看到,注册完之后红线比蓝线要多得多,因为注册完之后就和zookeeper没什么事了,consumer从注册中心获得provider的信息后,便直接和provider建立连接,如图中所示,是通过NettyClient建立的连接,然后从注册中心查阅特定的dubbo service服务,然后建立引用关系

2 测试

使用PostMan测试如下(其实直接用链接打开就可以测试了…)

这里写图片描述
这里写图片描述

使用actuator查看如下

以简单地查看dubbo信息为例:
这里写图片描述
dubbo还开放了很多其他的endpoint来监控
如dubbo/configs查看配置信息,dubbo/references查看引用实体等.
需要注意的是,由于使用的是SpringBoot2,所以Actuator的基础路径是ip:port/actuator,以前只是ip:port而已,这一点在dubbo的官方说明里还没有更改,详情请看Spring Boot 2.0官方文档之 Actuator

其他

到目前来看监控还是很不方便的,特别是当服务较多的时候,我们都值得Spring Cloud的服务治理中心是有终端网页的,图形化界面,关系看起来非常直观,舒服,当然Dubbo也有,而且还原生支持中文,那就是Dubbo Admin,只不过它得另外部署,界面如下,部署放在下一篇文章说
这里写图片描述
这里写图片描述

文章参考:
http://dubbo.apache.org
http://start.dubbo.io/
https://github.com/apache/incubator-dubbo-spring-boot-project/blob/master/README_CN.md

猜你喜欢

转载自blog.csdn.net/alinyua/article/details/81019925