Skip to content

Commit

Permalink
feat(server): admin port and interface (#709)
Browse files Browse the repository at this point in the history
* feat(server): admin port and interface

Signed-off-by: Boaz Sade <[email protected]>
  • Loading branch information
boazsade authored Jan 19, 2023
1 parent 5af6ee9 commit 49e53d5
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 3 deletions.
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,
"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

0 comments on commit 49e53d5

Please sign in to comment.