Skip to content

Conversation

@killme2008
Copy link
Contributor

@killme2008 killme2008 commented May 27, 2025

Motivation:

Retains only essential information while awaiting a response during replication.

Modification:

Currently, replicator sends entries asynchronously, but the RPC invocation callback retains the entire request in memory, delaying its release. This is especially problematic for large requests, as it leads to high memory usage.

This PR introduces RpcRequestHeader for InstallSnapshotRequest and AppendEntriesRequest, which retains only essential information while awaiting a response. This should significantly reduce memory consumption during replication.

Result:

Fixes #.

If there is no issue then describe the changes introduced by this PR.

Summary by CodeRabbit

  • Refactor
    • Improved internal handling of RPC request metadata to reduce memory usage and decouple response processing from full request messages. No changes to user-facing functionality.
  • New Features
    • Introduced a new abstraction to encapsulate request metadata, enhancing efficiency in RPC response handling.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 27, 2025

Walkthrough

The changes introduce a new RpcRequestHeader class to encapsulate essential metadata from Raft RPC requests, replacing direct usage of protobuf request messages in the Replicator class. Method signatures and response handling logic in Replicator are updated to utilize this lightweight header abstraction, reducing coupling to protocol buffer messages. Corresponding test code is updated to pass RpcRequestHeader instances instead of raw request messages.

Changes

File(s) Change Summary
jraft-core/src/main/java/com/alipay/sofa/jraft/core/Replicator.java Refactored to use RpcRequestHeader instead of protobuf request messages in RPC response handling; updated method signatures and internal logic accordingly.
jraft-core/src/main/java/com/alipay/sofa/jraft/core/RpcRequestHeader.java Introduced new RpcRequestHeader class to encapsulate key metadata from Raft RPC requests.
jraft-core/src/test/java/com/alipay/sofa/jraft/core/ReplicatorTest.java Updated tests to replace protobuf request messages with RpcRequestHeader instances when invoking onRpcReturned.

Sequence Diagram(s)

sequenceDiagram
    participant Leader
    participant Replicator
    participant Follower

    Leader->>Replicator: Create AppendEntriesRequest/InstallSnapshotRequest
    Replicator->>RpcRequestHeader: Extract metadata (prevLogIndex, prevLogTerm, entriesCount, dataBytes, meta)
    Replicator->>Follower: Send RPC (AppendEntries/InstallSnapshot)
    Follower-->>Replicator: Responds with RPC Response
    Replicator->>Replicator: Handle response using RpcRequestHeader
Loading

Poem

In the warren of code, a header appears,
Wrapping metadata, light as rabbit ears.
No more protobuf bloat, just the facts we require,
For replicators swift, and clusters that never tire.
With headers in paw, we hop on our quest—
Refactored and nimble, our Raft runs its best!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b9c2b57 and d7f5064.

📒 Files selected for processing (1)
  • jraft-core/src/main/java/com/alipay/sofa/jraft/core/RpcRequestHeader.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • jraft-core/src/main/java/com/alipay/sofa/jraft/core/RpcRequestHeader.java
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: test_storage_java_impl
  • GitHub Check: test_rheakv_core
  • GitHub Check: test_jraft_core
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR reduces memory consumption during replication by introducing a new RpcRequestHeader that retains only essential metadata from requests.

  • Introduces RpcRequestHeader to encapsulate minimal request data
  • Updates replicator methods and callbacks to utilize RpcRequestHeader instead of holding full request objects

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
jraft-core/src/main/java/com/alipay/sofa/jraft/core/RpcRequestHeader.java Added a new class to store minimal header data for RPC requests
jraft-core/src/main/java/com/alipay/sofa/jraft/core/Replicator.java Modified request handling and callbacks to use RpcRequestHeader for improved memory efficiency

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
jraft-core/src/main/java/com/alipay/sofa/jraft/core/RpcRequestHeader.java (2)

21-26: Update the class documentation to reflect both request types.

The class comment mentions only AppendEntriesRequest, but the implementation also handles InstallSnapshotRequest (via the snapshot constructor). Update the documentation to accurately reflect this dual purpose.

 /**
- * AppendEntriesRequest header, which only keeps the request metadata info without the data.
+ * RPC request header for AppendEntriesRequest and InstallSnapshotRequest, which only keeps the request metadata info without the data.
  * It's designed to reduce the memory consumption for RPC.
  * @author dennis
  *
  */

52-70: Consider making getter visibility consistent.

The getMeta() method is public while all other getters are package-private. Since the class itself is package-private, consider making all getters package-private for consistency.

-    public SnapshotMeta getMeta() {
+    SnapshotMeta getMeta() {
         return meta;
     }
jraft-core/src/main/java/com/alipay/sofa/jraft/core/Replicator.java (1)

823-825: Extract duplicated RpcRequestHeader creation logic.

The logic for creating RpcRequestHeader from AppendEntriesRequest is duplicated. Consider extracting this to a helper method to follow the DRY principle.

Add a helper method:

private static RpcRequestHeader createHeaderFromAppendEntriesRequest(final AppendEntriesRequest request) {
    return new RpcRequestHeader(
        request.getPrevLogIndex(),
        request.getPrevLogTerm(),
        request.getEntriesCount(),
        request.getData() != null ? request.getData().size() : 0
    );
}

Then use it in both locations:

-RpcRequestHeader header = new RpcRequestHeader(request.getPrevLogIndex(),
-    request.getPrevLogTerm(), request.getEntriesCount(), request.getData()!=null?request.getData().size():0);
+RpcRequestHeader header = createHeaderFromAppendEntriesRequest(request);

Also applies to: 1693-1694

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94c0a41 and 5e4a51f.

📒 Files selected for processing (2)
  • jraft-core/src/main/java/com/alipay/sofa/jraft/core/Replicator.java (9 hunks)
  • jraft-core/src/main/java/com/alipay/sofa/jraft/core/RpcRequestHeader.java (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
jraft-core/src/main/java/com/alipay/sofa/jraft/core/RpcRequestHeader.java (1)
jraft-core/src/main/java/com/alipay/sofa/jraft/entity/RaftOutter.java (2)
  • RaftOutter (22-3114)
  • SnapshotMeta (1818-3070)
🔇 Additional comments (5)
jraft-core/src/main/java/com/alipay/sofa/jraft/core/RpcRequestHeader.java (1)

27-71: LGTM! Well-designed class for memory optimization.

The immutable design with final fields is excellent for thread safety and aligns well with the PR's objective to reduce memory consumption. The class effectively encapsulates only the essential metadata needed for RPC response handling.

jraft-core/src/main/java/com/alipay/sofa/jraft/core/Replicator.java (4)

428-445: Good refactoring to reduce memory footprint.

The change from Message to RpcRequestHeader in the RpcResponse class effectively reduces memory consumption by avoiding retention of full request payloads during RPC processing.


696-697: Correct usage of the snapshot constructor.

The code properly creates a lightweight RpcRequestHeader containing only the snapshot metadata, which is sufficient for handling the install snapshot response.


1411-1412: Efficient use of pre-calculated data size.

Good improvement - using getDataBytes() from the header avoids redundant calculations and potential null pointer issues.


1261-1379:

Details

✅ Verification successful

Verify that all request field accesses are properly migrated.

The refactoring correctly updates all method signatures and RPC callbacks to use RpcRequestHeader. The changes maintain the same functionality while reducing memory usage.

Let me verify that no direct accesses to the original request fields remain in the response handling code:


🏁 Script executed:

#!/bin/bash
# Description: Check for any remaining direct accesses to protobuf request fields in response handling

# Search for potential missed conversions in Replicator.java
echo "Checking for potential missed request field accesses in response handling..."
rg -A 5 -B 5 "request\.(get|has)" jraft-core/src/main/java/com/alipay/sofa/jraft/core/Replicator.java | grep -E "(onRpcReturned|onAppendEntriesReturned|onInstallSnapshotReturned)" -A 10 -B 10 || echo "No concerning patterns found"

# Verify all RpcRequestHeader usages are consistent
echo -e "\nVerifying RpcRequestHeader usage patterns..."
ast-grep --pattern 'new RpcRequestHeader($$$)' jraft-core/src/main/java/com/alipay/sofa/jraft/core/Replicator.java

Length of output: 5906


All request field accesses properly migrated

No direct accesses to protobuf request fields remain in response handling. The only remaining request.getXxx() calls occur within RPC callbacks to construct the new RpcRequestHeader, which is intentional.

  • In onAppendEntriesReturned and onInstallSnapshotReturned, request refers to RpcRequestHeader, not the original protobuf object.
  • All direct protobuf field accesses are confined to header construction in the RPC closures.

No further changes needed.

@killme2008 killme2008 requested a review from Copilot May 27, 2025 22:21
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR reduces memory usage in the replication module by replacing full RPC request retention with a lightweight header. It introduces a new RpcRequestHeader type and updates both production code and tests to use it.

  • Added RpcRequestHeader to capture only essential metadata for AppendEntries and Snapshot RPCs.
  • Refactored Replicator and its inner RpcResponse to carry RpcRequestHeader instead of full Message requests.
  • Updated unit tests to wrap requests with the new header type.

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
RpcRequestHeader.java New header class storing only metadata for RPC requests
Replicator.java Replaced Message request parameters with RpcRequestHeader and updated metrics calls
ReplicatorTest.java Updated test calls to pass RpcRequestHeader instances
Comments suppressed due to low confidence (2)

jraft-core/src/main/java/com/alipay/sofa/jraft/core/RpcRequestHeader.java:33

  • [nitpick] The field name dataBytes suggests a byte length but it actually counts entries; consider renaming to dataCount or similar for clarity.
final int          dataBytes;

jraft-core/src/main/java/com/alipay/sofa/jraft/core/Replicator.java:1690

  • [nitpick] There are two spaces between final and RpcRequestHeader; align spacing to project style for consistency.
final  RpcRequestHeader header = new RpcRequestHeader(request);

Co-authored-by: Copilot <[email protected]>
@killme2008 killme2008 changed the title feat: only keeps request header to reduce memory in replicator feat: only retains request header to reduce memory during replication May 27, 2025
Copy link
Contributor

@fengjiachun fengjiachun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@fengjiachun fengjiachun merged commit eda479b into master May 28, 2025
10 checks passed
@fengjiachun fengjiachun deleted the feature/reduce-replication-mem branch May 28, 2025 02:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants