-
Notifications
You must be signed in to change notification settings - Fork 0
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 client max connection #136
base: unstable
Are you sure you want to change the base?
Changes from 7 commits
eaa8fe8
e01a031
a3d3ba3
ab5c2c2
3e07a20
9edb5b4
80da4ab
e555f07
1743986
e79f013
81a60af
92fec59
30a2327
c7b7c79
239f72f
50a3929
4e9c500
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,17 +90,25 @@ class ThreadManager { | |
|
||
uint64_t DoTCPConnect(T &t, int fd, const std::shared_ptr<Connection> &conn); | ||
|
||
uint32_t getClientCount() const { return clientCount_.load(); } | ||
|
||
void clientCountIncrement() { clientCount_.fetch_add(1, std::memory_order_relaxed); } | ||
|
||
void clientCountDecrement() { clientCount_.fetch_sub(1, std::memory_order_relaxed); } | ||
|
||
private: | ||
const int8_t index_ = 0; // The index of the thread | ||
std::atomic<bool> running_ = true; // Whether the thread is running | ||
|
||
NetOptions netOptions_; | ||
|
||
inline static std::atomic<uint32_t> clientCount_{0}; | ||
|
||
std::unique_ptr<IOThread> readThread_; // Read thread | ||
std::unique_ptr<IOThread> writeThread_; // Write thread | ||
|
||
// All connections for the current thread | ||
std::unordered_map<uint64_t, std::pair<T, std::shared_ptr<Connection>>> connections_; | ||
std::unordered_map<uint64_t, std::pair<T, std::shared_ptr<Connection>>> | ||
connections_; // All connections for the current thread | ||
|
||
std::shared_mutex mutex_; | ||
|
||
|
@@ -116,7 +124,10 @@ class ThreadManager { | |
}; | ||
|
||
template <typename T> | ||
requires HasSetFdFunction<T> ThreadManager<T>::~ThreadManager() { Stop(); } | ||
requires HasSetFdFunction<T> | ||
ThreadManager<T>::~ThreadManager() { | ||
Stop(); | ||
} | ||
|
||
template <typename T> | ||
requires HasSetFdFunction<T> | ||
|
@@ -145,6 +156,14 @@ void ThreadManager<T>::Stop() { | |
template <typename T> | ||
requires HasSetFdFunction<T> | ||
void ThreadManager<T>::OnNetEventCreate(int fd, const std::shared_ptr<Connection> &conn) { | ||
if (getClientCount() >= netOptions_.GetMaxClients()) { | ||
INFO("Max client connetions, refuse new connection fd: %d", fd); | ||
std::string response = "-ERR max clients reached\r\n"; | ||
::send(fd, response.c_str(), response.size(), 0); | ||
::close(fd); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 添加日志 |
||
return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 返回 redis 格式的一个 response |
||
} | ||
|
||
T t; | ||
onInit_(&t); | ||
auto connId = getConnId(); | ||
|
@@ -166,6 +185,7 @@ void ThreadManager<T>::OnNetEventCreate(int fd, const std::shared_ptr<Connection | |
} | ||
|
||
onCreate_(connId, t, conn->addr_); | ||
clientCountIncrement(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix potential race condition in client counting. There's a race condition between checking the client count and incrementing it. Another thread could add a client between the check and increment, potentially exceeding the max limit. template <typename T>
requires HasSetFdFunction<T>
void ThreadManager<T>::OnNetEventCreate(int fd, const std::shared_ptr<Connection> &conn) {
- if (getClientCount() >= netOptions_.GetMaxClients()) {
+ if (!client_count_.compare_exchange_strong(
+ expected,
+ expected + 1,
+ std::memory_order_seq_cst,
+ std::memory_order_seq_cst) ||
+ expected >= netOptions_.GetMaxClients()) {
INFO("Max client connections, refuse new connection fd: %d", fd);
std::string response = "-ERR max clients reached\r\n";
::send(fd, response.c_str(), response.size(), 0);
::close(fd);
return;
}
// ... rest of the connection setup ...
- clientCountIncrement(); // Remove this as we've already incremented atomically
} Also applies to: 225-225 🧰 Tools🪛 GitHub Actions: kiwi[error] File has clang-format style issues |
||
} | ||
|
||
template <typename T> | ||
|
@@ -202,11 +222,14 @@ void ThreadManager<T>::OnNetEventClose(uint64_t connId, std::string &&err) { | |
iter->second.second->netEvent_->Close(); // close socket | ||
onClose_(iter->second.first, std::move(err)); | ||
connections_.erase(iter); | ||
clientCountDecrement(); | ||
} | ||
|
||
template <typename T> | ||
requires HasSetFdFunction<T> | ||
void ThreadManager<T>::CloseConnection(uint64_t connId) { OnNetEventClose(connId, ""); } | ||
void ThreadManager<T>::CloseConnection(uint64_t connId) { | ||
OnNetEventClose(connId, ""); | ||
} | ||
|
||
template <typename T> | ||
requires HasSetFdFunction<T> | ||
|
@@ -330,8 +353,8 @@ bool ThreadManager<T>::CreateWriteThread() { | |
} | ||
|
||
template <typename T> | ||
requires HasSetFdFunction<T> uint64_t ThreadManager<T>::DoTCPConnect(T &t, int fd, | ||
const std::shared_ptr<Connection> &conn) { | ||
requires HasSetFdFunction<T> | ||
uint64_t ThreadManager<T>::DoTCPConnect(T &t, int fd, const std::shared_ptr<Connection> &conn) { | ||
auto connId = getConnId(); | ||
if constexpr (IsPointer_v<T>) { | ||
t->SetConnId(connId); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Maintain consistent naming convention and review memory ordering.
Method names should follow the class's snake_case convention:
getClientCount
→get_client_count
clientCountIncrement
→client_count_increment
clientCountDecrement
→client_count_decrement
Consider using
std::memory_order_seq_cst
instead ofmemory_order_relaxed
for the atomic operations since the client count is used for critical decision-making inOnNetEventCreate
.📝 Committable suggestion
🧰 Tools
🪛 GitHub Actions: kiwi
[error] File has clang-format style issues