Class: Invoker::Power::Balancer

Inherits:
Object
  • Object
show all
Defined in:
lib/invoker/power/balancer.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(connection, protocol) ⇒ Balancer

Returns a new instance of Balancer.



41
42
43
44
45
46
47
48
# File 'lib/invoker/power/balancer.rb', line 41

def initialize(connection, protocol)
  @connection = connection
  @protocol = protocol
  @http_parser = HttpParser.new(protocol)
  @session = nil
  @upgraded_to = nil
  @buffer = []
end

Instance Attribute Details

#connectionObject

Returns the value of attribute connection.



25
26
27
# File 'lib/invoker/power/balancer.rb', line 25

def connection
  @connection
end

#http_parserObject

Returns the value of attribute http_parser.



25
26
27
# File 'lib/invoker/power/balancer.rb', line 25

def http_parser
  @http_parser
end

#protocolObject

Returns the value of attribute protocol.



25
26
27
# File 'lib/invoker/power/balancer.rb', line 25

def protocol
  @protocol
end

#sessionObject

Returns the value of attribute session.



25
26
27
# File 'lib/invoker/power/balancer.rb', line 25

def session
  @session
end

#upgraded_toObject

Returns the value of attribute upgraded_to.



25
26
27
# File 'lib/invoker/power/balancer.rb', line 25

def upgraded_to
  @upgraded_to
end

Class Method Details

.run(options = {}) ⇒ Object



27
28
29
30
# File 'lib/invoker/power/balancer.rb', line 27

def self.run(options = {})
  start_http_proxy(InvokerHttpProxy, 'http', options)
  start_http_proxy(InvokerHttpsProxy, 'https', options)
end

.start_http_proxy(proxy_class, protocol, options) ⇒ Object



32
33
34
35
36
37
38
39
# File 'lib/invoker/power/balancer.rb', line 32

def self.start_http_proxy(proxy_class, protocol, options)
  port = protocol == 'http' ? Invoker.config.http_port : Invoker.config.https_port
  EventMachine.start_server('0.0.0.0', port,
                            proxy_class, options) do |connection|
    balancer = Balancer.new(connection, protocol)
    balancer.install_callbacks
  end
end

Instance Method Details

#append_for_http_parsing(data) ⇒ Object



92
93
94
95
96
97
# File 'lib/invoker/power/balancer.rb', line 92

def append_for_http_parsing(data)
  http_parser << data
rescue HTTP::Parser::Error
  http_parser.reset
  connection.close_connection_after_writing
end

#backend_data(backend, data) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/invoker/power/balancer.rb', line 99

def backend_data(backend, data)
  @backend_data = true

  # check backend data for websockets connection. check for upgrade headers
  # - Upgarde: websocket\r\n
  if data =~ /Upgrade: websocket/
    @upgraded_to = "websocket"
  end

  data
end

#complete_message_received(full_message) ⇒ Object



58
59
60
61
# File 'lib/invoker/power/balancer.rb', line 58

def complete_message_received(full_message)
  connection.relay_to_servers(full_message)
  http_parser.reset
end

#frontend_disconnect(backend, name) ⇒ Object



111
112
113
114
115
116
117
118
# File 'lib/invoker/power/balancer.rb', line 111

def frontend_disconnect(backend, name)
  http_parser.reset
  unless @backend_data
    return_error_page(503)
  end
  @backend_data = false
  connection.close_connection_after_writing if backend == session
end

#headers_received(headers) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/invoker/power/balancer.rb', line 63

def headers_received(headers)
  if @session
    return
  end
  @session = UUID.generate()
  if !headers['Host'] || headers['Host'].empty?
    return_error_page(400)
    return
  end

  dns_check_response = UrlRewriter.new.select_backend_config(headers['Host'])
  if dns_check_response && dns_check_response.port
    connection.server(session, host: dns_check_response.ip, port: dns_check_response.port)
  else
    return_error_page(404)
    http_parser.reset
    connection.close_connection_after_writing
  end
end

#install_callbacksObject



50
51
52
53
54
55
56
# File 'lib/invoker/power/balancer.rb', line 50

def install_callbacks
  http_parser.on_headers_complete { |headers| headers_received(headers) }
  http_parser.on_message_complete { |full_message| complete_message_received(full_message) }
  connection.on_data { |data| upstream_data(data) }
  connection.on_response { |backend, data| backend_data(backend, data) }
  connection.on_finish { |backend, name| frontend_disconnect(backend, name) }
end

#upstream_data(data) ⇒ Object



83
84
85
86
87
88
89
90
# File 'lib/invoker/power/balancer.rb', line 83

def upstream_data(data)
  if upgraded_to == "websocket"
    data
  else
    append_for_http_parsing(data)
    nil
  end
end