sentinel 端口_Sentinel原理:控制台是如何获取到实时数据的

Sentinel 系列教程,现已上传到 github 和 gitee 中:

  • GitHub:

    https://github.com/all4you/sentinel-tutorial

  • Gitee:

    https://gitee.com/all_4_you/sentinel-tutorial

8d3e55af82b1e222b565c2735e2a6c0d.png

Sentinel 能够被大家所认可,除了他自身的轻量级,高性能,可扩展之外,跟控制台的好用和易用也有着莫大的关系,因为通过控制台极大的方便了我们日常的运维工作。

我们可以在控制台上操作各种限流、降级、系统保护的规则,也可以查看每个资源的实时数据,还能管理集群环境下的服务端与客户端机器。

但是控制台只是一个独立的 spring boot 应用,他本身是没有任何数据的,他的数据都是从其他的 sentinel 实例中获取的,那他是如何获取到这些数据的呢?带着这个疑问我们从源码中寻找答案。

最简单的方法莫过于启动一个控制台的实例,然后从页面上查看每个接口请求的url,然后再到 dashboard 的代码中去深挖下去。

怎么启动控制台,这里就不再详细描述了,大家可以看 Sentinel实战:使用控制台管理规则 这篇文章去了解下,简单的几步就可以启动一个控制台了。

我们就以一个简单的查看【流控规则】为例来描述,点击【流控规则】进入页面后,按F11打开network就可以看到请求的url了,如下图所示:

76a5f763f2aa4b356ab3794f395ffafd.png

可以看到,请求的 url 是 /v1/flow/rules 我们直接在源码中全局搜索 /rules ,为什么不搜索 /v1/flow/rules 呢,因为有可能 url 被拆分成两部分,我们直接搜完整的 url 可能搜不到结果。如下图所示:

11b796f43befa54682c26f9eb34c0d97.png

我们要找的应该就是 FlowControllerV1 这个类了,打开这个类看下类上修饰的值是不是 /v1/flow 如下图所示:

7c62d36cbda2eab0051fffa8de1f780e.png

从图中可以看出来,dashboard 是通过一个叫 SentinelApiClient 的类去指定的 ip 和 port 处获取数据的。这个 ip 和 port 是前端页面直接提交给后端的,而前端页面又是通过 /app/{app}/machines.json 接口获取机器列表的。

连接 dashboard

这里的机器列表中展示的就是所有连接到 dashboard 上的 sentinel 的实例,包括普通限流的 sentinel-core 和集群模式下的 token-server 和 token-client。我们可以回想一下,一个 sentinel-core 的实例要接入 dashboard 的几个步骤:

  1. 引入 dashboard 的依赖

  2. 配置 dashboard 的 ip 和 port

  3. 初始化 sentinel-core,连接 dashboard

sentinel-core 在初始化的时候,通过 JVM 参数中指定的 dashboard 的 ip 和 port,会主动向 dashboard 发起连接的请求,该请求是通过 HeartbeatSender 接口以心跳的方式发送的,并将自己的 ip 和 port 告知 dashboard。这里 sentinel-core 上报给 dashboard 的端口是 sentinel 对外暴露的自己的 CommandCenter 的端口。

HeartbeatSender 有两个实现类,一个是通过 http,另一个是通过 netty,我们看 http 的实现类:

SimpleHttpHeartbeatSender.java

private final HeartbeatMessage heartBeat = new HeartbeatMessage();

private final SimpleHttpClient httpClient = new SimpleHttpClient();

@Override

public boolean sendHeartbeat() throws Exception {

   if (TransportConfig.getRuntimePort() <= 0) {

       RecordLog.info("[SimpleHttpHeartbeatSender] Runtime port not initialized, won't send heartbeat");

       return false;

   }

   InetSocketAddress addr = getAvailableAddress();

   if (addr == null) {

       return false;

   }

   SimpleHttpRequest request = new SimpleHttpRequest(addr, HEARTBEAT_PATH);

   request.setParams(heartBeat.generateCurrentMessage());

   try {

       SimpleHttpResponse response = httpClient.post(request);

       if (response.getStatusCode() == OK_STATUS) {

           return true;

       }

   } catch (Exception e) {

       RecordLog.warn("[SimpleHttpHeartbeatSender] Failed to send heartbeat to " + addr + " : ", e);

   }

   return false;

}

通过一个 HttpClient 向 dashboard 发送了自己的信息,包括 ip port 和版本号等信息。

其中 consoleHost 和 consolePort 的值就是从 JVM 参数 csp.sentinel.dashboard.server 中获取的。

dashboard 在接收到 sentinel-core 的连接之后,就会与 sentinel-core 建立连接,并将 sentinel-core 上报的 ip 和 port 的信息包装成一个 MachineInfo 对象,然后通过 SimpleMachineDiscovery 将该对象保存在一个 map 中,如下图所示:

705e44b9452a9b08d78abed71d74beba.png

定时发送心跳

sentinel-core 连接上 dashboard 之后,并不是就结束了,事实上 sentinel-core 是通过一个 ScheduledExecutorService 的定时任务,每隔 10 秒钟向 dashboard 发送一次心跳信息。发送心跳的目的主要是告诉 dashboard 我这台 sentinel 的实例还活着,你可以继续向我请求数据。

这也就是为什么 dashboard 中每个 app 对应的机器列表要用 Set 来保存的原因,如果用 List 来保存的话就可能存在同一台机器保存了多次的情况。

心跳可以维持双方之间的连接是正常的,但是也有可能因为各种原因,某一方或者双方都离线了,那他们之间的连接就丢失了。

1.sentinel-core 宕机

如果是 sentinel-core 宕机了,那么这时 dashboard 中保存在内存里面的机器列表还是存在的。目前 dashboard 只是在接收到 sentinel-core 发送过来的心跳包的时候更新一次机器列表,当 sentinel-core 宕机了,不再发送心跳数据的时候,dashboard 是没有将 “失联” 的 sentinel-core 实例给去除的。而是页面上每次查询的时候,会去用当前时间减去机器上次心跳包的时间,如果时间差大于 5 分钟了,才会将该机器标记为 “失联”。

所以我们在页面上的机器列表中,需要至少等到 5 分钟之后,才会将具体失联的 sentinel-core 的机器标记为 “失联”。如下图所示:

4fdbd00063e7d10b1acd86d3fa826f5c.png

2.dashboard 宕机

如果 dashboard 宕机了,sentinel-core 的定时任务实际上是会一直请求下去的,只要 dashboard 恢复后就会自动重新连接上 dashboard,双方之间的连接又会恢复正常了,如果 dashboard 一直不恢复,那么 sentinel-core 就会一直报错,在 sentinel-record.log 中我们会看到如下的报错信息:

1f237594d80aa61f0ee55a24c964db88.png

不过实际生产中,不可能出现 dashboard 宕机了一直没人去恢复的情况的,如果真出现这种情况的话,那就要吃故障了。

请求数据

当 dashboard 有了具体的 sentinel-core 实例的 ip 和 port 之后,就可以去请求所需要的数据了。

让我们再回到最开始的地方,我在页面上查询某一台机器的限流的规则时,是将该机器的 ip 和 port 以及 appName 都传给了服务端,服务端通过这些信息去具体的远程实例中请求所需的数据,拿到数据后再封装成 dashboard 所需的格式返回给前端页面进行展示。

具体请求限流规则列表的代码在 SentinelApiClient 中,如下所示:

SentinelApiClient.java

public List<FlowRuleEntity> fetchFlowRuleOfMachine(String app, String ip, int port) {

   String url = "http://" + ip + ":" + port + "/" + GET_RULES_PATH + "?type=" + FLOW_RULE_TYPE;

   String body = httpGetContent(url);

   logger.info("FlowRule Body:{}", body);

   List<FlowRule> rules = RuleUtils.parseFlowRule(body);

   if (rules != null) {

       return rules.stream().map(rule -> FlowRuleEntity.fromFlowRule(app, ip, port, rule))

           .collect(Collectors.toList());

   } else {

       return null;

   }

}

可以看到也是通过一个 httpClient 请求的数据,然后再对结果进行转换,具体请求的过程是在 httpGetContent 方法中进行的,我们看下该方法,如下所示:

private String httpGetContent(String url) {

   final HttpGet httpGet = new HttpGet(url);

   final CountDownLatch latch = new CountDownLatch(1);

   final AtomicReference<String> reference = new AtomicReference<>();

   httpClient.execute(httpGet, new FutureCallback<HttpResponse>() {

       @Override

       public void completed(final HttpResponse response) {

           try {

               reference.set(getBody(response));

           } catch (Exception e) {

               logger.info("httpGetContent " + url + " error:", e);

           } finally {

               latch.countDown();

           }

       }

       @Override

       public void failed(final Exception ex) {

           latch.countDown();

           logger.info("httpGetContent " + url + " failed:", ex);

       }

       @Override

       public void cancelled() {

           latch.countDown();

       }

   });

   try {

       latch.await(5, TimeUnit.SECONDS);

   } catch (Exception e) {

       logger.info("wait http client error:", e);

   }

   return reference.get();

}

从代码中可以看到,是通过一个异步的 httpClient 再结合 CountDownLatch 等待 5 秒的超时时间去获取结果的。

获取数据的请求从 dashboard 中发出去了,那 sentinel-core 中是怎么进行相应处理的呢?看过我其他文章的同学肯定还记得, sentinel-core 在启动的时候,执行了一个 InitExecutor.init 的方法,该方法会触发所有 InitFunc 实现类的 init 方法,其中就包括两个最重要的实现类:

  • HeartbeatSenderInitFunc

  • CommandCenterInitFunc

HeartbeatSenderInitFunc 会启动一个 HeartbeatSender 来定时的向 dashboard 发送自己的心跳包,而 CommandCenterInitFunc 则会启动一个 CommandCenter 对外提供 sentinel-core 的数据服务,而这些数据服务是通过一个一个的 CommandHandler 来提供的,如下图所示:

57f86deb5ea14f8247d736c85b13cf52.png

总结

现在我们已经知道了 dashboard 是如何获取到实时数据的了,具体的流程如下所示:

1.首先 sentinel-core 向 dashboard 发送心跳包

2.dashboard 将 sentinel-core 的机器信息保存在内存中

3.dashboard 根据 sentinel-core 的机器信息通过 httpClient 获取实时的数据

4.sentinel-core 接收到请求之后,会找到具体的 CommandHandler 来处理

5.sentinel-core 将处理好的结果返回给 dashboard

思考

1.数据安全性

sentinel-dashboard 和 sentinel-core 之间的通讯是基于 http 的,没有进行加密或鉴权,可能会存在数据安全性的问题,不过这些数据并非是很机密的数据,对安全性要求并不是很高,另外增加了鉴权或加密之后,对于性能和实效性有一定的影响。

2.SentinelApiClient

目前所有的数据请求都是通过 SentinelApiClient 类去完成的,该类中充斥着大量的方法,都是发送 http 请求的。代码的可读性和可维护性不高,所以需要对该类进行重构,目前我能够想到的有两种方法:

1)通过将 sentinel-core 注册为 rpc 服务,dashboard 就像调用本地方法一样去调用 sentinel-core 中的方法,不过这样的话需要引入服务注册和发现的依赖了。

2)通过 netty 实现私有的协议,sentinel-core 通过 netty 启动一个 CommandCenter 来对外提供服务。dashboard 通过发送 Packet 来进行数据请求,sentinel-core 来处理 Packet。不过这种方法跟目前的做法没有太大的区别,唯一比较好的可能就是不需要为每种请求都写一个方法,只需要定义好具体的 Packet 就好了。

更多原创好文

请关注「逅弈逐码」

2b31d6cda77da562457d40ffdb802120.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/533818.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 最小二乘回归 高斯核_「机器学习」一文读懂线性回归、岭回归和Lasso回归...

点击上方蓝色字体&#xff0c;关注AI小白入门哟作者 | 文杰编辑 | yuquanle本文介绍线性回归模型&#xff0c;从梯度下降和最小二乘的角度来求解线性回归问题&#xff0c;以概率的方式解释了线性回归为什么采用平方损失&#xff0c;然后介绍了线性回归中常用的两种范数来解决过…

优先队列默认是小顶堆吗_一分钟带你读懂什么是堆?

堆其实就是一种特殊的队列——优先队列。 普通的队列游戏规则很简单&#xff1a;就是先进先出&#xff1b;但这种优先队列搞特殊&#xff0c;不是按照进队列的时间顺序&#xff0c;而是按照每个元素的优先级来比拼&#xff0c;优先级高的在堆顶。 这也很容易理解吧&#xff0c;…

python 注释一段话_Python快速入门(一)

引言Python作为一个&#xff0c;目前最火的编程语言之一&#xff0c;已经渗透到了各行各业。它易学好懂&#xff0c;拥有着丰富的库&#xff0c;功能齐全。人生苦短&#xff0c;就用Python。这个快速入门系列分为六篇&#xff0c;包含了Python大部分基础知识&#xff0c;每篇阅…

linux ibus获取窗体位置,Ubuntu 12.04 显示ibus 的输入框

在虚拟机中安装了Ubuntu 12.04&#xff0c;系统是英文版本的&#xff0c;我能接受&#xff0c;但是苦于没有中文输入法。起先&#xff0c;我是安装SCIM&#xff0c;结果我折腾了半天&#xff0c;发现其只能在lib-office下使用。firefox,文字编辑器中都不能调出SCIM。无奈将其卸…

python批量下载文件教程_Python抓包菜鸟教程:批量下载图片的方法,电脑和手机都能用...

笔者看上了一组图集&#xff0c;然后准备一张一张下载时&#xff0c;瞄了一眼&#xff0c;这组图集还有100&#xff0c;好吧&#xff0c;我酸了。 笔者就是试试工具&#xff0c;你们别像我这样用&#xff0c;这么好的工具&#xff0c;做自媒体&#xff0c;那绝对了那如何批量下…

esxi挂载Linux的nfs盘,ESXi安装centos7挂载群晖NFS

前段时间折腾了ESXi&#xff0c;然后无尽的折腾接踵而来&#xff0c;今天要说的是如何安装centos7并挂载群晖虚拟机的NFS共享文件夹直接步入正题&#xff01;先是下载centos7镜像&#xff0c;因为我是用来当服务器的&#xff0c;所以只需要minimal版即可【centos下载链接】自己…

传统的6d位姿估计fangfa1_李飞飞团队最新论文:基于anchor关键点的类别级物体6D位姿跟踪...

点击上方“3D视觉工坊”&#xff0c;选择“星标”干货第一时间送达简介作者提出了一种基于RGB-D的深度学习方法6PACK&#xff0c;能够实时的跟踪已知类别物体。通过学习用少量的3D关键点来简洁地表示一个物体&#xff0c;基于这些关键点&#xff0c;通过关键点匹配来估计物体在…

安卓system镜像分区_玩机爱好者想要的PT分区到底是什么?可以使现有的安卓系统更快!...

小编第一次看见PT分区这个词。就比较好奇他到底是什么神仙技术。今天&#xff0c;小编给大家科普一下&#xff0c;可能小编理解的也不是特别准确&#xff0c;请各位谅解&#xff01;&#xff01; 欢迎关注小编。各位玩机爱好者总是沉浸在各种ROM包、第三发Rec&#xff0c;以及各…

python求和1到100_python等差数列求和公式前 100 项的和实例

python等差数列求和公式前 100 项的和实例 最近跑去学了下python,一个很简单的题&#xff0c;结果发现数学公示忘了&#xff0c;在不用for循环的情况下居然有些懵&#xff0c;记录为下.. 题&#xff1a;等差数列可以定义为每一项与它的前一项的差等于一个常数&#xff0c;可以用…

jupyter kernel_新乡联通案例分享:Jupyter开发环境配置的常用技巧

Jupyter开发环境配置的常用技巧新乡联通网管中心 邢少华Python开发环境中&#xff0c;大部分人使用的是Jupyter&#xff0c;在Jupyter中有几个令人困扰的问题&#xff1a;1. Jupyter的默认打开目录如何修改2. Jupyter默认使用的浏览器如何修改3. 好用的Jupyter插件如何安装4.…

二叉树 中序遍历 python_LeetCode 105 树 从前序与中序遍历序列构造二叉树(Medium)

17(105) 从前序与中序遍历序列构造二叉树(Medium)描述根据一棵树的前序遍历与中序遍历构造二叉树。注意: 你可以假设树中没有重复的元素。示例例如&#xff0c;给出前序遍历 preorder [3,9,20,15,7] 中序遍历 inorder [9,3,15,20,7]返回如下的二叉树&#xff1a;3/ 9 20/ 1…

计算payload长度c语言,C语言0长度数组(可变数组/柔性数组)详解

1 零长度数组概念众所周知, GNU/GCC 在标准的 C/C 基础上做了有实用性的扩展, 零长度数组(Arrays of Length Zero) 就是其中一个知名的扩展.多数情况下, 其应用在变长数组中, 其定义如下struct Packet{ int state; int len; char cData[0]; //这里的0长结构体就为变长结构体提供…

go语言调用c 的头文件 so,golang 学习(10): 使用go语言调用c语言的so动态库-Go语言中文社区...

一、前言最近在学习go&#xff0c;因为需要调用c语言打包成的so动态库里面的方法&#xff0c;避免自己再去造轮子&#xff0c;所以想直接使用golang调用so&#xff0c;但是参考了其他博客大佬写的&#xff0c;我每一步原封不动的写下来&#xff0c;结果都是一堆错误&#xff0c…

android 开机动画 渐变,[Parallax Animation]实现知乎 Android 客户端启动页视差滚动效果...

前言Parallax Scrolling (视差滚动)&#xff0c;是一种常见的动画效果。视差一词来源于天文学&#xff0c;但在日常生活中也有它的身影。在疾驰的动车上看风景时&#xff0c;会发现越是离得近的&#xff0c;相对运动速度越快&#xff0c;而远处的山川河流只是缓慢的移动着&…

python可以做计量分析吗_技术分享 - python数据分析(2)——数据特征分析(上)...

1 分布分析 分布分析能揭示数据的分布特征和分布类型。对于定量数据&#xff0c;欲了解其分布形式是对称的还是非对称的&#xff0c;发现某些特大或特小的可疑值&#xff0c;可通过绘制频率分布表、绘制频率分布直方图、绘制茎叶图进行直观地分析&#xff1b;对于定性分类数据&…

matlab的7.3版本是什么_乐建工程宝V6.3版本升级说明公告

尊敬的乐建工程宝客户&#xff1a;您好&#xff01;为了给客户提供更加优质的产品和服务&#xff0c;我司已于2019年11月20日开始乐建工程宝V6.3版本升级服务。目前&#xff0c;Android系统各应用市场已基本审核完毕&#xff0c;iOS系统已上传AppStore&#xff0c;目前苹果官方…

origin设置不同区域的颜色_[测试狗]Origin入门教程(二十四):效率翻倍小技巧——修改默认字体...

在使用Origin的时候&#xff0c;对于每次绘图都需要更改字体觉得很麻烦&#xff0c;因为Origin默认的字体为Arial&#xff0c;但是我们常用的字体一般为Times New Roman&#xff0c;在下拉框的很底部&#xff0c;每次更改都很浪费时间。那为什么不把他设置成默认字体呢&#xf…

cgi web 调用多次启动_全面了解CGI、FastCGI、PHPFPM

一、抛个砖1、Web Server传递数据的方法正式说CGI之前&#xff0c;先来了解一下Web Server传递数据的另外一种方法&#xff1a;PHP Module加载方式。相信都会想起Apache吧&#xff0c;初学php时&#xff0c;在windows上安装完php和Apache之后&#xff0c;为了让Apache能够解析p…

mysql 按月和年累加_广西柳州市市场监管局公布市2020年11月(第一批)电梯按需维保试点名单...

中国质量新闻网讯 根据《柳州市改进电梯维护保养模式试点工作方案》&#xff0c;近日&#xff0c;广西柳州市市场监管局公布柳州市首批按需维保试点电梯名单&#xff0c;冠亚蓝湾国际小区和南庆安置小区共46台电梯成为首批试点电梯&#xff0c;标志着柳州市全面启动了按需维保改…

上传 mp4 格式判断_视频如何转换成通用的MP4格式?按下这个键,10秒就能搞定...

我们在网上下载视频的时候&#xff0c;有很多的视频都是无法播放的&#xff0c;或者是需要特定的播放器才可以播放。其实&#xff0c;只要把这些视频的格式转换成通用的MP4格式即可。如果你还不知道怎么转换视频格式&#xff0c;下面就教大家两个小方法&#xff0c;百试百灵。一…