/swift-rapid

Swift implementation of the Rapid cluster membership protocol

Primary LanguageSwiftApache License 2.0Apache-2.0

swift-rapid

Swift implementation of the Rapid Membership Protocol. It is inspired by the Java implementation.

This is a proof-of-concept / playground project and is not meant for production use as yet.

A few notes about this implementation:

  • it uses GRPC as a communication layer. There are likely more efficient ways to go about it than full-blown GRPC. The communication layer is pluggable, see MessagingClient and MessagingServer
  • the edge failure detector is pluggable as well, see EdgeFailureDetectorProvider
    • the default failure detector implementation is the the New Adaptive Accrual Failure Detector which was chosen here simply because it is easier to implement than the Phi Accrual Failure Detector. Read more about it here
  • at the time of writing this there aren't many established concurrency primitives in Swift so this project uses a few of them creatively. It makes use of:
  • at the core of it all is the RapidStateMachine which follows the pattern outlined in this talk. The most interesting states are active and viewChanging. A lot of care is put into stashing/keeping alerts for "future" configurations in order to honor the virtual synchrony requirements of Rapid and yet at the same time to allow for progress in settings where some nodes are faster than others (see this article on a very large cluster where this happens)

Building

  • run ./generateProtos.sh to generate the message protocol with swift-protobuf. This script expects protoc to be available on the path.
  • run swift test to verify that the tests are passing. You may need to increase the maximum number of allowed open files on your system (using e.g. ulimit -n 20000 on linux).
  • run swift build to build the binaries

Running via the CLI

To assemble a cluster for testing puropses, you can use the SwiftRapidCLI interface:

  • run ./SwiftRapidCLI start (under .build/<yourPlatform>/debug) to start a seed node on localhost:8000
  • run ./SwiftRapidCLI join localhost 8000 --port 8001 to join the cluster and listen on localhost:8001
  • note: for Paxos to be able to reach consensus you need at least 3 nodes, so make sure that you e.g. run at least a 5 port cluster

Running via the API

The entry point for this project is the RapidCluster class.

In order to start a seed node, use the start method:

 try RapidCluster.Builder.with {
    $0.host = "localhost"
    $0.port = 8000
    $0.registerSubscription(callback: { event in
        // print out any event on stdout
        print(event)
    })
}.start()

In order to join a seed node, use the join method:

let cluster = try RapidCluster.Builder.with {
    $0.host = "localhost"
    $0.port = 8001
    $0.registerSubscription(callback: { event in
        print(event)
    })
}.join(host: "localhost", port: 8000)

// print all members
print(try cluster.getMemberList())