네트워크 좌표
네트워크 좌표 (Network coordinates)
이 문서는 Consul의 카탈로그(catalog) 작업에서 네트워크 좌표가 어떤 역할을 하는지 설명해 드릴게요. 네트워크 좌표를 이해하면 서비스 탐색과 장애 조치(failover) 동작을 더 정확히 예측할 수 있어요.
출처: 문서
본문
이 페이지는 Consul 카탈로그 작업에서 네트워크 좌표(Network Coordinates)의 역할을 설명합니다.
소개 (Introduction)
Consul은 네트워크 토모그래피(Network Tomography) 시스템을 사용하여 클러스터 내 노드들의 네트워크 좌표를 계산합니다. 이 좌표를 이용하면 임의의 두 노드 사이의 네트워크 왕복 시간(RTT, Round Trip Time)을 추정할 수 있습니다. Consul은 서비스를 반환할 때 RTT를 사용할 수 있습니다. 예를 들어 요청을 보내는 노드와 가장 가까운 서비스 노드를 찾거나, 다음으로 가까운 데이터센터의 서비스로 장애 조치(failover)할 수 있습니다.
Consul은 클러스터 내 에이전트 간 가십(Gossip) 통신도 제공하는 Serf 라이브러리를 사용하여 네트워크 좌표와 그 RTT를 결정합니다.
Consul에서의 네트워크 좌표 (Network coordinates in Consul)
네트워크 좌표는 Consul 안에서 여러 방식으로 나타납니다:
consul rtt명령은 임의의 두 노드 사이의 네트워크 왕복 시간을 조회합니다.- Catalog API 엔드포인트와 Health API 엔드포인트는
?near=파라미터를 포함하면 특정 노드로부터의 네트워크 왕복 시간을 기준으로 쿼리 결과를 정렬할 수 있습니다. - Prepared Query는 네트워크 왕복 시간을 기준으로 서비스를 다른 Consul 데이터센터로 자동 장애 조치할 수 있습니다.
- Coordinate 엔드포인트는 다른 애플리케이션에서 사용할 수 있도록 원시 네트워크 좌표를 노출합니다.
Consul은 Serf를 사용하여 LAN 가십 풀과 WAN 가십 풀을 모두 관리하지만, 네트워크 좌표는 이 두 풀 사이에서 호환되지 않습니다. LAN 네트워크 좌표는 다른 LAN 좌표와만 작동하고, WAN 네트워크 좌표는 다른 WAN 좌표와만 작동합니다.
좌표 다루기 (Working with Coordinates)
두 노드의 네트워크 좌표를 사용하여 그들의 RTT를 계산할 수 있습니다.
다음 예시는 Coordinate API 엔드포인트의 응답을 보여줍니다.
Coordinate 엔드포인트에서 가져온 샘플 좌표
[
{
"Node": "agent-one",
"Segment": "",
"Coord": {
"Adjustment": 0.1,
"Error": 1.5,
"Height": 0.02,
"Vec": [0.34,0.68,0.003,0.01,0.05,0.1,0.34,0.06]
}
}
]
모든 값은 초(seconds) 단위의 부동 소수점 숫자입니다. 예외는 Error 항목으로, 이 값은 거리 계산에는 사용되지 않습니다.
다음 Go 코드는 두 좌표 사이의 거리를 계산합니다:
Go로 두 좌표 사이의 거리 계산하기
import (
"math"
"time"
"github.com/hashicorp/serf/coordinate"
)
func dist(a *coordinate.Coordinate, b *coordinate.Coordinate) time.Duration {
// Coordinates will always have the same dimensionality, so this is
// just a sanity check.
if len(a.Vec) != len(b.Vec) {
panic("dimensions aren't compatible")
}
// Calculate the Euclidean distance plus the heights.
sumsq := 0.0
for i := 0; i < len(a.Vec); i++ {
diff := a.Vec[i] - b.Vec[i]
sumsq += diff * diff
}
rtt := math.Sqrt(sumsq) + a.Height + b.Height
// Apply the adjustment components, guarding against negatives.
adjusted := rtt + a.Adjustment + b.Adjustment
if adjusted > 0.0 {
rtt = adjusted
}
// Go's times are natively nanoseconds, so we convert from seconds.
const secondsToNanoseconds = 1.0e9
return time.Duration(rtt * secondsToNanoseconds)
}