feat: auto detecting local IP to use as hostname (#5314)

* feat: auto detecting hostname

* chore: update config.md

* chore: bring back hostname

* chore: apply suggestions from CR

* chore: use const

* chore: apply suggesions from CR

* fix: fix sqlness
This commit is contained in:
Weny Xu
2025-01-08 20:06:31 +08:00
committed by GitHub
parent 52eebfce77
commit 7f307a4cac
25 changed files with 131 additions and 20 deletions

2
Cargo.lock generated
View File

@@ -6499,6 +6499,7 @@ dependencies = [
"humantime-serde",
"itertools 0.10.5",
"lazy_static",
"local-ip-address",
"once_cell",
"parking_lot 0.12.3",
"prometheus",
@@ -10892,6 +10893,7 @@ dependencies = [
"json5",
"jsonb",
"lazy_static",
"local-ip-address",
"log-query",
"loki-api",
"mime_guess",

View File

@@ -135,6 +135,7 @@ humantime-serde = "1.1"
itertools = "0.10"
jsonb = { git = "https://github.com/databendlabs/jsonb.git", rev = "8c8d2fc294a39f3ff08909d60f718639cfba3875", default-features = false }
lazy_static = "1.4"
local-ip-address = "0.6"
meter-core = { git = "https://github.com/GreptimeTeam/greptime-meter.git", rev = "a10facb353b41460eeb98578868ebf19c2084fac" }
mockall = "0.11.4"
moka = "0.12"

View File

@@ -214,7 +214,7 @@
| `http.body_limit` | String | `64MB` | HTTP request body limit.<br/>The following units are supported: `B`, `KB`, `KiB`, `MB`, `MiB`, `GB`, `GiB`, `TB`, `TiB`, `PB`, `PiB`.<br/>Set to 0 to disable limit. |
| `grpc` | -- | -- | The gRPC server options. |
| `grpc.addr` | String | `127.0.0.1:4001` | The address to bind the gRPC server. |
| `grpc.hostname` | String | `127.0.0.1` | The hostname advertised to the metasrv,<br/>and used for connections from outside the host |
| `grpc.hostname` | String | `127.0.0.1:4001` | The hostname advertised to the metasrv,<br/>and used for connections from outside the host |
| `grpc.runtime_size` | Integer | `8` | The number of server worker threads. |
| `grpc.tls` | -- | -- | gRPC server TLS options, see `mysql.tls` section. |
| `grpc.tls.mode` | String | `disable` | TLS mode. |
@@ -378,7 +378,7 @@
| `http.body_limit` | String | `64MB` | HTTP request body limit.<br/>The following units are supported: `B`, `KB`, `KiB`, `MB`, `MiB`, `GB`, `GiB`, `TB`, `TiB`, `PB`, `PiB`.<br/>Set to 0 to disable limit. |
| `grpc` | -- | -- | The gRPC server options. |
| `grpc.addr` | String | `127.0.0.1:3001` | The address to bind the gRPC server. |
| `grpc.hostname` | String | `127.0.0.1` | The hostname advertised to the metasrv,<br/>and used for connections from outside the host |
| `grpc.hostname` | String | `127.0.0.1:3001` | The hostname advertised to the metasrv,<br/>and used for connections from outside the host |
| `grpc.runtime_size` | Integer | `8` | The number of server worker threads. |
| `grpc.max_recv_message_size` | String | `512MB` | The maximum receive message size for gRPC server. |
| `grpc.max_send_message_size` | String | `512MB` | The maximum send message size for gRPC server. |

View File

@@ -59,7 +59,7 @@ body_limit = "64MB"
addr = "127.0.0.1:3001"
## The hostname advertised to the metasrv,
## and used for connections from outside the host
hostname = "127.0.0.1"
hostname = "127.0.0.1:3001"
## The number of server worker threads.
runtime_size = 8
## The maximum receive message size for gRPC server.

View File

@@ -38,7 +38,7 @@ body_limit = "64MB"
addr = "127.0.0.1:4001"
## The hostname advertised to the metasrv,
## and used for connections from outside the host
hostname = "127.0.0.1"
hostname = "127.0.0.1:4001"
## The number of server worker threads.
runtime_size = 8

View File

@@ -276,7 +276,8 @@ impl StartCommand {
info!("Datanode options: {:#?}", opts);
let plugin_opts = opts.plugins;
let opts = opts.component;
let mut opts = opts.component;
opts.grpc.detect_hostname();
let mut plugins = Plugins::new();
plugins::setup_datanode_plugins(&mut plugins, &plugin_opts, &opts)
.await

View File

@@ -222,7 +222,8 @@ impl StartCommand {
info!("Flownode start command: {:#?}", self);
info!("Flownode options: {:#?}", opts);
let opts = opts.component;
let mut opts = opts.component;
opts.grpc.detect_hostname();
// TODO(discord9): make it not optionale after cluster id is required
let cluster_id = opts.cluster_id.unwrap_or(0);

View File

@@ -268,7 +268,8 @@ impl StartCommand {
info!("Frontend options: {:#?}", opts);
let plugin_opts = opts.plugins;
let opts = opts.component;
let mut opts = opts.component;
opts.grpc.detect_hostname();
let mut plugins = Plugins::new();
plugins::setup_frontend_plugins(&mut plugins, &plugin_opts, &opts)
.await

View File

@@ -272,7 +272,8 @@ impl StartCommand {
info!("Metasrv options: {:#?}", opts);
let plugin_opts = opts.plugins;
let opts = opts.component;
let mut opts = opts.component;
opts.detect_server_addr();
let mut plugins = Plugins::new();
plugins::setup_metasrv_plugins(&mut plugins, &plugin_opts, &opts)
.await

View File

@@ -461,7 +461,8 @@ impl StartCommand {
let mut plugins = Plugins::new();
let plugin_opts = opts.plugins;
let opts = opts.component;
let mut opts = opts.component;
opts.grpc.detect_hostname();
let fe_opts = opts.frontend_options();
let dn_opts = opts.datanode_options();

View File

@@ -85,7 +85,9 @@ fn test_load_datanode_example_config() {
remote_write: Some(Default::default()),
..Default::default()
},
grpc: GrpcOptions::default().with_addr("127.0.0.1:3001"),
grpc: GrpcOptions::default()
.with_addr("127.0.0.1:3001")
.with_hostname("127.0.0.1:3001"),
rpc_addr: Some("127.0.0.1:3001".to_string()),
rpc_hostname: Some("127.0.0.1".to_string()),
rpc_runtime_size: Some(8),
@@ -137,6 +139,7 @@ fn test_load_frontend_example_config() {
remote_write: Some(Default::default()),
..Default::default()
},
grpc: GrpcOptions::default().with_hostname("127.0.0.1:4001"),
..Default::default()
},
..Default::default()
@@ -154,6 +157,7 @@ fn test_load_metasrv_example_config() {
component: MetasrvOptions {
selector: SelectorType::default(),
data_home: "/tmp/metasrv/".to_string(),
server_addr: "127.0.0.1:3002".to_string(),
logging: LoggingOptions {
dir: "/tmp/greptimedb/logs".to_string(),
level: Some("info".to_string()),

View File

@@ -45,6 +45,7 @@ humantime.workspace = true
humantime-serde.workspace = true
itertools.workspace = true
lazy_static.workspace = true
local-ip-address.workspace = true
once_cell.workspace = true
parking_lot.workspace = true
prometheus.workspace = true

View File

@@ -142,11 +142,14 @@ pub struct MetasrvOptions {
pub backend: BackendImpl,
}
const DEFAULT_METASRV_ADDR_PORT: &str = "3002";
impl Default for MetasrvOptions {
fn default() -> Self {
Self {
bind_addr: "127.0.0.1:3002".to_string(),
server_addr: "127.0.0.1:3002".to_string(),
bind_addr: format!("127.0.0.1:{}", DEFAULT_METASRV_ADDR_PORT),
// If server_addr is not set, the server will use the local ip address as the server address.
server_addr: String::new(),
store_addrs: vec!["127.0.0.1:2379".to_string()],
selector: SelectorType::default(),
use_memory_store: false,
@@ -184,6 +187,31 @@ impl Configurable for MetasrvOptions {
}
}
impl MetasrvOptions {
/// Detect server address if `auto_server_addr` is true.
pub fn detect_server_addr(&mut self) {
if self.server_addr.is_empty() {
match local_ip_address::local_ip() {
Ok(ip) => {
let detected_addr = format!(
"{}:{}",
ip,
self.bind_addr
.split(':')
.nth(1)
.unwrap_or(DEFAULT_METASRV_ADDR_PORT)
);
info!("Using detected: {} as server address", detected_addr);
self.server_addr = detected_addr;
}
Err(e) => {
error!("Failed to detect local ip address: {}", e);
}
}
}
}
}
pub struct MetasrvInfo {
pub server_addr: String,
}

View File

@@ -44,12 +44,32 @@ pub struct MockInfo {
pub async fn mock_with_memstore() -> MockInfo {
let kv_backend = Arc::new(MemoryKvBackend::new());
let in_memory = Arc::new(MemoryKvBackend::new());
mock(Default::default(), kv_backend, None, None, Some(in_memory)).await
mock(
MetasrvOptions {
server_addr: "127.0.0.1:3002".to_string(),
..Default::default()
},
kv_backend,
None,
None,
Some(in_memory),
)
.await
}
pub async fn mock_with_etcdstore(addr: &str) -> MockInfo {
let kv_backend = EtcdStore::with_endpoints([addr], 128).await.unwrap();
mock(Default::default(), kv_backend, None, None, None).await
mock(
MetasrvOptions {
server_addr: "127.0.0.1:3002".to_string(),
..Default::default()
},
kv_backend,
None,
None,
None,
)
.await
}
pub async fn mock(

View File

@@ -194,6 +194,7 @@ mod tests {
use super::get_node_id;
use crate::metasrv::builder::MetasrvBuilder;
use crate::metasrv::MetasrvOptions;
#[tokio::test]
async fn test_ask_leader() {
@@ -201,6 +202,10 @@ mod tests {
let metasrv = MetasrvBuilder::new()
.kv_backend(kv_backend)
.options(MetasrvOptions {
server_addr: "127.0.0.1:3002".to_string(),
..Default::default()
})
.build()
.await
.unwrap();

View File

@@ -306,6 +306,7 @@ mod tests {
#[tokio::test]
async fn test_batch_put() {
common_telemetry::init_default_ut_logging();
let metasrv = new_metasrv().await;
let mut req = BatchPutRequest::default();

View File

@@ -65,6 +65,7 @@ influxdb_line_protocol = { git = "https://github.com/evenyag/influxdb_iox", bran
itertools.workspace = true
jsonb.workspace = true
lazy_static.workspace = true
local-ip-address.workspace = true
log-query.workspace = true
loki-api = "0.1"
mime_guess = "2.0"

View File

@@ -65,11 +65,39 @@ pub struct GrpcOptions {
pub tls: TlsOption,
}
impl GrpcOptions {
/// Detect hostname if `auto_hostname` is true.
pub fn detect_hostname(&mut self) {
if self.hostname.is_empty() {
match local_ip_address::local_ip() {
Ok(ip) => {
let detected_addr = format!(
"{}:{}",
ip,
self.addr
.split(':')
.nth(1)
.unwrap_or(DEFAULT_GRPC_ADDR_PORT)
);
info!("Using detected: {} as server address", detected_addr);
self.hostname = detected_addr;
}
Err(e) => {
error!("Failed to detect local ip address: {}", e);
}
}
}
}
}
const DEFAULT_GRPC_ADDR_PORT: &str = "4001";
impl Default for GrpcOptions {
fn default() -> Self {
Self {
addr: "127.0.0.1:4001".to_string(),
hostname: "127.0.0.1".to_string(),
addr: format!("127.0.0.1:{}", DEFAULT_GRPC_ADDR_PORT),
// If hostname is not set, the server will use the local ip address as the hostname.
hostname: String::new(),
max_recv_message_size: DEFAULT_MAX_GRPC_RECV_MESSAGE_SIZE,
max_send_message_size: DEFAULT_MAX_GRPC_SEND_MESSAGE_SIZE,
runtime_size: 8,
@@ -83,6 +111,11 @@ impl GrpcOptions {
self.addr = addr.to_string();
self
}
pub fn with_hostname(mut self, hostname: &str) -> Self {
self.hostname = hostname.to_string();
self
}
}
pub struct GrpcServer {

View File

@@ -185,6 +185,7 @@ impl GreptimeDbClusterBuilder {
max_metadata_value_size: None,
},
wal: self.metasrv_wal_config.clone(),
server_addr: "127.0.0.1:3002".to_string(),
..Default::default()
};

View File

@@ -45,6 +45,7 @@ use frontend::instance::builder::FrontendBuilder;
use frontend::instance::{FrontendInstance, Instance, StandaloneDatanodeManager};
use meta_srv::metasrv::{FLOW_ID_SEQ, TABLE_ID_SEQ};
use query::stats::StatementStatistics;
use servers::grpc::GrpcOptions;
use servers::Mode;
use snafu::ResultExt;
@@ -291,6 +292,7 @@ impl GreptimeDbStandaloneBuilder {
procedure: procedure_config,
metadata_store: kv_backend_config,
wal: self.metasrv_wal_config.clone().into(),
grpc: GrpcOptions::default().with_hostname("127.0.0.1:4001"),
..StandaloneOptions::default()
};

View File

@@ -349,7 +349,9 @@ pub(crate) fn create_datanode_opts(
providers,
store: default_store,
},
grpc: GrpcOptions::default().with_addr(PEER_PLACEHOLDER_ADDR),
grpc: GrpcOptions::default()
.with_addr(PEER_PLACEHOLDER_ADDR)
.with_hostname(PEER_PLACEHOLDER_ADDR),
mode,
wal: wal_config,
..Default::default()

View File

@@ -850,7 +850,7 @@ is_strict_mode = false
[grpc]
addr = "127.0.0.1:4001"
hostname = "127.0.0.1"
hostname = "127.0.0.1:4001"
max_recv_message_size = "512MiB"
max_send_message_size = "512MiB"
runtime_size = 8

View File

@@ -1,8 +1,6 @@
node_id = 1
mode = 'distributed'
require_lease_before_startup = true
rpc_addr = '127.0.0.1:29410'
rpc_hostname = '127.0.0.1'
rpc_runtime_size = 8
[wal]

View File

@@ -0,0 +1,3 @@
[grpc]
addr = "127.0.0.1:29401"
hostname = "127.0.0.1:29401"

View File

@@ -356,6 +356,8 @@ impl Env {
"--log-dir={}/greptimedb-frontend/logs",
self.sqlness_home.display()
),
"-c".to_string(),
self.generate_config_file(subcommand, db_ctx),
];
(
args,
@@ -456,6 +458,7 @@ impl Env {
"start".to_string(),
];
args.push(format!("--rpc-addr=127.0.0.1:2941{id}"));
args.push(format!("--rpc-hostname=127.0.0.1:2941{id}"));
args.push(format!("--http-addr=127.0.0.1:2943{id}"));
args.push(format!("--data-home={}", data_home.display()));
args.push(format!("--log-dir={}/logs", data_home.display()));
@@ -480,6 +483,7 @@ impl Env {
"start".to_string(),
];
args.push(format!("--rpc-addr=127.0.0.1:2968{id}"));
args.push(format!("--rpc-hostname=127.0.0.1:2968{id}"));
args.push(format!("--node-id={id}"));
args.push(format!(
"--log-dir={}/greptimedb-flownode/logs",