mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-09 11:41:51 +00:00
Add latency measurement service to VC (#4024)
## Issue Addressed
NA
## Proposed Changes
Adds a service which periodically polls (11s into each mainnet slot) the `node/version` endpoint on each BN and roughly measures the round-trip latency. The latency is exposed as a `DEBG` log and a Prometheus metric.
The `--latency-measurement-service` has been added to the VC, with the following options:
- `--latency-measurement-service true`: enable the service (default).
- `--latency-measurement-service`: (without a value) has the same effect.
- `--latency-measurement-service false`: disable the service.
## Additional Info
Whilst looking at our staking setup, I think the BN+VC latency is contributing to late blocks. Now that we have to wait for the builders to respond it's nice to try and do everything we can to reduce that latency. Having visibility is the first step.
This commit is contained in:
@@ -14,7 +14,7 @@ use std::fmt::Debug;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::{sync::RwLock, time::sleep};
|
||||
use types::{ChainSpec, Config, EthSpec};
|
||||
|
||||
@@ -27,6 +27,14 @@ use types::{ChainSpec, Config, EthSpec};
|
||||
/// having the correct nodes up and running prior to the start of the slot.
|
||||
const SLOT_LOOKAHEAD: Duration = Duration::from_secs(1);
|
||||
|
||||
/// Indicates a measurement of latency between the VC and a BN.
|
||||
pub struct LatencyMeasurement {
|
||||
/// An identifier for the beacon node (e.g. the URL).
|
||||
pub beacon_node_id: String,
|
||||
/// The round-trip latency, if the BN responded successfully.
|
||||
pub latency: Option<Duration>,
|
||||
}
|
||||
|
||||
/// Starts a service that will routinely try and update the status of the provided `beacon_nodes`.
|
||||
///
|
||||
/// See `SLOT_LOOKAHEAD` for information about when this should run.
|
||||
@@ -394,6 +402,47 @@ impl<T: SlotClock, E: EthSpec> BeaconNodeFallback<T, E> {
|
||||
let _ = future::join_all(futures).await;
|
||||
}
|
||||
|
||||
/// Concurrently send a request to all candidates (regardless of
|
||||
/// offline/online) status and attempt to collect a rough reading on the
|
||||
/// latency between the VC and candidate.
|
||||
pub async fn measure_latency(&self) -> Vec<LatencyMeasurement> {
|
||||
let futures: Vec<_> = self
|
||||
.candidates
|
||||
.iter()
|
||||
.map(|candidate| async {
|
||||
let beacon_node_id = candidate.beacon_node.to_string();
|
||||
// The `node/version` endpoint is used since I imagine it would
|
||||
// require the least processing in the BN and therefore measure
|
||||
// the connection moreso than the BNs processing speed.
|
||||
//
|
||||
// I imagine all clients have the version string availble as a
|
||||
// pre-computed string.
|
||||
let response_instant = candidate
|
||||
.beacon_node
|
||||
.get_node_version()
|
||||
.await
|
||||
.ok()
|
||||
.map(|_| Instant::now());
|
||||
(beacon_node_id, response_instant)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let request_instant = Instant::now();
|
||||
|
||||
// Send the request to all BNs at the same time. This might involve some
|
||||
// queueing on the sending host, however I hope it will avoid bias
|
||||
// caused by sending requests at different times.
|
||||
future::join_all(futures)
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|(beacon_node_id, response_instant)| LatencyMeasurement {
|
||||
beacon_node_id,
|
||||
latency: response_instant
|
||||
.and_then(|response| response.checked_duration_since(request_instant)),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Run `func` against each candidate in `self`, returning immediately if a result is found.
|
||||
/// Otherwise, return all the errors encountered along the way.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user