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,一经查实,立即删除!

相关文章

linux桌面时区设置,如何在Ubuntu 20.04上设置或更改时区

对于许多与系统相关的任务和进程&#xff0c;使用正确的时区至关重要。 例如&#xff0c;cron守护程序使用系统的时区执行cron作业&#xff0c;而日志文件中的时间戳基于系统的同一时区。在Ubuntu上&#xff0c;系统的时区是在安装过程中设置的&#xff0c;但以后可以轻松更改。…

ironpython2.7.9_IronPython下载

IronPython是一种在 .NET 及 Mono上的 Python 实现&#xff0c;由微软的 Jim Hugunin所发起&#xff0c;是一个开源的项目&#xff0c;基于微软的DLR引擎&#xff1b;托管于微软的开源网站 CodePlex。IronPython 的官方并未实现 Python通用类库&#xff0c;仅实现了部分核心类。…

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

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

天宫初级认证答案_跨境电商人才初级认证试题以及答案

跨境电商人才初级认证试题以及答案跨境电商人才初级认证试题一&#xff0c;单选题(共40题,每题1分,共40分)1.在拍摄反光性产品时,就是从哪个角度进行拍摄的A、正面B、侧面参考答案:B2.信用证就是一种( )信用A、商业B、银行C、民间D、企业参考答案:B3、阿里巴巴专业术语中,MA的全…

Linux打包软件版本带时间,带你写一个 linux 下的打包软件 tar

相信你对 linux 的 .tar.gz 有点熟悉&#xff0c;这就是先 tar 打包(.tar 后缀)&#xff0c;再对此 tar 文件用 gzip 压缩(.tar.gz)的后缀名。值得注意的是&#xff0c; tar 不是压缩软件&#xff0c;它只做把一堆文件/文件夹打包到一个文件(tar 文件)里的事情&#xff0c;而文…

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

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

螺旋测微器b类不确定度_物理实验直测量不确定度评估.ppt

物理实验直测量不确定度评估直接测量不确定度评估 Gauss分布 测量列的平均值、标准差 A类不确定度 t分布 B类不确定度 直接测量的合成不确定度 Gauss分布 也称正态分布。 δ的平均值等于0、方差为σ。 特征&#xff1a; 对称性——大于平均值与小于平均值的概率相等&#xff1b…

python 执行shell_python执行shell命令的方法

python执行shell命令的方法 os模块 os.system方式&#xff1a; import os os.system(top) os.system(cat /proc/cpuinfo) 说明 这个调用相当直接&#xff0c;且是同步进行的&#xff0c;程序需要阻塞并等待返回。 返回值是依赖于系统的&#xff0c;直接返回系统的调用返回值&am…

linux下c语言读取roed文件,如何在Linux系统上安装Android4.4.docx

Android (x86)项目致力于移植 Android系统到X86处理器上&#xff0c;使用户可以更容易的在任何电脑上安装Android。他们通过使用android源码&#xff0c;增加补丁来使 Android能够在X86处理器&#xff0c;笔记本电脑和平板 电脑下工作。前一段时间&#xff0c;项目组发布了最新…

微信小程序setinterval_简单谈谈setTimeout与setInterval

感谢踩过的坑sf社区的第一篇文章。最近在做一个拍卖的微信小程序&#xff0c;用到了定时器setTimout和setInterval,简单谈谈这两个api。setTimeout最常见的用法就是第二种(第三种mdn文档不推荐)&#xff0c;如:var timeoutId setTimeout(function() {console.log(hello world!…

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。无奈将其卸…

transporter上传卡正在交付_【iOS】Xcode11使用Transporter将APP上传到App Store,卡在正在验证APP...

问题&#xff1a;在使用Transporter时&#xff0c;会卡主&#xff0c;一直显示正在验证APP在这里插入图片描述解决方案一&#xff1a;利用V-P-N在这里插入图片描述使用安全上网(V-P-N)&#xff0c;双击打开iTMSTransporter&#xff0c;等待几分钟lichuangMacBook-Pro-3 ~ % /Ap…

python练手经典100例微盘_20个Python练手经典案例,能全做对的人确实很少!

100个Python练手小程序&#xff0c;学习python的很好的资料&#xff0c;覆盖了python中的每一部分&#xff0c;可以边学习边练习&#xff0c;更容易掌握python。 如果你感觉学不会&#xff1f;莫慌&#xff0c;小编推荐大家加入群&#xff0c; 前面548中间377后面875&#xff0…

小红帽linux各功能中英,英文短剧《小红帽》剧本台词完整版---中英对照文本版...

大灰狼和小红帽的故事红帽第一场&#xff1a;小红帽家 妈妈&#xff1a; (妈妈拿着一个篮子&#xff0c;把桌子上的水果放在篮子里) 小红帽唱着歌&#xff0c;欢快地跑进来)Hi,mummy, what are you doing? 嘿&#xff0c;妈妈 你在什么&#xff1f; 妈妈&#xff1a; (一边把水…

uipath循环datatable_UiPath之DataTable转换为List和Array

今天给大家分享一下&#xff0c;如何将DataTable转为List和Array&#xff0c;为此小U也花了不少时间研究&#xff0c;最后发现没有那么复杂。先来说说List和Array的区别&#xff1a;List&#xff1a;就像一个链条&#xff0c;存储数据的空间可以不连续。Array&#xff1a;就像一…

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下载链接】自己…

python使用的编辑器_我用过的最好的python编辑器PyScripter

用了IDLE, PythonWin等几个python编辑器&#xff0c;在代码补全、参数提示等功能上都非常不满意。 终于找到PyScripter并且试用了一下&#xff0c;代码补全、参数提示等功能非常强大。这个功能其实非常重要&#xff0c;可以大大提高开发效率&#xff0c;减少出错。很满意.PyScr…

linux is not unix由来,一些奇怪的 unix 指令名字的由来(转)

一些奇怪的 unix 指令名字的由来(转)[more]一些奇怪的 unix 指令名字的由来awk "Aho Weinberger and Kernighan"这个语言以作者 Al Aho, Peter Weinberger 和 Brian Kernighan 的姓来命名。grep "Global Regular Expression Print"grep 来自 ed 的列印所…