right_support 2.6.16 → 2.6.17
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.
@@ -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
|
|