Dubbo和Zookeeper集成

项目存放地址:https://github.com/Rechiard/ProjectCollection,后缀名为"Dubbo+Zookeeper"

分布式、集群、Dubbo+Zookeeper+SpringBoot

什么是分布式系统?

分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统。

分布式系统是由一组通过网络进行通信、为了完成共同的任务和协调工作的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。其目的是利用更多的机器、处理更多的数据。

分布式系统(distributed system)是建立在网络之上的软件系统

首先需要明确的是,只有当单个节点的处理能力无法满足日益增长的计算、存储任务的时候,且硬件的提升高昂到得不偿失的时候,应用程序也不能进一步优化的时候,我们才需要考虑分布式系统。通俗的来说,也就是使用的人多了,数据多了,承受不住了,才考虑分布式,一开始是不考虑分布式系统的。

其中就会牵扯到负载均衡的概念,也就是说我们通过Nginx代理服务器将多个单机联系起来的时候需要考虑的事情是比单机服务器没有的问题。

Dubbo和Zookeeper集成

什么是集群?

多台服务器组成的一组计算机,作为一个整体存在,向用户提供一组网络资源,这些单个的服务器就是集群的节点。

集群拥有以下两个特点:

  1. 可扩展性: 集群的性能不限制于单一的服务实体,新的服务实体可以动态的添加到集群,从而增强集群的性能。

  2. 高可用性: 集群当其中一个节点发生故障时,这台节点上面所运行的应用程序将在另一台节点被自动接管,消除单点故障对于增强数据可用性、可达性和可靠性是非常重要的。

集群必须拥有以下两大能力:

  1. 负载均衡:负载均衡把任务比较均匀的分布到集群环境下的计算和网络资源,以提高数据吞吐量。
  2. 错误恢复:如果集群中的某一台服务器由于故障或者维护需要无法使用,资源和应用程序将转移到可用的集群节点上。这种由于某个节点的资源不能工作,另一个可用节点中的资源能够透明的接管并继续完成任务的过程,叫做错误恢复。

负载均衡和错误恢复要求各服务器中有执行同一任务的资源存在,而且对于同一任务的各个资源来说,执行任务所需的信息视图必须是相同的。

分布式和集群的区别

  1. 分布式是指将不同的业务分布到不同的地方。

  2. 而集群是指将几台服务器集中在一起,实在同一个业务。

  3. 分布式的每一个节点,都可以用来做集群。而集群不一定就是分布式了

例如:互联网*问的人多了,就可以做一个集群,前面放一个响应服务器,后面几台服务器完成同一业务,如果有业务访问的时候,响应服务器看哪台服务器的负载不是很重,就将任务交给哪台去完成。

而分布式,从狭义上理解,也与集群差不多,但是它的组织比较松散,不像集群,有一定组织性,一台服务器宕了,其他的服务器可以顶上来。分布式的每一个节点,都完成不同的业务,一个节点宕了,这个业务就不可访问了。


Dubbo

RPC

RPC,就是Remote Procedure Call的简称,翻译成中文就是远程过程调用。是一种进程间的通信方式,他是一种技术的思想,而不是规范。

首先说说本地过程调用,就相当于在自己的计算机中有方法A和B,A可以直接调用B。所以远程过程调用就是计算机的方法A想用调用另一台计算机的方法B就要利用到远程过程调用。

RPC与HTTP都是用来网络通讯和序列化的。

Dubbo的由来

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

Dubbo和Zookeeper集成

单一应用架构

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

缺点:

  1. 性能扩展比较难
  2. 协同开发问题
  3. 不利于升级维护

垂直应用架构

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

缺点:公用莫怪无法重复利用,开发性的浪费

分布式服务架构

当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。

流动计算架构

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

总结

Dubbo作为一款高性能、轻量级的开源 Java RPC服务框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

Dubbo和Zookeeper集成


Dubbo的工作原理

Dubbo和Zookeeper集成

服务提供者(Provider): 暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。

服务消费者(Consumer): 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己需要的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

注册中心(Registry): 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

监控中心(Monitor): 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一条统计数据到监控中心。

调用关系说明

  • 服务容器负责启动,加载,运行服务提供者
  • 服务提供者在启动时,向注册中心注册自己提供的服务
  • 服务消费者在启动时,向注册中心订阅自己所需的服务
  • 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
  • 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一条统计数据到监控中心。

Dubbo环境搭建

在安装Dubbo之前需要了解一下Zookeeper:

Zookeeper

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

相当于**在Dubbo工作原理中的注册中心(Registry)**的功能。

Window下安装zookeeper

  1. 下载zookeeper:https://zookeeper.apache.org/releases.html

  2. 运行/bin/zkServer.cmd,初次运行会报错,没有zoo.cfg配置文件;可能会闪退

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

  3. 一般的错误信息都是因为在/conf下没有zoo.cfg,所以我们需要复制conf/zoo_simple.cfg这个文件然后改名为zoo.cfg就可以运行zkServer.cmd了

  4. 运行成功之后,需要使用zkCli.cmd测试

  5. 一下是一些zookeeper的一些Linxu代码:

    • ls /:列出zookeeper根下保存的所有节点
    • create -e /xxx 123:创建一个xxx的节点,值为2123
    • get /xxx:获取/xxx节点的值

window下安装dubbo-admin(官方的dubbo的监控管理后台)

dubbo本身并不是一个服务软件,它其实就是一个jar包,能够帮你的java程序连接到zookeeper,并利用zookeeper消费、提供服务。

但是为了让用户更好的管理监控众多的dubbo服务,官方提供了一个可视化的监控程序dubbo-admin,不过这个监控即使不装也不影响使用。就类似于Swagger一样的图形化界面的功能使用网页。

  1. dubbo-admin的压缩包的下载页面:https://github.com/apache/dubbo-admin/tree/master

  2. 解压之后,利用idea或者cmd将文件打包,指令为:

    mvn clean package -Dmaven.test.skip=true
    
  3. 打包好了之后,运行zkServer.cmd文件,然后双击刚刚打包的jar包或者使用cmd指令:java -jar dubbo-admin-0.0.1-SNAPSHOT.jar,如果没有报错的话就可以在访问:localhost:7001,登录的账户密码应该就是dubbo-admin里的application.properties里的账户密码信息,一般是设为root-root,以下为登录成功页面:

    Dubbo和Zookeeper集成


SpringBoot+Dubbo+zookeeper

  1. 启动zookeeper !

  2. IDEA创建一个空项目;

  3. 创建一个模块,实现服务提供者:provider-server , 选择web依赖即可

  4. 项目创建完毕,我们写一个服务,比如卖票的服务;

编写接口:

package com.example.provider.service;

public interface TicketService {
   public String getTicket();
}

编写实体类:

package com.example.provider.service;

public class TicketServiceImpl implements TicketService {
   @Override
   public String getTicket() {
       return "《Java》";
  }
}
  1. 创建一个模块,实现服务消费者:consumer-server , 选择web依赖即可

  2. 项目创建完毕,我们写一个服务,比如用户的服务;

编写service

package com.kuang.consumer.service;

public class UserService {
   //我们需要去拿去注册中心的服务
}

需求:现在我们的用户想使用买票的服务,这要怎么弄呢 ?

服务提供者

1、将服务提供者注册到注册中心,我们需要整合Dubbo和zookeeper,所以需要导包

我们从dubbo官网进入github,看下方的帮助文档,找到dubbo-springboot,找到依赖包

<!-- Dubbo Spring Boot Starter -->
<dependency>
   <groupId>org.apache.dubbo</groupId>
   <artifactId>dubbo-spring-boot-starter</artifactId>
   <version>2.7.3</version>
</dependency>    

zookeeper的包我们去maven仓库下载,zkclient;

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

【新版的坑】zookeeper及其依赖包,解决日志冲突,还需要剔除日志依赖;

<!-- 引入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.6</version>
   <!--排除这个slf4j-log4j12-->
   <exclusions>
       <exclusion>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-log4j12</artifactId>
       </exclusion>
   </exclusions>
</dependency>

2、在springboot配置文件中配置dubbo相关属性!

#当前应用名字
dubbo.application.name=provider-server
#注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181
#扫描指定包下服务
dubbo.scan.base-packages=com.kuang.provider.service

3、在service的实现类中配置服务注解,发布服务!注意导包问题,这里的@Service注解注意是dubbo包里面的。

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

@Service //将服务发布出去
@Component //放在容器中
public class TicketServiceImpl implements TicketService {
   @Override
   public String getTicket() {
       return "《狂神说Java》";
  }
}

逻辑理解 :应用启动起来,dubbo就会扫描指定的包下带有@component注解的服务,将它发布在指定的注册中心中!

启动zookeeper和之前打包的dubbo-admin,并且最后运行此实验项目provider-server,可以在dubbo-admin监控到provider-server注入进来了中[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E2W8ci4U-1642560471151)(/content/textImgs/image-20210306112603392.png)]

服务消费者

1、导入依赖,和之前的依赖一样;

<!--dubbo-->
<!-- Dubbo Spring Boot Starter -->
<dependency>
   <groupId>org.apache.dubbo</groupId>
   <artifactId>dubbo-spring-boot-starter</artifactId>
   <version>2.7.3</version>
</dependency>
<!--zookeeper-->
<!-- 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>

2、配置参数

#当前应用名字
dubbo.application.name=consumer-server
#注册中心地址
dubbo.registry.address=zookeeper://127.0.0.1:2181

3. 本来正常步骤是需要将服务提供者的接口打包,然后用pom文件导入,我们这里使用简单的方式,直接将服务的接口拿过来,路径必须保证正确,即和服务提供者相同;

4. 完善消费者的服务类,这里的@Service是springboot中的。

package com.kuang.consumer.service;

import com.kuang.provider.service.TicketService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

@Service //注入到容器中
public class UserService {

   @Reference //远程引用指定的服务,他会按照全类名进行匹配,看谁给注册中心注册了这个全类名
   TicketService ticketService;

   public void bugTicket(){
       String ticket = ticketService.getTicket();
       System.out.println("在注册中心买到"+ticket);
  }

}

5. 测试类编写;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ConsumerServerApplicationTests {

   @Autowired
   UserService userService;

   @Test
   public void contextLoads() {

       userService.bugTicket();

  }

}

启动测试

1. 开启zookeeper

2. 打开dubbo-admin实现监控【可以不用做】

3. 开启服务者,也就是先启动provider-server主启动类

4. 消费者消费测试结果

监控中心 :

Dubbo和Zookeeper集成

ok , 这就是SpingBoot + dubbo + zookeeper实现分布式开发的应用,其实就是一个服务拆分的思想;

上一篇:SpringCloud基本认知


下一篇:动力节点-王妈妈Springboot教程(七)SpringBoot集成Dubbo