源码分析

public class Env {
public static final Sph sph = new CtSph();
static {
// 在Env类的静态代码块中,
// 触发了一系列初始化操作,
// 其中就包括发送心跳包的初始化。
// 如果Env类一直没有被用到,
// 那么不会触发该初始操作。
// 这也印证了官方的“确保客户端有访问量,
// 才开始向控制台发送心跳包”的说法,
// 因为有访问量就会用到Env类。
InitExecutor.doInit();
}
}

InitExecutor.doInit方法的核心源码:

// 通过SPI获取实现了InitFunc接口的实现类,
// 其中初始化发送心跳包的类是HeartbeatSenderInitFunc。
ServiceLoader<InitFunc> loader = ServiceLoaderUtil.getServiceLoader(InitFunc.class);
List<OrderWrapper> initList = new ArrayList<OrderWrapper>();
// 按照InitOrder注解的值对实现类进行排序
for (InitFunc initFunc : loader) {
RecordLog.info("Found init func: " + initFunc.getClass().getCanonicalName());
insertSorted(initList, initFunc);
}
// 按照顺序调用每一个实现类的init方法,
// 其中也包括HeartbeatSenderInitFunc实现类。
for (OrderWrapper w : initList) {
w.func.init();
RecordLog.info(String.format("Executing %s with order %d",
w.func.getClass().getCanonicalName(), w.order));
}

HeartbeatSenderInitFunc.init方法的源码:

// 通过SPI获取HeartbeatSender的实现类,
// 默认的实现类是SimpleHttpHeartbeatSender。
HeartbeatSender sender = HeartbeatSenderProvider.getHeartbeatSender();
if (sender == null) {
RecordLog.warn("WARN: No HeartbeatSender loaded");
return;
}
// 初始化一个支持定时及周期性任务执行的线程池
initSchedulerIfNeeded();
// 获取发送心跳包的时间间隔,如果没有配置
//则调用HeartbeatSender.intervalMs方法获取。
// 在SimpleHttpHeartbeatSender类中,
// intervalMs返回的数值是10000,也就是10秒。
long interval = retrieveInterval(sender);
setIntervalIfNotExists(interval);
// 设置周期性任务
scheduleHeartbeatTask(sender, interval);

HeartbeatSenderInitFunc.scheduleHeartbeatTask方法的核心源码:

pool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
// 每隔interval毫秒,
// 执行一次sender的sendHeartbeat方法。
sender.sendHeartbeat();
} catch (Throwable e) {
RecordLog.warn("Send heartbeat error", e);
}
}
}, 5000, interval, TimeUnit.MILLISECONDS);

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

SimpleHttpHeartbeatSender.sendHeartbeat方法的核心源码:

// 通过csp.sentinel.dashboard.server配置,
// 获取第一个服务端的IP和端口
InetSocketAddress addr = getAvailableAddress();
if (addr == null) {
return false;
} SimpleHttpRequest request = new SimpleHttpRequest(addr, HEARTBEAT_PATH);
// 构建心跳包的参数,
// 包括客户端IP、端口、应用名称等信息。
request.setParams(heartBeat.generateCurrentMessage());
try {
// 向服务端发送POST请求
SimpleHttpResponse response = httpClient.post(request);
// 状态码为200时,返回true。
if (response.getStatusCode() == OK_STATUS) {
return true;
}
} catch (Exception e) {
RecordLog.warn("Failed to send heartbeat to " + addr + " : ", e);
}
return false;

调用流程

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

分析结果

在客户端首次调用后,默认为每隔10秒向控制台发送心跳包。

可以通过SentinelConfig.setConfig方法修改间隔配置,比如,把心跳包发送时间间隔改为30秒:

SentinelConfig.setConfig(TransportConfig.HEARTBEAT_INTERVAL_MS, "30000");

另外,热更新控制台的IP和端口也有可能实现,比如:先修改csp.sentinel.dashboard.server的配置值,然后再调用SimpleHttpHeartbeatSender的getDefaultConsoleIps方法。

微信公众号:万猫学社

微信扫描二维码

获得更多Java技术干货

通俗易懂的阿里Sentinel源码分析:如何向控制台发送心跳包?的更多相关文章

  1. 2. Sentinel源码分析—Sentinel是如何进行流量统计的?

    这一篇我还是继续上一篇没有讲完的内容,先上一个例子: private static final int threadCount = 100; public static void main(Strin ...

  2. 3. Sentinel源码分析— QPS流量控制是如何实现的?

    Sentinel源码解析系列: 1.Sentinel源码分析-FlowRuleManager加载规则做了什么? 2. Sentinel源码分析-Sentinel是如何进行流量统计的? 上回我们用基于并 ...

  3. 4.Sentinel源码分析— Sentinel是如何做到降级的?

    各位中秋节快乐啊,我觉得在这个月圆之夜有必要写一篇源码解析,以表示我内心的高兴~ Sentinel源码解析系列: 1.Sentinel源码分析-FlowRuleManager加载规则做了什么? 2. ...

  4. 5.Sentinel源码分析—Sentinel如何实现自适应限流?

    Sentinel源码解析系列: 1.Sentinel源码分析-FlowRuleManager加载规则做了什么? 2. Sentinel源码分析-Sentinel是如何进行流量统计的? 3. Senti ...

  5. 6.Sentinel源码分析—Sentinel是如何动态加载配置限流的?

    Sentinel源码解析系列: 1.Sentinel源码分析-FlowRuleManager加载规则做了什么? 2. Sentinel源码分析-Sentinel是如何进行流量统计的? 3. Senti ...

  6. 7.Sentinel源码分析—Sentinel是怎么和控制台通信的?

    这里会介绍: Sentinel会使用多线程的方式实现一个类Reactor的IO模型 Sentinel会使用心跳检测来观察控制台是否正常 Sentinel源码解析系列: 1.Sentinel源码分析-F ...

  7. 阿里sentinel源码研究深入

    1. 阿里sentinel源码研究深入 1.1. 前言 昨天已经把sentinel成功部署到线上环境,可参考我上篇博文,该走的坑也都走了一遍,已经可以初步使用它的限流和降级功能,根据我目前的实践,限流 ...

  8. Sentinel 源码分析- 熔断降级原理分析

    直接从Sentinel 源码demo ExceptionRatioCircuitBreakerDemo看起 直接看他的main函数 public static void main(String[] a ...

  9. Spark RPC框架源码分析(三)Spark心跳机制分析

    一.Spark心跳概述 前面两节中介绍了Spark RPC的基本知识,以及深入剖析了Spark RPC中一些源码的实现流程. 具体可以看这里: Spark RPC框架源码分析(二)运行时序 Spark ...

随机推荐

  1. JavaScript (四) js的基本语法 - - 函数练习、arguments、函数定义、作用域、预解析

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.函数练习 1.求最值 // - 求2个数中的最大值 function getMax(num1, nu ...

  2. ASP.NET MVC 数据传递 视图向控制器传递

    视图向控制器传递 MVC 视图向控制器传递,就是获取用户输入的数据,在去进行操作 好了,我们不多说直接进行我们的案例. 在HomeController类中添加下来方法 [HttpPost] publi ...

  3. Java实现 蓝桥杯 算法提高 小X的购物计划

    试题 算法提高 小X的购物计划 问题描述 小X打算去超市shopping.小X没什么钱,只有N元.超市里有M种物品,每种物品都需要money,在小X心中有一个重要度.有的物品有无限件,有的物品只有几件 ...

  4. Java实现 LeetCode 762 二进制表示中质数个计算置位(位运算+JDK的方法)

    762. 二进制表示中质数个计算置位 给定两个整数 L 和 R ,找到闭区间 [L, R] 范围内,计算置位位数为质数的整数个数. (注意,计算置位代表二进制表示中1的个数.例如 21 的二进制表示 ...

  5. Java实现 LeetCode 695 岛屿的最大面积(DFS)

    695. 岛屿的最大面积 给定一个包含了一些 0 和 1 的非空二维数组 grid . 一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相 ...

  6. Java实现 蓝桥杯 基础练习 闰年判断

    基础练习 闰年判断 时间限制:1.0s 内存限制:256.0MB 提交此题 锦囊1 锦囊2 问题描述 给定一个年份,判断这一年是不是闰年. 当以下情况之一满足时,这一年是闰年: 年份是4的倍数而不是1 ...

  7. Java实现 LeetCode 482 密钥格式化

    482. 密钥格式化 给定一个密钥字符串S,只包含字母,数字以及 '-'(破折号).N 个 '-' 将字符串分成了 N+1 组.给定一个数字 K,重新格式化字符串,除了第一个分组以外,每个分组要包含 ...

  8. Java实现 LeetCode 1两数之和

    1. 两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这 ...

  9. Android中如何使用Listview

    第一步 首先在xml文件中声明一个List View控件,并且标明id (这一步其实不用说,怕自学Android的小白不懂,就好比当初的我,哈哈) <?xml version="1.0 ...

  10. thinkphp5升级thinkphp6完整步骤

    在php.ini文件中  打开  php_openssl扩展,去掉前面的;extension=php_openssl.dll 在phpstudy的WWW目录打开cmd,输入composer creat ...