Skip to content

Instantly share code, notes, and snippets.

@quark-zju
Created July 9, 2014 04:30
Show Gist options
  • Save quark-zju/39c2f096a706cc60e00d to your computer and use it in GitHub Desktop.
Save quark-zju/39c2f096a706cc60e00d to your computer and use it in GitHub Desktop.
Find the best server (lowest ping loss and latency) from a list of servers
#!/usr/bin/env ruby
require 'thread_safe'
require 'resolv'
exit 1 if Process.uid != 0
SERVERS = %w[
site-g1.example.com
site-g2.example.com
site-p1.example.com
site-p2.example.com
site-p3.example.com
site-s1.example.com
site-s2.example.com
site-s4.example.com
site-k1.example.com
]
def default_route
@default_router =
begin
route = `ip route | grep 'default via'`
route.gsub('default', '')
end
end
def nslookup(hostname, nameservers = ['114.114.114.114'])
Resolv::DNS.new(nameserver: nameservers).getaddress(hostname).to_s
end
def ping(ip)
# set default route
system "ip route replace #{ip}/32 #{default_route}"
result = `ping -i 0.2 -c 40 -n #{ip}`
received = result[/(\d+) received/, 1].to_i
avg = result[/\/([0-9\.]+)\//, 1].to_f
{
loss: 1.0 - received / 40.0,
rtt: avg
}
end
def find_best_server
threads = []
server_ping_results = ThreadSafe::Hash.new
SERVERS.map do |server|
thread = Thread.new do
ip = nslookup(server)
res = ping ip
puts "#{server} (#{ip}) #{res}"
server_ping_results[server] = res.merge(ip: ip)
end
threads.push thread
end
threads.each(&:join)
# Find the best
server, ping_result = server_ping_results.min_by do |k, v|
v[:loss] * 1e10 + v[:rtt]
end
ip = ping_result[:ip]
puts "Chosen: #{server} (#{ip})"
# TODO
raise 'Implement here'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment