github.com/unionj-cloud/go-doudou/v2@v2.3.5/toolkit/memberlist/config.go (about) 1 package memberlist 2 3 import ( 4 "fmt" 5 "io" 6 "log" 7 "net" 8 "os" 9 "strings" 10 "time" 11 12 "github.com/hashicorp/go-multierror" 13 ) 14 15 type Config struct { 16 // The name of this node. This must be unique in the cluster. 17 Name string 18 19 // Transport is a hook for providing custom code to communicate with 20 // other nodes. If this is left nil, then memberlist will by default 21 // make a NetTransport using BindAddr and BindPort from this structure. 22 Transport Transport 23 24 // Configuration related to what address to bind to and ports to 25 // listen on. The port is used for both UDP and TCP gossip. It is 26 // assumed other nodes are running on this port, but they do not need 27 // to. 28 BindAddr string 29 BindPort int 30 31 // Configuration related to what address to advertise to other 32 // cluster members. Used for nat traversal. 33 AdvertiseAddr string 34 AdvertisePort int 35 36 // ProtocolVersion is the configured protocol version that we 37 // will _speak_. This must be between ProtocolVersionMin and 38 // ProtocolVersionMax. 39 ProtocolVersion uint8 40 41 // TCPTimeout is the timeout for establishing a stream connection with 42 // a remote node for a full state sync, and for stream read and write 43 // operations. This is a legacy name for backwards compatibility, but 44 // should really be called StreamTimeout now that we have generalized 45 // the transport. 46 TCPTimeout time.Duration 47 48 // IndirectChecks is the number of nodes that will be asked to perform 49 // an indirect probe of a node in the case a direct probe fails. Memberlist 50 // waits for an ack from any single indirect node, so increasing this 51 // number will increase the likelihood that an indirect probe will succeed 52 // at the expense of bandwidth. 53 IndirectChecks int 54 55 // RetransmitMult is the multiplier for the number of retransmissions 56 // that are attempted for messages broadcasted over gossip. The actual 57 // count of retransmissions is calculated using the formula: 58 // 59 // Retransmits = RetransmitMult * log(N+1) 60 // 61 // This allows the retransmits to scale properly with cluster size. The 62 // higher the multiplier, the more likely a failed broadcast is to converge 63 // at the expense of increased bandwidth. 64 RetransmitMult int 65 66 // SuspicionMult is the multiplier for determining the time an 67 // inaccessible node is considered suspect before declaring it dead. 68 // The actual timeout is calculated using the formula: 69 // 70 // SuspicionTimeout = SuspicionMult * log(N+1) * ProbeInterval 71 // 72 // This allows the timeout to scale properly with expected propagation 73 // delay with a larger cluster size. The higher the multiplier, the longer 74 // an inaccessible node is considered part of the cluster before declaring 75 // it dead, giving that suspect node more time to refute if it is indeed 76 // still alive. 77 SuspicionMult int 78 79 // SuspicionMaxTimeoutMult is the multiplier applied to the 80 // SuspicionTimeout used as an upper bound on detection time. This max 81 // timeout is calculated using the formula: 82 // 83 // SuspicionMaxTimeout = SuspicionMaxTimeoutMult * SuspicionTimeout 84 // 85 // If everything is working properly, confirmations from other nodes will 86 // accelerate suspicion timers in a manner which will cause the timeout 87 // to reach the base SuspicionTimeout before that elapses, so this value 88 // will typically only come into play if a node is experiencing issues 89 // communicating with other nodes. It should be set to a something fairly 90 // large so that a node having problems will have a lot of chances to 91 // recover before falsely declaring other nodes as failed, but short 92 // enough for a legitimately isolated node to still make progress marking 93 // nodes failed in a reasonable amount of time. 94 SuspicionMaxTimeoutMult int 95 96 // PushPullInterval is the interval between complete state syncs. 97 // Complete state syncs are done with a single node over TCP and are 98 // quite expensive relative to standard gossiped messages. Setting this 99 // to zero will disable state push/pull syncs completely. 100 // 101 // Setting this interval lower (more frequent) will increase convergence 102 // speeds across larger clusters at the expense of increased bandwidth 103 // usage. 104 PushPullInterval time.Duration 105 106 // ProbeInterval and ProbeTimeout are used to configure probing 107 // behavior for memberlist. 108 // 109 // ProbeInterval is the interval between random node probes. Setting 110 // this lower (more frequent) will cause the memberlist cluster to detect 111 // failed nodes more quickly at the expense of increased bandwidth usage. 112 // 113 // ProbeTimeout is the timeout to wait for an ack from a probed node 114 // before assuming it is unhealthy. This should be set to 99-percentile 115 // of RTT (round-trip time) on your network. 116 ProbeInterval time.Duration 117 ProbeTimeout time.Duration 118 119 // DisableTcpPings will turn off the fallback TCP pings that are attempted 120 // if the direct UDP ping fails. These get pipelined along with the 121 // indirect UDP pings. 122 DisableTcpPings bool 123 124 // DisableTcpPingsForNode is like DisableTcpPings, but lets you control 125 // whether to perform TCP pings on a node-by-node basis. 126 DisableTcpPingsForNode func(nodeName string) bool 127 128 // AwarenessMaxMultiplier will increase the probe interval if the node 129 // becomes aware that it might be degraded and not meeting the soft real 130 // time requirements to reliably probe other nodes. 131 AwarenessMaxMultiplier int 132 133 // GossipInterval and GossipNodes are used to configure the gossip 134 // behavior of memberlist. 135 // 136 // GossipInterval is the interval between sending messages that need 137 // to be gossiped that haven't been able to piggyback on probing messages. 138 // If this is set to zero, non-piggyback gossip is disabled. By lowering 139 // this value (more frequent) gossip messages are propagated across 140 // the cluster more quickly at the expense of increased bandwidth. 141 // 142 // GossipNodes is the number of random nodes to send gossip messages to 143 // per GossipInterval. Increasing this number causes the gossip messages 144 // to propagate across the cluster more quickly at the expense of 145 // increased bandwidth. 146 // 147 // GossipToTheDeadTime is the interval after which a node has died that 148 // we will still try to gossip to it. This gives it a chance to refute. 149 GossipInterval time.Duration 150 GossipNodes int 151 GossipToTheDeadTime time.Duration 152 153 // WeightInterval is the interval between calculating local node weight and enqueue a message carrying the result 154 // weight is calculated using the formula: 155 // 156 // Weight = (AwarenessMaxMultiplier - AwarenessScore) * 0.6 + AwarenessMaxMultiplier * CPUIdlePercent * 0.4 157 // 158 // local node weight messages will be gossiped to remote nodes. Remote nodes will use it to implement smooth 159 // weighted round-robin load balance algo for choosing the next service provider 160 // By default, this is 0, means not enabled 161 WeightInterval time.Duration 162 163 // GossipVerifyIncoming controls whether to enforce encryption for incoming 164 // gossip. It is used for upshifting from unencrypted to encrypted gossip on 165 // a running cluster. 166 GossipVerifyIncoming bool 167 168 // GossipVerifyOutgoing controls whether to enforce encryption for outgoing 169 // gossip. It is used for upshifting from unencrypted to encrypted gossip on 170 // a running cluster. 171 GossipVerifyOutgoing bool 172 173 // EnableCompression is used to control message compression. This can 174 // be used to reduce bandwidth usage at the cost of slightly more CPU 175 // utilization. This is only available starting at protocol version 1. 176 EnableCompression bool 177 178 // SecretKey is used to initialize the primary encryption key in a keyring. 179 // The primary encryption key is the only key used to encrypt messages and 180 // the first key used while attempting to decrypt messages. Providing a 181 // value for this primary key will enable message-level encryption and 182 // verification, and automatically install the key onto the keyring. 183 // The value should be either 16, 24, or 32 bytes to select AES-128, 184 // AES-192, or AES-256. 185 SecretKey []byte 186 187 // The keyring holds all of the encryption keys used internally. It is 188 // automatically initialized using the SecretKey and SecretKeys values. 189 Keyring *Keyring 190 191 // Delegate and Events are delegates for receiving and providing 192 // data to memberlist via callback mechanisms. For Delegate, see 193 // the Delegate interface. For Events, see the EventDelegate interface. 194 // 195 // The DelegateProtocolMin/Max are used to guarantee protocol-compatibility 196 // for any custom messages that the delegate might do (broadcasts, 197 // local/remote state, etc.). If you don't set these, then the protocol 198 // versions will just be zero, and version compliance won't be done. 199 Delegate Delegate 200 DelegateProtocolVersion uint8 201 DelegateProtocolMin uint8 202 DelegateProtocolMax uint8 203 Events EventDelegate 204 Conflict ConflictDelegate 205 Merge MergeDelegate 206 Ping PingDelegate 207 Alive AliveDelegate 208 209 // DNSConfigPath points to the system's DNS config file, usually located 210 // at /etc/resolv.conf. It can be overridden via config for easier testing. 211 DNSConfigPath string 212 213 // LogOutput is the writer where logs should be sent. If this is not 214 // set, logging will go to stderr by default. You cannot specify both LogOutput 215 // and Logger at the same time. 216 LogOutput io.Writer 217 218 // Logger is a custom logger which you provide. If Logger is set, it will use 219 // this for the internal logger. If Logger is not set, it will fall back to the 220 // behavior for using LogOutput. You cannot specify both LogOutput and Logger 221 // at the same time. 222 Logger *log.Logger 223 224 // Size of Memberlist's internal channel which handles UDP messages. The 225 // size of this determines the size of the queue which Memberlist will keep 226 // while UDP messages are handled. 227 HandoffQueueDepth int 228 229 // Maximum number of bytes that memberlist will put in a packet (this 230 // will be for UDP packets by default with a NetTransport). A safe value 231 // for this is typically 1400 bytes (which is the default). However, 232 // depending on your network's MTU (Maximum Transmission Unit) you may 233 // be able to increase this to get more content into each gossip packet. 234 // This is a legacy name for backward compatibility but should really be 235 // called PacketBufferSize now that we have generalized the transport. 236 UDPBufferSize int 237 238 // DeadNodeReclaimTime controls the time before a dead node's name can be 239 // reclaimed by one with a different address or port. By default, this is 0, 240 // meaning nodes cannot be reclaimed this way. 241 DeadNodeReclaimTime time.Duration 242 243 // RequireNodeNames controls if the name of a node is required when sending 244 // a message to that node. 245 RequireNodeNames bool 246 // CIDRsAllowed If nil, allow any connection (default), otherwise specify all networks 247 // allowed to connect (you must specify IPv6/IPv4 separately) 248 // Using [] will block all connections. 249 CIDRsAllowed []net.IPNet 250 } 251 252 // ParseCIDRs return a possible empty list of all Network that have been parsed 253 // In case of error, it returns successfully parsed CIDRs and the last error found 254 func ParseCIDRs(v []string) ([]net.IPNet, error) { 255 nets := make([]net.IPNet, 0) 256 if v == nil { 257 return nets, nil 258 } 259 var errs error 260 hasErrors := false 261 for _, p := range v { 262 _, net, err := net.ParseCIDR(strings.TrimSpace(p)) 263 if err != nil { 264 err = fmt.Errorf("invalid cidr: %s", p) 265 errs = multierror.Append(errs, err) 266 hasErrors = true 267 } else { 268 nets = append(nets, *net) 269 } 270 } 271 if !hasErrors { 272 errs = nil 273 } 274 return nets, errs 275 } 276 277 // DefaultLANConfig returns a sane set of configurations for Memberlist. 278 // It uses the hostname as the node name, and otherwise sets very conservative 279 // values that are sane for most LAN environments. The default configuration 280 // errs on the side of caution, choosing values that are optimized 281 // for higher convergence at the cost of higher bandwidth usage. Regardless, 282 // these values are a good starting point when getting started with memberlist. 283 func DefaultLANConfig() *Config { 284 hostname, _ := os.Hostname() 285 return &Config{ 286 Name: hostname, 287 BindAddr: "0.0.0.0", 288 BindPort: 7946, 289 AdvertiseAddr: "", 290 AdvertisePort: 7946, 291 ProtocolVersion: ProtocolVersion2Compatible, 292 TCPTimeout: 10 * time.Second, // Timeout after 10 seconds 293 IndirectChecks: 3, // Use 3 nodes for the indirect ping 294 RetransmitMult: 4, // Retransmit a message 4 * log(N+1) nodes 295 SuspicionMult: 4, // Suspect a node for 4 * log(N+1) * Interval 296 SuspicionMaxTimeoutMult: 6, // For 10k nodes this will give a max timeout of 120 seconds when SuspicionMult is 5: 6 * suspicionTimeout(5, 10000, time.Second) 297 PushPullInterval: 30 * time.Second, // Low frequency 298 ProbeTimeout: 500 * time.Millisecond, // Reasonable RTT time for LAN 299 ProbeInterval: 1 * time.Second, // Failure check every second 300 DisableTcpPings: false, // TCP pings are safe, even with mixed versions 301 AwarenessMaxMultiplier: 8, // Probe interval backs off to 8 seconds 302 303 GossipNodes: 3, // Gossip to 3 nodes 304 GossipInterval: 200 * time.Millisecond, // Gossip more rapidly 305 GossipToTheDeadTime: 30 * time.Second, // Same as push/pull 306 GossipVerifyIncoming: true, 307 GossipVerifyOutgoing: true, 308 309 EnableCompression: true, // Enable compression by default 310 311 SecretKey: nil, 312 Keyring: nil, 313 314 DNSConfigPath: "/etc/resolv.conf", 315 316 HandoffQueueDepth: 1024, 317 UDPBufferSize: 1400, 318 CIDRsAllowed: nil, // same as allow all 319 } 320 } 321 322 // DefaultWANConfig works like DefaultConfig, however it returns a configuration 323 // that is optimized for most WAN environments. The default configuration is 324 // still very conservative and errs on the side of caution. 325 func DefaultWANConfig() *Config { 326 conf := DefaultLANConfig() 327 conf.TCPTimeout = 30 * time.Second 328 conf.SuspicionMult = 6 329 conf.PushPullInterval = 60 * time.Second 330 conf.ProbeTimeout = 3 * time.Second 331 conf.ProbeInterval = 5 * time.Second 332 conf.GossipNodes = 4 // Gossip less frequently, but to an additional node 333 conf.GossipInterval = 500 * time.Millisecond 334 conf.GossipToTheDeadTime = 60 * time.Second 335 return conf 336 } 337 338 // IPMustBeChecked return true if IPAllowed must be called 339 func (c *Config) IPMustBeChecked() bool { 340 return len(c.CIDRsAllowed) > 0 341 } 342 343 // IPAllowed return an error if access to memberlist is denied 344 func (c *Config) IPAllowed(ip net.IP) error { 345 if !c.IPMustBeChecked() { 346 return nil 347 } 348 for _, n := range c.CIDRsAllowed { 349 if n.Contains(ip) { 350 return nil 351 } 352 } 353 return fmt.Errorf("%s is not allowed", ip) 354 } 355 356 var LookupIP = net.LookupIP 357 358 // AddrAllowed return an error if access to memberlist is denied 359 // addr can either be an ip address or a dns address 360 func (c *Config) AddrAllowed(addr string) error { 361 if !c.IPMustBeChecked() { 362 return nil 363 } 364 ip := net.ParseIP(addr) 365 if ip == nil { 366 ips, err := LookupIP(addr) 367 if err != nil || len(ips) == 0 { 368 return fmt.Errorf("%s is not allowed", addr) 369 } 370 ip = ips[0] 371 } 372 return c.IPAllowed(ip) 373 } 374 375 // Returns whether or not encryption is enabled 376 func (c *Config) EncryptionEnabled() bool { 377 return c.Keyring != nil && len(c.Keyring.GetKeys()) > 0 378 }