-
Notifications
You must be signed in to change notification settings - Fork 52
Remove useless grpc connections #233
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
base: master
Are you sure you want to change the base?
Changes from 12 commits
cc9d62e
f62f97c
f515951
1905fd0
9ae7add
091ee63
13d5ec8
d4acdd6
8f88f45
5c28d30
23e7942
885eb4c
0a8b2a7
82e22bb
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 |
|---|---|---|
| @@ -1,9 +1,39 @@ | ||
| #include <pingcap/Exception.h> | ||
| #include <pingcap/kv/Rpc.h> | ||
|
|
||
| namespace pingcap | ||
| { | ||
| namespace kv | ||
| { | ||
| namespace | ||
| { | ||
| bool isConnValid(const std::shared_ptr<KvConnClient> & conn_client, size_t rpc_timeout) | ||
| { | ||
| auto state = conn_client->channel->GetState(false); | ||
| if (state == GRPC_CHANNEL_READY) | ||
| return true; | ||
|
|
||
| auto deadline = std::chrono::system_clock::now() + std::chrono::seconds(rpc_timeout); | ||
| return conn_client->channel->WaitForConnected(deadline); | ||
| } | ||
|
|
||
| bool isConnArrayValid(const ConnArrayPtr & conn_array, size_t rpc_timeout) | ||
| { | ||
| std::vector<std::shared_ptr<KvConnClient>> conn_snapshot; | ||
| { | ||
| std::lock_guard<std::mutex> lock(conn_array->mutex); | ||
| conn_snapshot = conn_array->vec; | ||
| } | ||
|
|
||
| for (const auto & conn_client : conn_snapshot) | ||
| { | ||
| if (!isConnValid(conn_client, rpc_timeout)) | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| } // namespace | ||
|
|
||
| ConnArray::ConnArray(size_t max_size, const std::string & addr, const ClusterConfig & config_) | ||
| : address(addr) | ||
| , index(0) | ||
|
|
@@ -22,6 +52,88 @@ std::shared_ptr<KvConnClient> ConnArray::get() | |
| return vec[index]; | ||
| } | ||
|
|
||
| void RpcClient::run() | ||
| { | ||
| while (!stopped.load()) | ||
| { | ||
| bool has_invalid_conns = false; | ||
| { | ||
| std::unique_lock lock(mutex); | ||
| scan_cv.wait_for(lock, scan_interval, [this] { | ||
| return stopped.load() || !invalid_conns.empty(); | ||
| }); | ||
| has_invalid_conns = !invalid_conns.empty(); | ||
| } | ||
|
|
||
| if (stopped.load()) | ||
| return; | ||
|
|
||
| if (has_invalid_conns) | ||
| { | ||
| removeInvalidConns(); | ||
| continue; | ||
| } | ||
|
|
||
| try | ||
| { | ||
| scanConns(); | ||
| removeInvalidConns(); | ||
| } | ||
| catch (...) | ||
| { | ||
| log->warning(getCurrentExceptionMsg("RpcClient scan conns failed: ")); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void RpcClient::stop() | ||
| { | ||
| stopped.store(true); | ||
| scan_cv.notify_all(); | ||
| } | ||
|
|
||
| void RpcClient::scanConns() | ||
| { | ||
| std::vector<std::pair<std::string, ConnArrayPtr>> conn_snapshot; | ||
| { | ||
| std::lock_guard<std::mutex> lock(mutex); | ||
| conn_snapshot.reserve(conns.size()); | ||
| for (const auto & [addr, conn_array] : conns) | ||
| conn_snapshot.emplace_back(addr, conn_array); | ||
| } | ||
|
|
||
| for (const auto & [addr, conn_array] : conn_snapshot) | ||
| { | ||
| if (!isConnArrayValid(conn_array, detect_rpc_timeout)) | ||
| { | ||
| std::lock_guard<std::mutex> lock(mutex); | ||
| invalid_conns.push_back(addr); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void RpcClient::markConnInvalid(const std::string & addr) | ||
| { | ||
| std::lock_guard<std::mutex> lock(mutex); | ||
| invalid_conns.push_back(addr); | ||
| scan_cv.notify_all(); | ||
| } | ||
|
|
||
| void RpcClient::removeInvalidConns() | ||
| { | ||
| std::lock_guard<std::mutex> lock(mutex); | ||
| if (invalid_conns.empty()) | ||
| return; | ||
|
|
||
| for (const auto & addr : invalid_conns) | ||
| { | ||
| log->information("delete unavailable addr: " + addr); | ||
| conns.erase(addr); | ||
| } | ||
|
|
||
| invalid_conns.clear(); | ||
|
Comment on lines
+95
to
+134
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. Don’t erase newly recreated connection pools from stale scan results.
One possible fix using the existing conditional remover void RpcClient::scanConns()
{
std::vector<std::pair<std::string, ConnArrayPtr>> conn_snapshot;
@@
for (const auto & [addr, conn_array] : conn_snapshot)
{
if (!isConnArrayValid(conn_array, detect_rpc_timeout))
{
- std::lock_guard<std::mutex> lock(mutex);
- invalid_conns.push_back(addr);
+ removeConn(addr, conn_array);
}
}
}If the scan path still needs batched logging/removal, store 🧰 Tools🪛 Clang (14.0.6)[error] 95-95: method 'scanConns' can be made static (readability-convert-member-functions-to-static,-warnings-as-errors) [error] 122-122: method 'removeInvalidConns' can be made static (readability-convert-member-functions-to-static,-warnings-as-errors) 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| ConnArrayPtr RpcClient::getConnArray(const std::string & addr) | ||
| { | ||
| std::lock_guard<std::mutex> lock(mutex); | ||
|
|
@@ -40,5 +152,19 @@ ConnArrayPtr RpcClient::createConnArray(const std::string & addr) | |
| return conn_array; | ||
| } | ||
|
|
||
| void RpcClient::removeConn(const std::string & addr) | ||
| { | ||
| std::lock_guard<std::mutex> lock(mutex); | ||
| conns.erase(addr); | ||
| } | ||
|
|
||
| void RpcClient::removeConn(const std::string & addr, const ConnArrayPtr & expected) | ||
| { | ||
| std::lock_guard<std::mutex> lock(mutex); | ||
| auto it = conns.find(addr); | ||
| if (it != conns.end() && it->second == expected) | ||
| conns.erase(it); | ||
| } | ||
|
|
||
| } // namespace kv | ||
| } // namespace pingcap | ||
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.
Align
dropConnIfNeeded()with the shared removal predicate.shouldRemoveConnOnStatus()treats bothUNAVAILABLEandCANCELLEDas removable, butdropConnIfNeeded()only handlesUNAVAILABLE. SinceonSendFail()uses this helper, unary failures and stream setup failures withCANCELLEDwon’t invalidate the connection, whileStreamReader::finish()will.Proposed fix
inline void dropConnIfNeeded(const RpcClientPtr & client, const std::string & addr, const ::grpc::Status & status) { - if (status.error_code() == grpc::StatusCode::UNAVAILABLE) + if (shouldRemoveConnOnStatus(status)) client->markConnInvalid(addr); }📝 Committable suggestion
🤖 Prompt for AI Agents