SDS Heartbeat Mechanism and Strategy Distribution: A Complete Interaction Flow Guide

The SDS heartbeat mechanism and strategy distribution interaction flow involves a bidirectional sync where clients periodically upload runtime metrics to the server while pulling updated downgrade strategies every 5 seconds, ensuring real-time strategy propagation with minimal latency.

In the didi/sds repository, the client-side heartbeat service and server-side strategy distribution work together to maintain a self-healing degradation system. This article breaks down the exact interaction flow between the SDS heartbeat mechanism and strategy distribution, referencing actual source file paths and method implementations from the codebase.

How the SDS Heartbeat Mechanism Uploads Runtime Metrics

Initializing the Heartbeat Service

The interaction begins when the client initializes the singleton heartbeat service. In sds-client/src/main/java/com/didiglobal/sds/client/service/SdsHeartBeatService.java, the createOnlyOne(..) method builds the server URL list and triggers the first pull of strategies.

public static void createOnlyOne(String appGroupName,
                                 String appName,
                                 String serverAddrList) {
    // Singleton initialization logic
    // Builds server URL list and triggers initial strategy pull
}

Periodic Upload of Cycle Statistics

Once initialized, the client periodically uploads runtime statistics. The uploadHeartbeatData() method collects the latest cycle statistics from SdsPowerfulCounterService, builds a HeartbeatRequest, and POSTs it to /sds/heartbeat/add.

public void uploadHeartbeatData() {
    Date now = new Date();
    Map<String, SdsCycleInfo> pointInfoMap = buildPointCycleInfo(now.getTime());

    HeartbeatRequest clientRequest = new HeartbeatRequest();
    clientRequest.setAppGroupName(appGroupName);
    clientRequest.setAppName(appName);
    clientRequest.setIp(IpUtils.getIp());
    clientRequest.setHostname(IpUtils.getHostname());
    clientRequest.setStatisticsCycleTime(
        new Date(DateUtils.getLastCycleEndTime(CYCLE_BUCKET_NUM * BUCKET_TIME, now.getTime())));
    clientRequest.setPointInfoMap(pointInfoMap);
    
    HttpUtils.post(getCurUploadUrl(), param);
}

Server-Side Persistence

On the server side, sds-admin/src/main/java/com/didiglobal/sds/admin/controller/HeartbeatController.java receives the request via the heartbeat() method. This parses the JSON, validates the request, and forwards to HeartbeatService.saveHeartbeatInfo.

In sds-admin/src/main/java/com/didiglobal/sds/admin/service/impl/HeartbeatServiceImpl.java, the saveHeartbeatInfo() method persists the heartbeat data via HeartbeatDao and updates the point-dictionary table, making the metrics visible to the monitoring UI.

Strategy Distribution: Pulling the Latest Downgrade Configuration

Client-Side Strategy Pull Request

Every 5 seconds, the client checks for updated strategies. The updatePointStrategyFromWebServer() method in SdsHeartBeatService sends a HeartbeatRequest containing the client's current version and the list of points it cares about to /sds/heartbeat/pullstrategy.

public void updatePointStrategyFromWebServer() {
    HeartbeatRequest clientRequest = new HeartbeatRequest();
    clientRequest.setAppGroupName(appGroupName);
    clientRequest.setAppName(appName);
    clientRequest.setIp(IpUtils.getIp());
    clientRequest.setHostname(IpUtils.getHostname());
    clientRequest.setVersion(version);                // client's known version
    clientRequest.setPointList(allPointsInUse);       // from SdsPowerfulCounterService
    
    // HTTP POST to /sds/heartbeat/pullstrategy
    HeartBeatResponse response = JSON.parseObject(body, HeartBeatResponse.class);
    if (response.isChanged()) {
        version = response.getVersion();
        resetPointInfo(convertToMap(response.getStrategies()));
    }
}

Server-Side Version Comparison

The server endpoint HeartbeatController#pullPointStrategy() parses the request and calls HeartbeatService.checkAndGetNewestPointStrategy(). In HeartbeatServiceImpl, the server compares the client's version with the stored AppInfo.version.

If the versions differ, the server fetches the latest PointStrategy and PointReturnValue from the database via PointStrategyDao and PointReturnValueDao, builds a HeartBeatResponse with changed=true, and returns the new version and strategy list.

public HeartBeatResponse checkAndGetNewestPointStrategy(HeartbeatRequest heartbeatRequest) {
    // validate request
    AppInfoDO appInfoDO = appInfoDao.queryAppInfo(...);
    if (Objects.equals(heartbeatRequest.getVersion(), appInfoDO.getVersion())) {
        response.setChanged(false);
        return response;
    }
    // version changed → fetch PointStrategy and ReturnValue
    List<PointStrategyDO> pointStrategyDOList = pointStrategyDao.queryPointStrategyBatch(...);
    // build SdsStrategy list
    response.setChanged(true);
    response.setVersion(appInfoDO.getVersion());
    response.setStrategies(strategies);
    return response;
}

Client Cache Refresh

When the client receives a response with isChanged() set to true, it resets its internal maps. The resetPointInfo() method calls SdsStrategyService.resetAll(strategies) to update the strategy cache and SdsDowngradeReturnValueService.reset(strategyMap) to update return-value configuration.

All subsequent downgrade checks use the fresh strategy data from SdsStrategyService, which holds the latest point-to-strategy mapping used by the executor chain during downgrade checks.

Complete Code Example: Setting Up the Heartbeat Client

// ---------------------------------------------------
// 1️⃣ Initialise the SDS client (once per JVM)
String appGroup = "order-service";
String appName  = "order-create";
String servers  = "http://sds-server-1:8080,http://sds-server-2:8080";

SdsClient client = SdsClientFactory.getOrCreateSdsClient(
        appGroup, appName, servers);   // internally calls SdsHeartBeatService.createOnlyOne

// ---------------------------------------------------
// 2️⃣ Start the periodic heartbeat (already scheduled by CycleDataService)
// No extra code needed – uploadHeartbeatData() is invoked automatically every cycle.

// ---------------------------------------------------
// 3️⃣ (Optional) Manually trigger a strategy pull
SdsHeartBeatService.getInstance().updatePointStrategyFromWebServer();

All the heavy lifting is performed inside the heartbeat service; the client developer only needs to create the client once.

Key Source Files in the SDS Repository

File Responsibility Link
sds-client/src/main/java/com/didiglobal/sds/client/service/SdsHeartBeatService.java Core client heartbeat & pull logic view
sds-admin/src/main/java/com/didiglobal/sds/admin/controller/HeartbeatController.java HTTP entry points (add, pullstrategy) view
sds-admin/src/main/java/com/didiglobal/sds/admin/service/impl/HeartbeatServiceImpl.java Business logic for persisting heartbeats & delivering strategies view
sds-client/src/main/java/com/didiglobal/sds/client/service/SdsStrategyService.java In-memory cache of point → SdsStrategy mapping, refreshed on pull view
sds-client/src/main/java/com/didiglobal/sds/client/bean/HeartbeatRequest.java & HeartBeatResponse.java Data contract between client and server request / response
sds-admin/src/main/java/com/didiglobal/sds/admin/dao/PointStrategyDao.java Fetches latest strategies for a given app (interface path) sds-admin/src/main/java/com/didiglobal/sds/admin/dao/PointStrategyDao.java

Summary

  • Bidirectional Sync: The SDS heartbeat mechanism and strategy distribution operate as a continuous loop—clients upload metrics while simultaneously pulling configuration updates.
  • Version-Based Updates: The server compares the client's known version against the stored AppInfo.version to determine if new strategies must be returned, minimizing unnecessary data transfer.
  • Automatic Refresh: Upon detecting a version change, the client invokes SdsStrategyService.resetAll() and SdsDowngradeReturnValueService.reset() to immediately apply new downgrade rules without requiring application restart.
  • 5-Second Pull Interval: The strategy pull runs on a fixed 5-second schedule, ensuring that critical degradation configuration changes propagate to all client instances with minimal latency.

Frequently Asked Questions

How often does the SDS client pull strategy updates?

The SDS client pulls strategy updates every 5 seconds via the updatePointStrategyFromWebServer() method in SdsHeartBeatService. This fixed interval ensures that any changes made in the SDS admin console propagate to client applications with minimal delay, while the version comparison logic prevents unnecessary data processing when configurations remain unchanged.

What data is included in the SDS heartbeat request?

The HeartbeatRequest object sent from client to server includes the application group name, application name, client IP and hostname, current version number, and a map of point statistics (pointInfoMap) containing cycle counters from SdsPowerfulCounterService. When pulling strategies, the request also includes the list of points the client currently cares about (pointList), allowing the server to return only relevant configurations.

How does the server detect if a client needs new strategies?

The server detects the need for new strategies through version comparison in HeartbeatServiceImpl.checkAndGetNewestPointStrategy(). The server queries the AppInfo table to retrieve the current global version for the application group and name, then compares it against the version sent by the client in the HeartbeatRequest. If Objects.equals() returns false, the server fetches the latest PointStrategy and PointReturnValue records from the database and returns them with changed=true.

What happens when the SDS client receives updated strategies?

When the client receives a response with isChanged() set to true, it immediately refreshes its internal caches through the resetPointInfo() method. This invokes SdsStrategyService.resetAll(strategies) to update the point-to-strategy mapping and SdsDowngradeReturnValueService.reset(strategyMap) to update return-value configurations. These changes take effect instantly for all subsequent downgrade checks without requiring application restart, as the executor chain reads directly from the refreshed SdsStrategyService cache.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →