Allow nodes to advertise a different rpc address over gossip (#13053) (#13077)

* Allow nodes to advertise a different rpc address over gossip

* Feedback

(cherry picked from commit 8b0242a5d8)

Co-authored-by: Justin Starry <justin@solana.com>
This commit is contained in:
mergify[bot]
2020-10-22 04:44:41 +00:00
committed by GitHub
parent bff820d549
commit b90b46fee1
4 changed files with 105 additions and 16 deletions

View File

@ -1267,14 +1267,16 @@ pub fn process_show_gossip(rpc_client: &RpcClient, config: &CliConfig) -> Proces
.into_iter()
.map(|node| {
format!(
"{:15} | {:44} | {:6} | {:5} | {:5} | {}",
"{:15} | {:44} | {:6} | {:5} | {:21} | {}",
node.gossip
.map(|addr| addr.ip().to_string())
.unwrap_or_else(|| "none".to_string()),
format_labeled_address(&node.pubkey, &config.address_labels),
format_port(node.gossip),
format_port(node.tpu),
format_port(node.rpc),
node.rpc
.map(|addr| addr.to_string())
.unwrap_or_else(|| "none".to_string()),
node.version.unwrap_or_else(|| "unknown".to_string()),
)
})
@ -1282,9 +1284,9 @@ pub fn process_show_gossip(rpc_client: &RpcClient, config: &CliConfig) -> Proces
Ok(format!(
"IP Address | Node identifier \
| Gossip | TPU | RPC | Version\n\
| Gossip | TPU | RPC Address | Version\n\
----------------+----------------------------------------------+\
--------+-------+-------+----------------\n\
--------+-------+-----------------------+----------------\n\
{}\n\
Nodes: {}",
s.join("\n"),

View File

@ -530,6 +530,70 @@ impl ClusterInfo {
.unwrap_or_else(|| EpochSlots::new(self.id(), timestamp()))
}
pub fn rpc_info_trace(&self) -> String {
let now = timestamp();
let my_pubkey = self.id();
let my_shred_version = self.my_shred_version();
let nodes: Vec<_> = self
.all_peers()
.into_iter()
.filter_map(|(node, last_updated)| {
if !ContactInfo::is_valid_address(&node.rpc) {
info!("invalid rpc: {}", node.rpc.to_string());
return None;
}
let node_version = self.get_node_version(&node.id);
if my_shred_version != 0
&& (node.shred_version != 0 && node.shred_version != my_shred_version)
{
return None;
}
fn addr_to_string(default_ip: &IpAddr, addr: &SocketAddr) -> String {
if ContactInfo::is_valid_address(addr) {
if &addr.ip() == default_ip {
addr.port().to_string()
} else {
addr.to_string()
}
} else {
"none".to_string()
}
}
let rpc_addr = node.rpc.ip();
Some(format!(
"{:15} {:2}| {:5} | {:44} |{:^9}| {:5}| {:5}| {:5}| {}\n",
rpc_addr.to_string(),
if node.id == my_pubkey { "me" } else { "" }.to_string(),
now.saturating_sub(last_updated),
node.id.to_string(),
if let Some(node_version) = node_version {
node_version.to_string()
} else {
"-".to_string()
},
addr_to_string(&rpc_addr, &node.rpc),
addr_to_string(&rpc_addr, &node.rpc_pubsub),
addr_to_string(&rpc_addr, &node.rpc_banks),
node.shred_version,
))
})
.collect();
format!(
"RPC Address |Age(ms)| Node identifier \
| Version | RPC |PubSub| Banks|ShredVer\n\
------------------+-------+----------------------------------------------+---------+\
------+------+------+--------\n\
{}\
RPC Enabled Nodes: {}",
nodes.join(""),
nodes.len(),
)
}
pub fn contact_info_trace(&self) -> String {
let now = timestamp();
let mut spy_nodes = 0;
@ -562,7 +626,7 @@ impl ClusterInfo {
}
let ip_addr = node.gossip.ip();
Some(format!(
"{:15} {:2}| {:5} | {:44} |{:^9}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n",
"{:15} {:2}| {:5} | {:44} |{:^9}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {:5}| {}\n",
if ContactInfo::is_valid_address(&node.gossip) {
ip_addr.to_string()
} else {
@ -583,9 +647,6 @@ impl ClusterInfo {
addr_to_string(&ip_addr, &node.tvu_forwards),
addr_to_string(&ip_addr, &node.repair),
addr_to_string(&ip_addr, &node.serve_repair),
addr_to_string(&ip_addr, &node.rpc),
addr_to_string(&ip_addr, &node.rpc_pubsub),
addr_to_string(&ip_addr, &node.rpc_banks),
node.shred_version,
))
}
@ -594,9 +655,9 @@ impl ClusterInfo {
format!(
"IP Address |Age(ms)| Node identifier \
| Version |Gossip| TPU |TPUfwd| TVU |TVUfwd|Repair|ServeR| RPC |PubSub|ShredVer\n\
| Version |Gossip| TPU |TPUfwd| TVU |TVUfwd|Repair|ServeR|ShredVer\n\
------------------+-------+----------------------------------------------+---------+\
------+------+------+------+------+------+------+------+------+--------\n\
------+------+------+------+------+------+------+--------\n\
{}\
Nodes: {}{}{}",
nodes.join(""),
@ -1580,7 +1641,11 @@ impl ClusterInfo {
thread_mem_usage::datapoint("solana-gossip");
if start - last_contact_info_trace > 10000 {
// Log contact info every 10 seconds
info!("\n{}", self.contact_info_trace());
info!(
"\n{}\n\n{}",
self.contact_info_trace(),
self.rpc_info_trace()
);
last_contact_info_trace = start;
}

View File

@ -386,11 +386,10 @@ impl Validator {
if let Some((rpc_addr, rpc_pubsub_addr, rpc_banks_addr)) = config.rpc_addrs {
if ContactInfo::is_valid_address(&node.info.rpc) {
assert!(ContactInfo::is_valid_address(&node.info.rpc_pubsub));
assert_eq!(rpc_addr.port(), node.info.rpc.port());
assert_eq!(rpc_pubsub_addr.port(), node.info.rpc_pubsub.port());
assert_eq!(rpc_banks_addr.port(), node.info.rpc_banks.port());
assert!(ContactInfo::is_valid_address(&node.info.rpc_banks));
} else {
assert!(!ContactInfo::is_valid_address(&node.info.rpc_pubsub));
assert!(!ContactInfo::is_valid_address(&node.info.rpc_banks));
}
let tpu_address = cluster_info.my_contact_info().tpu;
let (bank_notification_sender, bank_notification_receiver) = unbounded();

View File

@ -154,7 +154,7 @@ fn get_rpc_node(
let mut retry_reason = None;
loop {
sleep(Duration::from_secs(1));
info!("\n{}", cluster_info.contact_info_trace());
info!("\n{}", cluster_info.rpc_info_trace());
let shred_version = validator_config
.expected_shred_version
@ -1058,6 +1058,17 @@ pub fn main() {
.help("IP address for the node to advertise in gossip when \
--entrypoint is not provided [default: 127.0.0.1]"),
)
.arg(
Arg::with_name("public_rpc_addr")
.long("public-rpc-address")
.value_name("HOST:PORT")
.takes_value(true)
.conflicts_with("private_rpc")
.validator(solana_net_utils::is_host_port)
.help("RPC address for the node to advertise publicly in gossip. \
Useful for nodes running behind a load balancer or proxy \
[default: use --rpc-bind-address / --rpc-port]"),
)
.arg(
Arg::with_name("dynamic_port_range")
.long("dynamic-port-range")
@ -1593,6 +1604,13 @@ pub fn main() {
})
});
let public_rpc_addr = matches.value_of("public_rpc_addr").map(|addr| {
solana_net_utils::parse_host_port(addr).unwrap_or_else(|e| {
eprintln!("failed to parse public rpc address: {}", e);
exit(1);
})
});
let logfile = {
let logfile = matches
.value_of("logfile")
@ -1668,7 +1686,12 @@ pub fn main() {
}
if !private_rpc {
if let Some((rpc_addr, rpc_pubsub_addr, rpc_banks_addr)) = validator_config.rpc_addrs {
if let Some(public_rpc_addr) = public_rpc_addr {
node.info.rpc = public_rpc_addr;
node.info.rpc_pubsub = public_rpc_addr;
node.info.rpc_banks = public_rpc_addr;
} else if let Some((rpc_addr, rpc_pubsub_addr, rpc_banks_addr)) = validator_config.rpc_addrs
{
node.info.rpc = SocketAddr::new(node.info.gossip.ip(), rpc_addr.port());
node.info.rpc_pubsub = SocketAddr::new(node.info.gossip.ip(), rpc_pubsub_addr.port());
node.info.rpc_banks = SocketAddr::new(node.info.gossip.ip(), rpc_banks_addr.port());