4 个稳定版本
使用旧 Rust 2015
1.0.3 | 2016 年 9 月 27 日 |
---|---|
1.0.2 | 2016 年 9 月 10 日 |
#7 in #kademlia
130KB
2.5K SLoC
Subotai
Subotai 是一个基于 Kademlia 的分布式哈希表。它设计得易于使用、安全且快速。以下是使其与其他 DHT 区别的一些想法
-
外部同步,内部并发:所有公共方法都是阻塞的,并返回一个合理的或明确的超时结果。然而,内部 subotai 完全并发,并行操作通常会相互帮助完成。
-
优先引入节点,然后解决冲突:Subotai 与原始 Kademlia 实现不同之处在于,它给新接触到的临时节点以全桶的优先权。这使得网络更加动态和能够快速适应,同时仍提供防御性状态来保护基本
DDoS
攻击。 -
灵活的存储:键空间中的每个键都可以存储任意数量的不同条目,每个条目具有独立的过期时间。
-
急迫:Subotai 是“急迫”的,这意味着它将尝试从不响应的节点那里永不等待响应。在可能的情况下,查询会并行发送,并在一小部分节点响应时继续处理。
Subotai 支持自动密钥重新发布,提供良好的保证,确保条目将保留在网络中,直到配置的过期日期。手动将条目存储在网络中可以刷新过期日期。
Subotai 还支持缓存,以平衡围绕特定键的密集流量。
如何使用
假设我们在一台机器上运行以下代码
fn main() {
let node = node::Node::new().unwrap();
// We join the network through the address of any live node.
let seed = net::SocketAddr::from_str("192.168.1.100:50000").unwrap();
node.bootstrap(&seed);
// We store a key->data pair.
let my_key = hash::SubotaiHash::sha1("example_key");
let my_data = vec![0u8,1,2,3,4,5];
node.store(my_key, node::StorageEntry::Blob(my_data));
}
只要网络中有足够数量的节点(一个可配置的数量,被认为是网络活跃的足够数量),我们就成功地将数据存储在表中。
现在,在非常、非常遥远的另一台机器上...
fn main() {
let node = node::Node::new().unwrap();
// We join the same network (can be on a different node).
let seed = net::SocketAddr::from_str("192.168.1.230:40000").unwrap();
node.bootstrap(&seed);
// We retrieve all entries for the same key.
let my_key = hash::SubotaiHash::sha1("example_key");
let retrieved_entries = node.retrieve(&my_key).unwrap();
// We get what we stored. In O(log n) number of steps, of course!
assert_eq!(retrieved_entries.len(), 1);
let expected_data = vec![0u8,1,2,3,4,5];
assert_eq!(*retrieved_entries.first().unwrap(), node::StorageEntry::Blob(expected_data));
}
项目状态
Subotai 功能完整,但处于测试的早期阶段。我专注于使 API 尽可能稳定(部分是通过通过工厂处理所有配置,以防止新的配置选项成为破坏性更改),并为构建在它之上的实际应用提供功能基线。
尽管每个功能都经过了单元测试,但网络尚未在实际条件下进行测试。我真的非常感谢任何实验!只是请确保不要将其用于任何关键任务:)。
关于测试的说明
苏博泰的单元测试套件有些繁琐,因为库广泛使用超时来进行决策。这意味着,除非你正在运行一台非常强大的机器,否则你应该使用 cargo test
命令与 RUST_TEST_THREADS=1
一起运行。否则,过多的并行测试可能会导致到处超时,使得网络错误地将节点识别为已死亡。
依赖项
约4MB
约76K SLoC