Skip to content
This repository was archived by the owner on Jan 25, 2022. It is now read-only.

Commit

Permalink
Publish active app list (compressed) thru nats
Browse files Browse the repository at this point in the history
Change-Id: If0aa956ec55bdcd281525368b98a10860c8d47da
  • Loading branch information
Anfernee Gui committed Jun 27, 2012
1 parent 721ea78 commit e7b8b5b
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 21 deletions.
3 changes: 3 additions & 0 deletions config/router.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ pid: /var/vcap/sys/run/router.pid

# Uncomment and set true to show requests-per-second stats for all aps not only top 10. If not specified or set false only 10 apps are shown
# expose_all_apps: true
#
# enable_nonprod_apps: true
# flush_apps_interval: 30
2 changes: 2 additions & 0 deletions lib/router.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
require 'socket'
require 'yaml'
require 'openssl'
require 'set'
require 'zlib'

require 'rubygems'
require 'bundler/setup'
Expand Down
34 changes: 32 additions & 2 deletions lib/router/router.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,20 @@ def config(config)

@session_key = config['session_key'] || '14fbc303b76bacd1e0a3ab641c11d11400341c5d'
@expose_all_apps = config['status']['expose_all_apps'] if config['status']

@enable_nonprod_apps = config['enable_nonprod_apps'] || false
if @enable_nonprod_apps
@flush_apps_interval = config['flush_apps_interval'] || 30
@active_apps = Set.new
end
end

def setup_listeners
NATS.subscribe('router.register') { |msg|
msg_hash = Yajl::Parser.parse(msg, :symbolize_keys => true)
return unless uris = msg_hash[:uris]
uris.each { |uri| register_droplet(uri, msg_hash[:host], msg_hash[:port], msg_hash[:tags]) }
uris.each { |uri| register_droplet(uri, msg_hash[:host], msg_hash[:port],
msg_hash[:tags], msg_hash[:app]) }
}
NATS.subscribe('router.unregister') { |msg|
msg_hash = Yajl::Parser.parse(msg, :symbolize_keys => true)
Expand All @@ -56,6 +63,11 @@ def setup_sweepers
EM.add_periodic_timer(CHECK_SWEEPER) {
check_registered_urls
}
if @enable_nonprod_apps
EM.add_periodic_timer(@flush_apps_interval) do
flush_active_apps
end
end
end

def calc_rps
Expand Down Expand Up @@ -154,7 +166,7 @@ def lookup_droplet(url)
@droplets[url.downcase]
end

def register_droplet(url, host, port, tags)
def register_droplet(url, host, port, tags, app_id)
return unless host && port
url.downcase!
droplets = @droplets[url] || []
Expand All @@ -168,6 +180,7 @@ def register_droplet(url, host, port, tags)
}
tags.delete_if { |key, value| key.nil? || value.nil? } if tags
droplet = {
:app => app_id,
:host => host,
:port => port,
:clients => Hash.new(0),
Expand Down Expand Up @@ -212,5 +225,22 @@ def add_tag_metrics(tags)
end
end

def add_active_app(app_id)
return unless @enable_nonprod_apps

@active_apps << app_id
end

def flush_active_apps
return unless @enable_nonprod_apps

msg = Yajl::Encoder.encode(@active_apps.to_a)
zmsg = Zlib::Deflate.deflate(msg)

log.info("Flushing active apps, app size: #{@active_apps.size}, msg size: #{zmsg.size}")
NATS.publish('router.active_apps', zmsg)

@active_apps.clear
end
end
end
3 changes: 3 additions & 0 deletions lib/router/router_uls_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class ParserError < StandardError; end
# Update droplet stats
update_droplet_stats(droplet)

# Update active apps
Router.add_active_app(droplet[:app]) if droplet[:app]

# Get session cookie for droplet
new_sticky = Router.get_session_cookie(droplet)

Expand Down
21 changes: 21 additions & 0 deletions spec/functional/router_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,27 @@
app.verify_unregistered
end

it 'should properly publish active applications set' do
# setup the "app"
app1 = TestApp.new('router_test1.vcap.me')
app2 = TestApp.new('router_test2.vcap.me')
dea = DummyDea.new(@nats_server.uri, '1234')
dea.register_app(app1)
dea.register_app(app2)
app1.verify_registered
app2.verify_registered
original_apps_set = Set.new([app1.id, app2.id])

NATS.start(:uri => @nats_server.uri) do
NATS.subscribe('router.active_apps') do |msg|
apps_list = Yajl::Parser.parse(Zlib::Inflate.inflate(msg))
apps_set = Set.new(apps_list)
apps_set.should == original_apps_set

This comment has been minimized.

Copy link
@resouer

resouer Sep 4, 2012

The gerrit test result says that: "expected: #<Set: {}>..."

Why do this test expect a empty set?

This comment has been minimized.

Copy link
@anfernee

anfernee Sep 4, 2012

Contributor

it means apps_set is empty. it is expected to be original_apps_set.

NATS.stop
end
end
end

it 'should generate the same token as router v1 did' do
Router.config({})
token = Router.generate_session_cookie(ROUTER_V1_DROPLET)
Expand Down
4 changes: 3 additions & 1 deletion spec/functional/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ module Functional
class TestApp
class UsageError < StandardError; end

attr_reader :uris, :droplet
attr_reader :uris, :droplet, :id

def initialize(*uris)
@uris = uris
@id = Random.rand(10000)
end

def bind_droplet(droplet)
Expand Down Expand Up @@ -104,6 +105,7 @@ def reg_hash_for_app(app, tags = {})
{ :dea => @dea_id,
:host => @host,
:port => app.port,
:app => app.id,
:uris => app.uris,
:tags => tags
}
Expand Down
3 changes: 2 additions & 1 deletion spec/lib/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ def initialize(nats_uri, dir)

mbus = "mbus: #{nats_uri}"
log_info = "logging:\n level: debug\n file: #{logfile}"
enable_nonprod = "enable_nonprod_apps: true\nflush_apps_interval: 2\n"

config = %Q{sock: #{UNIX_SOCK}\n#{mbus}\n#{log_info}\npid: #{pidfile}\nlocal_route: 127.0.0.1\nstatus:\n port: #{STATUS_PORT}\n user: #{STATUS_USER}\n password: #{STATUS_PASSWD}}
config = %Q{sock: #{UNIX_SOCK}\n#{mbus}\n#{log_info}\n#{enable_nonprod}\npid: #{pidfile}\nlocal_route: 127.0.0.1\nstatus:\n port: #{STATUS_PORT}\n user: #{STATUS_USER}\n password: #{STATUS_PASSWD}}

# Write the config
File.open(config_file, 'w') { |f| f.puts "#{config}" }
Expand Down
34 changes: 17 additions & 17 deletions spec/unit/router_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ def setup
end

it 'should register a droplet' do
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {}, 123)
VCAP::Component.varz[:droplets].should == 1
VCAP::Component.varz[:urls].should == 1
end

it 'should allow proper lookup' do
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {}, 123)
droplets = Router.lookup_droplet('foo.vcap.me')
droplets.should be_instance_of Array
droplets.should have(1).items
Expand All @@ -57,38 +57,38 @@ def setup
end

it 'should allow looking up uppercase uri' do
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {}, 123)
droplets = Router.lookup_droplet('FOO.VCAP.ME')
droplets.should be_instance_of Array
droplets.should have(1).items
end

it 'should count droplets independent of URL' do
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {}, 123)
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {}, 123)
VCAP::Component.varz[:droplets].should == 2
VCAP::Component.varz[:urls].should == 1
end

it 'should return multiple droplets for a url when they exist' do
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {}, 123)
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {}, 123)
droplets = Router.lookup_droplet('foo.vcap.me')
droplets.should be_instance_of Array
droplets.should have(2).items
end

it 'should ignore duplicates' do
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {}, 123)
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {}, 123)
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {}, 123)
VCAP::Component.varz[:droplets].should == 2
VCAP::Component.varz[:urls].should == 1
end

it 'should record tags' do
VCAP::Component.varz[:tags]["component"].should be_nil
Router.register_droplet('foobar.vcap.me', '10.0.1.22', 2225, {"component" => "test"})
Router.register_droplet('foobar.vcap.me', '10.0.1.22', 2225, {"component" => "test"}, 123)
VCAP::Component.varz[:tags]["component"]["test"].should_not be_nil
droplets = Router.lookup_droplet('foobar.vcap.me')
droplets.first[:tags].should == {"component" => "test"}
Expand All @@ -102,30 +102,30 @@ def setup
end

it 'should unregister a droplet' do
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {}, 123)
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {}, 123)
Router.unregister_droplet('foo.vcap.me', '10.0.1.22', 2224)
VCAP::Component.varz[:droplets].should == 1
VCAP::Component.varz[:urls].should == 1
end

it 'should unregister a droplet that had tags' do
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {})
Router.register_droplet('foobar.vcap.me', '10.0.1.22', 2225, {"component" => "test"})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2224, {}, 123)
Router.register_droplet('foobar.vcap.me', '10.0.1.22', 2225, {"component" => "test"}, 123)
Router.unregister_droplet('foobar.vcap.me', '10.0.1.22', 2225)
VCAP::Component.varz[:droplets].should == 1
VCAP::Component.varz[:urls].should == 1
end

it 'should not return unregistered items' do
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {}, 123)
Router.unregister_droplet('foo.vcap.me', '10.0.1.22', 2222)
droplets = Router.lookup_droplet('foo.vcap.me')
droplets.should be_nil
end

it 'should properly account for urls and droplets' do
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {})
Router.register_droplet('foo.vcap.me', '10.0.1.22', 2222, {}, 123)
Router.unregister_droplet('foo.vcap.me', '10.0.1.22', 2222)
VCAP::Component.varz[:droplets].should == 0
VCAP::Component.varz[:urls].should == 0
Expand Down

0 comments on commit e7b8b5b

Please sign in to comment.