Crate ruserf_core
source ·Expand description
RuSerf
A highly customable, adaptable, runtime agnostic and WASM/WASI friendly decentralized solution for service discovery and orchestration that is lightweight, highly available, and fault tolerant.
Port and improve HashiCorp’s serf to Rust.
English | 简体中文
§Introduction
ruserf is a decentralized solution for service discovery and orchestration that is lightweight, highly available, and fault tolerant.
The use cases for such a library are far-reaching: all distributed systems require membership, and ruserf is a re-usable solution to managing cluster membership and node failure detection.
ruserf is eventually consistent but converges quickly on average. The speed at which it converges can be heavily tuned via various knobs on the protocol. Node failures are detected and network partitions are partially tolerated by attempting to communicate to potentially dead nodes through multiple routes.
ruserf is WASM/WASI friendly, all crates can be compiled to wasm-wasi
and wasm-unknown-unknown
(need to configure the crate features).
§Design
Unlike the original Go implementation, Rust’s ruserf use highly generic and layered architecture, users can easily implement a component by themselves and plug it to the ruserf. Users can even custom their own Id
and Address
.
Here are the layers:
-
Transport Layer
By default, Rust’s ruserf provides two kinds of transport –
QuicTransport
andNetTransport
.-
Runtime Layer
Async runtime agnostic are provided by
agnostic
’s Runtime trait,tokio
,async-std
andsmol
are supported by default. Users can implement their ownRuntime
and plug it into the ruserf. -
Address Resolver Layer
The address resolver layer is supported by
nodecraft
’s AddressResolver trait. -
Serialize/Deserilize Layer
By default, Rust’s ruserf is using
length-prefix encoding (Lpe)
to serialize/deserialize messages to bytes or visa-vise. The implemention ofLpe
tries the best to avoid reallocating when doing the serialize/deserialize.But, users can use any other serialize/deserialize framework by implementing
Wire
trait. -
Three kinds of different builtin stream layers for
NetTransport
:Tcp
: based on TCP and UDPTls
: based onrustls
and UDPNativeTls
: based onnative-tls
and UDP
-
QUIC transport is an experimental transport implementation, it is well tested but still experimental.
Two kinds of different builtin stream layers for
QuicTransport
:
Users can still implement their own stream layer for different kinds of transport implementations.
-
-
Delegate Layer
This layer is used as a reactor for different kinds of messages.
-
Delegate
Delegate is the trait that clients must implement if they want to hook into the gossip layer of Serf. All the methods must be thread-safe, as they can and generally will be called concurrently.
Here are the sub delegate traits:
-
MergeDelegate
Used to involve a client in a potential cluster merge operation. Namely, when a node does a promised push/pull (as part of a join), the delegate is involved and allowed to cancel the join based on custom logic. The merge delegate is NOT invoked as part of the push-pull anti-entropy.
-
TransformDelegate
A delegate for encoding and decoding. Used to control how
ruserf
should encode/decode messages. -
ReconnectDelegate
Used to custom reconnect behavior, users can implement to allow overriding the reconnect timeout for individual members.
-
-
CompositeDelegate
CompositeDelegate is a helpful struct to split the
Delegate
into multiple small delegates, so that users do not need to implement fullDelegate
when they only want to custom some methods in the Delegate.
-
§Protocol
ruserf is based on “SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol”. However, Hashicorp developers extends the protocol in a number of ways:
Several extensions are made to increase propagation speed and convergence rate. Another set of extensions, that Hashicorp developers call Lifeguard, are made to make ruserf more robust in the presence of slow message processing (due to factors such as CPU starvation, and network delay or loss). For details on all of these extensions, please read Hashicorp’s paper “Lifeguard : SWIM-ing with Situational Awareness”, along with the ruserf source.
§Installation
[dependencies]
ruserf = "0.1"
§Q & A
-
Does Rust’s ruserf implemenetation compatible to Go’s serf?
No but yes! By default, it is not compatible. But the secret is the serialize/deserilize layer, Go’s serf use the msgpack as the serialization/deserialization framework, so in theory, if you can implement a
TransformDelegate
trait which compat to Go’s serf, then it becomes compatible. -
If Go’s serf adds more functionalities, will this project also support?
Yes! And this project may also add more functionalities whereas the Go’s serf does not have. e.g. wasmer support, bindings to other languages and etc.
§Related Projects
agnostic
: helps you to develop runtime agnostic cratesnodecraft
: crafting seamless node operations for distributed systems, which provides foundational traits for node identification and address resolution.transformable
: transform its representation between structured and byte form.peekable
: peekable reader and async readermemberlist
: A highly customable, adaptable, runtime agnostic and WASM/WASI friendly Gossip protocol which helps manage cluster membership and member failure detection.
§License
ruserf
is under the terms of the MPL-2.0 license.
See LICENSE for details.
Copyright (c) 2024 Al Liu.
Copyright (c) 2013 HashiCorp, Inc.
Modules§
- Coordinate.
- Delegate traits and its implementations.
- Errors for
ruserf
. - Events for
Serf
- key_manager
encryption
Secret key management. - tests
test
All unit test fns are exported in thetests
module. This module is used for users want to use other async runtime, and want to use the test if memberlist also works with their runtime. - The types used in
ruserf
.
Macros§
- unit_tests
test
and (test
ortest
)Addtest
prefix to the predefined unit test fn with a givenRuntime
- unit_tests_with_expr
test
and (test
ortest
)Addtest
prefix to the predefined unit test fn with a givenRuntime
Structs§
- Options used to configure the memberlist.
- Used to represent a single response from a node
- The configuration for creating a Serf instance.
- Provided to
Serf::query
to configure the parameters of the query. If not provided, sane defaults will be used. - Returned for each new Query. It is used to collect Ack’s as well as responses and to provide those back to a client.
- Serf is a single node that is part of a single cluster that gets events about joins/leaves/failures/etc. It is created with the Create method.
- UnknownRecordType is used to indicate that we encountered an unknown record type while reading a snapshot file.
Enums§
- The state of the Serf instance.
- Errors that can occur while interacting with snapshots
Type Aliases§
- Exports the default delegate type