Springboot整合Dubbo+Zookeeper

一:什么是Dubbo

Dubbo是一款高性能、轻量级的开源Java RPC框架,
它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
即实现了多个独立应用之间的解耦且可以远程调用对方的服务

二、为什么需要 dubbo

很多时候,因为项目需要用到分布式架构,所以就引用了dubbo这项技术,但是至于为什么我们需要用到这个技术
可能自身并不是很了解,但是,其实了解技术的来由及背景知识,对于理解一项技术还是有帮助的,
在以前,我们只需要一个服务器,将程序全部打包好就可以,但是,随着流量的增大,常规的垂直应用架构已无法应对,所以,架构就发生了演变。

所需演变的方面
1 单一应用架构
2 应用和数据库单独部署
3 应用和数据库集群部署
4 数据库压力变大,读写分离
5 使用缓存技术加快速度
6 数据库分库分表
7 应用分为不同的类型拆分

发展到这个阶段的时候,我们发现,应用与应用之间的关系已经十分的复杂了,就会出现以下几个问题(以下摘录于官网):

① 当服务越来越多时,服务 URL 配置管理变得非常困难,F5 硬件负载均衡器的单点压力也越来越大。
② 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。
③ 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?

为了解决这由于架构的演变所产生的问题几个问题,于是,dubbo 产生了。当然,解决这个问题的技术不止 dubbo 。

三、关键点介绍:

1.注册与发现  
    Dubbo使用zookeeper做服务的注册中心,就是服务的提供者以临时节点的形式将服务Server信息注册保存到Zookeeper的dubbo目录下
的provider的节点下,供消费者发现调用。

2.负载均衡
    Dubbo支持负载均衡策略,就是同一个Dubbo服务被多台服务器启用后,会在Zookeeper提供者节点下显示多个相同接口名称节点。
    消费者在调用Dubbo负载均衡服务时,采用权重的算法策略选择具体某个服务器上的服务,权重策略以*2倍数设置。

3.容错机制
    Dubbo的提供者在Zookeeper上使用的是临时节点,一旦提供者所在服务挂掉,该节点的客户端连接将会关闭,故节点自动消失。所以消费者调用接口时将不会轮询到已经挂掉的接口上(延迟例外)。

4.Dubbo协议
    Dubbo常用协议有两种:dubbo、hessian
    dubbo:
      Dubbo 缺省协议是dubbo协议,采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。

hessian:
      Hessian底层采用Http通讯(同步),采用Servlet暴露服务。适用于传入传出参数数据包较大,消费者并发量少,提供者较多,可传文件。

5.Dubbo容器
    Dubbo在java jvm中有自己的容器,和Spring IOC的bean一样,将服务对象保存到自己的容器中。

6.监控中心
    监控中心主要是用来服务监控和服务治理。
    服务治理包含:负载均衡策略、服务状态、容错、路由规则限定、服务降级等。具体可以下载Dubbo监控中心客户端查看与设置。
dubbo监控中心下载和搭建启动参考网址https://blog.csdn.net/a704397849/article/details/91904842

四、节点角色说明

节点 角色说明
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心
Container 服务运行容器

看了这几个概念后似乎发现,其实 Dubbo 的架构也是很简单的(其实现细节是复杂的),为什么这么说呢,有没有发现,
其实很像"生产者-消费者"模型。只是在这种模型上,加上了注册中心和监控中心,用于管理提供方提供的url,以及监控和管理整个过程

那么dubbo发布-订阅的过程是怎样的呢?

1、启动容器,加载,运行服务提供者。
2、服务提供者在启动时,在注册中心发布注册自己提供的服务。
3、服务消费者在启动时,在注册中心订阅自己所需的服务

容器如何启动呢?

即java中整合了dubbo,在spirngboot的启动类上加一个启动的注解,服务启动即自动开启容器

当然作为一个类似于中间件的dubbo框架,肯定也有对它某些配置自定义的方式 如

1、注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
2、服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
3、服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
这些均可在java配置文件中进行配置,下面在详细讲述

五、zookeeper

欲实现dubbo架构先要搭建zookeeper集群作为服务注册发现中心,安装集群步骤参考网址https://blog.csdn.net/weixin_43784880/article/details/104428651

此前就完成了dubbo-admin和zookepper集群的搭建,启动后进行下面步骤

六、SpringBoot整合Dubbo和Zookeeper

先说明后不乱:

这里创建了一个主工程dubbo-hotels,其下包含了api、dubbo-provider、dubbo-customer
api: 主要存放公共实体类、需要远程调用的服务接口、也可以放一些公用的工具类工程
dubbo-provider: 服务提供工程 将接口实现类的服务暴露出去
dubbo-customer: 服务调用工程 远程从zookeeper调用提供者暴露的服务
切记:因为服务接口只是写在api工程中,所以dubbo-provider、dubbo-customer两个工程都需要在pom文件中引入api的jar包,下面会一一阐述

父工程
1、先创建一个springboot主工程 dubbo-hotels
主工程添加依赖如下:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
<!--    添加springboot父级依赖-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <!--自定义该工程的jar包的坐标-->
    <groupId>com.hotels</groupId>
    <artifactId>dubbo-hotels</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>dubbo-hotels</name>

    <modules>
        <!-- 服务消费者工程 -->
        <module>dubbbo-customer</module>
        <module>hotel-customer</module>
        <!--  服务提供者工程-->
        <module>hotel-provider</module>
        <module>dubbo-provider</module>
        <!-- 主要放实体、接口、也可以放一些公用的工具类工程-->
        <module>api</module>
    </modules>

<!--    dependency依赖 版本号 的变量,也可以不要直接将版本号写在version中-->
  <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <dubbo-spring-boot>1.0.0</dubbo-spring-boot>
      <dubbo.version>2.5.5</dubbo.version>
      <zkclient.version>0.10</zkclient.version>
      <lombok.version>1.16.18</lombok.version>
      <spring-boot.version>1.5.7.RELEASE</spring-boot.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
      <!--开启web-->
        <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>

        <!-- 使用lombok实现JavaBean的get、set、toString、hashCode、equals等方法的自动生成  -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- Spring Boot Dubbo 依赖 -->
        <dependency>
            <groupId>com.alibaba.spring.boot</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>
        <!--zookeeper的客户端依赖-->
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.11</version>
            <type>pom</type>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>UTF-8</encoding>
                </configuration>

            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

到这里父工程配置结束

服务接口工程 api
1、pom写法

<?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 https://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>2.2.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.hotels</groupId>
    <artifactId>api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>api</name>

    <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</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2、服务接口类

package com.hotel1.demo.api;

public interface DubboUserServer {
    String getUser(Integer id);
}

跟普通接口没有两样,为了简单明了我这里只有一个方法,如果用到实体类操作数据库,可以创建实体类
无需其他过多配置,服务接口工程的配置结束

服务提供工程 dubbo-privoder
1、pom加入

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--子工程为了继承父工程的依赖,节省代码,可以在parent标签中加入父工程的jar包坐标-->
    <parent>
        <groupId>com.hotels</groupId>
        <artifactId>dubbo-hotels</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <groupId>com.hotels</groupId>
    <artifactId>dubbo-privoder</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>dubbo-privoder</name>

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

    <dependencies>
      <!--  为了引入api服务接口来实现接口类,需要引入api工程的jar包  这样可以引入api中的类-->
        <dependency>
            <groupId>com.hotels</groupId>
            <artifactId>api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

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

父工程的依赖可以被子工程引入,即子工程无需再写一遍依赖,只需要parent父级依赖指定成子工程即可
dubbo-provider引入dubbo-hotels的pom,如图
Springboot整合Dubbo+Zookeeper_第1张图片
A工程想要引入B工程的类,需要以依赖的形式引入B类的jar,如图
Springboot整合Dubbo+Zookeeper_第2张图片

无论是dependency引入还是parent父级引入,关键在于要一一对应号groupId、artifactId、version等坐标和版本,否则出错

2、接口实现类

package com.provider.demo.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.hotel1.demo.api.DubboUserServer;  //此处的DubboUserServer正是引入了api工程的接口,dubbo-provider中并不需要写此接口
import org.springframework.stereotype.Component;

//用到实体类对的话实体类要实现序列化接口
@Service(interfaceClass = DubboUserServer.class)//使用dubbo提供的service注解来暴露服务
@Component 
public class DubboUserServerImpl implements DubboUserServer {

    @Override
    public String getUser(Integer id) {
        String name = "";
        if(1==id){
            name = "董";
        }else if(2==id){
            name = "刘";
        }else{
            name = "杨";
        }
        return name;
    }

}

3、启动类

package com.provider.demo;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo//添加此注解开启dubbo容器  必要
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

4、properties.yml

server:
  port: 8083     //tomcat端口

dubbo:
  application:
     name: server-privoder  //应用程序名
  registry:
     address: zookeeper://127.0.0.1:2181?backup=127.0.0.1:2182,127.0.0.1:2183  //我这里是zookeeper集群的写法
  protocol:
     name: dubbo
    #修改默认端口要写成字符串形式,如果写20880数字将无法识别,暴露的服务使用的是默认端口20880
     port: "20881"
  scan: com.provider.demo.impl   //用来扫描使用了dubbo暴露服务注解@Service的类所在的包

① 上面的文件其实就是类似 spring 的配置文件,而且,dubbo 底层就是 spring。

② 节点:dubbo:application
就是整个项目在分布式架构中的唯一名称,可以在 name 属性中配置,另外还可以配置 owner 字段,表示属于谁。
下面的参数是可以不配置的,这里配置是因为出现了端口的冲突,所以配置。

③ 节点:dubbo:monitor
监控中心配置, 用于配置连接监控中心相关信息,可以不配置,不是必须的参数。 本文就没有配置

④ 节点:dubbo:registry
配置注册中心的信息,比如,这里我们可以配置 zookeeper 作为我们的注册中心。address 是注册中心的地址,
也可以配置 N/A 表示由 dubbo 自动分配地址。或者说是一种直连的方式,不通过注册中心。

⑤ 节点:dubbo:protocol
name:服务发布的时候 dubbo 依赖什么协议,可以配置 dubbo、webserovice、Thrift、Hessain、http等协议,用name来指定。
这里仅解释两种协议:
dubbo:缺省协议是dubbo协议,采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。
hessian:Hessian底层采用Http通讯(同步),采用Servlet暴露服务。适用于传入传出参数数据包较大,消费者并发量少,提供者较多,可传文件。

port:服务暴露的端口用port来指定,此处的端口数字必须用字符串表示,否则无法识别,会使用dubbo默认端口20880

⑥ 节点:dubbo:scan:
用来扫描使用了dubbo暴露服务注解@Service的类所在的包

服务消费工程 dubbo-customer
pom

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.hotels</groupId>
        <artifactId>dubbo-hotels</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <groupId>com.hotels</groupId>
    <artifactId>dubbo-customer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>dubbo-customer</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.hotels</groupId>
            <artifactId>api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

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

</project>

5、测试web类

package com.customer.demo.web;

import com.hotel1.demo.api.DubboUserServer;
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {

   
//引入服务接口的注解  关键地方
    @Reference
    DubboUserServer dubboUserServer;


    @RequestMapping(value = "/show", method = RequestMethod.GET)
    public String shows() {

        return dubboUserServer.getUser(2);
    }

}

6、启动类同理加上@EnableDubbo

7、properties.yml

server:
  port: 8084

dubbo:
  application:
     name: server-customer
  registry:
    address: zookeeper://127.0.0.1:2181?backup=127.0.0.1:2182,127.0.0.1:2183
  protocol:
     name: dubbo
    #修改默认端口要写成字符串形式
     port: "20880"
  scan: com.customer.demo.web   //扫描注解@Reference调用服务的类所在的包

启动dubbo-customer,在浏览器地址栏输入http://127.0.0.1:8084/test/show 即可测试

你可能感兴趣的:(Springboot整合Dubbo+Zookeeper)