Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add tcp keep alive #110

Merged
merged 15 commits into from
Jan 18, 2025
Merged

feat: add tcp keep alive #110

merged 15 commits into from
Jan 18, 2025

Conversation

lankunGitHub
Copy link
Collaborator

@lankunGitHub lankunGitHub commented Dec 11, 2024

Title

Add TCP KeepAlive Support #103

Description

tcp keepalive is enabled by default. You can use the tcp-keepalive option in the kiwi.conf file to change the value. If the value is set to 0, this function is disabled

Summary by CodeRabbit

  • New Features

    • Added TCP keep-alive configuration to maintain network connections.
    • Introduced new configuration options for database path, log level, and log file.
    • Enhanced network connection management with configurable keep-alive settings.
  • Configuration Updates

    • Added tcp-keepalive directive with a default 300-second interval.
    • New configuration parameters for database and logging management.
  • Performance Improvements

    • Implemented TCP keep-alive mechanism to detect and manage dead connections.
    • Centralized network options configuration for better control and flexibility.

Copy link

coderabbitai bot commented Dec 11, 2024

Warning

Rate limit exceeded

@lankunGitHub has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 8 minutes and 53 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between c43ed8a and e3aa75c.

📒 Files selected for processing (6)
  • src/config.cc (1 hunks)
  • src/config.h (1 hunks)
  • src/kiwi.cc (1 hunks)
  • src/net/base_socket.h (2 hunks)
  • src/net/event_server.h (2 hunks)
  • src/net/thread_manager.h (1 hunks)

Walkthrough

This pull request introduces TCP keep-alive functionality to the KiwiDB system. The changes span multiple files, adding a new configuration option for TCP keep-alive with a default value of 300 seconds. A new NetOptions class is introduced to manage network-related configuration settings, including TCP keep-alive timeout. The modifications enhance connection management by allowing configurable keep-alive probes to detect and maintain network connections more effectively.

Changes

File Change Summary
etc/conf/kiwi.conf Added tcp-keepalive 300 directive
src/config.cc Added configuration parameters for TCP keep-alive, database path, log level, and log file
src/config.h Added tcp_keepalive member variable
src/net/thread_manager.h Updated constructor to use NetOptions, added TCP keep-alive support
src/kiwi.cc Enhanced Init method to manage TCP keep-alive settings
src/net/base_socket.cc Added SetTcpKeepAlive() method to configure socket keep-alive settings
src/net/base_socket.h Added methods and member variable for TCP keep-alive
src/net/event_server.h Updated to use TCP keep-alive option
src/net/net_options.h Added methods and member variable for TCP keep-alive in NetOptions

Sequence Diagram

sequenceDiagram
    participant Config as Configuration
    participant NetOptions as NetOptions
    participant EventServer as Event Server
    participant BaseSocket as Base Socket

    Config->>NetOptions: Set TCP Keep-Alive
    NetOptions->>EventServer: Configure Keep-Alive
    EventServer->>BaseSocket: Apply Keep-Alive Settings
    BaseSocket-->>BaseSocket: Set Socket Options
Loading

Poem

🐰 Keepin' connections alive and bright,
With TCP's magical keepalive might!
Seconds ticking, sockets stay strong,
No more dead links to string along.
A rabbit's network, forever tight! 🌐


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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.

@lankunGitHub lankunGitHub changed the title Feature/tcp keepalive feat: add tcp keep alive Dec 11, 2024
@@ -16,6 +16,9 @@ ip 127.0.0.1
# Close the connection after a client is idle for N seconds (0 to disable)
timeout 0

# Enable the tcp keep-alive function (0 to disable)
tcp-keepalive 300
Copy link
Collaborator

Choose a reason for hiding this comment

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

我认为在注释里加上时间的单位会好一点,像16 line 一样

@@ -9,6 +9,7 @@

#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
Copy link
Collaborator

Choose a reason for hiding this comment

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

我认为不要在这里加头文件,在需要它的地方再加

Copy link
Collaborator

@lqxhub lqxhub left a comment

Choose a reason for hiding this comment

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

这个keeplive 和我最开始设想的不一样, 这个只是操作系统提供的一个探活选项,但是不能超时自动断开

redis的keeplieve可以参考
int clientsCronHandleTimeout(client *c, mstime_t now_ms) {

不过可以先实现这个, 自动断开的keeplive后面再考虑

src/client.cc Outdated
@@ -288,6 +288,49 @@ bool PClient::SendPacket(UnboundedBuffer& data) {
return true;
}

void PClient::SetTcpKeepAlive(int fd) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

这部分功能应该放到net目录中,对client来说是透明的

@@ -114,7 +114,8 @@ class ThreadManager {
};

template <typename T>
requires HasSetFdFunction<T> ThreadManager<T>::~ThreadManager() { Stop(); }
requires HasSetFdFunction<T>
ThreadManager<T>::~ThreadManager() { Stop(); }
Copy link
Collaborator

Choose a reason for hiding this comment

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

这里恢复,要不然格式化不通过, 使用 clang-format-13这个版本的进行格式化,

protected:
bool NoBlock() const { return noBlock_; }

private:
int type_ = SOCKET_NONE; // socket type (TCP/UDP)
bool noBlock_ = true;
uint32_t tcpKeepAlive_; // TCP keepalive
Copy link
Contributor

Choose a reason for hiding this comment

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

把变量名称改为 uint32_t tcp_keep_alive_ = 300;

Copy link

@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 (4)
src/net/net_options.h (2)

25-27: Add input validation and documentation for TCP keep-alive timeout.

Consider adding validation for the timeout value and documenting the units and valid range.

-  void SetOpTcpKeepAlive(uint32_t tcpKeepAlive) { tcpKeepAlive_ = tcpKeepAlive; }
+  /**
+   * Sets the TCP keep-alive timeout in seconds.
+   * @param tcpKeepAlive The timeout value in seconds. Set to 0 to disable keep-alive.
+   * @throws std::invalid_argument if tcpKeepAlive exceeds system limits
+   */
+  void SetOpTcpKeepAlive(const uint32_t tcpKeepAlive) {
+    // Most systems limit TCP_KEEPIDLE to 32767
+    if (tcpKeepAlive > 32767 && tcpKeepAlive != 0) {
+      throw std::invalid_argument("TCP keep-alive timeout exceeds maximum value");
+    }
+    tcpKeepAlive_ = tcpKeepAlive;
+  }

34-34: Document the default keep-alive timeout value.

Add a comment explaining why 300 seconds was chosen as the default value.

-  uint32_t tcpKeepAlive_ = 300;  // The timeout of the keepalive connection in seconds
+  uint32_t tcpKeepAlive_ = 300;  // Default TCP keep-alive timeout (300s) based on common production settings
src/net/base_socket.cc (1)

63-104: Enhance error handling and parameter validation.

The implementation looks good but could benefit from:

  1. More descriptive error messages including the actual values being set
  2. System-specific parameter validation
  3. Documentation for the keep-alive parameters
 void BaseSocket::SetTcpKeepAlive() {
   if (tcpKeepAlive_ == 0) {
     return;
   }
 
   int enabled = 1;
   uint32_t idle = tcpKeepAlive_;
-  uint32_t intvl = idle / 3;
-  int cnt = 3;
+  // Keep-alive probe interval (recommended: 1/3 of idle time)
+  uint32_t intvl = std::max(uint32_t(1), idle / 3);
+  // Number of unacknowledged probes before connection is dropped
+  int cnt = 3;
 
   if (setsockopt(Fd(), SOL_SOCKET, SO_KEEPALIVE, &enabled, sizeof(enabled)) == -1) {
-    WARN("SetTcpKeepAlive fd:{} error:{}", Fd(), errno);
+    WARN("Failed to enable TCP keep-alive on fd:{}, error:{} ({})", 
+         Fd(), errno, strerror(errno));
     return;
   }
 
 #ifdef TCP_KEEPIDLE
   if (setsockopt(Fd(), IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(idle))) {
-    WARN("SetTcpKeepAlive fd:{} error:{}", Fd(), errno);
+    WARN("Failed to set TCP_KEEPIDLE={} on fd:{}, error:{} ({})", 
+         idle, Fd(), errno, strerror(errno));
     return;
   }
 #elif defined(TCP_KEEPALIVE)
   /* support MacOS */
   if (setsockopt(Fd(), IPPROTO_TCP, TCP_KEEPALIVE, &idle, sizeof(idle))) {
-    WARN("SetTcpKeepAlive fd:{} error:{}", Fd(), errno);
+    WARN("Failed to set TCP_KEEPALIVE={} on fd:{}, error:{} ({})", 
+         idle, Fd(), errno, strerror(errno));
     return;
   }
 #endif
 
 #ifdef TCP_KEEPINTVL
   if (setsockopt(Fd(), IPPROTO_TCP, TCP_KEEPINTVL, &intvl, sizeof(intvl))) {
-    WARN("SetTcpKeepAlive fd:{} error:{}", Fd(), errno);
+    WARN("Failed to set TCP_KEEPINTVL={} on fd:{}, error:{} ({})", 
+         intvl, Fd(), errno, strerror(errno));
     return;
   }
 #endif
 
 #ifdef TCP_KEEPCNT
   if (setsockopt(Fd(), IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt))) {
-    WARN("SetTcpKeepAlive fd:{} error:{}", Fd(), errno);
+    WARN("Failed to set TCP_KEEPCNT={} on fd:{}, error:{} ({})", 
+         cnt, Fd(), errno, strerror(errno));
     return;
   }
 #endif
 }
src/config.cc (1)

140-140: Add range validation for tcp-keepalive configuration.

Consider using AddNumberWithLimit to enforce valid range for the TCP keep-alive timeout.

- AddNumber("tcp-keepalive", true, &tcp_keepalive);
+ // Most systems limit TCP_KEEPIDLE to 32767
+ AddNumberWithLimit<uint32_t>("tcp-keepalive", true, &tcp_keepalive, 0, 32767);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 75b6d76 and bdf441c.

📒 Files selected for processing (9)
  • etc/conf/kiwi.conf (1 hunks)
  • src/config.cc (1 hunks)
  • src/config.h (1 hunks)
  • src/kiwi.cc (1 hunks)
  • src/net/base_socket.cc (2 hunks)
  • src/net/base_socket.h (2 hunks)
  • src/net/event_server.h (2 hunks)
  • src/net/net_options.h (1 hunks)
  • src/net/thread_manager.h (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/config.h
  • src/net/event_server.h
  • src/kiwi.cc
  • etc/conf/kiwi.conf
  • src/net/thread_manager.h
  • src/net/base_socket.h
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_on_ubuntu
  • GitHub Check: build_on_macos
🔇 Additional comments (2)
src/net/base_socket.cc (1)

34-34: Consider adding error handling for TCP keep-alive initialization.

The OnCreate method should handle potential errors from SetTcpKeepAlive.

src/config.cc (1)

140-143: ⚠️ Potential issue

Remove duplicate configuration entries.

The following configuration entries are duplicated:

  • db-path
  • loglevel
  • logfile
  AddNumber("tcp-keepalive", true, &tcp_keepalive);
  AddString("db-path", false, {&db_path});
  AddStringWithFunc("loglevel", &CheckLogLevel, false, {&log_level});
  AddString("logfile", false, {&log_dir});
- AddString("db-path", false, &db_path);
- AddStringWithFunc("loglevel", &CheckLogLevel, false, &log_level);
- AddString("logfile", false, &log_dir);

Likely invalid or redundant comment.

Copy link

@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: 1

🧹 Nitpick comments (1)
src/config.cc (1)

140-140: Add value limits for tcp-keepalive parameter

Consider using AddNumberWithLimit instead of AddNumber to enforce reasonable bounds for the TCP keep-alive timeout. This helps prevent extreme values that could impact system performance.

-  AddNumber("tcp-keepalive", true, &tcp_keepalive);
+  AddNumberWithLimit<uint32_t>("tcp-keepalive", true, &tcp_keepalive, 0, 3600);  // 0 to disable, max 1 hour
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6e104a5 and c43ed8a.

📒 Files selected for processing (2)
  • src/config.cc (1 hunks)
  • src/net/base_socket.h (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/net/base_socket.h
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_on_ubuntu
  • GitHub Check: build_on_macos
🔇 Additional comments (1)
src/config.cc (1)

140-140: Verify TCP keep-alive implementation across the codebase

Let's verify the consistent usage of the tcp-keepalive configuration and proper error handling in socket operations.

Run the following script to analyze the implementation:

✅ Verification successful

TCP keep-alive implementation is properly integrated and robust

The verification confirms:

  • Proper error handling for all socket operations including keep-alive setup
  • Thread-safe socket resource management with atomic operations
  • Consistent configuration usage from config through to socket setup
  • Clean socket cleanup in all execution paths
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify TCP keep-alive implementation across the codebase

# Check for proper error handling in socket operations
echo "Checking error handling in socket operations..."
rg -A 5 "SetTcpKeepAlive|setsockopt.*SO_KEEPALIVE"

# Verify consistent usage of the configuration value
echo "Checking usage of tcp_keepalive configuration..."
rg -A 3 "tcp_keepalive"

# Check for potential memory leaks in socket handling
echo "Checking socket resource management..."
ast-grep --pattern 'class $_Socket {
  $$$
  ~$_Socket() {
    $$$
  }
  $$$
}'

Length of output: 3245


Script:

#!/bin/bash
# Check socket cleanup implementation
echo "Checking socket cleanup..."
rg -A 5 "~BaseSocket|Close\(\)" src/net/

# Verify socket fd management
echo "Checking socket fd handling..."
rg "fd_\s*=|Fd\(\)" src/net/base_socket

Length of output: 3247

Comment on lines +141 to +143
AddString("db-path", false, &db_path);
AddStringWithFunc("loglevel", &CheckLogLevel, false, &log_level);
AddString("logfile", false, &log_dir);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove duplicate configuration entries

The following configuration parameters are defined twice:

  • db-path
  • loglevel
  • logfile

This appears to be a merge conflict or copy-paste error. Please remove the duplicate entries.

  AddNumber("tcp-keepalive", true, &tcp_keepalive);
  AddString("db-path", false, &db_path);
  AddStringWithFunc("loglevel", &CheckLogLevel, false, &log_level);
  AddString("logfile", false, &log_dir);
-  AddString("db-path", false, &db_path);
-  AddStringWithFunc("loglevel", &CheckLogLevel, false, &log_level);
-  AddString("logfile", false, &log_dir);

Also applies to: 144-146

@luky116 luky116 merged commit 9937125 into unstable Jan 18, 2025
4 of 5 checks passed
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.

5 participants