关于本文档 · 贡献者 · 文档协议 · 致谢
关于本文档
文档名称:《微服务和消列队列》
使用协议:《知识共享公共许可协议(CCPL)》
贡献者
| 贡献者名称 | 贡献度 | 文档变更记录 | 个人主页 |
|---|---|---|---|
| 马哥(马永亮) | 主编 | http://github.com/iKubernetes/ | |
| 杰哥(张士杰) | 作者 | http://blogs.studylinux.net/ | |
| 王晓春 | 作者 | 版本迭代升级 | http://www.wangxiaochun.com |
文档协议
署名要求 :使用本系列文档,您必须保留本页中的文档来源信息,具体请参考《知识共享 (Creative Commons) 署名4.0公共许可协议国际版》。
非商业化使用 :遵循《知识共享公共许可协议(CCPL)》,并且您不能将本文档用于马哥教育相关业务之外的其他任何商业用途。
您的权利 :遵循本协议后,在马哥教育相关业务之外的领域,您将有以下使用权限:
共享 — 允许以非商业性质复制本作品。
改编 — 在原基础上修改、转换或以本作品为基础进行重新编辑并用于个人非商业使用。
致谢
本文档中,部分素材参考了相关项目的文档,以及通过搜索引擎获得的内容,这里先一并向相关的贡献者表示感谢。
内容概述
-
微服务
-
ZooKeeper
-
Kafka
Dubbo
1 微服务
1.1 服务架构演变

1.2 单体架构
-
传统架构(单机系统),一个项目一个工程:比如商品、订单、支付、库存、登录、注册等等,统一部署,一个进程
-
all in one的架构方式,把所有的功能单元放在一个应用里。然后把整个应用部署到一台服务器上。 如果负载能力不行,将整个应用进行水平复制,进行扩展,然后通过负载均衡实现访问。 Java实现:JSP、Servlet,打包成一个jar、war部署
-
易于开发和测试:也十分方便部署;当需要扩展时,只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了。
-
如果某个功能模块出问题,有可能全站不可访问,修改Bug后、某模块功能修改或升级后,需要停掉整个服务,重新整体重新打包、部署这个应用war包,功能模块相互之间耦合度高,相互影响,不适合当今互联网业务功能的快速迭代。
-
特别是对于一个大型应用,我们不可能吧所有内容都放在一个应用里面,我们如何维护、如何分工合作都是问题。如果项目庞大,管理难度大
-
web应用服务器:开源的tomcat、jetty、glassfish。商用的有weblogic、websphere、Jboss
1.3 微服务
https://www.martinfowler.com/microservices/

In short, the microservice architectural style is an approach to developing a
single application as a suite of small services, each running in its own process
and communicating with lightweight mechanisms, often an HTTP resource API. These
services are built around business capabilities and independently deployable by
fully automated deployment machinery. There is a bare minimum of centralized
management of these services, which may be written in different programming
languages and use different data storage technologies.
简而言之,微服务架构风格是一种将单个应用程序开发为一套小型服务的方法,每个服务都在自己的进程中运
行并与轻量级机制(通常是 HTTP 资源 API)进行通信。这些服务围绕业务功能构建,并可通过全自动部署
机制独立部署。对这些服务进行最低限度的集中管理,这些服务可能用不同的编程语言编写并使用不同的数据
存储技术。
-- James Lewis and Martin Fowler (2014)
-
属于SOA(Service Oriented Architecture)的子集
-
微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底去掉耦合,每一个微服务提供单个业务功能,一个服务只做一件事。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等
-
从技术角度讲就是一种小而独立的处理过程,类似与进程的概念,能够自行单独启动或销毁微服务架构(分布式系统),各个模块/服务,各自独立出来,"让专业的人干专业的事",独立部署。分布式系统中,不同的服务可以使用各自独立的数据库。
-
服务之间采用轻量级的通信机制(通常是基于HTTP的RESTful API)。
-
微服务设计的思想改变了原有的企业研发团队组织架构。传统的研发组织架构是水平架构,前端、 后端、DBA、测试分别有自己对应的团队,属于水平团队组织架构。而微服务的设计思想对团队的划分有着一定的影响,使得团队组织架构的划分更倾向于垂直架构,比如用户业务是一个团队来负责,支付业务是一个团队来负责。但实际上在企业中并不会把团队组织架构拆分得这么绝对,垂直架构只是一种理想的架构
-
微服务的实现框架有多种,不同的应用架构,部署方式也有不同
1.4 单体架构和微服务比较


1.5 微服务的优缺点
微服务优点:
-
每个服务足够内聚,足够小,代码容易理解。这样能聚焦一个简单唯一的业务功能或业务需求。 开发简单、开发效率提高,一个服务可能就是专业的只干一件事,微服务能够被小团队单独开发, 这个小团队可以是2到5人的开发人员组成
-
微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的。 微服务能使用不同的语言开发
-
易于和第三方集成,微服务运行容易且灵活的方式集成自动部署,通过持续集成工具,如: Jenkins、Hudson、Bamboo
-
微服务易于被一个开发人员理解、修改和维护,这样小团队能够更关注自己的工作成果,无需通过合作才能体现价值
-
微服务允许你利用融合最新技术。微服务只是业务逻辑的代码,不会和HTML/CSS或其他界面组件混合,即前后端分离
-
每个微服务都有自己的存储能力,一般都有自己的独立的数据库,也可以有统一数据库
微服务缺点 :
-
微服务把原有的一个项目拆分成多个独立工程,增加了开发、测试、运维、监控等的复杂度微服务架构需要保证不同服务之间的数据一致性,引入了分布式事务和异步补偿机制,为设计和开发带来一定挑战
-
开发人员和运维需要处理分布式系统的复杂性,需要更强的技术能力
-
微服务适用于复杂的大系统,对于小型应用使用微服务,进行盲目的拆分只会增加其维护和开发成本
1.6 微服务技术栈

1.7 常见的微服务框架
Dubbo
阿里开源贡献给了ASF,目前已经是Apache的顶级项目
-
一款高性能的Java RPC服务框架,微服务生态体系中的一个重要组件
-
将单体程序分解成多个功能服务模块,模块间使用Dubbo框架提供的高性能RPC通信
内部协调使用 Zookeeper,实现服务注册、服务发现和服务治理
- Spring cloud
一个完整的微服务解决方案,相当于Dubbo的超集
- 微服务框架,将单体应用拆分为粒度更小的单一功能服务
基于HTTP协议的REST(Representational State Transfer 表述性状态转移)风格实现模块间通信
2 ZooKeeper
2.1 ZooKeeper 介绍

ZooKeeper 的由来
下面这段内容摘自《从Paxos到Zookeeper 》第四章第一节的某段内容:
Zookeeper最早起源于雅虎研究院的一个研究小组。在当时,研究人员发现,在雅虎内部很多大型系统基本都需要依赖一个类似的系统来进行分布式协调,但是这些系统往往都存在分布式单点问题。所以,雅虎的开发人员就试图开发一个通用的无单点问题的分布式协调框架,以便让开发人员将精力集中在处理业务逻辑上。
关于“ZooKeeper”这个项目的名字,其实也有一段趣闻。在立项初期,考虑到之前内部很多项目都是使用动物的名字来命名的(例如著名的Pig项目),雅虎的工程师希望给这个项目也取一个动物的名字。时任研究院的首席科学家RaghuRamakrishnan开玩笑地说:“在这样下去,我们这儿就变成动物园了!”此话一出,大家纷纷表示就叫动物园管理员吧一一一因为各个以动物命名的分布式组件放在一起,雅虎的整个分布式系统看上去就像一个大型的动物园了,而Zookeeper正好要用来进行分布式环境的协调一一于是,Zookeeper的名字也就由此诞生了。
ZooKeeper 是一个开源的分布式协调服务,ZooKeeper框架最初是在“Yahoo!"上构建的,用于以简单而稳健的方式访问他们的应用程序。 后来,Apache ZooKeeper成为Hadoop,HBase和其他分布式框架使用的有组织服务的标准。 例如,Apache HBase使用ZooKeeper跟踪分布式数据的状态。ZooKeeper 的设计目标是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。
ZooKeeper 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
Zookeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心(提供发布订阅服务)。 服务生产者将自己提供的服务注册到Zookeeper中心,服务的消费者在进行服务调用的时候先到 Zookeeper中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据。在 Dubbo架构中 Zookeeper 就担任了注册中心这一角色。
官网:
https://zookeeper.apache.org/
官方文档:
https://zookeeper.apache.org/doc/
2.2 ZooKeeper 工作原理
ZooKeeper 是一个分布式服务框架,它主要是用来解决分布式应用中经常遇到的一些数据管理问题, 如:命名服务、状态同步、配置中心、集群管理等。
2.2.1 ZooKeeper 功能
2.2.1.1 命名服务
命名服务是分布式系统中比较常见的一类场景。命名服务是分布式系统最基本的公共服务之一。在分布式系统中,被命名的实体通常可以是集群中的机器、提供的服务地址或远程对象等——这些我们都可以统称它们为名字(Name),其中较为常见的就是一些分布式服务框架(如RPC、RMI)中的服务地址列表,通过使用命名服务,客户端应用能够根据指定名字来获取资源的实体、服务地址和提供者的信息等。
Zookeeper 数据模型
在 Zookeeper 中,节点分为两类
第一类是指构成Zookeeper集群的主机,称之为主机节点
第二类则是指内存中zookeeper数据模型中的数据单元,用来存储各种数据内容,称之为数据节点 ZNode。
Zookeeper内部维护了一个层次关系(树状结构)的数据模型,它的表现形式类似于Linux的文件系统,甚至操
作的种类都一致。
Zookeeper数据模型中有自己的根目录(/),根目录下有多个子目录,每个子目录后面有若干个文件,由斜杠
(/)进行分割的路径,就是一个ZNode,每个 ZNode上都会保存自己的数据内容和一系列属性信息.

2.2.1.2 状态同步
每个节点除了存储数据内容和 node 节点状态信息之外,还存储了已经注册的APP 的状态信息,当有些节点或APP 不可用,就将当前状态同步给其他服务。
2.2.1.3 配置中心
现在我们大多数应用都是采用的是分布式开发的应用,搭建到不同的服务器上,我们的配置文件,同一个应用程序的配置文件一样,还有就是多个程序存在相同的配置,当我们配置文件中有个配置属性需要改变,需要改变每个程序的配置属性,这样会很麻烦的去修改配置,那么可用使用ZooKeeper 来实现配置中心
ZooKeeper 采用的是推拉相结合的方式:客户端向服务端注册自己需要关注的节点,一旦该节点的数据发生变更,那么服务端就会向相应的客户端发送Watcher事件通知,客户端接收到这个消息通知后,需要主动到服务端获取最新的数据。
Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,此应用比较流行
2.2.1.4 集群管理
所谓集群管理,包括集群监控与集群控制两大块,前者侧重对集群运行时状态的收集,后者则是对集群进行操作与控制,在日常开发和运维过程中,我们经常会有类似于如下的需求:
希望知道当前集群中究竟有多少机器在工作。
对集群中每台机器的运行时状态进行数据收集。对集群中机器进行上下线操作。
ZooKeeper 具有以下两大特性:
- 客户端如果对ZooKeeper 的一个数据节点注册 Watcher监听,那么当该数据节点的内容或是其子节点列表发生变更时,ZooKeeper 服务器就会向已注册订阅的客户端发送变更通知。 对在ZooKeeper上创建的临时节点,一旦客户端与服务器之间的会话失效,那么该临时节点也就被自动清除。
Watcher(事件监听器)是 Zookeeper 中的一个很重要的特性。Zookeeper 允许用户在指定节点上注册一些 Watcher,并且在一些特定事件触发的时候, ZooKeeper 服务端会将事件通知到感兴趣的客户端上去,该机制是 Zookeeper 实现分布式协调服务的重要特性。
2.2.2 ZooKeeper 服务流程


-
生产者启动
-
生产者注册至zookeeper
-
消费者启动并订阅频道
-
zookeeper 通知消费者事件
-
消费者调用生产者
-
监控中心负责统计和监控服务状态
2.3 ZooKeeper 单机部署
单机版的 ZooKeeper 安装
官方文档:
https://zookeeper.apache.org/doc/r3.6.2/zookeeperStarted.html#sc_InstallingSingl
eMode
2.3.1 配置 Java 环境
官方依赖介绍
https://zookeeper.apache.org/doc/r3.8.0/zookeeperAdmin.html#sc_systemReq
https://zookeeper.apache.org/doc/r3.6.2/zookeeperAdmin.html#sc_requiredSoftware
[root@ubuntu1804 ~]#apt -y install openjdk-8-jdk
[root@ubuntu1804 ~]#Java -version
openjdk version "1.8.0_282"
OpenJDK Runtime Environment (build 1.8.0_282-8u282-b08-0ubuntu1~18.04-b08)
OpenJDK 64-Bit Server VM (build 25.282-b08, mixed mode)
2.3.2 部署 ZooKeeper
历史版本下载
https://archive.apache.org/dist/zookeeper/
范例: 安装单机 zookeeper
#官方下载
[root@ubuntu1804 ~]#wget -P /usr/local/src
https://downloads.apache.org/zookeeper/stable/apache-zookeeper-3.6.3-bin.tar.gz
#国内镜像下载
[root@ubuntu1804 ~]#wget -P /usr/local/src
https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/stable/apache-zookeeper-
3.6.3-bin.tar.gz
[root@ubuntu1804 ~]#tar xf /usr/local/src/apache-zookeeper-3.6.3-bin.tar.gz -C
/usr/local/
[root@ubuntu1804 ~]#ln -s /usr/local/apache-zookeeper-3.6.3-bin
/usr/local/zookeeper
[root@ubuntu1804 ~]#echo 'PATH=/usr/local/zookeeper/bin:$PATH' >
/etc/profile.d/zookeeper.sh
[root@ubuntu1804 ~]#. /etc/profile.d/zookeeper.sh
[root@ubuntu1804 ~]#ll /usr/local/zookeeper/
total 48
drwxr-xr-x 6 root root 4096 Feb 1519:19 ./
drwxr-xr-x 11 root root 4096 Feb 1519:20 ../
drwxr-xr-x 2 wang wang 4096 Sep 420:43 bin/
drwxr-xr-x 2 wang wang 4096 Sep 420:43 conf/
drwxr-xr-x 5 wang wang 4096 Sep 420:44 docs/
drwxr-xr-x 2 root root 4096 Feb 1519:19 lib/
-rw-r--r--1 wang wang 11358 Sep 420:43 LICENSE.txt
-rw-r--r--1 wang wang 432 Sep 420:43 NOTICE.txt
-rw-r--r--1 wang wang 1963 Sep 420:43 README.md
-rw-r--r--1 wang wang 3166 Sep 420:43 README_packaging.md
[root@ubuntu1804 ~]#ls /usr/local/zookeeper/bin/
README.txt zkCli.cmd zkEnv.cmd zkServer.cmd zkServer.sh
zkSnapShotToolkit.sh zkTxnLogToolkit.sh
zkCleanup.sh zkCli.sh zkEnv.sh zkServer-initialize.sh zkSnapShotToolkit.cmd
zkTxnLogToolkit.cmd
[root@ubuntu1804 ~]#ls /usr/local/zookeeper/conf/
configuration.xsl log4j.properties zoo_sample.cfg
[root@ubuntu1804 ~]#cp /usr/local/zookeeper/conf/zoo_sample.cfg
/usr/local/zookeeper/conf/zoo.cfg
#默认配置可不做修改
[root@ubuntu1804 ~]#grep -v "#" /usr/local/zookeeper/conf/zoo.cfg
tickTime=2000#"滴答时间",用于配置Zookeeper中最小的时间单元长度,单位毫秒,是其它时间配置
的基础
initLimit=10#初始化时间,包含启动和数据同步,其值是tickTime的倍数
syncLimit=5#正常工作,心跳监测的时间间隔,其值是tickTime的倍数
dataDir=/tmp/zookeeper #配置Zookeeper服务存储数据的目录,基于安全,可以修改为
dataDir=/usr/local/zookeeper/data
#dataLogdir=/usr/local/zookeeper/logs #可以指定日志路径
clientPort=2181#配置当前Zookeeper服务对外暴露的端口,用户客户端和服务端建立连接会话
autopurge.snapRetainCount=3#3.4.0中的新增功能:启用后,ZooKeeper 自动清除功能,会将只保
留此最新3个快照和相应的事务日志,并分别保留在dataDir 和dataLogDir中,删除其余部分,默认值为3,
最小值为3
autopurge.purgeInterval=24#3.4.0及之后版本,ZK提供了自动清理日志和快照文件的功能,这个参
数指定了清理频率,单位是小时,需要配置一个1或更大的整数,默认是 0,表示不开启自动清理功能
2.3.3 启动 ZooKeeper
#查看选项
[root@ubuntu1804 ~]#zkServer.sh --help
#前台启动观察启动过程
[root@ubuntu1804 ~]#zkServer.sh start-foreground
#后台启动
[root@ubuntu1804 ~]#zkServer.sh start
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
#注意:如果配置service,zkServer.sh和systemctl不要混用,否则无法启动
2.3.4 验证 ZooKeeper
[root@ubuntu1804 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: standalone
[root@ubuntu1804 ~]#ss -ntpl|grep 2181
LISTEN 050 *:2181 *:* users:(("java",pid=1041,fd=70))
[root@ubuntu1804 ~]#pstree -p 1041
java(1041)─┬─{java}(1044)
├─{java}(1045)
├─{java}(1046)
├─{java}(1047)
├─{java}(1048)
├─{java}(1049)
├─{java}(1050)
├─{java}(1051)
├─{java}(1052)
├─{java}(1053)
├─{java}(1054)
├─{java}(1055)
2.3.5 一键安装 ZooKeeper 脚本
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2020-06-20
#FileName: install_zookeeper.sh
#URL: http://www.wangxiaochun.com
#Description: The test script
#Copyright (C): 2022 All rights reserved
#********************************************************************
ZK_VERSION=3.8.0
#ZK_VERSION=3.6.3
#ZK_VERSION=3.7.1
ZK_URL=https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-${ZK_VERS
ION}/apache-zookeeper-${ZK_VERSION}-bin.tar.gz
#ZK_URL="https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/stable/apache-
zookeeper-${ZK_VERSION}-bin.tar.gz"
#ZK_URL="https://downloads.apache.org/zookeeper/stable/apache-
zookeeper-${ZK_VERSION}-bin.tar.gz"
INSTALL_DIR=/usr/local/zookeeper
HOST=`hostname -I|awk '{print $1}'`
. /etc/os-release
color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo-n"$1" && $MOVE_TO_COL
echo-n"["
if [ $2="success"-o$2="0" ] ;then
${SETCOLOR_SUCCESS}
echo-n$" OK "
elif [ $2="failure"-o$2="1" ] ;then
${SETCOLOR_FAILURE}
echo-n$"FAILED"
else
${SETCOLOR_WARNING}
echo-n$"WARNING"
fi
${SETCOLOR_NORMAL}
echo-n"]"
echo
}
install_jdk() {
if [ $ID='centos'-o$ID='rocky' ];then
yum -y install java-1.8.0-openjdk-devel || { color "安装JDK失败!"1; exit
1; }
else
apt update
apt install openjdk-11-jdk -y || { color "安装JDK失败!"1; exit1; }
#apt install openjdk-8-jdk -y || { color "安装JDK失败!" 1; exit 1; }
fi
java -version
}
install_zookeeper() {
wget-P /usr/local/src/ --no-check-certificate$ZK_URL || { color "下载失败!"
1 ;exit ; }
tar xf /usr/local/src/${ZK_URL##*/}-C /usr/local
ln-s /usr/local/apache-zookeeper-*-bin/ ${INSTALL_DIR}
echo"PATH=${INSTALL_DIR}/bin:$PATH" > /etc/profile.d/zookeeper.sh
. /etc/profile.d/zookeeper.sh
mkdir-p${INSTALL_DIR}/data
cat > ${INSTALL_DIR}/conf/zoo.cfg <<EOF
tickTime=2000
initLimit=10
syncLimit=5
dataDir=${INSTALL_DIR}/data
clientPort=2181
maxClientCnxns=128
autopurge.snapRetainCount=3
autopurge.purgeInterval=24
EOF
cat > /lib/systemd/system/zookeeper.service <<EOF
[Unit]
Description=zookeeper.service
After=network.target
[Service]
Type=forking
#Environment=${INSTALL_DIR}
ExecStart=${INSTALL_DIR}/bin/zkServer.sh start
ExecStop=${INSTALL_DIR}/bin/zkServer.sh stop
ExecReload=${INSTALL_DIR}/bin/zkServer.sh restart
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now zookeeper.service
systemctl is-active zookeeper.service
if [ $?-eq0 ] ;then
color "zookeeper 安装成功!"0
else
color "zookeeper 安装失败!"1
exit1
fi
}
install_jdk
install_zookeeper
2.4 ZooKeeper 集群部署
2.4.1 ZooKeeper 集群介绍
ZooKeeper集群用于解决单点和单机性能及数据高可用等问题。
2.4.1.1 集群结构


zookeeper集群基于Master/Slave的模型,处于主要地位(处理写操作)的主机称为Master(Leader)节
点,处于次要地位(处理读操作)的主机称为 slave节点,生产中读取的方式一般是以异步复制方式来实现
的。
对于n台server,每个server都知道彼此的存在。只要有>n/2台server节点可用,整个zookeeper系统保
持可用。
因此zookeeper集群通常由奇数台Server节点组成
当进行写操作时,由Master(leader)完成,并且同步到其它Slave(follower)节点,当在保证写操作在所有
节点的总数过半后,才会认为写操作成功
官方链接: 下图表示读的比例越高,性能越好
http://zookeeper.apache.org/doc/r3.7.0/zookeeperOver.html

2.4.1.2 集群角色

| 序 号 |
角色 | 职责描述 |
|---|---|---|
| 1 | 领导者 (Leader) |
负责处理写入请求的,事务请求的唯一调度和处理者,负责进行投票发起和决议,更新系统状态 |
| 2 | 跟随者 (Follower) |
接收客户请求并向客户端返回结果,在选Leader过程中参与投票 |
| 3 | 观察者 (Observer) |
转交客户端写请求给leader节点,和同步leader状态和Follower唯一区别就是不参与Leader投票,也不参与写操作的"过半写成功"策略 |
| 4 | 学习者 (Learner) |
和leader进行状态同步的节点统称Learner,包括:Follower和Observer |
| 5 | 客户端 (client) |
请求发起方 |
2.4.1.3 选举过程
节点角色状态:
LOOKING:寻找 Leader 状态,处于该状态需要进入选举流程
-
LEADING:领导者状态,处于该状态的节点说明是角色已经是Leader
-
FOLLOWING:跟随者状态,表示 Leader已经选举出来,当前节点角色是follower OBSERVER:观察者状态,表明当前节点角色是 observer
选举 ID:
-
ZXID(zookeeper transaction id):每个改变 Zookeeper状态的操作都会形成一个对应的zxid。 ZXID最大的节点优先选为Leader
-
myid:服务器的唯一标识(SID),通过配置 myid 文件指定,集群中唯一,当ZXID一样时,myid大的节点优先选为Leader
ZooKeeper 集群选举过程:
当集群中的 zookeeper 节点启动以后,会根据配置文件中指定的 zookeeper节点地址进行leader 选择操作,过程如下:
每个zookeeper 都会发出投票,由于是第一次选举leader,因此每个节点都会把自己当做leader 角色进行选举,每个zookeeper 的投票中都会包含自己的myid和zxid,此时zookeeper 1 的投票为myid 为 1,初始zxid有一个初始值0x0,后期会随着数据更新而自动变化,zookeeper2 的投票为myid 为2,初始zxid 为初始生成的值。
-
每个节点接受并检查对方的投票信息,比如投票时间、是否状态为LOOKING状态的投票。
-
对比投票,优先检查zxid,如果zxid 不一样则 zxid 大的为leader,如果zxid相同则继续对比 myid,myid 大的一方为 leader
成为 Leader 的必要条件: Leader 要具有最高的zxid;当集群的规模是 n 时,集群中大多数的机器(至少n/2+1)得到响应并follower 选出的 Leader。
心跳机制:Leader 与 Follower 利用 PING 来感知对方的是否存活,当 Leader无法响应PING 时,将重新发起 Leader 选举。
当 Leader 服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB(Zookeeper Atomic Broadcast) 协议就会进入恢复模式并选举产生新的Leader服务器。这个过程大致如下:
-
Leader Election(选举阶段):节点在一开始都处于选举阶段,只要有一个节点得到超半数节点的票数,它就可以当选准 leader。
-
Discovery(发现阶段):在这个阶段,followers 跟准 leader 进行通信,同步 followers 最近接收的事务提议。
-
Synchronization(同步阶段):同步阶段主要是利用 leader 前一阶段获得的最新提议历史,同步集群中所有的副本。同步完成之后准 leader 才会成为真正的 leader。
-
Broadcast(广播阶段) :到了这个阶段,Zookeeper 集群才能正式对外提供事务服务,并且 leader 可以进行消息广播。同时如果有新的节点加入,还需要对新节点进行同步
ZAB 协议介绍
ZAB(ZooKeeper Atomic Broadcast 原子广播)协议是为分布式协调服务 ZooKeeper 专门设计的一
种支持崩溃恢复的原子广播协议。在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于
该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。
2.4.1.4 ZooKeeper 集群特性
整个集群中只要有超过集群数量一半的 zookeeper工作是正常的,那么整个集群对外就是可用的
假如有 2 台服务器做了一个 Zookeeper 集群,只要有任何一台故障或宕机,那么这个 ZooKeeper集群就不可用了,因为剩下的一台没有超过集群一半的数量,但是假如有三台zookeeper 组成一个集群, 那么损坏一台就还剩两台,大于 3台的一半,所以损坏一台还是可以正常运行的,但是再损坏一台就只剩一台集群就不可用了。那么要是 4 台组成一个zookeeper集群,损坏一台集群肯定是正常的,那么损坏两台就还剩两台,那么2台不大于集群数量的一半,所以 3 台的 zookeeper 集群和 4 台的 zookeeper集群损坏两台的结果都是集群不可用,以此类推 5 台和 6 台以及 7 台和 8台都是同理
另外偶数节点可以会造成"脑裂"现象,所以这也就是为什么集群一般都是奇数的原因。
2.4.2 ZooKeeper 集群部署
官方文档:
https://zookeeper.apache.org/doc/r3.6.2/zookeeperAdmin.html#sc_zkMulitServerSetu
p
2.4.2.1 环境准备
#三台ubuntu18.04
zookeeper-node1.wang.org 10.0.0.101
zookeeper-node2.wang.org 10.0.0.102
zookeeper-node3.wang.org 10.0.0.103
# 在三个节点都安装 JDK
[root@zookeeper-node1 ~]#apt -y install openjdk-8-jdk
[root@zookeeper-node2 ~]#apt -y install openjdk-8-jdk
[root@zookeeper-node3 ~]#apt -y install openjdk-8-jdk
2.4.2.2 在所有节点下载并解压缩 ZooKeeper 包文件
[root@zookeeper-node1 ~]#wget -P /usr/local/src
https://downloads.apache.org/zookeeper/stable/apache-zookeeper-3.6.3-bin.tar.gz
[root@zookeeper-node1 ~]#tar xf /usr/local/src/apache-zookeeper-3.6.3-bin.tar.gz
-C /usr/local/
[root@zookeeper-node1 ~]#ln -s /usr/local/apache-zookeeper-3.6.3-bin
/usr/local/zookeeper
[root@zookeeper-node1 ~]#echo 'PATH=/usr/local/zookeeper/bin:$PATH' >
/etc/profile.d/zookeeper.sh
[root@zookeeper-node1 ~]#. /etc/profile.d/zookeeper.sh
2.4.2.3 准备配置文件
#三个节点都要创建数据目录
[root@zookeeper-node1 ~]#mkdir /usr/local/zookeeper/data
#基于模板配置文件生成配置文件
[root@zookeeper-node1 ~]#cp /usr/local/zookeeper/conf/zoo_sample.cfg
/usr/local/zookeeper/conf/zoo.cfg
#修改配置文件
[root@zookeeper-node1 ~]#vim /usr/local/zookeeper/conf/zoo.cfg
#配置文件内容
[root@zookeeper-node1 ~]#grep -v "\^\#" /usr/local/zookeeper/conf/zoo.cfg
tickTime=2000#服务器与服务器之间的单次心跳检测时间间隔,单位为毫秒
initLimit=10#集群中leader 服务器与follower服务器初始连接心跳次数,即多少个 2000 毫秒
syncLimit=5#leader 与follower之间连接完成之后,后期检测发送和应答的心跳次数,如果该
follower在设置的时间内(5*2000)不能与 leader 进行通信,那么此 follower将被视为不可用。
dataDir=/usr/local/zookeeper/data #自定义的zookeeper保存数据的目录
clientPort=2181#客户端连接 Zookeeper 服务器的端口,Zookeeper会监听这个端口,接受客户端的
访问请求
maxClientCnxns=128#单个客户端IP 可以和zookeeper保持的连接数
autopurge.snapRetainCount=3#3.4.0中的新增功能:启用后,ZooKeeper 自动清除功能,会将只保
留此最新3个快照和相应的事务日志,并分别保留在dataDir 和dataLogDir中,删除其余部分,默认值为3,
最小值为3
autopurge.purgeInterval=24#3.4.0及之后版本,ZK提供了自动清理日志和快照文件的功能,这个参
数指定了清理频率,单位是小时,需要配置一个1或更大的整数,默认是 0,表示不开启自动清理功能
#格式: server.MyID服务器唯一编号=服务器IP:Leader和Follower的数据同步端口(只有leader才会打
开):Leader和Follower选举端口(L和F都有)
server.1=10.0.0.101:2888:3888
server.2=10.0.0.102:2888:3888
server.3=10.0.0.103:2888:3888
#如果添加节点,只需要在所有节点上添加新节点的上面形式的配置行,在新节点创建myid文件,并重启所有节
点服务即可
[root@zookeeper-node1 ~]#scp /usr/local/zookeeper/conf/zoo.cfg
10.0.0.102:/usr/local/zookeeper/conf/
[root@zookeeper-node1 ~]#scp /usr/local/zookeeper/conf/zoo.cfg
10.0.0.103:/usr/local/zookeeper/conf/
2.4.2.4 在各个节点生成ID文件
注意: 各个myid文件的内容要和zoo.cfg文件相匹配
[root@zookeeper-node1 ~]#echo 1 > /usr/local/zookeeper/data/myid
[root@zookeeper-node2 ~]#echo 2 > /usr/local/zookeeper/data/myid
[root@zookeeper-node3 ~]#echo 3 > /usr/local/zookeeper/data/myid
2.4.2.5 各服务器启动 zookeeper
#注意:在所有三个节点快速启动服务,否则会造成集群失败
[root@zookeeper-node1 ~]#zkServer.sh start
[root@zookeeper-node2 ~]#zkServer.sh start
[root@zookeeper-node3 ~]#zkServer.sh start
#注意:如果无法启动查看日志
[root@zookeeper-node1 ~]#cat /usr/local/zookeeper/logs/zookeeper-root-server-
zookeeper-node1.wang.org.out
2.4.5.6 查看集群状态
#follower会监听3888/tcp端口
[root@zookeeper-node1 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
[root@zookeeper-node1 ~]#ss -ntl |grep 888
LISTEN 050 [::ffff:10.0.0.101]:3888 *:*
#只有leader监听2888/tcp端口
[root@zookeeper-node2 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: leader
[root@zookeeper-node2 ~]#ss -ntl|grep 888
LISTEN 050 [::ffff:10.0.0.102]:3888 *:*
LISTEN 050 [::ffff:10.0.0.102]:2888 *:*
[root@zookeeper-node3 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
[root@zookeeper-node3 ~]#ss -ntl|grep 888
LISTEN 050 [::ffff:10.0.0.103:3888 *:*
2.5 客户端访问
2.5.1 命令行客户端访问 ZooKeeper
#可连接至zookeeper 集群中的任意一台zookeeper 节点进行以下操作,zkCli.sh 默认连接本机
[root@zookeeper-node1 ~]#zkCli.sh -server 10.0.0.103:2181
[zk: 10.0.0.103:2181(CONNECTED) 0] ls /
[zookeeper]
[zk: 10.0.0.103:2181(CONNECTED) 1] #两个TAB 可以列出所有支持命令
addWatch addauth close config connect create
delete deleteall delquota get getAcl
getAllChildrenNumber
getEphemerals history listquota ls printwatches quit
reconfig redo removewatches set setAcl setquota
stat sync version
[zk: 10.0.0.103:2181(CONNECTED) 1] version
ZooKeeper CLI version: 3.6.2--803c7f1a12f85978cb049af5e4ef23bd8b688715, built on
09/04/2020 12:44 GMT
#默认创建持久节点,即退出不丢失,create -e 可以创建临时节点(退出就丢失)
#持久节点才支持创建子节点,临时节点不支持,如: create /app1/subapp1 "subdata" ,不能递归创建
[zk: 10.0.0.103:2181(CONNECTED) 2] create /app1 "hello,zookeeper"
Created /app1
[zk: 10.0.0.103:2181(CONNECTED) 3] ls /
[app1, zookeeper]
#get -s /app1可以查看更详细的信息
[zk: 10.0.0.103:2181(CONNECTED) 4] get /app1
hello,zookeeper
#修改已有节点的值
[zk: 10.0.0.103:2181(CONNECTED) 5] set /app1 "hello,linux"
[zk: 10.0.0.103:2181(CONNECTED) 6] get /app1
hello,linux
#删除不包含子节点的节点(相当于rmdir),如果想删除所有节点内的数据,使用deleteall /path(相当于
rm -rf)
[zk: 10.0.0.103:2181(CONNECTED) 7] delete /app1
[zk: 10.0.0.103:2181(CONNECTED) 8] ls /
[zookeeper]
#查看已知节点元数据
[zk: 10.0.0.103:2181(CONNECTED) 9] stat /zookeeper
zxid = Ox0 #节点创建时的zxid
ctime = Thu Jan 0108:00:00 CST 1970#节点创建时间
mzxid = Ox0 #节点最近一次更新时的zxid
mtime = Thu Jan 0108:00:00 cST 1970#节点最近一次更新的时间
pzxid = Ox0 #父节点创建时的zxid
cversion =-1#子节点数据更新次数
dataversion =0#本节点数据更新次数
aclversion = o #节点ACL(授权信息)的更新次数
ephemera10wner = Ox0 #持久节点值为0,临时节点值为sessionid
dataLength =0#节点数据长度
numchi1dren =1#子节点个数
[zk: 10.0.0.103:2181(CONNECTED) 10] quit
2.5.2 nc 访问 ZooKeeper
ZooKeeper支持某些特定的四字命令字母与其的交互。它们大多是查询命令,用来获取 ZooKeeper服务的当前状态及相关信息。用户在客户端可以通过 netcat 或telnet向zookeeper发送下面命令
常见命令列表
conf #输出相关服务配置的详细信息
cons #列出所有连接到服务器的客户端的完全的连接/会话的详细信息
envi #输出关于服务环境的详细信息
dump #列出未经处理的会话和临时节点
stat #查看哪个节点被选择作为Follower或者Leader
ruok #测试是否启动了该Server,若回复imok表示已经启动
mntr #输出一些运行时信息
reqs #列出未经处理的请求
wchs #列出服务器watch的简要信息
wchc #通过session列出服务器watch的详细信息
wchp #通过路径列出服务器watch的详细信息
srvr #输出服务的所有信息
srst #重置服务器统计信息
kill#关掉Server
isro #查看该服务的节点权限信息
命令的安全限制
#默认情况下,这些4字命令有可能会被拒绝,发送如下报错
xxx is not executed because it is not in the whitelist.
#解决办法:在 zoo.cfg文件中添加如下配置,如果是集群需要在所有节点上添加下面配置
# vim conf/zoo.cfg
4lw.commands.whitelist=*
#在服务状态查看命令中有很多存在隐患的命令,所以为了避免生产中因为这些命令的安全隐患,所以我们要对
这些命令进行一些安全限制,只需要编辑服务的zoo.cfg文件即可
# vim conf/zoo.cfg
4lw.commands.whitelist=stat,ruok,conf,isro
范例:
ubuntu18.04安装netcat
#apt -y install netcat-traditional
#查看节点服务状态
echo stat | nc127.0.0.1 2181
#查看节点服务配置
echo conf | nc127.0.0.1 2181
#查看节点服务环境
echo envi | nc127.0.0.1 2181
#查看节点服务会话
echo cons | nc127.0.0.1 2181
echo dump | nc127.0.0.1 2181
#也支持 telnet,但不能用 | telnet 形式
[root@ubuntu1804 ~]#telnet 127.0.0.1 2181
Trying 10.0.0.8...
Connected to 10.0.0.8.
Escape character is '^]'.
cons
/10.0.0.100:52154[0](queued=0,recved=1,sent=0)
/127.0.0.1:59566[1]
(queued=0,recved=8,sent=8,sid=0x100004b74080001,lop=PING,est=1635560454029,to=30
000,lcxid=0x0,lzxid=0x9,lresp=5205692,llat=0,minlat=0,avglat=0,maxlat=2)
Connection closed by foreign host.
2.5.3 图形化客户端 ZooInspector
github链接
https://github.com/zzhang5/zooinspector
https://gitee.com/lbtooth/zooinspector.git
2.5.3.1 Linux 客户端
2.5.3.1.1 编译 zooinspector
注意:此软件因年代久远不再更新,当前只支持在Ubuntu18.04和Rocky8编译安装,不支持更高版本, 如Ubuntu20.04等
#https://github.com/zzhang5/zooinspector
Build
$git clone https://github.com/zzhang5/zooinspector.git
$cd zooinspector/
$mvn clean package -Dmaven.test.skip=true
Run
$chmod+x target/zooinspector-pkg/bin/zooinspector.sh
$target/zooinspector-pkg/bin/zooinspector.sh

范例: 编译 zooinspector
#注意:在Ubuntu18.04或Rocky8上编译,不支持Ubuntu20.04以上版本
#github
[root@zookeeper-node1 ~]#git clone https://github.com/zzhang5/zooinspector.git
#国内镜像
[root@zookeeper-node1 ~]#git clone https://gitee.com/lbtooth/zooinspector.git
[root@zookeeper-node1 ~]#cd zooinspector/
[root@zookeeper-node1 zooinspector]#apt install maven -y
#镜像加速
[root@zookeeper-node1 zooinspector]#vim /etc/maven/settings.xml
<mirrors>
<!--阿里云镜像-->
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
#编译,此步骤需要较长时间下载,可能数分钟
[root@zookeeper-node1 zooinspector]#mvn clean package -Dmaven.test.skip=true


2.5.3.1.2 客户端使用
[root@zookeeper-node1 zooinspector]#ls
pom.xml README.md src target
[root@zookeeper-node1 zooinspector]#du -sh .
7.3M .
[root@zookeeper-node1 zooinspector]#chmod +x target/zooinspector-
pkg/bin/zooinspector.sh
[root@zookeeper-node1 zooinspector]#target/zooinspector-pkg/bin/zooinspector.sh
#自动打开下面图形界面

2.5.3.2 Windows 客户端使用
先下载并安装 JDK
注意: Oracle官网需要登录才能下载
https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html
运行下面命令
D:\技术\上课文件\消息队列与微服务文件\ZooInspector\build>java -jar zookeeper-dev-
ZooInspector.jar
#或者直接使用Linux上面编译生成的文件zookinspector-1.0-SNAPSHOT-pkg.tar在Windows中解压
缩,直接运行里的zooinspector.bat即可




删除
2.5.4 Python 访问 ZooKeeper
[root@zookeeper-node1 ~]#apt -y install python3 python3-kazoo
[root@zookeeper-node1 ~]#cat zookeepe_test.py
#!/usr/bin/python3
from kazoo.client import KazooClient
zk = KazooClient(hosts='10.0.0.101:2181')
zk.start()
# 创建节点:makepath 设置为 True ,父节点不存在则创建,其他参数不填均为默认
zk.create('/zkapp/test',b'this is a test',makepath=True)
# 操作完后关闭zk连接
data=zk.get('/zkapp/test')
print(data)
zk.stop()
[root@zookeeper-node1 ~]#chmod +x ./zookeepe_test.py
[root@zookeeper-node1 ~]#./zookeepe_test.py
3 Kafka
3.1 消息队列简介
3.1.1 消息队列历史
1983 年在MIT 工作的26岁的印度小伙 Vivek Ranadive突发奇想,以前我们的软件相互通信,都是点对点的,而且要实现相同的协议,能不能有一种专门用来通信的中间件,就像主板(BUS)一样,把不同的软件集成起来呢?于是他搞了一家公司(Teknekron),开发了世界上第一个消息队列软件The Information Bus(TIB)。最开始的时候,它被高盛这些公司用在金融交易里面。因为TIB 实现了发布订阅 (Publish/Subscribe)模型,信息的生产者和消费者可以完全解耦,这个特性引起了电信行业特别是新闻机构的注意。1994年路透社收购了Teknekron。
TIB 的成功马上引起了业界大佬IBM 的注意,他们研发了自己的IBM MQ(IBMWesphere)。后面微软也加入了这场战斗,研发了MSMQ。这个时候,每个厂商的产品是孤立的,大家都有自己的技术壁垒。 比如一个应用订阅了IBM MQ 的消息,如果有要订阅MSMQ 的消息,因为协议、API 不同,又要重复去实现。。
JDBC 协议大家非常熟悉吧?J2EE 制定了JDBC 的规范,那么那么各个数据库厂商自己去实现协议,提供 jar 包,在Java 里面就可以使用相同的API 做操作不同的数据库了。MQ 产品的问题也是一样的,2001 年的时候,SUN 公司发布了 JMS 规范,它想要在各大厂商的MQ 上面统一包装一层Java 的规范,大家都只需要针对API 编程就可以了,不需要关注使用了什么样的消息中间件,只要选择合适的MQ 驱动。但是JMS 只适用于Java 语言,它是跟语言绑定的,没有从根本上解决这个问题(只是一个API)。
所以在2006 年的时候,AMQP 规范发布了。它是跨语言和跨平台的,真正地促进了消息队列的繁荣发展。
2007 年的时候,Rabbit 技术公司基于Erlang语言开发了符合AMQP 规范RabbitMQ 1.0。从最开始用在金融行业里面,现在RabbitMQ 已经在世界各地的公司中遍地开花。国内的绝大部分大厂都在用 RabbitMQ,包括头条,美团,滴滴(TMD),去哪儿,艺龙,淘宝也有用。
3.1.2 MQ 定义
#阿里云消息队列
https://www.aliyun.com/product/ons?
spm=5176.234368.h2v3icoap.427.2620db25lcHi1Q&aly_as=Tz_Lue_o
在分布式场景中,相对于大量的用户请求来说,内部的功能主机之间、功能模块之间等,数据传递的数据量是无法想象的,因为一个用户请求,会涉及到各种内部的业务逻辑跳转等操作。那么,在大量用户的业务场景中,如何保证所有的内部业务逻辑请求都处于稳定而且快捷的数据传递呢? 消息队列 (Message Queue)技术可以满足此需求
消息队列(Message Queue,简称 MQ)是构建分布式互联网应用的基础设施,通过 MQ 实现的松耦合架构设计可以提高系统可用性以及可扩展性,是适用于现代应用的最佳设计方案。
消息队列是一种异步的服务间通信方式,适用于无服务器和微服务架构。消息在被处理和删除之前一直存储在队列上。每条消息仅可被一位用户处理一次。消息队列可被用于分离重量级处理、缓冲或批处理工作以及缓解高峰期工作负载。
3.1.3 MQ 使用场合

消息队列作为高并发系统的核心组件之一,能够帮助业务系统结构提升开发效率和系统稳定性
消息队列主要有以下应用场景
削峰填谷
诸如电商业务中的秒杀、抢红包、企业开门红等大型活动时皆会带来较高的流量脉冲,或因没做相应的保护而导致系统超负荷甚至崩溃,或因限制太过导致请求大量失败而影响用户体验,消息队列可提供削峰填谷的服务来解决该问题。
异步解耦
交易系统作为淘宝等电商的最核心的系统,每笔交易订单数据的产生会引起几百个下游业务系统的关注,包括物流、购物车、积分、流计算分析等等,整体业务系统庞大而且复杂,消息队列可实现异步通信和应用解耦,确保主站业务的连续性。
顺序收发
细数日常中需要保证顺序的应用场景非常多,例如证券交易过程时间优先原则,交易系统中的订单创建、支付、退款等流程,航班中的旅客登机消息处理等等。与先进先出FIFO(First In First Out)原理类似,消息队列提供的顺序消息即保证消息FIFO。
分布式事务一致性
交易系统、支付红包等场景需要确保数据的最终一致性,大量引入消息队列的分布式事务,既可以实现系统之间的解耦,又可以保证最终的数据一致性。
大数据分析
数据在“流动”中产生价值,传统数据分析大多是基于批量计算模型,而无法做到实时的数据分析, 利用消息队列与流式计算引擎相结合,可以很方便的实现业务数据的实时分析。
分布式缓存同步
电商的大促,各个分会场琳琅满目的商品需要实时感知价格变化,大量并发访问数据库导致会场页面响应时间长,集中式缓存因带宽瓶颈,限制了商品变更的访问流量,通过消息队列构建分布式缓存,实时通知商品数据的变化
蓄流压测
线上有些链路不方便做压力测试,可以通过堆积一定量消息再放开来压测
3.1.4 主流 MQ
目前主流的消息队列软件有 Kafka、RabbitMQ、ActiveMQ、RocketMQ等,还有相对小众的消息队列软件如ZeroMQ、Apache Qpid 等。

3.2 Kafka 介绍

阿里云消息队列
https://www.aliyun.com/product/ons?
spm=5176.234368.h2v3icoap.427.2620db25lcHi1Q&aly_as=Tz_Lue_o
Kafka 被称为下一代分布式消息系统,由 Scala 和 Java编写,是非营利性组织ASF(Apache Software Foundation)基金会中的一个开源项目,比如:HTTP Server、Tomcat、Hadoop、ActiveMQ等开源软件都属于 Apache基金会的开源软件,类似的消息系统还有RabbitMQ、ActiveMQ、ZeroMQ。
Kafka用于构建实时数据管道和流应用程序。 它具有水平可伸缩性,容错性,快速性,可在数千家组织中同时投入生产协同工作。
官网: http://kafka.apache.org/
3.3 常用消息队列对比
kafka 最主要的优势是其具备分布式功能、并可以结合 zookeeper 可以实现动态扩容,Kafka 是一种高吞吐量的分布式发布订阅消息系统。

3.4 Kafka 特点和优势

特点
分布式: 多机实现,不允许单机
分区: 一个消息.可以拆分出多个,分别存储在多个位置
-
多副本: 防止信息丢失,可以多来几个备份
-
多订阅者: 可以有很多应用连接kafka
-
Zookeeper: 早期版本的Kafka依赖于zookeeper, 2021年4月19日Kafka 2.8.0正式发布,此版本包括了很多重要改动,最主要的是kafka通过自我管理的仲裁来替代ZooKeeper,即Kafka将不再需要ZooKeeper!
优势
-
Kafka 通过 O(1)的磁盘数据结构提供消息的持久化,这种结构对于即使数以 TB 级别以上的消息存储也能够保持长时间的稳定性能。
-
高吞吐量:即使是非常普通的硬件Kafka也可以支持每秒数百万的消息。支持通过Kafka 服务器分区消息。
-
分布式: Kafka 基于分布式集群实现高可用的容错机制,可以实现自动的故障转移
-
顺序保证:在大多数使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。 Kafka保证一个Partiton内的消息的有序性(分区间数据是无序的,如果对数据的顺序有要求,应将在创建主题时将分区数partitions设置为1) 支持 Hadoop 并行数据加载
-
通常用于大数据场合,传递单条消息比较大,而Rabbitmq 消息主要是传输业务的指令数据,单条数据较小
随机和顺序IO比较

O(1)就是最低的时空复杂度,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空
间都不变,哈希算法就是典型的O(1)时间复杂度,无论数据规模多大,都可以在一次计算后找到目标
3.5 Kafka 角色和流程
3.5.1 Kafka 角色

Producer :Producer即生产者,消息的产生者,是消息的入口。负责发布消息到Kafka broker。
Consumer :消费者,用于消费消息,即处理消息
Consumer group: 每个consumer 属于一个特定的consumer group(可为每个consumer 指定 group name,若不指定 group name 则属于默认的group),使用 consumer high level API 时,同一topic 的一条消息只能被同一个consumer group 内的一个consumer 消费,但多个consumer group 可同时消费这一消息。
Broker :Broker是kafka实例,每个服务器上可以有一个或多个kafka的实例,假设每个broker对应一台服务器。每个kafka集群内的broker都有一个 不重复 的编号,如: broker-0、broker-1等……
Topic :消息的主题,可以理解为消息的分类,相当于Redis的Key和ES中的索引,kafka的数据就保存在topic。在每个broker上都可以创建多个topic。物理上不同 topic 的消息分开存储在不同的文件夹,逻辑上一个 topic的消息虽然保存于一个或多个broker 上, 但用户只需指定消息的topic即可生产或消费数据而不必关心数据存于何处,topic 在逻辑上对record(记录、日志)进行分组保存,消费者需要订阅相应的topic 才能消费topic中的消息。

Replication : 同样数据的副本,包括leader和follower的副本数,基本于数据安全,建议至少2个,是Kafka 的高可靠性的保障,和ES不同的,ES中的副本数不包括主分片数
Partition :是物理上的概念,每个topic 分割为一个或多个partition,即一个topic切分为多份.创建 topic时可指定 parition 数量,partition的表现形式就是一个一个的文件夹,该文件夹下存储该partition 的数据和索引文件,分区的作用还可以实现负载均衡,提高kafka的吞吐量。同一个topic在不同的分区的数据是不重复的,一般Partition数不要超过节点数,注意同一个partition数据是有顺序的,但不同的 partition则是无序的。
为了实现数据的高可用,比如将分区 0 的数据分散到不同的kafka 节点,每一个分区都有一个 broker 作为 Leader 和一个 broker 作为Follower,类似于ES中的主分片和副本分片,
AR : Assigned Replicas,分区中的所有副本的统称,AR= lSR+ OSR
lSR :ln Sync Replicas,所有与leader副本保持同步的副本 follower和leader本身组成的集合,是AR的子集
OSR :out-of-Sync Replied,所有与leader副本同步不能同步的 follower的集合,是AR的子集
分区的优势:
-
实现存储空间的横向扩容,即将多个kafka服务器的空间结合利用提升性能,多服务器读写
-
实现高可用,分区leader 分布在不同的kafka 服务器,假设分区因子为 3, 分区 0 的leader为服务器A,则服务器 B 和服务器 C 为 A 的follower,而分区 1 的leader为服务器B,则服务器 A 和C 为服务器B 的follower,而分区 2 的leader 为C,则服务器A 和 B 为C 的follower。

3.5.2 Kafka 写入消息的流程

3.6 Kafka 部署
官方文档:
http://kafka.apache.org/quickstart

3.6.1 环境准备 ZooKeeper
当前版本 Kafka 依赖 Zookeeper 服务,但以后将不再依赖
http://kafka.apache.org/quickstart
# Note: Soon, ZooKeeper will no longer be required by Apache Kafka.
环境说明
#在三个Ubuntu18.04节点提前部署zookeeper和kafka三个节点复用
node1:10.0.0.101
node2:10.0.0.102
node3:10.0.0.103
#注意:生产中zookeeper和kafka一般是分开独立部署的,kafka安装前需要安装java环境
确保三个节点的zookeeper启动
[root@node1 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
[root@node2 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: leader
[root@node3 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port fou
3.6.2 版本选择
kafka 基于scala语言实现,所以使用kafka需要指定scala的相应的版本.kafka 为多个版本的Scala构建。这仅在使用 Scala 时才重要,并且希望为使用的相同 Scala 版本构建一个版本。否则,任何版本都可以
kafka下载链接
http://kafka.apache.org/downloads
kafka版本格式
kafka_<scala 版本>_<kafka 版本>
#示例:kafka_2.13-2.7.0.tgz
scala 语言官网: https://www.scala-lang.org/
scale 与 java关系:https://baike.baidu.com/item/Scala/2462287?fr=aladdin
3.6.3 各节点部署 Kafka
3.6.3.1 Kafka 节点配置
配置文件说明
#配置文件 ./conf/server.properties内容说明
############################# Server Basics###############################
# broker的id,值为整数,且必须唯一,在一个集群中不能重复
broker.id=1
############################# Socket ServerSettings ######################
# kafka监听端口,默认9092
listeners=PLAINTEXT://10.0.0.101:9092
# 处理网络请求的线程数量,默认为3个
num.network.threads=3
# 执行磁盘IO操作的线程数量,默认为8个
num.io.threads=8
# socket服务发送数据的缓冲区大小,默认100KB
socket.send.buffer.bytes=102400
# socket服务接受数据的缓冲区大小,默认100KB
socket.receive.buffer.bytes=102400
# socket服务所能接受的一个请求的最大大小,默认为100M
socket.request.max.bytes=104857600
############################# Log Basics###################################
# kafka存储消息数据的目录
log.dirs=../data
# 每个topic默认的partition
num.partitions=1
# 设置副本数量为3,当Leader的Replication故障,会进行故障自动转移。
default.replication.factor=3
# 在启动时恢复数据和关闭时刷新数据时每个数据目录的线程数量
num.recovery.threads.per.data.dir=1
############################# Log FlushPolicy #############################
# 消息刷新到磁盘中的消息条数阈值
log.flush.interval.messages=10000
# 消息刷新到磁盘中的最大时间间隔,1s
log.flush.interval.ms=1000
############################# Log RetentionPolicy #########################
# 日志保留小时数,超时会自动删除,默认为7天
log.retention.hours=168
# 日志保留大小,超出大小会自动删除,默认为1G
#log.retention.bytes=1073741824
# 日志分片策略,单个日志文件的大小最大为1G,超出后则创建一个新的日志文件
log.segment.bytes=1073741824
# 每隔多长时间检测数据是否达到删除条件,300s
log.retention.check.interval.ms=300000
############################# Zookeeper ####################################
# Zookeeper连接信息,如果是zookeeper集群,则以逗号隔开
zookeeper.connect=10.0.0.101:2181,10.0.0.102:2181,10.0.0.103:2181
# 连接zookeeper的超时时间,6s
zookeeper.connection.timeout.ms=6000
范例:
#在所有节点上执行安装java
[root@node1 ~]#apt install openjdk-8-jdk -y
#在所有节点上执行下载,官方下载
[root@node1 ~]#wget https://archive.apache.org/dist/kafka/2.7.0/kafka_2.13-
2.7.0.tgz
[root@node1 ~]#wget https://downloads.apache.org/kafka/3.3.1/kafka_2.13-
3.3.1.tgz
#国内镜像下载
[root@node1 ~]#wget
https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/3.3.1/kafka_2.13-3.3.1.tgz
[root@node1 ~]#wget
https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/3.0.0/kafka_2.13-3.0.0.tgz
[root@node1 ~]#wget https://mirror.bit.edu.cn/apache/kafka/2.7.0/kafka_2.13-
2.7.0.tgz
# 解压缩
[root@node1 ~]#tar xf kafka_2.13-2.7.0.tgz -C /usr/local/
[root@node1 ~]#ln -s /usr/local/kafka_2.13-2.7.0/ /usr/local/kafka
# 配置 PATH 变量
[root@node1 ~]#echo 'PATH=/usr/local/kafka/bin:$PATH' > /etc/profile.d/kafka.sh
[root@node1 ~]#. /etc/profile.d/kafka.sh
# 修改配置文件
[root@node1 ~]#vim /usr/local/kafka/config/server.properties
broker.id=1#每个broker在集群中每个节点的正整数唯一标识,此值保存在log.dirs下的
meta.properties文件
listeners=PLAINTEXT://10.0.0.101:9092 #指定当前主机的IP做为监听地址,注意:不支持0.0.0.0
log.dirs=/usr/local/kafka/data #kakfa用于保存数据的目录,所有的消息都会存储在该目录当中
num.partitions=1#设置创建新的topic时默认分区数量,建议和kafka的节点数量一致
default.replication.factor=3#指定默认的副本数为3,可以实现故障的自动转移
log.retention.hours=168#设置kafka中消息保留时间,默认为168小时即7天
zookeeper.connect=10.0.0.101:2181,10.0.0.102:2181,10.0.0.103:2181 #指定连接的zk的地
址,zk中存储了broker的元数据信息
zookeeper.connection.timeout.ms=6000#设置连接zookeeper的超时时间,单位为ms,默认6秒钟
# 准备数据目录
[root@node1 ~]#mkdir /usr/local/kafka/data
[root@node1 ~]#scp /usr/local/kafka/config/server.properties
10.0.0.102:/usr/local/kafka/config
[root@node1 ~]#scp /usr/local/kafka/config/server.properties
10.0.0.103:/usr/local/kafka/config
# 修改第 2 个节点配置
[root@node2 ~]#vim /usr/local/kafka/config/server.properties
broker.id=2#每个broker 在集群中的唯一标识,正整数。
listeners=PLAINTEXT://10.0.0.102:9092 #指定当前主机的IP做为监听地址,注意:不支持0.0.0.0
# 修改第 3 个节点配置
[root@node3 ~]#vim /usr/local/kafka/config/server.properties
broker.id=31#每个broker 在集群中的唯一标识,正整数。
listeners=PLAINTEXT://10.0.0.103:9092 #指定当前主机的IP做为监听地址,注意:不支持0.0.0.0
3.6.3.2 启动服务
在所有kafka节点执行下面操作
[root@node1 ~]#vim vim /usr/local/kafka/bin/kafka-server-start.sh
if[ " x$KAFKA_HEAP_OPTS"="x"] ; then
exportKAFKA_HEAP_OPTS=" -Xmx1G-Xms1G"#可以调整内存
fi
[root@node1 ~]#kafka-server-start.sh -daemon
/usr/local/kafka/config/server.properties
3.6.3.3 确保服务启动状态
[root@node1 ~]#ss -ntl|grep 9092
LISTEN 050 [::ffff:10.0.0.101]:9092 *:*
[root@node1 ~]#tail /usr/local/kafka/logs/server.log
[2021-02-16 12:10:01,276] INFO [ExpirationReaper-1-AlterAcls]: Starting
(kafka.server.DelayedOperationPurgatory$ExpiredOperationReaper)
[2021-02-16 12:10:01,311] INFO [/config/changes-event-process-thread]: Starting
(kafka.common.ZkNodeChangeNotificationListener$ChangeEventProcessThread)
[2021-02-16 12:10:01,332] INFO [SocketServer brokerId=1] Starting socket server
acceptors and processors (kafka.network.SocketServer)
[2021-02-16 12:10:01,339] INFO [SocketServer brokerId=1] Started data-plane
acceptor and processor(s) for endpoint : ListenerName(PLAINTEXT)
(kafka.network.SocketServer)
[2021-02-16 12:10:01,340] INFO [SocketServer brokerId=1] Started socket server
acceptors and processors (kafka.network.SocketServer)
[2021-02-16 12:10:01,344] INFO Kafka version: 2.7.0
(org.apache.kafka.common.utils.AppInfoParser)
[2021-02-16 12:10:01,344] INFO Kafka commitId: 448719dc99a19793
(org.apache.kafka.common.utils.AppInfoParser)
[2021-02-16 12:10:01,344] INFO Kafka startTimeMs: 1613448601340
(org.apache.kafka.common.utils.AppInfoParser)
[2021-02-16 12:10:01,346] INFO [KafkaServer id=1] started
(kafka.server.KafkaServer)
[2021-02-16 12:10:01,391] INFO [broker-1-to-controller-send-thread]: Recorded
new controller, from now on will use broker 1
(kafka.server.BrokerToControllerRequestThread)
#如果使用id,还需要修改/usr/local/kafka/data/meta.properties
#打开zooinspector可以看到三个id

-
Broker 依赖于 Zookeeper,每个Broker 的id 和 Topic、Partition这些元数据信息都会写入 Zookeeper 的 ZNode 节点中
-
consumer 依赖于Zookeeper,Consumer 在消费消息时,每消费完一条消息,会将产生的offset 保存到 Zookeeper 中,下次消费在当前offset往后继续消费.kafka0.9 之前Consumer 的offset 存储在 Zookeeper 中,kafka0.9 以后offset存储在本地。
-
Partition 依赖于 Zookeeper,Partition 完成Replication 备份后,选举出一个Leader,这个是依托于 Zookeeper 的选举机制实现的
3.6.3.4 准备Kafka的service文件
[root@node1 ~]#cat /lib/systemd/system/kafka.service
[unit]
Description=Apache kafka
After=network.target
[service]
Type=simple
#Environment=JAVA_HOME=/data/server/java
PIDFile=/usr/local/kafka/kafka.pid
Execstart=/usr/local/kafka/bin/kafka-server-start.sh
/usr/local/kafka/config/server. properties
Execstop=/bin/kill -TERM${MAINPID}
Restart=always
RestartSec=20
[Install]
wantedBy=multi-user.target
[root@node1 ~]#systemctl daemon-load
[root@node1 ~]#systemctl restart kafka.service
3.7 Kafka 读写数据
参考文档
http://kafka.apache.org/quickstart
常见命令
kafka-topics.sh #消息的管理命令
kafka-console-producer.sh #生产者的模拟命令
kafka-console-consumer.sh #消费者的模拟命令
3.7.1 创建 Topic
创建名为 wang,partitions(分区)为3,replication(每个分区的副本数/每个分区的分区因子)为 2 的 topic(主题)
# 新版命令
[root@node1 ~]#/usr/local/kafka/bin/kafka-topics.sh --create --topic wang --
bootstrap-server 10.0.0.101:9092 --partitions 3 --replication-factor 2
# 在各节点上观察生成的相关数据
[root@node1 ~]#ls /usr/local/kafka/data/
[root@node2 ~]#ls /usr/local/kafka/data/
[root@node3 ~]#ls /usr/local/kafka/data/
# 旧版命令
[root@node1 ~]#/usr/local/kafka/bin/kafka-topics.sh --create --zookeeper
10.0.0.101:2181,10.0.0.102:2181,10.0.0.103:2181 --partitions 3 --replication-
factor 2 --topic wang
Created topic wang.
3.7.2 获取所有 Topic
# 新版命令
[root@node1 ~]#/usr/local/kafka/bin/kafka-topics.sh --list --bootstrap-server
10.0.0.101:9092
# 旧版命令
[root@node1 ~]#/usr/local/kafka/bin/kafka-topics.sh --list --zookeeper
10.0.0.101:2181,10.0.0.102:2181,10.0.0.103:2181
wang

3.7.3 验证 Topic 详情
状态说明:wang 有三个分区分别为0、1、2,分区0的leader是3 (broker.id),分区 0 有2 个副本, 并且状态都为 lsr(ln-sync,表示可以参加选举成为 leader)。
#新版命令
[root@node1 ~]#/usr/local/kafka/bin/kafka-topics.sh --describe --bootstrap-
server 10.0.0.101:9092 --topic wang
Topic: wang TopicId: beg6bPXwToW1yp7cuv7F8w PartitionCount: 3
ReplicationFactor: 2 Configs:
Topic: wang Partition: 0 Leader: 3 Replicas: 3,1 Isr: 3,1
Topic: wang Partition: 1 Leader: 1 Replicas: 1,2 Isr: 1,2
Topic: wang Partition: 2 Leader: 2 Replicas: 2,3 Isr: 2,3
#旧版命令
[root@node1 ~]#/usr/local/kafka/bin/kafka-topics.sh --describe --zookeeper
10.0.0.101:2181,10.0.0.102:2181,10.0.0.103:2181 --topic wang
Topic: wang PartitionCount: 3 ReplicationFactor: 2 Configs:
Topic: wang Partition: 0 Leader: 3 Replicas: 3,2 Isr: 3,2
Topic: wang Partition: 1 Leader: 1 Replicas: 1,3 Isr: 1,3
Topic: wang Partition: 2 Leader: 2 Replicas: 2,1 Isr: 2,1
3.7.4 生产 Topic
kafka-console-producer.sh 格式
#发送消息命令格式:
kafka-console-producer.sh --broker-list <kafkaIP1>:<端口>,<kafkaIP2>:<端口> --
topic <topic名称>
范例:
#交互式输入消息,按Ctrl+C退出
[root@node1 ~]#/usr/local/kafka/bin/kafka-console-producer.sh --broker-list
10.0.0.101:9092,10.0.0.102:9092,10.0.0.103:9092 --topic wang
>message1
>message2
>message3
>
#或者下面方式
[root@node1 ~]#/usr/local/kafka/bin/kafka-console-producer.sh --topic wang --
bootstrap-server 10.0.0.101:9092
3.7.5 消费 Topic
kafka-console-consumer.sh 格式
#接收消息命令格式:
kafka-console-consumer.sh --bootstrap-server <host>:<post> --topic <topic名称> --
from-beginning--consumer-property group.id=<组名称>
注意:
消息者先生产消息,消费都后续才启动,也能收到之前生产的消息
- 同一个消息在同一个group内的消费者只有被一个消费者消费,比如:共100条消息,在一个group 内有A,B两个消费者,其中A消费50条,B消费另外的50条消息。从而实现负载均衡,不同group 内的消费者则可以同时消费同一个消息
范例:
#交互式持续接收消息,按Ctrl+C退出
[root@node2 ~]# /usr/local/kafka/bin/kafka-console-consumer.sh --topic wang --
bootstrap-server 10.0.0.102:9092 --from-beginning
message1
message3
message2
#支持多个生产者和消费者
3.7.6 删除 Topic
# 新版本
[root@node3 ~]#/usr/local/kafka/bin/kafka-topics.sh --delete --bootstrap-server
10.0.0.101:2181,10.0.0.102:2181,10.0.0.103:2181 --topic wang
# 旧版本
[root@node3 ~]#/usr/local/kafka/bin/kafka-topics.sh --delete --zookeeper
10.0.0.101:2181,10.0.0.102:2181,10.0.0.103:2181 --topic wang
Topic wang is marked for deletion.
Note: This will have no impact if delete.topic.enable is not set to true.
3.8 Kafka 在 ZooKeeper 里面的存储结构

topic 结构
/brokers/topics/[topic]
partition结构
/brokers/topics/[topic]/partitions/[partitionId]/state
broker信息
/brokers/ids/[o...N]
控制器
/controller
存储center controller中央控制器所在kafka broker的信息
消费者
消费者信息:
/consumers/[groupId]/ids /[consumerIdstring]
每个consumer都有一个唯一的ID,此id用来标记消费者信息
消费者管理者:
/consumers/[groupId]/owners/[topic]/[partitionid]
3.9 图形工具 Offset Explorer (Kafka Tool)

Offset Explorer ,旧称Kafka Tool,工具是一个 GUI 应用程序,用于管理和使用 Apache Kafka 群集。 它提供了一个直观的 UI,允许人们快速查看 Kafka 群集中的对象以及存储在群集主题中的消息。它包含面向开发人员和管理员的功能。一些关键功能包括
-
快速查看您的所有 Kafka 集群,包括其经纪人、主题和消费者
-
查看分区中邮件的内容并添加新邮件
-
查看消费者的偏移量,包括阿帕奇风暴卡夫卡喷口消费者
-
以漂亮的打印格式显示 JSON和 XML 消息
-
添加和删除主题以及其他管理功能
-
将单个邮件从分区保存到本地硬盘驱动器
-
编写自己的插件,允许您查看自定义数据格式
Kafka 工具在Windows、Linux 和 Mac 操作系统上运行
官网:
https://www.kafkatool.com/
下载链接:
https://www.kafkatool.com/download.html



修改类型

查看数据

3.10 基于 Web 的 kafka-eagle
https://github.com/smartloli/kafka-eagle-bin

4 Dubbo
4.1 Dubbo 介绍

Apache Dubbo 是一款高性能、轻量级的开源RPC服务框架
Apache Dubbo 提供了六大核心能力:面向接口代理的高性能RPC调用,智能容错和负载均衡,服务自动注册和发现,高度可扩展能力,运行期流量调度,可视化的服务治理与运维。
SpringCloud 提供了微服务的全家桶的整套解决方案,Dubbo只是实现了微服务中RPC部分的功能,基本相当于SpringCloud中的Feign,还需要组合其它服务才能实现全部功能
阿里云微服务
https://promotion.aliyun.com/ntms/act/edasdubbo.html
Dubbo 官网
https://dubbo.apache.org/zh/
Dubbo 架构
https://dubbo.apache.org/zh/docs/v2.7/user/preface/architecture/
Dubbo 运维
https://dubbo.apache.org/zh/docs/v2.7/admin/
Dubbo 简介
https://help.aliyun.com/document_detail/99299.html

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




中
EDAS(Enterprise
心开源组件 Distributed Application 托管说明类
Service)组件型注
Nacos(推荐)、 只需将应用部署到 EDAS
册 Nacos(推荐)、EDAS注
ZooKeeper(推荐)、 中,即可默认接入注册中中册中心
etcd、Consul、Eureka 心心配
Nacos(推荐)、 只需将应用部署到EDAS
置
ZooKeeper(推荐)、 Nacos(推荐) 中,即可默认接入配置中中
Apollo 心心元数您只需将应用部署到
Nacos(推荐)、Redis(推据 Nacos(推荐) EDAS中,即可默认接入荐)、ZooKeeper
中元数据中心。
心
Dubbo服务框架的工作流程如下:
-
提供者在启动时,在注册中心注册服务。
-
消费者在启动时,在注册中心订阅所需的服务。
-
注册中心返回提供者地址列表给消费者。如果提供者发生变更,注册中心将推送变更数据给消费者。
-
消费者基于软负载均衡算法,从提供者地址列表中选一个提供者进行调用。
Nacos 介绍
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态
服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架
构 (例如微服务范式、云原生范式) 的服务基础设施。
Nacos 官网
https://nacos.io/zh-cn/
4.2 实现 Dubbo 架构

环境说明
#准备三台zookeeper集群
#10.0.0.101 node1
#10.0.0.102 node2
#10.0.0.103 node3
#准备两台主机充当provider
#10.0.0.104 provider1
#10.0.0.105 provider2
#准备两台主机充当consumer
#10.0.0.106 consumer1
#10.0.0.107 consumer2
官方 Demo
https://github.com/apache/dubbo/tree/master/dubbo-demo
4.2.1 准备 ZooKeeper 提供注册中心
基于 ZooKeeper 发现并管理 provider 和consumer准备环境
官方说明: https://dubbo.apache.org/zh/docs/references/registry/zookeeper/
Zookeeper 是 Apache Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用

流程说明:
-
服务提供者启动时: 向
/dubbo/com.foo.BarService/providers目录下写入自己的 URL 地址服务消费者启动时: 订阅/dubbo/com.foo.BarService/providers目录下的提供者 URL 地址。 并向/dubbo/com.foo.BarService/consumers目录下写入自己的 URL 地址 -
监控中心启动时: 订阅
/dubbo/com.foo.BarService目录下的所有提供者和消费者 URL 地址。
支持以下功能:
当提供者出现断电等异常停机时,注册中心能自动删除提供者信息
-
当注册中心重启时,能自动恢复注册数据,以及订阅请求当会话过期时,能自动恢复注册数据,以及订阅请求
-
当设置
<dubbo:registry check="false" />时,记录失败注册和订阅请求,后台定时重试 -
可通过
<dubbo:registry username="admin" password="1234" />设置 zookeeper 登录信息可通过<dubbo:registry group="dubbo" />设置 zookeeper 的根节点,不配置将使用默认的根节点。 -
支持
*号通配符<dubbo:reference group="*" version="*" />,可订阅服务的所有分组和所有版本的提供者
ZooKeeper 配置说明
https://dubbo.apache.org/zh/docs/v2.7/user/references/registry/zookeeper/
ZooKeeper 环境准备
#准备三台 ZooKeeper 集群
#10.0.0.101 node1
#10.0.0.102 node2
#10.0.0.103 node3
[root@node1 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
[root@node2 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: leader
[root@node3 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
4.2.2 生产者示例
注意:此案例只支持Ubuntu18.04和Jdk8或11,但不支持Ubuntu20.04
https://github.com/apache/dubbo/tree/dubbo-2.1.5
https://github.com/apache/dubbo/tree/dubbo-2.1.5/dubbo-demo-provider
在10.0.0.104 和 10.0.0.105 主机在启动 provider
#Ubuntu系统
[root@ubuntu1804 ~]#apt -y install openjdk-8-jdk net-tools
#红帽系统
[root@centos8 ~]#yum -y install java-1.8.0-openjdk-devel nc
[root@ubuntu1804 ~]#tar xf dubbo-demo-provider-2.1.5-assembly.tar.gz -C
/usr/local/
[root@ubuntu1804 ~]#ln -s /usr/local/dubbo-demo-provider-2.1.5/
/usr/local/dubbo-demo-provider
[root@ubuntu1804 ~]#vim /usr/local/dubbo-demo-provider/conf/dubbo.properties
#dubbo.registry.address=multicast://224.5.6.7:1234 #注释此行,不使用默认的组播注册中
心,添加下面行使用zk做为注册中心
dubbo.registry.address=zookeeper://10.0.0.101:2181 | zookeeper://10.0.0.102:2181
| zookeeper://10.0.0.103:2181 #修改此行, zk集群配置
#dubbo.registry.address=zookeeper://10.0.0.101:2181 #单zk节点使用此配置
#启动provider
[root@ubuntu1804 ~]#/usr/local/dubbo-demo-provider/bin/start.sh
Starting the demo-provider ....
OK!
PID: 20846
STDOUT: logs/stdout.log
[root@ubuntu1804 ~]#cat /usr/local/dubbo-demo-provider/logs/stdout.log
OpenJDK 64-Bit Server VM warning: ignoring option PermSize=128m; support was
removed in8.0
log4j:WARN No appenders could be found for logger
(com.alibaba.dubbo.common.logger.LoggerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more
info.
[2021-02-17 21:10:55] Dubbo service server started!
[root@ubuntu1804 ~]#ss -ntlp|grep java
LISTEN 0500.0.0.0:20880 0.0.0.0:* users:(("java",pid=20846,fd=51))
#当消费者主机启动后,可以观察到下面日志
[root@ubuntu1804 ~]#tail -f /usr/local/dubbo-demo-provider/logs/*
==> /usr/local/dubbo-demo-provider/logs/stdout.log <==
[16:49:58] Hello world150, request from consumer: /10.0.0.107:48872
[16:49:58] Hello world180, request from consumer: /10.0.0.106:53872
[16:50:02] Hello world152, request from consumer: /10.0.0.107:48872
[16:50:02] Hello world182, request from consumer: /10.0.0.106:53872
[16:50:06] Hello world154, request from consumer: /10.0.0.107:48872
#使用zk工具查看注册信息

4.2.3 消费者示例
https://github.com/apache/dubbo/tree/dubbo-2.1.5
https://github.com/apache/dubbo/tree/dubbo-2.1.5/dubbo-demo-consumer
在 10.0.0.106 和 10.0.0.107 主机在启动 consumer
[root@ubuntu1804 ~]#apt -y install openjdk-8-jdk
[root@centos8 ~]#yum -y install java-1.8.0-openjdk nc
[root@ubuntu1804 ~]#tar xf dubbo-demo-consumer-2.1.5-assembly.tar.gz -C
/usr/local/
[root@ubuntu1804 ~]#ln -s /usr/local/dubbo-demo-consumer-2.1.5/
/usr/local/dubbo-demo-consumer
#和provider一样的zk配置信息
[root@ubuntu1804 ~]#vim /usr/local/dubbo-demo-consumer/conf/dubbo.properties
#dubbo.registry.address=multicast://224.5.6.7:1234 #注释此行,不使用默认的组播注册中心,
添加下面行使用zk做为注册中心
#修改下面行指定zk集群配置
dubbo.registry.address=zookeeper://10.0.0.101:2181 | zookeeper://10.0.0.102:2181
| zookeeper://10.0.0.103:2181
#启动consumer
[root@ubuntu1804 ~]#/usr/local/dubbo-demo-consumer/bin/start.sh
Starting the demo-consumer ....OK!
PID: 20804
STDOUT: logs/stdout.log
#注意: 如果有多个生产者.则消费会轮询多个消费都进行服务
#观察消费者consumer日志
[root@ubuntu1804 ~]#tail -f /usr/local/dubbo-demo-consumer/logs/stdout.log
==> /usr/local/dubbo-demo-consumer/logs/stdout.log <==
[16:50:58] Hello world210, response form provider: 10.0.0.104:20880
[16:51:00] Hello world211, response form provider: 10.0.0.105:20880
[16:51:02] Hello world212, response form provider: 10.0.0.104:20880
[16:51:04] Hello world213, response form provider: 10.0.0.105:20880
[16:51:06] Hello world214, response form provider: 10.0.0.104:20880
#观察生产者provider日志
[root@ubuntu1804 ~]#tail -f /usr/local/dubbo-demo-provider/logs/stdout.log
OpenJDK 64-Bit Server VM warning: ignoring option PermSize=128m; support was
removed in8.0
log4j:WARN No appenders could be found for logger
(com.alibaba.dubbo.common.logger.LoggerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more
info.
[2021-02-17 21:10:55] Dubbo service server started!
[16:51:58] Hello world210, request from consumer: /10.0.0.107:48872
[16:51:59] Hello world240, request from consumer: /10.0.0.106:53872
[16:52:02] Hello world212, request from consumer: /10.0.0.107:48872
[16:52:03] Hello world242, request from consumer: /10.0.0.106:53872
[16:52:06] Hello world214, request from consumer: /10.0.0.107:48872
[16:52:07] Hello world244, request from consumer: /10.0.0.106:53872
4.3 编译安装 Dubbo的 Web 管理 Dubbo Admin (新版)
官方说明
https://github.com/apache/dubbo-admin

注意: 内存建议4G以上
4.3.1 编译 dubbo admin
[root@ubuntu1804 ~]#cd /usr/local/src/
#git方式下载,此方法很慢
[root@ubuntu1804 src]#git clone https://github.com/apache/dubbo-admin.git
#直接下载zip文件,再解压缩
[root@ubuntu1804 src]#ll dubbo-admin-develop.zip -h
-rw-r--r--1 root root 1.2M Feb 1816:08 dubbo-admin-develop.zip
[root@ubuntu1804 src]#unzip dubbo-admin-develop.zip
#进入到源码目录
[root@ubuntu1804 src]#cd dubbo-admin-develop/
[root@ubuntu1804 dubbo-admin-develop]#pwd
/usr/local/src/dubbo-admin-develop
[root@ubuntu1804 dubbo-admin-develop]#ls
codestyle doc dubbo-admin-distribution dubbo-admin-test LICENSE mvnw.cmd
pom.xml README_ZH.md
DISCLAIMER docker dubbo-admin-server dubbo-admin-ui mvnw NOTICE
README.md
# 修改 zookeeper 地址为实际 IP
[root@ubuntu1804 dubbo-admin-develop]#vim dubbo-admin-
server/src/main/resources/application.properties
admin.registry.address=zookeeper://10.0.0.101:2181,10.0.0.102:2181,10.0.0.103:21
81
admin.config-center=zookeeper://10.0.0.101:2181,10.0.0.102:2181,10.0.0.103:2181
admin.metadata-
report.address=zookeeper://10.0.0.101:2181,10.0.0.102:2181,10.0.0.103:2181
#优化maven配置
[root@ubuntu1804 dubbo-admin-develop]#echo 'export MAVEN_OPTS="-Xmx2g -Xms2g"' >>
/etc/profile.d/maven.sh
[root@ubuntu1804 dubbo-admin-develop]#source /etc/profile.d/maven.sh
#因为此项目中使用了nodejs,建议用下面方式加速
[root@ubuntu1804 dubbo-admin-develop]#apt -y install npm
[root@ubuntu1804 dubbo-admin-develop]#npm config get registry
https://registry.npmjs.org/
[root@ubuntu1804 dubbo-admin-develop]#npm config set registry
https://registry.npm.taobao.org
[root@ubuntu1804 dubbo-admin-develop]#npm config get registry
https://registry.npm.taobao.org/
#编译方法1:执行java编译
[root@ubuntu1804 dubbo-admin-develop]#mvn clean package
#编译方法2:执行java源码编译并跳过测试单元,推荐此方式
[root@ubuntu1804 dubbo-admin-develop]#mvn clean install package -
Dmaven.test.skip=true

如果报错:
[ERROR] Killed
[ERROR] npm ERR! code ELIFECYCLE
[ERROR] npm ERR! errno 137
[ERROR] npm ERR! [dubbo-admin-ui@1.0.0](mailto:dubbo-admin-ui@1.0.0) build:`node
build/build.js`
[ERROR] npm ERR! Exit status 137
[ERROR] npm ERR!
[ERROR] npm ERR! Failed at the [dubbo-admin-ui@1.0.0](mailto:dubbo-admin-
ui@1.0.0) build script.
解决办法:
服务器增加内存(推荐 4G 或以上),避免被内核OOM
4.3.2 编译完成
[INFO] --- maven-site-plugin:3.7:attach-descriptor (attach-descriptor) @ dubbo-
admin-test ---
[INFO] Skipping because packaging 'jar' is not pom.
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for dubbo-admin 0.3.0-SNAPSHOT:
[INFO]
[INFO] dubbo-admin ........................................ SUCCESS [ 2.800 s]
[INFO] dubbo-admin-ui ..................................... SUCCESS [01:43 min]
[INFO] dubbo-admin-server ................................. SUCCESS [01:13 min]
[INFO] dubbo-admin-distribution ........................... SUCCESS [ 1.330 s]
[INFO] dubbo-admin-test ................................... SUCCESS [ 27.633 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 03:28 min
[INFO] Finished at: 2021-02-18T18:29:56+08:00
[INFO] ------------------------------------------------------------------------
[root@ubuntu1804 dubbo-admin-develop]#

4.3.3 启动服务
#确保zookeeper已启动
[root@node1 ~]#zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
#启动dubbo admin方法1
[root@ubuntu1804 ~]#cd /usr/local/src/dubbo-admin-develop;mvn --projects dubbo-
admin-server spring-boot:run
#启动dubbo admin方法2
[root@ubuntu1804 ~]#java -jar /usr/local/src/dubbo-admin-develop/dubbo-admin-
distribution/target/dubbo-admin-0.3.0-SNAPSHOT.jar
--server.port=8888

4.3.4 登录 Web 界面验证
浏览器访问下面地址,用登录名和密码为root登录
http://dubbo-admin主机:8080/



4.4 编译安装 Dubbo的 Web 管理 dubbo admin (旧版)
Dubbo 提供了 Web 管理管理界面
说明文档:
https://github.com/apache/dubbo-admin/blob/develop/README_ZH.md

下载 dubbo-admin 链接如下
https://github.com/apache/dubbo-admin
https://github.com/apache/dubbo/tree/dubbo-2.6.0
#注意:dubbo-2.6.1以后的版本不再集成dubbo-admin,成为独立的项目dubbo-admin
4.4.1 下载 dubbo-admin 的 Web 管理源码

4.4.2 编译 Dubbo Admin 生成 war 包文件
在10.0.0.104主机上编译dubbo admin的java源码
#在10.0.0.104事先已安装JDK
[root@ubuntu1804 ~]#apt -y install maven
#镜像加速
root@ubuntu1804 ~]#vim /etc/maven/settings.xml
<mirrors>
<!--阿里云镜像-->
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror>
</mirrors>
#新版
[root@ubuntu1804 ~]#git clone https://github.com/apache/dubbo-admin.git
[root@ubuntu1804 ~]#cd dubbo-admin/
#旧版
[root@ubuntu1804 ~]#ll -h dubbo-dubbo-2.6.0.zip
-rw-r--r--1 root root 3.3M Feb 1722:32 dubbo-dubbo-2.6.0.zip
[root@ubuntu1804 ~]#unzip dubbo-dubbo-2.6.0.zip -d /usr/local/
[root@ubuntu1804 ~]#cd /usr/local/dubbo-dubbo-2.6.0/dubbo-admin/
[root@ubuntu1804 dubbo-admin]#du -sh .
2.9M .
[root@ubuntu1804 dubbo-admin]#ls
pom.xml src
#编译
[root@ubuntu1804 dubbo-admin]#mvn package -Dmaven.skip.test=true
.......
[INFO] Packaging webapp
[INFO] Assembling webapp [dubbo-admin] in [/usr/local/dubbo-dubbo-2.6.0/dubbo-
admin/target/dubbo-admin-2.6.0]
[INFO] Processing war project
[INFO] Copying webapp resources [/usr/local/dubbo-dubbo-2.6.0/dubbo-
admin/src/main/webapp]
[INFO] Webapp assembled in [180 msecs]
[INFO] Building war: /usr/local/dubbo-dubbo-2.6.0/dubbo-admin/target/dubbo-admin-
2.6.0.war
[INFO] WEB-INF/web.xml already added, skipping
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:08 min
[INFO] Finished at: 2021-02-17T23:21:23+08:00
[INFO] ------------------------------------------------------------------------
[root@ubuntu1804 dubbo-admin]#du -sh .
72M .
[root@ubuntu1804 dubbo-admin]#ls
pom.xml src target
[root@ubuntu1804 dubbo-admin]#ls target/
classes dubbo-admin-2.6.0 dubbo-admin-2.6.0.war generated-sources generated-
test-sources maven-archiver maven-status surefire-reports test-classes
[root@ubuntu1804 dubbo-admin]#cp target/dubbo-admin-2.6.0.war /root/

4.4.3 在 Tomcat 中部署 Dubbo Admin
[root@ubuntu1804 ~]#ll apache-tomcat-8.5.61.tar.gz dubbo-admin-2.6.0.war
-rw-r--r--1 root root 10492067 Jan 317:47 apache-tomcat-8.5.61.tar.gz
-rw-r--r--1 root root 32099502 Feb 1723:25 dubbo-admin-2.6.0.war
[root@ubuntu1804 ~]#tar xvf apache-tomcat-8.5.61.tar.gz -C /usr/local/
[root@ubuntu1804 ~]#ln -s /usr/local/apache-tomcat-8.5.61/ /usr/local/tomcat
#将war包文件解包到tomcat目录下
[root@ubuntu1804 ~]#unzip dubbo-admin-2.6.0.war -d
/usr/local/tomcat/webapps/dubbo-admin
#或者直接复制前面编译完的目录
[root@ubuntu1804 ~]#cp -r /usr/local/dubbo-dubbo-2.6.0/dubbo-
admin/target/dubbo-admin-2.6.0/ /usr/local/tomcat/dubbo-admin
[root@ubuntu1804 ~]#vim /usr/local/tomcat/webapps/dubbo-admin/WEB-
INF/dubbo.properties
[root@ubuntu1804 ~]#cat /usr/local/tomcat/webapps/dubbo-admin/WEB-
INF/dubbo.properties
#修改下面一行指定zk地址
dubbo.registry.address=zookeeper://10.0.0.101:2181 | zookeeper://10.0.0.102:2181
| zookeeper://10.0.0.103:2181
dubbo.admin.root.password=root #可保留默认密码
dubbo.admin.guest.password=guest #可保留默认密码
[root@ubuntu1804 ~]#/usr/local/tomcat/bin/startup.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr
Using CLASSPATH:
/usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.
4.4.4 验证登录 Dubbo 的 Web 管理页面
#打开浏览器访问登录下面地址, 使用用户名/密码:root/root登录,也可以用用户名/密码: guest/guest
登录
http://dubboadmin主机:8080/dubbo-admin/

