分布式理论

分布式系统是多个计算机的集合,每一个计算机对用户来说都像是单个系统

SpringBoot分布式 - 图1

就像这里的淘宝服务器,对于用户来说是单个的,但是其实是很多


但是注意,只有当单个节点的处理能力无法满足需要的时候我们才考虑分布式系统

RPC

http是一个协议,负责通信,基于网络

RPC也是一个协议,也是负责通信的,翻译成中文也是远程过程调用

A方法在A电脑上,B方法在B电脑上,RPC就是A电脑调用B方法,B电脑调用A方法。

RPC是一种思想,而不是规范。

RPC两个核心

  • 通讯
  • 序列化
  1. 客户端调用
  2. 序列化
  3. 发送消息
  4. 反序列化
  5. 调用本地服务
  6. 服务处理
  7. 返回处理结果
  8. 结果序列化
  9. 返回消息
  10. 反序列化
  11. 返回调用结果

Dubbo+Zookeeper+Spring boot

介绍

Dubbo:https://dubbo.apache.org/zh-cn/

Dubbo是一个java的RPC框架,所以RPC由Dubbo来做了,专注于RPC

Dubbo原来是阿里的,但是现在交给Apache了


SpringBoot分布式 - 图2

服务提供者Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。 服务消费者Consumer) 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 注册中心Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者 监控中心Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心

调用关系说明 l 服务容器负责启动,加载,运行服务提供者。 l 服务提供者在启动时,向注册中心注册自己提供的服务。 l 服务消费者在启动时,向注册中心订阅自己所需的服务。 l 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 l 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 l 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。


环境搭建

注册中心

推荐使用Zookeeper注册中心:http://dubbo.apache.org/zh-cn/docs/user/references/registry/zookeeper.html

SpringBoot分布式 - 图3

Zookeeper的搭建

  1. 几乎和Tomcat一模一样,直接下载下来然后解压到环境中即可
    http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.14/
  2. 运行/bin/zkServer.cmd ,初次运行会报错,没有zoo.cfg配置文件
  3. 复制/conf/zoo_sample.cfg,将副本的名字改为zoo.cfg,这样就有了
    SpringBoot分布式 - 图4

可能遇到问题:闪退 !

解决方案:编辑zkServer.cmd文件末尾添加pause 。这样运行出错就不会退出,会提示错误信息,方便找到原因。

SpringBoot分布式 - 图5



Dubbo-admin的搭建:

  1. 下载dubbo-admin
    地址 :https://github.com/apache/dubbo-admin/tree/master
  2. 类似Tomcat解压到环境
    修改 dubbo-admin\src\main\resources\application.properties 指定zookeeper地址```

    默认端口号

    server.port=7001 spring.velocity.cache=false spring.velocity.charset=UTF-8 spring.velocity.layout-url=/templates/default.vm spring.messages.fallback-to-system-locale=false spring.messages.basename=i18n/message spring.root.password=root spring.guest.password=guest

注册中心的地址,去监控哪个注册中心,这里默认监控zookeeper,端口号为2181没问题

dubbo.registry.address=zookeeper://127.0.0.1:2181

  1. 3. 在项目目录下打包dubbo-admin

mvn clean package -Dmaven.test.skip=true

> ![](https://img2020.cnblogs.com/blog/2043786/202101/2043786-20210106193555189-1608143317.png#align=left&display=inline&height=624&margin=%5Bobject%20Object%5D&originHeight=624&originWidth=1223&status=done&style=none&width=1223)
> 第一次打包的过程有点慢,需要耐心等待!直到成功!
> ![](https://img2020.cnblogs.com/blog/2043786/202101/2043786-20210106193555421-1059313701.png#align=left&display=inline&height=624&margin=%5Bobject%20Object%5D&originHeight=624&originWidth=1223&status=done&style=none&width=1223)
> 
---

> 完成之后会出现jar包,就在dubbo-admin\target
> ![](https://img2020.cnblogs.com/blog/2043786/202101/2043786-20210106193555605-544704501.png#align=left&display=inline&height=354&margin=%5Bobject%20Object%5D&originHeight=354&originWidth=1196&status=done&style=none&width=1196)


4. 执行 dubbo-admin\target 下的dubbo-admin-0.0.1-SNAPSHOT.jar

java -jar dubbo-admin-0.0.1-SNAPSHOT.jar

> 【注意:zookeeper的服务一定要打开!】
> ![](https://img2020.cnblogs.com/blog/2043786/202101/2043786-20210106193555881-2139018903.png#align=left&display=inline&height=556&margin=%5Bobject%20Object%5D&originHeight=556&originWidth=1064&status=done&style=none&width=1064)
> 执行完毕,我们去访问一下 [http://localhost:7001/](http://localhost:7001/) , 这时候我们需要输入登录账户和密码,我们都是默认的root-root;
> 登录成功后,查看界面
> ![](https://img2020.cnblogs.com/blog/2043786/202101/2043786-20210106193556014-359640900.png#align=left&display=inline&height=1030&margin=%5Bobject%20Object%5D&originHeight=1030&originWidth=1920&status=done&style=none&width=1920)
> 安装完成!



---

`zookeeper`:注册中心

`dubbo-admin`是一个监控管理后台,它可以查看我们注册了哪些服务,哪些服务被消费了,可以不要

`dubbo`:jar包

---


---


<a name="f9a5fb82"></a>
## 项目整合

<a name="8cb94eb1"></a>
### 例子

我们以买票作为例子:

- 提供者服务提供票
- 消费者服务买票

提供者在注册中心注册自己,然后提供具体的方法,放到注册中心

消费者在注册中心注册自己,然后取注册中心拿到具体的方法,便于执行

<a name="c182e73c"></a>
### 快速开始

1. 创建两个`springboot`项目,一个叫做`consumer-service(消费者服务)`,一个叫做`provider-server(提供者服务)`
2. 分别在这两个项目中提供`pom`坐标```xml
        <!-- Dubbo启动器-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.3</version>
        </dependency>

       <!-- https://mvnrepository.com/artifact/com.github.sgroschupf/zkclient -->
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>

        <!-- 引入zookeeper -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
            <!--排除这个slf4j-log4j12-->
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

注意,提供者和使用者的项目都需要导入这些坐标

  1. 分别对提供者和使用者的环境进行配置
    • 提供者:provider-server ```properties

      更改一下springboot的端口号

      server.port=8001

当前应用名字,一般为项目的名称

dubbo.application.name=provider-server

注册中心地址

dubbo.registry.address=zookeeper://127.0.0.1:2181

方法的提供者要提供服务,那么扫描指定包下服务

dubbo.scan.base-packages=com.bean.service


   - 使用者:`consumer-service`
```properties
# 更改一下springboot的端口号
server.port=8002

#当前应用名字
dubbo.application.name=consumer-service

#注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181

# 方法的使用者不必进行方法的注册
  1. 提供者:provider-server:进行service的编写
    • TicketService ```java package com.bean.service;

public interface TicketService { String getTicket(); }


   - `TicketServiceImpl`
```java
package com.bean.service;

import org.apache.dubbo.config.annotation.Service;
import org.springframework.stereotype.Component;

@Service
@Component
public class TicketServiceImpl implements TicketService{

    @Override
    public String getTicket() {
        return "票";
    }
}

这里注意 我们建议使用两个@Service,因为这里有两个@Service注解,一个是Spring的,一个是Dubbo的 我们使用了一个@Service,是Dubbo的注解 使用了@Component来对Spring的@Service进行替换 这样的好处就是可以明确的区分Dubbo和Spring的注解

  1. 使用者:consumer-service:进行service的编写
    • TicketService ```java package com.bean.service;

//这里也是一个比较坑的地方:因为我们调用的是其他项目的方法,不能自动注入 //所以我们要在自己的项目中写一个接口,不用写实现类 //这个接口要注意,路径必须完全相同:com.bean.service.TicketService public interface TicketService { String getTicket(); }

> 我们要在自己的项目中写一个接口,不用写实现类
> 这个接口要注意:
> 提供者和使用者的路径必须完全相同:`com.bean.service.TicketService`

   - `UserService`
```java
package com.bean.service;

import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

//这个方法是使用的方法
@Service    //这里注意,这里使用的注解是Spring的,不是Dubbo的
public class UserService {

    //自动注入,类似@Autowried,但是我们注入的不是本地方法,是RPC协议的
    //注意,导入的包是dubbo的
    @Reference  
    TicketService ticketService;

    public void use(){
        String ticket = ticketService.getTicket();
        System.out.println(ticket);
    }
}

当我们注入好之后,就可以使用这个方法了,这里就是使用方法的服务

至此,环境搭建彻底完成

测试

  1. 启动zookeeper
  2. 启动dubbo-admin
  3. 启动提供者的tomcat:provider-server,在dubbo-admin进行查看> SpringBoot分布式 - 图6

    我们看到有了机器的IP,点击去查看


SpringBoot分布式 - 图7

  • 方法列表
  • 接口名
  1. 在使用端编写测试代码:```java @SpringBootTest class ConsumerServiceApplicationTests {

    @Autowired UserService userService;

    @Test void contextLoads() {

     userService.use();
    

    }

} ```

  1. 启动测试代码进行测试
    SpringBoot分布式 - 图8

成功