right_support 2.6.16 → 2.6.17
Sign up to get free protection for your applications and to get access to all the features.
@@ -69,14 +69,47 @@ module RightSupport::Net
|
|
69
69
|
# @raise URI::InvalidURIError if endpoints contains an invalid or URI
|
70
70
|
# @raise SocketError if endpoints contains an invalid or unresolvable hostname
|
71
71
|
def self.resolve(endpoints, opts={})
|
72
|
+
resolved_hostnames = resolve_with_hostnames(endpoints, opts)
|
73
|
+
resolved_endpoints = []
|
74
|
+
resolved_hostnames.each_value{ |v| resolved_endpoints.concat(v) }
|
75
|
+
return resolved_endpoints
|
76
|
+
end
|
77
|
+
|
78
|
+
# Similar to resolve, but return a hash of { hostnames => [endpoints] }
|
79
|
+
#
|
80
|
+
# Perform DNS resolution on a set of endpoints, where the endpoints may be hostnames or URIs.
|
81
|
+
# Expand out the list to include one entry per distinct address that is assigned to a given
|
82
|
+
# hostname, but preserve other aspects of the endpoints --. URIs will remain URIs with the
|
83
|
+
# same protocol, path-info, and so forth, but the hostname component will be resolved to IP
|
84
|
+
# addresses and the URI will be duplicated in the output, once for each distinct IP address.
|
85
|
+
#
|
86
|
+
# Although this method does accept IPv4 dotted-quad addresses as input, it does not accept
|
87
|
+
# IPv6 addresses. However, given hostnames or URIs as input, one _can_ resolve the hostnames
|
88
|
+
# to IPv6 addresses by specifying the appropriate address_family in the options.
|
89
|
+
#
|
90
|
+
# It should never be necessary to specify a different :socket_type or :protocol, but these
|
91
|
+
# options are exposed just in case.
|
92
|
+
#
|
93
|
+
# @param [Array<String>] endpoints a mixed list of hostnames, IPv4 addresses or URIs that contain them
|
94
|
+
# @option opts [Integer] :retry number of times to retry SocketError; default is 3
|
95
|
+
# @option opts [Integer] :address_family what kind of IP addresses to resolve; default is Socket::AF_INET (IPv4)
|
96
|
+
# @option opts [Integer] :socket_type socket-type context to pass to getaddrinfo, default is Socket::SOCK_STREAM
|
97
|
+
# @option opts [Integer] :protocol protocol context to pass to getaddrinfo, default is Socket::IPPROTO_TCP
|
98
|
+
#
|
99
|
+
# @return [Hash<hostnames => [endpoints]>] Hash with keys of hostnames and values of arrays of all associated IP addresses
|
100
|
+
#
|
101
|
+
# @raise URI::InvalidURIError if endpoints contains an invalid or URI
|
102
|
+
# @raise SocketError if endpoints contains an invalid or unresolvable hostname
|
103
|
+
def self.resolve_with_hostnames(endpoints, opts={})
|
72
104
|
opts = DEFAULT_RESOLVE_OPTIONS.merge(opts)
|
73
105
|
endpoints = [endpoints] unless endpoints.respond_to?(:each)
|
74
106
|
|
75
|
-
|
107
|
+
hostname_hash = {}
|
76
108
|
retries = 0
|
77
109
|
|
78
110
|
endpoints.each do |endpoint|
|
79
111
|
begin
|
112
|
+
resolved_endpoints = []
|
80
113
|
if endpoint.include?(':')
|
81
114
|
# It contains a colon, therefore it must be a URI -- we don't support IPv6
|
82
115
|
uri = URI.parse(endpoint)
|
@@ -100,6 +133,7 @@ module RightSupport::Net
|
|
100
133
|
resolved_endpoints << info[3]
|
101
134
|
end
|
102
135
|
end
|
136
|
+
hostname_hash[endpoint.to_s] = resolved_endpoints
|
103
137
|
rescue SocketError => e
|
104
138
|
retries += 1
|
105
139
|
if retries < opts[:retry]
|
@@ -110,7 +144,7 @@ module RightSupport::Net
|
|
110
144
|
end
|
111
145
|
end
|
112
146
|
|
113
|
-
|
147
|
+
hostname_hash
|
114
148
|
end
|
115
149
|
|
116
150
|
end
|
@@ -190,6 +190,17 @@ module RightSupport::Net
|
|
190
190
|
end
|
191
191
|
end
|
192
192
|
|
193
|
+
# Un-resolve an IP address.
|
194
|
+
#
|
195
|
+
# === Parameters
|
196
|
+
# endpoint:: a network endpoint (e.g. HTTP URL) to be un-resolved
|
197
|
+
#
|
198
|
+
# === Return
|
199
|
+
# Return the first hostname that resolved to the IP (there should only ever be one)
|
200
|
+
def lookup_hostname(endpoint)
|
201
|
+
@resolved_hostnames.select{ |k,v| v.include?(endpoint) }.shift[0]
|
202
|
+
end
|
203
|
+
|
193
204
|
# Perform a request.
|
194
205
|
#
|
195
206
|
# === Block
|
@@ -268,11 +279,18 @@ module RightSupport::Net
|
|
268
279
|
return result if complete
|
269
280
|
|
270
281
|
# Produce a summary message for the exception that gives a bit of detail
|
271
|
-
msg = []
|
282
|
+
msg = []
|
283
|
+
stats = get_stats
|
272
284
|
exceptions.each_pair do |endpoint, list|
|
273
285
|
summary = []
|
274
286
|
list.each { |e| summary << e.class }
|
275
|
-
|
287
|
+
health = stats[endpoint] if stats[endpoint] != 'n/a'
|
288
|
+
if @resolved_hostnames
|
289
|
+
hostname = lookup_hostname(endpoint)
|
290
|
+
msg << "'#{hostname}' (#{endpoint}#{", "+health if health}) => [#{summary.uniq.join(', ')}]"
|
291
|
+
else
|
292
|
+
msg << "'#{endpoint}' #{"("+health+")" if health} => [#{summary.uniq.join(', ')}]"
|
293
|
+
end
|
276
294
|
end
|
277
295
|
message = "Request failed after #{n} tries to #{exceptions.keys.size} endpoints: (#{msg.join(', ')})"
|
278
296
|
|
@@ -284,7 +302,7 @@ module RightSupport::Net
|
|
284
302
|
# its endpoints. Merely proxies the balancing policy's get_stats method. If
|
285
303
|
# no method exists in the balancing policy, a hash of endpoints with "n/a" is
|
286
304
|
# returned.
|
287
|
-
#
|
305
|
+
#
|
288
306
|
# Examples
|
289
307
|
#
|
290
308
|
# A RequestBalancer created with endpoints [1,2,3,4,5] and using a HealthCheck
|
@@ -310,8 +328,9 @@ module RightSupport::Net
|
|
310
328
|
def handle_exception(endpoint, e, t0)
|
311
329
|
fatal = fatal_exception?(e)
|
312
330
|
duration = sprintf('%.4f', Time.now - t0)
|
313
|
-
|
314
|
-
|
331
|
+
ept = @resolved_hostnames ? "#{lookup_hostname(endpoint)}(#{endpoint})" : "#{endpoint}"
|
332
|
+
msg = "RequestBalancer: rescued #{fatal ? 'fatal' : 'retryable'} #{e.class.name} " +
|
333
|
+
"during request to #{ept}: #{e.message} after #{duration} seconds"
|
315
334
|
logger.error msg
|
316
335
|
@options[:on_exception].call(fatal, e, endpoint) if @options[:on_exception]
|
317
336
|
|
@@ -342,7 +361,9 @@ module RightSupport::Net
|
|
342
361
|
end
|
343
362
|
|
344
363
|
def resolve
|
345
|
-
|
364
|
+
@resolved_hostnames = RightSupport::Net::DNS.resolve_with_hostnames(@endpoints)
|
365
|
+
resolved_endpoints = []
|
366
|
+
@resolved_hostnames.each_value{ |v| resolved_endpoints.concat(v) }
|
346
367
|
logger.info("RequestBalancer: resolved #{@endpoints.inspect} to #{resolved_endpoints.inspect}")
|
347
368
|
@ips = resolved_endpoints
|
348
369
|
@policy.set_endpoints(@ips)
|
@@ -106,13 +106,15 @@ module RightSupport
|
|
106
106
|
# === Return
|
107
107
|
# (String|Array|Hash):: Value(s) converted to decimal digit string
|
108
108
|
def self.enough_precision(value)
|
109
|
-
scale = [1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0]
|
110
|
-
enough = lambda { |v|
|
111
|
-
(v >=
|
112
|
-
(v >= 0
|
113
|
-
(v >= 0.
|
114
|
-
(v
|
115
|
-
(v
|
109
|
+
scale = [1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0]
|
110
|
+
enough = lambda { |v| v = v.abs
|
111
|
+
(v >= 10.0 ? 0 :
|
112
|
+
(v >= 1.0 ? 1 :
|
113
|
+
(v >= 0.1 ? 2 :
|
114
|
+
(v >= 0.01 ? 3 :
|
115
|
+
(v >= 0.001 ? 4 :
|
116
|
+
(v >= 0.0001 ? 5 :
|
117
|
+
(v >= 0.0000005 ? 6 : 0))))))) }
|
116
118
|
digit_str = lambda { |p, v| sprintf("%.#{p}f", (v * scale[p]).round / scale[p])}
|
117
119
|
|
118
120
|
if value.is_a?(Float)
|
data/right_support.gemspec
CHANGED
@@ -7,8 +7,8 @@ spec = Gem::Specification.new do |s|
|
|
7
7
|
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
8
8
|
|
9
9
|
s.name = 'right_support'
|
10
|
-
s.version = '2.6.
|
11
|
-
s.date = '2013-01-
|
10
|
+
s.version = '2.6.17'
|
11
|
+
s.date = '2013-01-29'
|
12
12
|
|
13
13
|
s.authors = ['Tony Spataro', 'Sergey Sergyenko', 'Ryan Williamson', 'Lee Kirchhoff', 'Sergey Enin', 'Alexey Karpik', 'Scott Messier']
|
14
14
|
s.email = 'support@rightscale.com'
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 53
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 2.6.
|
9
|
+
- 17
|
10
|
+
version: 2.6.17
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tony Spataro
|
@@ -21,7 +21,7 @@ autorequire:
|
|
21
21
|
bindir: bin
|
22
22
|
cert_chain: []
|
23
23
|
|
24
|
-
date: 2013-01-
|
24
|
+
date: 2013-01-29 00:00:00 -08:00
|
25
25
|
default_executable:
|
26
26
|
dependencies: []
|
27
27
|
|