dns-loadbalancer 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/dns-loadbalancer.rb +65 -0
  3. metadata +85 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 00361dd09de0683a2c765fda0238e36a81cc019204fc7fd0950ae1c8fd1e548a
4
+ data.tar.gz: 53c2244c604b15fa6bb5d491a87418eaf119c8efcd6aa037febf44357df5ff9e
5
+ SHA512:
6
+ metadata.gz: 6e6cdaf34cf4ef16ea43c85785c800ac4545fceec1088f253c02ee7500575e651deb5c8839a2ca6d479698253773399ac1299a7854e37aa013d9ae19e7f5a224
7
+ data.tar.gz: c999c74ff7f5975e7e12ed5f33976ba84782950593bbd60e5d80083874d8bff01f33f969738f510237dbc289fa1a001f92667e5b45cf20deb816d61f9e921ce0
@@ -0,0 +1,65 @@
1
+ require 'net/ping/tcp'
2
+ require 'resolv'
3
+ require 'ipaddress'
4
+
5
+ class DNSLoadBalancer
6
+ attr_reader :hosts, :port
7
+
8
+ def initialize(hosts, port, verbose: true)
9
+ @hosts = hosts.split(',')
10
+ @port = port
11
+ @verbose = verbose
12
+ end
13
+
14
+ def run
15
+ start = Time.now
16
+ ip_addresses = hosts.flat_map do |h|
17
+ result = resolve(h)
18
+ log "Resolved #{h} to IP addresses: #{result}"
19
+ result
20
+ end
21
+ result = find_closest(ip_addresses)
22
+ log "Found fastest IP #{result} in #{(Time.now - start).round(2)}s"
23
+ result
24
+ end
25
+
26
+ private
27
+
28
+ def resolve(host)
29
+ return host.to_s if IPAddress.valid?(host.to_s)
30
+
31
+ dns_obj = Resolv::DNS.new(nameserver: ['1.1.1.1', '8.8.8.8', '8.8.4.4'])
32
+ resources = dns_obj.getresources(host, Resolv::DNS::Resource::IN::A)
33
+ resources.map(&:address).map(&:to_s)
34
+ end
35
+
36
+ def find_closest(ip_addresses)
37
+ pings = ip_addresses.map do |address|
38
+ duration = ping(address.to_s, port)
39
+ log "Pinging #{address.ljust(16, ' ')} #{duration || 'not reachable'}"
40
+ [address, duration]
41
+ end.to_h
42
+
43
+ fastest = pings.select { |_, v| v }.min_by(&:last)
44
+ fastest&.first || raise('no server accessible')
45
+ end
46
+
47
+ def ping(ip_address, port)
48
+ durations = 3.times.map do
49
+ p = Net::Ping::TCP.new(ip_address, port, 0.5)
50
+ p.ping?
51
+ p.duration
52
+ end
53
+
54
+ durations.compact!
55
+ return nil if durations.empty?
56
+
57
+ durations.sum / durations.length
58
+ end
59
+
60
+ def log(msg)
61
+ return unless @verbose
62
+
63
+ puts "[DNSLoadBalancer] #{msg}"
64
+ end
65
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dns-loadbalancer
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Ruben Stranders
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-09-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ipaddress
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: net-ping
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: resolv
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.2'
55
+ description:
56
+ email: ruben@fireservicerota.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - lib/dns-loadbalancer.rb
62
+ homepage: https://github.com/FireServiceRota/dns-loadbalancer
63
+ licenses:
64
+ - MIT
65
+ metadata: {}
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubygems_version: 3.3.7
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: Gem for resolving a DNS host to the closest IP address
85
+ test_files: []