galerab 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/bin/galerab ADDED
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'galerab'
4
+
5
+ path = ARGV.include?('-c') && ARGV[ARGV.index('-c') + 1]
6
+
7
+ unless path
8
+ path = ENV['GALERAB_CONFIG_PATH']
9
+
10
+ unless path
11
+ puts "Missing path for configuration file"
12
+ puts "Usage: command -c path/file.yml"
13
+ abort
14
+ end
15
+ end
16
+
17
+
18
+ puts "[#{Process.pid}] galerab starting with config file at #{ARGV[1]}"
19
+
20
+ confs = Configuration.new(path).conf
21
+
22
+ confs.each do |conf|
23
+ backend = Backend.new(conf[1])
24
+ conf = conf[1]
25
+
26
+ fork do
27
+ t = Thread.new do
28
+ while true
29
+ # Here we check if the backend is ready
30
+ next_backend = backend.get_next
31
+ puts "\nChecking if (wsrep_ready == ON) #{next_backend}\n"
32
+
33
+ begin
34
+ Sequel.connect(
35
+ "mysql://#{conf["user"]}:#{conf["password"]}@#{next_backend}/#{conf["database"]}"
36
+ ).fetch("show status like 'wsrep_ready'") do |row|
37
+ #row[:Value] = "OFF"
38
+ if row[:Value] == "OFF"
39
+ puts "#{next_backend} is not ready"
40
+ backend.not_ready.push(next_backend) unless backend.not_ready.include?(next_backend)
41
+ elsif row[:Value] == "ON"
42
+ puts "#{next_backend} is ready"
43
+ backend.not_ready.delete(next_backend) if backend.not_ready
44
+ end
45
+ end
46
+ rescue
47
+ puts "#{next_backend} is not ready"
48
+ backend.not_ready.push(next_backend) unless backend.not_ready.include?(next_backend)
49
+ end
50
+
51
+ sleep conf["check_every"]
52
+ end
53
+ end
54
+
55
+ t.join
56
+ BalancingProxy::Server.run(backend)
57
+ end
58
+ end
59
+
60
+ trap (:SIGHUP) do
61
+ $stdout.puts "Received SIGHUP, reloading config file"
62
+ backend.conf = YAML.load_file(ARGV[1])
63
+ $stdout.puts backend.conf["balancer_ports"].inspect
64
+ end
65
+
66
+ # release child processes before exit
67
+ confs.each { |conf| Process.wait }
data/files/galerab ADDED
@@ -0,0 +1,22 @@
1
+ #! /bin/sh
2
+
3
+ # Carry out specific functions when asked to by the system
4
+ case "$1" in
5
+ start)
6
+ echo "Starting script galerab "
7
+ nohup /usr/sbin/balancer </dev/null >/dev/null 2>&1 &
8
+ ;;
9
+ stop)
10
+ echo "Stopping script galerab"
11
+ kill `ps -ef | grep balancer | grep -v grep | awk '{print $2}'`
12
+ reload)
13
+ echo "reloading script galerab"
14
+ kill -s SIGHUP `ps -ef | grep balancer | grep -v grep | awk '{print $2}'`
15
+ ;;
16
+ *)
17
+ echo "Usage: /etc/init.d/galerab {start|stop}"
18
+ exit 1
19
+ ;;
20
+ esac
21
+
22
+ exit 0
data/files/galerab.yml ADDED
@@ -0,0 +1,17 @@
1
+ 1:
2
+ backends: ["localhost"]
3
+ check_every: 10
4
+ user: root
5
+ password: root
6
+ database: mysql
7
+ balancer_port: 3307
8
+ backend_port: 3306
9
+
10
+ 2:
11
+ backends: ["192.168.1.11"]
12
+ check_every: 10
13
+ user: root
14
+ password: root
15
+ database: mysql
16
+ balancer_port: 3308
17
+ backend_port: 3306
data/lib/galerab.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "rubygems"
2
+ require "thread"
3
+ require 'yaml'
4
+ require 'mysql2'
5
+ require 'sequel'
6
+ require 'em-proxy'
7
+ require 'ansi/code'
8
+ require 'galerab/backend'
9
+ require 'galerab/configuration'
10
+ require 'galerab/balancing_proxy'
@@ -0,0 +1,25 @@
1
+ class Backend
2
+ attr_accessor :not_ready, :conf
3
+
4
+ def initialize(conf)
5
+ @next_host = 0
6
+ @list = conf['backends']
7
+ @conf = conf
8
+ @not_ready = Array.new
9
+ end
10
+
11
+ # round robin load-balancing
12
+ def get_next
13
+ @next_host = @next_host + 1
14
+ @next_host = 0 if @next_host >= @list.size
15
+ unless @not_ready.include?(@list[@next_host])
16
+ @list[@next_host]
17
+ else
18
+ begin
19
+ get_next
20
+ rescue SystemStackError
21
+ nil
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,68 @@
1
+ module BalancingProxy
2
+ extend self
3
+
4
+ # Callbacks for em-proxy events
5
+ #
6
+ module Callbacks
7
+ include ANSI::Code
8
+ extend self
9
+
10
+ def on_select
11
+ lambda do |backend|
12
+ puts black_on_white { 'on_select'.ljust(12) } + " #{backend.inspect}"
13
+ backend.increment_counter if Backend.strategy == :balanced
14
+ end
15
+ end
16
+
17
+ def on_connect
18
+ lambda do |backend|
19
+ puts black_on_magenta { 'on_connect'.ljust(12) } + ' ' + bold { backend }
20
+ end
21
+ end
22
+
23
+ def on_data
24
+ lambda do |data|
25
+ puts black_on_yellow { 'on_data'.ljust(12) }, data
26
+ data
27
+ end
28
+ end
29
+
30
+ def on_response
31
+ lambda do |backend, resp|
32
+ puts black_on_green { 'on_response'.ljust(12) } + " from #{backend}", resp
33
+ resp
34
+ end
35
+ end
36
+
37
+ def on_finish
38
+ lambda do |backend|
39
+ puts black_on_cyan { 'on_finish'.ljust(12) } + " for #{backend}", ''
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ module Server
46
+ def run(backend)
47
+ # run the proxy server and wait for connections
48
+ balancer_port = backend.conf["balancer_port"]
49
+ backend_port = backend.conf["backend_port"]
50
+ puts ANSI::Code.bold { "Launching proxy at 0.0.0.0:#{balancer_port}...\n" }
51
+
52
+ Proxy.start(:host => '0.0.0.0', :port => balancer_port, :debug => false) do |conn|
53
+ backend_host = backend.get_next
54
+ if backend_host
55
+ conn.server backend_host, :host => backend_host, :port => backend_port
56
+ puts ANSI::Code.bold { "Farwarding to #{backend_host}\n" }
57
+
58
+ conn.on_connect &Callbacks.on_connect
59
+ conn.on_data &Callbacks.on_data
60
+ conn.on_response &Callbacks.on_response
61
+ conn.on_finish &Callbacks.on_finish
62
+ end
63
+ end
64
+ end
65
+
66
+ module_function :run
67
+ end
68
+ end
@@ -0,0 +1,7 @@
1
+ class Configuration
2
+ attr_accessor :conf
3
+
4
+ def initialize(path)
5
+ @conf = YAML.load_file(path)
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ class Proxy
2
+ def self.stop
3
+ puts "Terminating ProxyServer"
4
+ EventMachine.stop
5
+ end
6
+
7
+ # this is not used
8
+ def self.kill_childs(servers, signal)
9
+ servers.each do |server|
10
+ puts "Killing process #{server[:pid]} with #{signal} signal."
11
+ Process.kill(signal, server[:pid])
12
+ end
13
+
14
+ Process.kill(signal, Process.pid)
15
+ end
16
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configuration do
4
+ before(:each) do
5
+ @conf = Configuration.new(ENV['GALERAB_CONFIG_PATH']).conf
6
+ end
7
+
8
+ context "when loading the file" do
9
+ it "should load the YAML file" do
10
+ @conf.should be_true
11
+ end
12
+
13
+ it "should find two balancers in the config file" do
14
+ @conf.size.should be == 2
15
+ end
16
+
17
+ it "gets the backends for balancer 1" do
18
+ @conf[1]['backends'].size.should be == 3
19
+ @conf[1]['backends'][0].should be == "192.168.10.101"
20
+ @conf[1]['backends'][1].should be == "192.168.10.102"
21
+ @conf[1]['backends'][2].should be == "192.168.10.103"
22
+ end
23
+
24
+ it "loads the other parameters" do
25
+ @conf[1]['check_every'].size.should be == 8
26
+ @conf[1]['user'].should be == "your_user"
27
+ @conf[1]['password'].should be == "your_password"
28
+ @conf[1]['database'].should be == "your_db"
29
+ @conf[1]['balancer_port'].should be == 3307
30
+ @conf[1]['backend_port'].should be == 3306
31
+ end
32
+ end
33
+ end
34
+
35
+ describe Backend do
36
+ before(:each) do
37
+ @conf = Configuration.new(ENV['GALERAB_CONFIG_PATH']).conf.first
38
+ @backend = Backend.new(@conf[1])
39
+ end
40
+
41
+ context "round robin load balancing" do
42
+ it "returns the next backend" do
43
+ @backend.get_next.should be == "192.168.10.102"
44
+ @backend.get_next.should be == "192.168.10.103"
45
+ @backend.get_next.should be == "192.168.10.101"
46
+ @backend.get_next.should be == "192.168.10.102" # and again... that's why it is called round robin
47
+ end
48
+
49
+ it "does not return a backend that is not ready" do
50
+ @backend.not_ready.push("192.168.10.103")
51
+ @backend.get_next.should be == "192.168.10.102"
52
+ @backend.get_next.should be == "192.168.10.101"
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configuration do
4
+ before(:each) do
5
+ @conf = Configuration.new(ENV['GALERAB_CONFIG_PATH']).conf
6
+ end
7
+
8
+ context "when loading the file" do
9
+ it "should load the YAML file" do
10
+ @conf.should be_true
11
+ end
12
+
13
+ it "should find two balancers in the config file" do
14
+ @conf.size.should be == 2
15
+ end
16
+
17
+ it "gets the backends for balancer 1" do
18
+ @conf[1]['backends'].size.should be == 3
19
+ @conf[1]['backends'][0].should be == "192.168.10.101"
20
+ @conf[1]['backends'][1].should be == "192.168.10.102"
21
+ @conf[1]['backends'][2].should be == "192.168.10.103"
22
+ end
23
+
24
+ it "loads the other parameters" do
25
+ @conf[1]['check_every'].size.should be == 8
26
+ @conf[1]['user'].should be == "your_user"
27
+ @conf[1]['password'].should be == "your_password"
28
+ @conf[1]['database'].should be == "your_db"
29
+ @conf[1]['balancer_port'].should be == 3307
30
+ @conf[1]['backend_port'].should be == 3306
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ require 'rspec'
2
+ ENV['GALERAB_CONFIG_PATH'] = File.dirname(__FILE__) + '/galerab.yml'
3
+ require 'galerab'
4
+
5
+ RSpec.configure do |config|
6
+ config.color_enabled = true
7
+ config.formatter = 'documentation'
8
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: galerab
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Riccardo Tacconi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mysql2
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.3.11
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.3.11
30
+ - !ruby/object:Gem::Dependency
31
+ name: sequel
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 3.40.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 3.40.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: em-proxy
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.1.7
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.7
62
+ - !ruby/object:Gem::Dependency
63
+ name: ansi
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.4.3
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.4.3
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '2.5'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '2.5'
110
+ description: This load balancer is a transparent proxy to route r/w requests to MySql
111
+ backends
112
+ email: rtacconi@virtuelogic.net
113
+ executables:
114
+ - galerab
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - lib/galerab.rb
119
+ - lib/galerab/backend.rb
120
+ - lib/galerab/balancing_proxy.rb
121
+ - lib/galerab/configuration.rb
122
+ - lib/galerab/proxy.rb
123
+ - bin/galerab
124
+ - files/galerab
125
+ - files/galerab.yml
126
+ - spec/lib/backend_spec.rb
127
+ - spec/lib/configuration_spec.rb
128
+ - spec/spec_helper.rb
129
+ homepage: http://github.com/rtacconi/galerab
130
+ licenses:
131
+ - MIT
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ - lib
137
+ - lib/galera
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 1.8.24
153
+ signing_key:
154
+ specification_version: 3
155
+ summary: Load balancer for galera cluster
156
+ test_files:
157
+ - spec/lib/backend_spec.rb
158
+ - spec/lib/configuration_spec.rb
159
+ - spec/spec_helper.rb
160
+ has_rdoc: