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(server): admin port and interface #709

Merged
merged 2 commits into from
Jan 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ In addition, it has Dragonfly specific arguments options:
* `hz` - key expiry evaluation frequency. Default is 100. Lower frequency uses less cpu when
idle at the expense of slower eviction rate.
* `save_schedule` - glob spec for the UTC time to save a snapshot which matches HH:MM (24h time). default: ""
* `primary_port_http_enabled` - If true allows accessing http console on main TCP port, default: true
* `admin_port` - If set, would enable admin access to console on the assigned port. This supports both HTTP and RESP protocols. default disabled
* `admin_bind` - If set, the admin consol TCP connection would be bind the given address. This supports both HTTP and RESP protocols. default any

### Example Start Script, with popular options:

Expand Down
26 changes: 23 additions & 3 deletions src/facade/dragonfly_connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,17 @@

ABSL_FLAG(bool, tcp_nodelay, false,
"Configures dragonfly connections with socket option TCP_NODELAY");
ABSL_FLAG(bool, http_admin_console, true, "If true allows accessing http console on main TCP port");
ABSL_FLAG(bool, primary_port_http_enabled, true,
romange marked this conversation as resolved.
Show resolved Hide resolved
"If true allows accessing http console on main TCP port");

ABSL_FLAG(
std::uint16_t, admin_port, 0,
"If set, would enable admin access to console on the assigned port. This supports both HTTP "
"and RESP protocols");
ABSL_FLAG(std::string, admin_bind, "",
"If set, the admin consol TCP connection would be bind the given address. "
"This supports both HTTP and RESP "
"protocols");

using namespace util;
using namespace std;
Expand Down Expand Up @@ -326,8 +336,8 @@ void Connection::HandleRequests() {
#endif

io::Result<bool> http_res{false};
if (absl::GetFlag(FLAGS_http_admin_console))
http_res = CheckForHttpProto(peer);

http_res = CheckForHttpProto(peer);

if (http_res) {
if (*http_res) {
Expand Down Expand Up @@ -404,6 +414,16 @@ uint32 Connection::GetClientId() const {
}

io::Result<bool> Connection::CheckForHttpProto(FiberSocketBase* peer) {
bool enabled = absl::GetFlag(FLAGS_primary_port_http_enabled);
if (!enabled) {
uint16_t admin_port = absl::GetFlag(FLAGS_admin_port);
// check if this connection is from the admin port, if so, override primary_port_http_enabled
LinuxSocketBase* lsb = static_cast<LinuxSocketBase*>(socket_.get());
enabled = lsb->LocalEndpoint().port() == admin_port;
}
if (!enabled) {
return false;
}
size_t last_len = 0;
do {
auto buf = io_buf_.AppendBuffer();
Expand Down
21 changes: 21 additions & 0 deletions src/server/dfly_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ std::string AbslUnparseFlag(const MaxMemoryFlag& flag) {
ABSL_DECLARE_FLAG(uint32_t, port);
ABSL_DECLARE_FLAG(uint32_t, dbnum);
ABSL_DECLARE_FLAG(uint32_t, memcache_port);
ABSL_DECLARE_FLAG(uint16_t, admin_port);
ABSL_DECLARE_FLAG(std::string, admin_bind);

ABSL_FLAG(bool, use_large_pages, false, "If true - uses large memory pages for allocations");
ABSL_FLAG(string, bind, "",
Expand Down Expand Up @@ -319,6 +321,25 @@ bool RunEngine(ProactorPool* pool, AcceptServer* acceptor) {
}
}

std::uint16_t admin_port = GetFlag(FLAGS_admin_port);
if (admin_port != 0) {
const std::string& admin_bind = GetFlag(FLAGS_admin_bind);
// Note passing the result of c_str() for empty string in optimized mode don't work, we must
// explicitly set this to null in this case
const char* interface_addr = admin_bind.empty() ? nullptr : admin_bind.c_str();
const std::string printable_addr =
absl::StrCat("admin socket ", interface_addr ? interface_addr : "any", ":", admin_port);
Listener* admin_listener = new Listener{Protocol::REDIS, &service};
error_code ec = acceptor->AddListener(interface_addr, admin_port, admin_listener);

if (ec) {
LOG(ERROR) << "Failed to open " << printable_addr << ", error: " << ec.message();
delete admin_listener;
} else {
LOG(INFO) << "Listening on " << printable_addr;
}
}

error_code ec = acceptor->AddListener(bind_addr, port, main_listener);

if (ec) {
Expand Down