Dubbo学习笔记(四)——微服务架构

微服务架构

解决方案

  • Spring Boot + Spring Cloud
    组件多,功能完备,基于HTTP。

  • Spring Boot + Dubbo + Zookeeper
    组件少,功能不完备,基于RPC通信方案

微服务架构需要解决的难题

  1. 客户端如何访问这么多服务
    API 网关

  2. 服务与服务之间如何通信
    同步通信 HTTP(Apache Http Client) RPC(Dubbo)
    异步通信 消息队列(Kafka RabbitMQ RocketMQ)

  3. 服务治理
    基于客户端的服务注册与发现(Zookeeper)
    基于服务端的服务注册与发现(Eureka)

  4. 服务挂了怎么解决
    重试机制、服务熔断、服务降级、服务限流

ZooKeeper

是一种分布式协调服务,用于管理大型主机,主要用于解决分布环境当中多个进程之间的同步控制,让他们有序地去访问某种临界资源,防止造成脏数据的后果。

数据模型

它很像数据结构中的树。树是由节点组成的,数据存储是基于节点,这种节点叫做Znode。

不同于树的节点,Znode的引用方式是路径引用,类似于文件。

这样的层级结构,让每个Znode节点拥有唯一的路径,就像命名空间一样,对不同信息做出清晰的隔离。

Znode包含哪些元素:

  • data:节点存储的数据信息。
  • ACL:记录节点的访问权限。
  • stat:包含节点的各种元数据,例如事务ID、版本号、时间戳、大小等。
  • child:当前节点的子节点引用。

每个节点存储的数据最大为1MB。

Znode分成四种类型:

  • 临时节点:当创建节点的客户端与zookeeper断开之后,临时节点会被删除。
  • 临时顺序节点
  • 持久节点
  • 持久顺序节点

所谓顺序节点,就是在创建节点的时候,zookeeper根据创建的时间顺序给节点名称进行编号。

事件通知

watch可以理解为注册在特定节点上的触发器,当这个节点发生了改变,也就是调用了create、delete、setData方法的时候,会触发节点上注册的对应事件,请求watch的客户端会接收到异步通知。

一致性

为了防止单机会挂掉的情况,zookeeper维护了一个集群,主从模式,是一主多从结构的,一个master,多个slave。

在更新数据的时候,首先更新到master,然后再同步到slave,读取数据的时候,直接从任意位置读取,为了保持主从数据的一致性,zookeeper采用ZAB协议,类似于paxos。

ZAB协议
zookeeper atomic broadcast,有效解决了zookeeper集群崩溃和主从同步问题。
定义了节点三种状态:选举态、following、Leading。如果master挂了,集群会通过ZAB进行崩溃恢复,选举新的master。

  • 选举阶段:选举master的依据是投票,每个节点会将票投给事务id最大的节点,也就是数据最新的节点。
  • 发现阶段:在选举结束之后,Leading状态的准master会利用纪元号通知各个slave告诉自己是leader,这样避免脑裂。
  • 同步阶段:把master收集到的最新历史事务日志,同步给集群中所有的slave,当有半数slave同步成功,这个master才能成为正式的master。

ZAB数据写入:涉及到broadcast阶段,就是zookeeper常规情况下更新数据的时候,由master广播到所有slave,过程如下。

  1. 客户端发出写入数据请求给任意slave;
  2. slave把写入数据情况转发给master;
  3. master采用二段提交方式,先发送propose广播给slave;
  4. slave接收到propose消息,写入日志成功后,返回ack给master;
  5. 当master接收到半数以上ack消息,返回成功给客户端,并且广播commit给所有slave。

应用场景

  • 分布式锁
  • 服务注册和发现
  • 共享配置和状态信息

实现分布式锁

什么是分布式锁?

为了防止分布式系统中多个进程相互干扰,需要一种分布式协调技术来实现进程调度,其技术核心就是来实现分布式锁。

分布式锁应该具备以下条件:

  • 分布式系统环境下,一个方法在同一时间只能在一个线程执行;
  • 高可用的获取锁与释放锁;
  • 高性能的获取锁与释放锁;
  • 可重入性;
  • 具备失效机制,防止死锁;
  • 非阻塞锁特性,没有获取到锁的线程不会被阻塞,而是直接返回失败。

分布式锁的实现方式:

  • Memcached
  • Redis
  • Zookeeper:天生就是为了实现分布式锁的。
  • Chubby

客户端需要获取锁的时候,就创建指定的Znode,如果其他线程来获取锁,发现节点存在,就不能获得锁。
Znode有临时顺序节点:
利用临时性,当客户端连接的时候,就加锁,当客户端掉了,就解锁了,这样实现了加锁和解锁,同时防止了死锁。
利用有序性,多个进程创建一个锁,可以对锁节点进行编号排序,序号最小的锁节点可以获取资源,然后通过zookeeper的watch机制,当发现比自己小的锁节点被删除了,当前锁就能获取到资源了。

zookeeper于redis实现分布式锁的比较:

分布式锁 优点 缺点
zookeeper 有封装好的框架,容易实现,有等待锁的队列,大大提升竞争锁的效率。 添加和删除节点的性能较低。
Redis Set和Del指令的性能高。 实现复杂,需要考虑超时、原子性、误删等情况;没有等待锁的对垒,只能在客户端进行自旋获取,效率低。

配置

三种工作模式:

  • 单机模式
  • 集群模式:在多台机器上部署,适合线上。
  • 伪集群模式:在一台机器上部署多个zookeeper,适合实验环境。

三种端口号:

  • 2183:客户端连接zookeeper集群所使用的监听端口号。
  • 3888:选举leader使用。
  • 2888:集群内机器通讯使用。

单机模式配置文件

clientPort = 2181
dataDir = /data
dataLogDir = /datalog
tickTime = 2000
  • tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
  • dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
  • clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
  • dataLogDir:保存日志的目录。

集群模式配置文件

tickTime=2000
initLimit=10
syncLimit=5
dataLogDir=/opt/zookeeper/logs
dataDir=/opt/zookeeper/data
clientPort=2181
autopurge.snapRetainCount=500
autopurge.purgeInterval=24
server.1= 192.168.1.148:2888:3888
server.2= 192.168.1.149:2888:3888
server.3= 192.168.1.150:2888:3888
  • initLimit:这个配置项是用来配置zookeeper接受客户端(这里所说的客户端不是用户连接zookeeper服务器的客户端,而是zookeeper服务器集群中连接到leader的follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。
    当已经超过10个心跳的时间(也就是tickTime)长度后 zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 10*2000=20秒。

  • syncLimit:这个配置项标识leader与follower之间发送消息,请求和应答时间长度,最长不能超过多少个tickTime的时间长度,总的时间长度就是5*2000=10秒。

  • 定时清理:
    autopurge.purgeInterval,指定清理频率,单位是小时。
    autopurge.snapRetainCount,这个参数和上面的参数搭配使用,这个参数指定了需要保留的文件数目。

  • maxClientCnxns:限制连接到Zookeeper的客户端数量,限制并发连接的数量,它通过IP来区分不同的客户端。可以用来阻止一些Dos攻击。

  • server.A=B:C:D中的A是一个数字,表示这个是第几号服务器,B是这个服务器的IP地址,C第一个端口用来集群成员的信息交换,表示这个服务器与集群中的leader服务器交换信息的端口,D是在leader挂掉时专门用来进行选举leader所用的端口。

Dubbo

是一款高性能轻量级的开源Java RPC分布式服务框架,提供三大核心能力:

  • 面向接口的远程方法调用。
  • 智能容错和负载均衡。
  • 服务自动注册和发现。

具有特性:

  • 透明远程调用
  • 负载均衡机制
  • 容错重试机制
  • 自动注册发现
  • 性能日志监控
  • 服务治理中心
  • 自动治理中心

Dubbo功能介绍在之前的笔记中可以看到。

服务熔断

什么是服务熔断?
在微服务架构中,根据业务来拆分一个个的服务,服务与服务之间可以通过RPC相互调用,为了保证其高可用,单个服务通常会集群部署,如果单个服务出现了线程阻塞,调用这个服务就会出现阻塞,此时若有大量的请求涌入,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务之间的依赖性导致故障传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的雪崩效应

为了解决服务依赖导致的故障传播,提出了通过服务熔断。

服务熔断配置
利用Hystrix实现服务熔断,需要配置触发熔断的条件和熔断方法。如果对目标服务调用失败,并触发了熔断机制,就是调用熔断方法,防止阻塞。
可以在服务的提供者或者消费者上使用熔断机制。

你可能感兴趣的:(Dubbo,分布式,zookeeper)