DBLE Heartbeat Detection Module: Purpose and Source Code Analysis
This article explains the purpose of DBLE's heartbeat detection, including high‑availability switching, read load balancing, and idle connection management, and provides a detailed walkthrough of the module's source code—from the Scheduler initialization to the MySQLHeartbeat implementation—illustrating how the system monitors MySQL instance status.
Overview The DBLE heartbeat detection module ensures three main functions: (1) high‑availability switching of write nodes, (2) read‑load balancing based on the latest heartbeat status and optional slave‑threshold configuration, and (3) management of idle connections by sending PING packets. The article focuses on the first two functions.
Heartbeat Module Entry Point The periodic heartbeat task starts in Scheduler#init, which schedules dataSourceHeartbeatPeriod (default 10 seconds) via scheduler.scheduleAtFixedRate(...). This method returns a Runnable created in Scheduler#dataSourceHeartbeat.
scheduler.scheduleAtFixedRate(dataSourceHeartbeat(), 0L, system.getDataNodeHeartbeatPeriod(), TimeUnit.MILLISECONDS);
private Runnable dataSourceHeartbeat() {
return new Runnable() {
@Override
public void run() {
timerExecutor.execute(new Runnable() {
@Override
public void run() {
if (!DbleServer.getInstance().getConfig().isDataHostWithoutWR()) {
Map<String, AbstractPhysicalDBPool> hosts = DbleServer.getInstance().getConfig().getDataHosts();
for (AbstractPhysicalDBPool host : hosts.values()) {
host.doHeartbeat();
}
}
}
});
}
};
}AbstractPhysicalDBPool#doHeartbeat This abstract method has two concrete implementations: PhysicalDNPoolSingleWH (single write host) and PhysicalDBPool (multiple write hosts). Both implementations iterate over all data sources and invoke doHeartbeat() on each.
PhysicalDNPoolSingleWH#doHeartbeat The method loops through allSourceMap and calls source.doHeartbeat() for each non‑null PhysicalDatasource. If a source is null, a warning is logged.
public void doHeartbeat() {
for (PhysicalDatasource source : allSourceMap.values()) {
if (source != null) {
source.doHeartbeat();
} else {
LOGGER.warn(hostName + " current dataSource is null!");
}
}
}MySQLDatasource#doHeartbeat This concrete class (the only implementation of PhysicalDatasource in DBLE) checks recovery time, then calls heartbeat.heartbeat() if the heartbeat is not stopped.
public void doHeartbeat() {
if (TimeUtil.currentTimeMillis() < heartbeatRecoveryTime) {
return;
}
if (!heartbeat.isStop()) {
heartbeat.heartbeat();
}
}MySQLHeartbeat#heartbeat The method acquires a lock, creates a MySQLDetector if needed, and executes a HeartbeatSQLJob that runs the configured heartbeat SQL against the MySQL connection. It records send/receive timestamps and updates status variables.
public void heartbeat() {
reentrantLock.lock();
try {
if (isChecking.compareAndSet(false, true)) {
if (detector == null || detector.isQuit()) {
detector = new MySQLDetector(this);
detector.heartbeat();
} else {
detector.heartbeat();
}
} else {
if (detector != null) {
if (detector.isQuit()) {
isChecking.compareAndSet(true, false);
} else if (detector.isHeartbeatTimeout()) {
setResult(TIMEOUT_STATUS);
}
}
}
} finally {
reentrantLock.unlock();
}
}MySQLDetector#onResult After the SQL query finishes, this callback records the round‑trip time, examines the result map, and sets the status in MySQLHeartbeat (e.g., normal, error, or slave‑behind‑master delay) based on the configured heartbeat mode (slave, cluster, read‑only, or default).
public void onResult(SQLQueryResult<Map<String, String>> result) {
lastReceivedQryTime = System.currentTimeMillis();
heartbeat.getRecorder().set((lastReceivedQryTime - lastSendQryTime));
if (result.isSuccess()) {
PhysicalDatasource source = heartbeat.getSource();
Map<String, String> resultResult = result.getResult();
if (source.getHostConfig().isShowSlaveSql()) {
setStatusBySlave(source, resultResult);
} else if (source.getHostConfig().isShowClusterSql()) {
setStatusByCluster(resultResult);
} else if (source.getHostConfig().isSelectReadOnlySql()) {
setStatusByReadOnly(source, resultResult);
} else {
setStatusForNormalHeartbeat(source);
}
} else {
heartbeat.setResult(MySQLHeartbeat.ERROR_STATUS);
}
}Result Usage The final status and slave‑behind‑master latency are accessed via MySQLHeartbeat#getStatus and MySQLHeartbeat#getSlaveBehindMaster. These values drive DBLE's data‑source switching and read/write separation logic, fulfilling the first two heartbeat purposes described earlier.
Conclusion The article has detailed the DBLE heartbeat detection module, covering its functional goals and a step‑by‑step source‑code walkthrough, helping readers understand how DBLE monitors MySQL instance health and integrates the results into high‑availability and load‑balancing mechanisms.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Aikesheng Open Source Community
The Aikesheng Open Source Community provides stable, enterprise‑grade MySQL open‑source tools and services, releases a premium open‑source component each year (1024), and continuously operates and maintains them.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
