天天看点

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

目录

一、前言

二、总体设计方案

1、什么是Ignite

2、Ignite构建控制台集群

3、拉取客户端流量数据方案

4、客户端心跳方案

5、控制台集群登录方案

三、具体实现与改造

1、Ignite集群实现

2、登录实现

3、选举实现

4、规则存储实现

四、开源信息

1、开源地址

2、如何启动

3、登录界面

五、惯例

一、前言

最近在项目中使用到了Sentinel来做限流与降级,并封装了一套切合项目的自动限流降级框架。在使用Sentinel的过程中发现如下两个问题:

1、Sentinel提供的控制台只能够支持单机部署,存在单点故障的问题

2、Sentinel默认只支持单机限流,如果需要支持集群限流则要自己实现并提供Token Server。

为了让Sentinel能够完美的应用到项目中,因此我们必须要解决这两个棘手的问题。经过分析选型我们最终设计出了如下方案:

1、使用Ignite来解决控制台故障的问题

2、使用Raft协议来构建高可用性能的Token Server

当前项目已经完成了Ignite协议的控制台集群方案的设计元开发,而Token Server方案还在开发中。因此文本先介绍基于Ignite的控制台集群方案。

PS:该项目已经开源,开源信息在文章末尾。后续Token Server完成之后也将为大家开源。

二、总体设计方案

1、什么是Ignite

Ignite是以内存为中心的分布式数据库、缓存和处理平台,用于事务性、分析性和流式工作负载,提供内存速度在PB级规模。

Ignite 为应用和不同的数据源之间提供一个高性能、分布式内存中数据组织管理的框架。它包含如下组件:

1.高级的集群化

2.数据网格(JCache)

3.流计算和CEP

4.计算网格

5.服务网格

6.Ignite文件系统

7.分布式数据结构

8.分布式消息

9.分布式事件

10.Hadoop加速器

11.Spark共享RDD

总的来说其功能很强大,但是为了实现控制台集群,我们只需要知道Ignite可以做分布式缓存系统并且提供集群节点发现功能,且能够支持通过SQL查询缓存数据即可。

如果大家想要深入了解Ignite这个强大的组件。请访问其官网:https://ignite.apache.org/

2、Ignite构建控制台集群

由于Ignite提供集群发现功能,且能够支持基于内存的分布式缓存(Ignite的分布式缓存支持持久化,只是我们这里没有使用)。因此就可以用Ignite来构建控制台集群,同时将所有控制台需要临时数据都存到分布式集群中即可。整体架构图如下:

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

核心实现如下:

利用Ignite构建分布式内存集群,所有数据都存到内存集群中

在控制台集群前部署负载均衡,让浏览器通过负载均衡随机访问到控制台机器。

3、拉取客户端流量数据方案

熟悉Sentinel原生控制台原理的同学应该都知道,控制台上可以展示客户端的资源限流详情,如下图。而这个流量信息是控制台定时通过Http接口从客户端拉取过来的。当我们将控制台修改成集群之后,默认所有机器都会去拉取流量数据并存到Ignite分布式缓存中,这样就会导致流量数据不准。因此我们需要选举一台机器出来复制拉取数据。我们的方案是:利用Ignite自带的简单选举功能实现选举(官方文档:https://apacheignite.readme.io/docs/leader-election

)。通过这个功能,我们可以得到当前集群中最新或者最老的节点作为Leader。有了这个功能,我们能轻松的从集群中选举出Leader。

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

4、客户端心跳方案

由于默认的客户端心跳会发送到一个控制台。并且不会处理控制台失联宕机等场景。因此我们需要修改客户端的心跳发送逻辑,具体方案是采用随机选择控制台的方案。即随机选择配置控制台集群中的一台发送心跳,如果发送失败则自动选择下一台控制台机器。

5、控制台集群登录方案

默认控制台登录通过jsessionid实现,并将登录信息存储到session中。在集群方案中,我们使用UUID为用户生成一个唯一id作为其用户ID,并存储到cookie中。同时将其登录信息存储到分布式缓存集群中。这样每次访问只需要从cookie中获取用户ID,然后根据ID从分布式缓存集群获取到登录信息即可。

三、具体实现与改造

1、Ignite集群实现

基于Ignite分布式缓存,我们主要设计了三个缓存:

Machine:用于存储客户端机器信息。每次客户端发送心跳之后就会更新该缓存。

Metrics:用户存储客户端的流量信息。当Leader拉取到客户端的流量信息之后,就存储到该缓存中。缓存有效时间5分钟(因为控制台默认只展示过去5分钟的流量数据)。

Authority:用户登录信息,用户登录之后就存储到该缓存中。每次校验就从缓存中获取数据。缓存有效时间10分钟(10分钟后重新登录)。

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

2、登录实现

前面已经介绍过基本实现,本身实现也比较简单。这里直接贴代码吧。

登录成功后,创建cookie,并写入用户信息到缓存:

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

访问时从缓存中拉取数据判断用户登录状态是否有效:

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

3、选举实现

前面原理篇我们已经介绍过了,选举是通过获取集群中最新或者最老的节点作为Leader实现的。我的方案中使用最老的节点,这样可以防止在启动的过程中Leader不断变化。

那我们只需要在Ignite节点启动时候判断一下自己是否为Leader(最老节点)就OK了么?当然不是。因为如果Leader节点宕机了,集群中其他节点还必须要选举出一个新的Leader来。因此我们需要对集群中的节点进行监听。好在Ignite本身提供了事件机制。其可以监听Ignite内部的各类事件,如:节点变更,缓存变更,任务变更等等。所以我们可以利用其节点变更来得到当前节点Leader失联的消息即可。

该方案的选举过程和普通的选举过程有些区别。普通的选举是判断Leader节点挂了,自己启动选举流程。而Ignite的选举是判断到某个节点挂了,然后判断一下自己是否变成了最老的节点,如果是,则标记自己为Leader节点。下面是节点收到节点变更事件后的选举机制核心代码:

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

当机器变成Leader之后,其需要做如下两件事情:

a、不停从客户端机器拉取流量数据

b、将控制台集群所有地址通知给客户端。我们在实际项目中使用的统一配置中心通知。而开源代码中则没有提供具体实现。如有需要可以自行实现,具体实现请查看类:DashboardNodeRegister。

如下是为大家预留的控制台地址注册逻辑,如果需要实现,可修改该代码逻辑即可。

4、规则存储实现

默认的控制台中,每次查询到规则信息都存储在内存中由InMemoryRuleRepositoryAdapter实现。而在集群方案中,我们则将所有的规则数据存储到对应的缓存(流控,降级,系统等)中。为此我们重写了InMemoryRuleRepositoryAdapter,实现了其所有接口方法,让所有的操作都基于分布式缓存实现。该实现类为IgniteRuleRepositoryAdapter。同时每个规则都继承IgniteRuleRepositoryAdapter。结构关系如下图:

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

四、开源信息

1、开源地址

https://github.com/lifeofcoder/AutoLimiter

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

2、如何启动

集群控制台只需要直接打包部署autolimiter-dashboard-cluster工程即可。

application.properties文件中只需要修改配置ignite.register.addresses。填上控制台集群中所有机器的IP即可。其他配置和Sentinel的默认控制台完全一样。

默认的用户名和密码为:sentinel/ sentinel。

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

3、登录界面

由于没有对页面和功能做任何修改,因此其界面和原生的Sentinel控制台界面没有差别。

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

五、惯例

如果你对本文有任何疑问或者高见,欢迎添加公众号共同交流探讨(添加公众号可以获得”Java高级架构“上10G的视频和图文资料哦)。

【开源】Sentinel控制台集群方案(使用Ignite解决单点故障问题)目录一、前言二、总体设计方案三、具体实现与改造四、开源信息五、惯例

继续阅读