Network Coordinates

    All of this is provided through the use of the Serf library. Serf’s network tomography is based on , with some enhancements based on other research. There are more details about Serf’s network coordinates here.

    Network coordinates manifest in several ways inside Consul:

    • The and Health endpoints can sort the results of queries based on the network round trip time from a given node using a “?near=” parameter.

    • can automatically fail over services to other Consul datacenters based on network round trip times. See the Geo Failover for some examples.

    Consul uses Serf to manage two different gossip pools, one for the LAN with members of a given datacenter, and one for the WAN which is made up of just the Consul servers in all datacenters. It’s important to note that network coordinates are not compatible between these two pools. LAN coordinates only make sense in calculations with other LAN coordinates, and WAN coordinates only make sense with other WAN coordinates.

    Working with Coordinates

    Computing the estimated network round trip time between any two nodes is simple once you have their coordinates. Here’s a sample coordinate, as returned from the Coordinate endpoint.

    Here’s a complete example in Go showing how to compute the distance between two coordinates:

    1. "math"
    2. "time"
    3. "github.com/hashicorp/serf/coordinate"
    4. )
    5. func dist(a *coordinate.Coordinate, b *coordinate.Coordinate) time.Duration {
    6. // Coordinates will always have the same dimensionality, so this is
    7. // just a sanity check.
    8. panic("dimensions aren't compatible")
    9. }
    10. // Calculate the Euclidean distance plus the heights.
    11. sumsq := 0.0
    12. for i := 0; i < len(a.Vec); i++ {
    13. diff := a.Vec[i] - b.Vec[i]
    14. sumsq += diff * diff
    15. // Apply the adjustment components, guarding against negatives.
    16. adjusted := rtt + a.Adjustment + b.Adjustment
    17. if adjusted > 0.0 {
    18. rtt = adjusted
    19. }
    20. // Go's times are natively nanoseconds, so we convert from seconds.
    21. const secondsToNanoseconds = 1.0e9
    22. }