IPv4 マルチキャストによるフェイルオーバー
1. 概要
この記事では、IPv4 マルチキャストによるルーティングフェイルオーバーの Golang マイクロサンプルコードを投稿します。
2. はじめに
フェイルオーバー、マスター/スレーブ、死活監視構成は、どうしても設計が複雑化・大型化してしまいがちですが、この仕組みは、VRRP や HSRP、GLBP のようなルータ用のプロトコルは使用していないものの、ルーター、ローバーバランサー、リバースプロキシなどを別立てする必要がなく、応用次第ではとてもシンプルなマイクロサービスとして有用となりえるかもしれません。
UDP の信頼性をリトライにより担保し、マルチキャストにより処理コストを削減します。
また、応用次第では集権型監視設計ではなく、個々のコンピュータが相互に監視しあう分散型自律ネットワーク設計が可能となり、さらには、IPv6 による実用も可能です。
3. 環境
- RHEL-7 系
- Go 1.9
4. 構成
- master x 1
- MIP: 192.0.2.1
- VIP: 192.0.2.3
- backup x 1
- MIP: 192.0.2.2
5. 設計
- master:一定間隔でマルチキャストグループへハートビートを送信。
- backup:マスターノードからのハートビートを受信。
- backup:一定間隔でマスターノードからのハートビートの内容を監視。
- backup:マスターノードからのハートビート不達を検知。
- backup:一定回数のリトライ監視超過でマスターノードダウン判定。
- backup:VIP の奪取と、全ノード ARP テーブルへ VIP の更新をブロードキャスト。
6. Golang サンプルコード
@ master
$ sudo nvim ~/go/failover_multicast_ipv4_master.go
package main
import (
"fmt"
"net"
"time"
)
func main() {
mcast_ip4 := "224.0.0.1"
mcast_port := ":56789"
mcast_addr := mcast_ip4 + mcast_port
wait_time := 1
message := "master"
fmt.Printf("Send to multicast address: %s\n", mcast_addr)
conn, err := net.Dial("udp", mcast_addr)
_Error(err)
defer conn.Close()
for {
time.Sleep(time.Duration(wait_time) * time.Second)
conn.Write([]byte(message))
fmt.Printf("%s\n", message)
}
}
func _Error(_err error) {
if _err != nil {
panic(_err)
}
}
@ backup
$ sudo nvim ~/go/failover_multicast_ipv4_backup.go
package main
import (
"fmt"
"net"
"os/exec"
"time"
)
func main() {
mcast_ip4 := "224.0.0.1"
mcast_port := ":56789"
mcast_addr := mcast_ip4 + mcast_port
pulse_interval := 1
pulses := []int64{1, 1}
pulse_check := 0
pulse_retry := 3
ucast_vip4 := "192.0.2.3"
ucast_cidr := "/24"
ucast_mask := ucast_vip4 + ucast_cidr
ucast_if := "eth0"
fmt.Printf("Listen multicast address: %s\n", mcast_addr)
mcast_byte, err := net.ResolveUDPAddr("udp", mcast_addr)
_Error(err)
listener, err := net.ListenMulticastUDP("udp", nil, mcast_byte)
_Error(err)
defer listener.Close()
// For master pulse receiver
buffer := make([]byte, 8)
go func() {
for {
length, remote_mip4, err := listener.ReadFrom(buffer)
_Error(err)
if string(buffer[:length]) == "master" {
pulses[1] = time.Now.UnixNano()
fmt.Printf("Reveived multicast from Master MIP: %v\n", remote_mip4)
}
}
}()
// For master pulse checker
for {
// Sleep pulse check interval seconds
time.Sleep(time.Duration(pulse_interval) * time.Second)
// Wait master boot up
if pulses[1] == 1 {
continue
}
// Detected normal pulse
if pulses[0] != pulses[1] {
pulses[0] = pulses[1]
pulse_check = 0
continue
}
// Detected abnormal pulse
pulse_check++
// Retry pulse check
if pulse_check < pulse_retry {
fmt.Printf("Retry pulse check: %v\n", pulse_check)
continue
}
// Detected master cardiac arrest
fmt.Println("Detected master cardiac arrest.")
pulses[1] = 0
// Asign VIP
fmt.Printf("Reasign Unicast VIP: %s\n", ucast_mask)
err = exec.Command("ip", "-f", "inet", "addr", "add", ucast_mask, "dev", ucast_if).Run()
_Error(err)
// Execute arping
fmt.Println("Replace ARP tables.")
err = exec.Command("arping", "-q", "-U", "-c5", "-w1", ucast_vip4, "-I", ucast_if).Run()
_Error(err)
fmt.Println("Suceeded failover.")
break
}
}
func _Error(_err error) {
if _err != nil {
panic(_err)
}
}
7. Golang サンプル実行
@ master
$ sudo go run ~/go/failover_multicast_ipv4_master.go
[user@master ~/go]$ sudo go run failover_multicast_ipv4_master.go
Send to multicast address: 224.0.0.1:56789
master
master
...
@ backup
$ sudo go run ~/go/failover_multicast_ipv4_backup.go
[user@backup ~/go]$ sudo go run failover_multicast_ipv4_backup.go
Listen multicast address: 224.0.0.1:56789
Reveived multicast from Master MIP: 192.0.2.1:42573
Reveived multicast from Master MIP: 192.0.2.1:42573
...
@ master
[control]+[c]
[user@master ~/go]$ sudo go run failover_multicast_ipv4_master.go
Send to multicast address: 224.0.0.1:56789
master
master
...
^Csignal: interrupt
@ backup
[user@backup ~/go]$ sudo go run failover_multicast_ipv4_backup.go
Listen multicast address: 224.0.0.1:56789
Reveived multicast from Master MIP: 192.0.2.1:42573
Reveived multicast from Master MIP: 192.0.2.1:42573
...
Retry pulse check: 1
Retry pulse check: 2
Detected master cardiac arrest.
Reasign Unicast VIP: 192.0.2.3/24
Replace ARP tables.
Suceeded failover.
$ sudo ip addr
[user@backup ~/go]$ sudo ip addr
...
1: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
...
inet 192.0.2.2/24 brd 10.250.255.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet 192.0.2.3/24 scope global secondary eth0
valid_lft forever preferred_lft forever
..
8. まとめ
この記事では、IPv4 マルチキャストによるルーティングのフェイルオーバーの Golang マイクロサンプルコードを投稿しました。
フェイルオーバー、マスター/スレーブ、死活監視構成は、どうしても設計が複雑化・大型化してしまいがちですが、この仕組みは、VRRP や HSRP、GLBP のようなルータ用のプロトコルは使用していないものの、ルーター、ローバーバランサー、リバースプロキシなどを別立てする必要がなく、応用次第ではとてもシンプルなマイクロサービスとして有用となりえるかもしれません。
また、応用次第では個々のコンピュータを相互監視しあう自律ネットワーク設計が可能となりえます。
次回以降の記事で、シンプルな同期の仕組みを投稿する予定をしてますが、これらのマイクロサービスを組み合わせることで、とてもシンプルなデータリソースの冗長化構成への応用が可能となります。
Author And Source
この問題について(IPv4 マルチキャストによるフェイルオーバー), 我々は、より多くの情報をここで見つけました https://qiita.com/KyojiOsada/items/1f8253b93623f2267509著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .