This is an automated email from the ASF dual-hosted git repository.
guangmingchen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git
The following commit(s) were added to refs/heads/master by this push:
new f187d2ca Method level option to ignore server eovercrowded (#2820)
f187d2ca is described below
commit f187d2ca43142ef28b3e1b4a00028e2db2ad92ad
Author: Alan Muhammad <[email protected]>
AuthorDate: Wed Dec 4 11:39:32 2024 +0800
Method level option to ignore server eovercrowded (#2820)
* method level option to ignore server eovercrowded
* explain method-level option
* [fix] add _failed_to_set_ignore_eovercrowded
* [fix] update docs
* fix indent and add service level option in baidu_master_service
* refactor constructor and update docs
* update server.md
* rm useless methods and refactor getter/setter
* fix build
---------
Co-authored-by: lianxuechao <[email protected]>
---
docs/cn/server.md | 18 ++++++++++++++
docs/en/server.md | 20 +++++++++++++++
src/brpc/baidu_master_service.cpp | 2 +-
src/brpc/baidu_master_service.h | 9 +++++++
src/brpc/policy/baidu_rpc_protocol.cpp | 21 +++++++++++-----
src/brpc/policy/http_rpc_protocol.cpp | 4 ++-
src/brpc/policy/hulu_pbrpc_protocol.cpp | 14 ++++++-----
src/brpc/policy/sofa_pbrpc_protocol.cpp | 13 +++++-----
src/brpc/server.cpp | 43 ++++++++++++++++++++++++++++++++-
src/brpc/server.h | 10 ++++++++
10 files changed, 133 insertions(+), 21 deletions(-)
diff --git a/docs/cn/server.md b/docs/cn/server.md
index 9606ab1d..0e68c51d 100644
--- a/docs/cn/server.md
+++ b/docs/cn/server.md
@@ -1057,6 +1057,24 @@ Protobuf arena是一种Protobuf message内存管理机制,有着提高内存
注意:从Protobuf
v3.14.0开始,[默认开启arena](https://github.com/protocolbuffers/protobuf/releases/tag/v3.14.0https://github.com/protocolbuffers/protobuf/releases/tag/v3.14.0)。但是Protobuf
v3.14.0之前的版本,用户需要再proto文件中加上选项:`option cc_enable_arenas =
true;`,所以为了兼容性,可以统一都加上该选项。
+## server端忽略eovercrowded
+### server级别忽略eovercrowded
+设置ServerOptions.ignore_eovercrowded,默认值0代表不忽略
+
+### method级别忽略eovercrowded
+server.IgnoreEovercrowdedOf("...") =
...可设置method级别的ignore_eovercrowded。也可以通过设置ServerOptions.ignore_eovercrowded一次性为所有的method设置忽略eovercrowded。
+
+```c++
+ServerOptions.ignore_eovercrowded = true; // Set the default
ignore_eovercrowded for all methods
+server.IgnoreEovercrowdedOf("example.EchoService.Echo") = true;
+```
+
+此设置一般**发生在AddService后,server启动前**。当设置失败时(比如对应的method不存在),server会启动失败同时提示用户修正IgnoreEovercrowdedOf设置错误。
+
+当ServerOptions.ignore_eovercrowded和server.IgnoreEovercrowdedOf("...")=...同时被设置时,任何一个设置为true,就表示会忽略eovercrowded。
+
+注意:没有service级别的ignore_eovercrowded。
+
# FAQ
### Q: Fail to write into fd=1865 [email protected]:54742@8230: Got
EOF是什么意思
diff --git a/docs/en/server.md b/docs/en/server.md
index 1c2923a6..e49f8512 100644
--- a/docs/en/server.md
+++ b/docs/en/server.md
@@ -1051,6 +1051,26 @@ Users can set `ServerOptions.rpc_pb_message_factory =
brpc::GetArenaRpcPBMessage
Note: Since Protocol Buffers v3.14.0, Arenas are now unconditionally enabled.
However, for versions prior to Protobuf v3.14.0, users need to add the option
`option cc_enable_arenas = true;` to the proto file. so for compatibility, this
option can be added uniformly.
+## Ignoring eovercrowded on server-side
+### Ignore eovercrowded on server-level
+
+Set ServerOptions.ignore_eovercrowded. Default value is 0 which means not
ignored.
+
+### Ignore eovercrowded on method-level
+
+server.IgnoreEovercrowdedOf("...") = … sets ignore_eovercrowded of the method.
Possible settings:
+
+```c++
+ServerOptions.ignore_eovercrowded = true; // Set the default
ignore_eovercrowded for all methods
+server.IgnoreEovercrowdedOf("example.EchoService.Echo") = true;
+```
+
+The code is generally put **after AddService, before Start() of the server**.
When a setting fails(namely the method does not exist), server will fail to
start and notify user to fix settings on IgnoreEovercrowdedOf.
+
+When method-level and server-level ignore_eovercrowded are both set, if any
one of them is set to true, eovercrowded will be ignored.
+
+NOTE: No service-level ignore_eovercrowded.
+
# FAQ
### Q: Fail to write into fd=1865 [email protected]:54742@8230: Got
EOF
diff --git a/src/brpc/baidu_master_service.cpp
b/src/brpc/baidu_master_service.cpp
index 0b983732..b1b0fa0d 100644
--- a/src/brpc/baidu_master_service.cpp
+++ b/src/brpc/baidu_master_service.cpp
@@ -22,7 +22,7 @@
namespace brpc {
BaiduMasterService::BaiduMasterService()
- :_status(new(std::nothrow) MethodStatus) {
+ : _status(new (std::nothrow) MethodStatus), _ignore_eovercrowded(false) {
LOG_IF(FATAL, NULL == _status) << "Fail to new MethodStatus";
}
diff --git a/src/brpc/baidu_master_service.h b/src/brpc/baidu_master_service.h
index 9dc7ebbf..11846fd9 100644
--- a/src/brpc/baidu_master_service.h
+++ b/src/brpc/baidu_master_service.h
@@ -45,6 +45,14 @@ public:
return _max_concurrency;
}
+ bool ignore_eovercrowded() {
+ return _ignore_eovercrowded;
+ }
+
+ void set_ignore_eovercrowded(bool ignore_eovercrowded) {
+ _ignore_eovercrowded = ignore_eovercrowded;
+ }
+
virtual void ProcessRpcRequest(Controller* cntl,
const SerializedRequest* request,
SerializedResponse* response,
@@ -92,6 +100,7 @@ friend class Server;
MethodStatus* _status;
AdaptiveMaxConcurrency _max_concurrency;
+ bool _ignore_eovercrowded;
};
}
diff --git a/src/brpc/policy/baidu_rpc_protocol.cpp
b/src/brpc/policy/baidu_rpc_protocol.cpp
index 53866262..f8ea1f63 100644
--- a/src/brpc/policy/baidu_rpc_protocol.cpp
+++ b/src/brpc/policy/baidu_rpc_protocol.cpp
@@ -491,12 +491,6 @@ void ProcessRpcRequest(InputMessageBase* msg_base) {
cntl->SetFailed(ELOGOFF, "Server is stopping");
break;
}
-
- if (socket->is_overcrowded() &&
!server->options().ignore_eovercrowded) {
- cntl->SetFailed(EOVERCROWDED, "Connection to %s is overcrowded",
-
butil::endpoint2str(socket->remote_side()).c_str());
- break;
- }
if (!server_accessor.AddConcurrency(cntl.get())) {
cntl->SetFailed(
@@ -524,6 +518,13 @@ void ProcessRpcRequest(InputMessageBase* msg_base) {
google::protobuf::Service* svc = NULL;
google::protobuf::MethodDescriptor* method = NULL;
if (NULL != server->options().baidu_master_service) {
+ if (socket->is_overcrowded() &&
+ !server->options().ignore_eovercrowded &&
+ !server->options().baidu_master_service->ignore_eovercrowded()) {
+ cntl->SetFailed(EOVERCROWDED, "Connection to %s is overcrowded",
+
butil::endpoint2str(socket->remote_side()).c_str());
+ break;
+ }
svc = server->options().baidu_master_service;
auto sampled_request = new (std::nothrow) SampledRequest;
if (NULL == sampled_request) {
@@ -586,6 +587,14 @@ void ProcessRpcRequest(InputMessageBase* msg_base) {
mp->service->CallMethod(mp->method, cntl.get(), &breq, &bres,
NULL);
break;
}
+ if (socket->is_overcrowded() &&
+ !server->options().ignore_eovercrowded &&
+ !mp->ignore_eovercrowded) {
+ cntl->SetFailed(
+ EOVERCROWDED, "Connection to %s is overcrowded",
+ butil::endpoint2str(socket->remote_side()).c_str());
+ break;
+ }
// Switch to service-specific error.
non_service_error.release();
method_status = mp->status;
diff --git a/src/brpc/policy/http_rpc_protocol.cpp
b/src/brpc/policy/http_rpc_protocol.cpp
index 76f43c05..2dd18076 100644
--- a/src/brpc/policy/http_rpc_protocol.cpp
+++ b/src/brpc/policy/http_rpc_protocol.cpp
@@ -1495,7 +1495,9 @@ void ProcessHttpRequest(InputMessageBase *msg) {
// NOTE: accesses to builtin services are not counted as part of
// concurrency, therefore are not limited by ServerOptions.max_concurrency.
if (!sp->is_builtin_service && !sp->params.is_tabbed) {
- if (socket->is_overcrowded() &&
!server->options().ignore_eovercrowded) {
+ if (socket->is_overcrowded() &&
+ !server->options().ignore_eovercrowded &&
+ !sp->ignore_eovercrowded) {
cntl->SetFailed(EOVERCROWDED, "Connection to %s is overcrowded",
butil::endpoint2str(socket->remote_side()).c_str());
return;
diff --git a/src/brpc/policy/hulu_pbrpc_protocol.cpp
b/src/brpc/policy/hulu_pbrpc_protocol.cpp
index 20e9c827..bf4bd86f 100644
--- a/src/brpc/policy/hulu_pbrpc_protocol.cpp
+++ b/src/brpc/policy/hulu_pbrpc_protocol.cpp
@@ -422,12 +422,6 @@ void ProcessHuluRequest(InputMessageBase* msg_base) {
break;
}
- if (socket->is_overcrowded() &&
!server->options().ignore_eovercrowded) {
- cntl->SetFailed(EOVERCROWDED, "Connection to %s is overcrowded",
-
butil::endpoint2str(socket->remote_side()).c_str());
- break;
- }
-
if (!server_accessor.AddConcurrency(cntl.get())) {
cntl->SetFailed(ELIMIT, "Reached server's max_concurrency=%d",
server->options().max_concurrency);
@@ -454,6 +448,14 @@ void ProcessHuluRequest(InputMessageBase* msg_base) {
sp->service->CallMethod(sp->method, cntl.get(), &breq, &bres,
NULL);
break;
}
+ if (socket->is_overcrowded() &&
+ !server->options().ignore_eovercrowded &&
+ !sp->ignore_eovercrowded) {
+ cntl->SetFailed(EOVERCROWDED, "Connection to %s is overcrowded",
+
butil::endpoint2str(socket->remote_side()).c_str());
+ break;
+ }
+
// Switch to service-specific error.
non_service_error.release();
method_status = sp->status;
diff --git a/src/brpc/policy/sofa_pbrpc_protocol.cpp
b/src/brpc/policy/sofa_pbrpc_protocol.cpp
index ad58022f..ae128b40 100644
--- a/src/brpc/policy/sofa_pbrpc_protocol.cpp
+++ b/src/brpc/policy/sofa_pbrpc_protocol.cpp
@@ -381,12 +381,6 @@ void ProcessSofaRequest(InputMessageBase* msg_base) {
break;
}
- if (socket->is_overcrowded() &&
!server->options().ignore_eovercrowded) {
- cntl->SetFailed(EOVERCROWDED, "Connection to %s is overcrowded",
-
butil::endpoint2str(socket->remote_side()).c_str());
- break;
- }
-
if (!server_accessor.AddConcurrency(cntl.get())) {
cntl->SetFailed(
ELIMIT, "Reached server's max_concurrency=%d",
@@ -406,6 +400,13 @@ void ProcessSofaRequest(InputMessageBase* msg_base) {
meta.method().c_str());
break;
}
+ if (socket->is_overcrowded() &&
+ !server->options().ignore_eovercrowded &&
+ !sp->ignore_eovercrowded) {
+ cntl->SetFailed(EOVERCROWDED, "Connection to %s is overcrowded",
+
butil::endpoint2str(socket->remote_side()).c_str());
+ break;
+ }
// Switch to service-specific error.
non_service_error.release();
method_status = sp->status;
diff --git a/src/brpc/server.cpp b/src/brpc/server.cpp
index 34b3c460..2a5fb119 100644
--- a/src/brpc/server.cpp
+++ b/src/brpc/server.cpp
@@ -180,7 +180,8 @@ Server::MethodProperty::MethodProperty()
, http_url(NULL)
, service(NULL)
, method(NULL)
- , status(NULL) {
+ , status(NULL)
+ , ignore_eovercrowded(false) {
}
static timeval GetUptime(void* arg/*start_time*/) {
@@ -412,6 +413,7 @@ Server::Server(ProfilerLinker)
, _builtin_service_count(0)
, _virtual_service_count(0)
, _failed_to_set_max_concurrency_of_method(false)
+ , _failed_to_set_ignore_eovercrowded(false)
, _am(NULL)
, _internal_am(NULL)
, _first_service(NULL)
@@ -795,6 +797,7 @@ static bool OptionsAvailableOverRdma(const ServerOptions*
opt) {
#endif
static AdaptiveMaxConcurrency g_default_max_concurrency_of_method(0);
+static bool g_default_ignore_eovercrowded(false);
int Server::StartInternal(const butil::EndPoint& endpoint,
const PortRange& port_range,
@@ -806,6 +809,12 @@ int Server::StartInternal(const butil::EndPoint& endpoint,
"fix it before starting server";
return -1;
}
+ if (_failed_to_set_ignore_eovercrowded) {
+ _failed_to_set_ignore_eovercrowded = false;
+ LOG(ERROR) << "previous call to IgnoreEovercrowdedOf() was failed, "
+ "fix it before starting server";
+ return -1;
+ }
if (InitializeOnce() != 0) {
LOG(ERROR) << "Fail to initialize Server[" << version() << ']';
return -1;
@@ -2298,6 +2307,38 @@ int Server::MaxConcurrencyOf(google::protobuf::Service*
service,
return MaxConcurrencyOf(service->GetDescriptor()->full_name(),
method_name);
}
+bool& Server::IgnoreEovercrowdedOf(const butil::StringPiece& full_method_name)
{
+ MethodProperty* mp = _method_map.seek(full_method_name);
+ if (mp == NULL) {
+ LOG(ERROR) << "Fail to find method=" << full_method_name;
+ _failed_to_set_ignore_eovercrowded = true;
+ return g_default_ignore_eovercrowded;
+ }
+ if (IsRunning()) {
+ LOG(WARNING) << "IgnoreEovercrowdedOf is only allowd before Server
started";
+ return g_default_ignore_eovercrowded;
+ }
+ if (mp->status == NULL) {
+ LOG(ERROR) << "method=" << mp->method->full_name()
+ << " does not support ignore_eovercrowded";
+ _failed_to_set_ignore_eovercrowded = true;
+ return g_default_ignore_eovercrowded;
+ }
+ return mp->ignore_eovercrowded;
+}
+
+bool Server::IgnoreEovercrowdedOf(const butil::StringPiece& full_method_name)
const {
+ MethodProperty* mp = _method_map.seek(full_method_name);
+ if (IsRunning()) {
+ LOG(WARNING) << "IgnoreEovercrowdedOf is only allowd before Server
started";
+ return g_default_ignore_eovercrowded;
+ }
+ if (mp == NULL || mp->status == NULL) {
+ return false;
+ }
+ return mp->ignore_eovercrowded;
+}
+
bool Server::AcceptRequest(Controller* cntl) const {
const Interceptor* interceptor = _options.interceptor;
if (!interceptor) {
diff --git a/src/brpc/server.h b/src/brpc/server.h
index ee5a500d..8d1b093c 100644
--- a/src/brpc/server.h
+++ b/src/brpc/server.h
@@ -417,6 +417,12 @@ public:
const google::protobuf::MethodDescriptor* method;
MethodStatus* status;
AdaptiveMaxConcurrency max_concurrency;
+ // ignore_eovercrowded on method-level, it should be used with
carefulness.
+ // It might introduce inbalance between methods,
+ // as some methods(ignore_eovercrowded=true) might never return
eovercrowded
+ // while other methods(ignore_eovercrowded=false) keep returning
eovercrowded.
+ // currently only valid for baidu_master_service, baidu_rpc, http_rpc,
hulu_pbrpc and sofa_pbrpc protocols
+ bool ignore_eovercrowded;
MethodProperty();
};
@@ -595,6 +601,9 @@ public:
int MaxConcurrencyOf(google::protobuf::Service* service,
const butil::StringPiece& method_name) const;
+ bool& IgnoreEovercrowdedOf(const butil::StringPiece& full_method_name);
+ bool IgnoreEovercrowdedOf(const butil::StringPiece& full_method_name)
const;
+
int Concurrency() const {
return butil::subtle::NoBarrier_Load(&_concurrency);
};
@@ -731,6 +740,7 @@ friend class Controller;
// number of the virtual services for mapping URL to methods.
int _virtual_service_count;
bool _failed_to_set_max_concurrency_of_method;
+ bool _failed_to_set_ignore_eovercrowded;
Acceptor* _am;
Acceptor* _internal_am;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]