introduce peer center (#13)

peer_center is used to collect peer info into one peer node.

the center node is selected with the following rules:

1. has smallest peer id
2. TODO: has allow_to_be_center peer feature

peer center is not guaranteed to be stable and can be changed when peer enter
or leave.  it's used to reduce the cost to exchange infos between peers.
This commit is contained in:
Sijie.Sun
2024-02-06 13:29:12 +08:00
committed by GitHub
parent e3f2765fed
commit 7f8935a9d5
12 changed files with 542 additions and 38 deletions
+92
View File
@@ -0,0 +1,92 @@
use std::collections::BTreeMap;
use crate::peers::PeerId;
use super::{Digest, Error};
use easytier_rpc::PeerInfo;
#[derive(Debug, Clone, Hash, serde::Deserialize, serde::Serialize)]
pub enum LatencyLevel {
VeryLow,
Low,
Normal,
High,
VeryHigh,
}
impl LatencyLevel {
pub const fn from_latency_ms(lat_ms: u32) -> Self {
if lat_ms < 10 {
LatencyLevel::VeryLow
} else if lat_ms < 50 {
LatencyLevel::Low
} else if lat_ms < 100 {
LatencyLevel::Normal
} else if lat_ms < 200 {
LatencyLevel::High
} else {
LatencyLevel::VeryHigh
}
}
}
#[derive(Debug, Clone, Hash, serde::Deserialize, serde::Serialize)]
pub struct PeerConnInfoForGlobalMap {
to_peer_id: PeerId,
latency_level: LatencyLevel,
}
#[derive(Debug, Clone, Hash, serde::Deserialize, serde::Serialize)]
pub struct PeerInfoForGlobalMap {
pub direct_peers: BTreeMap<PeerId, Vec<PeerConnInfoForGlobalMap>>,
}
impl From<Vec<PeerInfo>> for PeerInfoForGlobalMap {
fn from(peers: Vec<PeerInfo>) -> Self {
let mut peer_map = BTreeMap::new();
for peer in peers {
let mut conn_info = Vec::new();
for conn in peer.conns {
conn_info.push(PeerConnInfoForGlobalMap {
to_peer_id: conn.peer_id.parse().unwrap(),
latency_level: LatencyLevel::from_latency_ms(
conn.stats.unwrap().latency_us as u32 / 1000,
),
});
}
// sort conn info so hash result is stable
conn_info.sort_by(|a, b| a.to_peer_id.cmp(&b.to_peer_id));
peer_map.insert(peer.peer_id.parse().unwrap(), conn_info);
}
PeerInfoForGlobalMap {
direct_peers: peer_map,
}
}
}
// a global peer topology map, peers can use it to find optimal path to other peers
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct GlobalPeerMap {
pub map: BTreeMap<PeerId, PeerInfoForGlobalMap>,
}
impl GlobalPeerMap {
pub fn new() -> Self {
GlobalPeerMap {
map: BTreeMap::new(),
}
}
}
#[tarpc::service]
pub trait PeerCenterService {
// report center server which peer is directly connected to me
// digest is a hash of current peer map, if digest not match, we need to transfer the whole map
async fn report_peers(
my_peer_id: PeerId,
peers: Option<PeerInfoForGlobalMap>,
digest: Digest,
) -> Result<(), Error>;
async fn get_global_peer_map(digest: Digest) -> Result<Option<GlobalPeerMap>, Error>;
}