ktl 1.0.0-java → 1.1.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ext/kafka.rb +20 -0
- data/lib/ktl.rb +1 -0
- data/lib/ktl/cluster.rb +32 -12
- data/lib/ktl/cluster_stats_task.rb +1 -1
- data/lib/ktl/continous_reassigner.rb +53 -0
- data/lib/ktl/migration_plan.rb +25 -6
- data/lib/ktl/reassigner.rb +59 -9
- data/lib/ktl/reassignment_task.rb +6 -3
- data/lib/ktl/shuffle_plan.rb +6 -18
- data/lib/ktl/version.rb +1 -1
- data/lib/ktl/zookeeper_client.rb +20 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 350c93c4fed5af08036c7e9e867df6f7c54cf26a
|
4
|
+
data.tar.gz: b3b963caa62735ca426a2d46919fbd09a350d67b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4b1da24ea11e84cca3fbbf678fecd01cbfb98d955ced80d44927935df43702a29ebc477e880dc9ffa0369c46f3235e6dd3ffa2e7cb51a903a8a89124b8b9ae6
|
7
|
+
data.tar.gz: 7d24168d5cde8623362a4e9873eb1b33e118c2e15c07975e7c6abbebc23a52911ef8878152cae2052d30b2c8ba36c2603afec39b52c32f0997a620f4f8511998
|
data/lib/ext/kafka.rb
CHANGED
@@ -12,6 +12,9 @@ end
|
|
12
12
|
|
13
13
|
module ZkClient
|
14
14
|
java_import 'org.I0Itec.zkclient.ZkClient'
|
15
|
+
java_import 'org.I0Itec.zkclient.IZkStateListener'
|
16
|
+
java_import 'org.I0Itec.zkclient.IZkDataListener'
|
17
|
+
java_import 'org.I0Itec.zkclient.IZkChildListener'
|
15
18
|
|
16
19
|
module Exception
|
17
20
|
include_package 'org.I0Itec.zkclient.exception'
|
@@ -127,6 +130,23 @@ module Kafka
|
|
127
130
|
)
|
128
131
|
Scala::Collection::JavaConversions.seq_as_java_list(broker_metadatas).to_a
|
129
132
|
end
|
133
|
+
|
134
|
+
def self.get_broker_rack(zk_client, broker_id)
|
135
|
+
broker_metadata = Kafka::Admin.get_broker_metadatas(zk_client, [broker_id]).first
|
136
|
+
if broker_metadata
|
137
|
+
rack = broker_metadata.rack
|
138
|
+
unless rack.defined?
|
139
|
+
raise "Broker #{broker_metadata.id} is missing rack information, unable to create rack aware shuffle plan."
|
140
|
+
end
|
141
|
+
rack.get
|
142
|
+
end
|
143
|
+
rescue Java::KafkaAdmin::AdminOperationException => e
|
144
|
+
if e.message.include? '--disable-rack-aware'
|
145
|
+
raise "Not all brokers have rack information. Unable to create rack aware shuffle plan."
|
146
|
+
else
|
147
|
+
raise e
|
148
|
+
end
|
149
|
+
end
|
130
150
|
end
|
131
151
|
|
132
152
|
module Protocol
|
data/lib/ktl.rb
CHANGED
@@ -42,6 +42,7 @@ require 'ktl/cluster_stats_task'
|
|
42
42
|
require 'ktl/decommission_plan'
|
43
43
|
require 'ktl/migration_plan'
|
44
44
|
require 'ktl/reassigner'
|
45
|
+
require 'ktl/continous_reassigner'
|
45
46
|
require 'ktl/reassignment_progress'
|
46
47
|
require 'ktl/reassignment_task'
|
47
48
|
require 'ktl/shuffle_plan'
|
data/lib/ktl/cluster.rb
CHANGED
@@ -28,16 +28,21 @@ module Ktl
|
|
28
28
|
end
|
29
29
|
|
30
30
|
desc 'migrate-broker', 'Migrate partitions from one broker to another'
|
31
|
-
option :from, aliases: %w[-f], type: :
|
32
|
-
option :to, aliases: %w[-t], type: :
|
31
|
+
option :from, aliases: %w[-f], type: :array, required: true, desc: 'Broker IDs to migrate away from'
|
32
|
+
option :to, aliases: %w[-t], type: :array, required: true, desc: 'Broker IDs to migrate to'
|
33
33
|
option :zookeeper, aliases: %w[-z], required: true, desc: 'ZooKeeper URI'
|
34
34
|
option :limit, aliases: %w[-l], type: :numeric, desc: 'Max number of partitions to reassign at a time'
|
35
|
+
option :verbose, aliases: %w[-v], desc: 'Verbose output'
|
36
|
+
option :dryrun, aliases: %w[-d], desc: 'Output reassignment plan without executing'
|
37
|
+
option :wait, aliases: %w[-w], type: :boolean, desc: 'Wait for all reassignments to finish'
|
38
|
+
option :delay, type: :numeric, desc: 'Delay in seconds between continous reassignment iterations, default 5s'
|
39
|
+
option :multi_step_migration, type: :boolean, default: true, desc: 'Perform migration in multiple steps, mirroring partitions to new brokers before removing the old'
|
35
40
|
def migrate_broker
|
36
41
|
with_zk_client do |zk_client|
|
37
|
-
|
38
|
-
plan = MigrationPlan.new(zk_client,
|
39
|
-
reassigner =
|
40
|
-
execute_reassignment(reassigner, plan)
|
42
|
+
old_brokers, new_brokers = options.values_at(:from, :to)
|
43
|
+
plan = MigrationPlan.new(zk_client, old_brokers.map(&:to_i), new_brokers.map(&:to_i), log_plan: options.verbose, logger: logger)
|
44
|
+
reassigner = create_reassigner(zk_client, options)
|
45
|
+
execute_reassignment(reassigner, plan, options)
|
41
46
|
end
|
42
47
|
end
|
43
48
|
|
@@ -51,6 +56,9 @@ module Ktl
|
|
51
56
|
option :zookeeper, aliases: %w[-z], required: true, desc: 'ZooKeeper URI'
|
52
57
|
option :verbose, aliases: %w[-v], desc: 'Verbose output'
|
53
58
|
option :dryrun, aliases: %w[-d], desc: 'Output reassignment plan without executing'
|
59
|
+
option :wait, aliases: %w[-w], type: :boolean, desc: 'Wait for all reassignments to finish'
|
60
|
+
option :delay, type: :numeric, desc: 'Delay in seconds between continous reassignment iterations, default 5s'
|
61
|
+
option :multi_step_migration, type: :boolean, default: true, desc: 'Perform migration in multiple steps, mirroring partitions to new brokers before removing the old'
|
54
62
|
def shuffle(regexp='.*')
|
55
63
|
with_zk_client do |zk_client|
|
56
64
|
plan_factory = if options.rack_aware
|
@@ -68,8 +76,8 @@ module Ktl
|
|
68
76
|
logger: logger,
|
69
77
|
log_plan: options.dryrun,
|
70
78
|
})
|
71
|
-
reassigner =
|
72
|
-
execute_reassignment(reassigner, plan, options
|
79
|
+
reassigner = create_reassigner(zk_client, options)
|
80
|
+
execute_reassignment(reassigner, plan, options)
|
73
81
|
end
|
74
82
|
end
|
75
83
|
|
@@ -77,6 +85,10 @@ module Ktl
|
|
77
85
|
option :limit, aliases: %w[-l], type: :numeric, desc: 'Max number of partitions to reassign at a time'
|
78
86
|
option :rendezvous, aliases: %w[-R], type: :boolean, desc: 'Whether to use Rendezvous-hashing'
|
79
87
|
option :zookeeper, aliases: %w[-z], required: true, desc: 'ZooKeeper URI'
|
88
|
+
option :verbose, aliases: %w[-v], desc: 'Verbose output'
|
89
|
+
option :dryrun, aliases: %w[-d], desc: 'Output reassignment plan without executing'
|
90
|
+
option :wait, aliases: %w[-w], type: :boolean, desc: 'Wait for all reassignments to finish'
|
91
|
+
option :delay, type: :numeric, desc: 'Delay in seconds between continous reassignment iterations, default 5s'
|
80
92
|
def decommission_broker(broker_id)
|
81
93
|
with_zk_client do |zk_client|
|
82
94
|
if options.rendezvous?
|
@@ -84,8 +96,8 @@ module Ktl
|
|
84
96
|
else
|
85
97
|
plan = DecommissionPlan.new(zk_client, broker_id.to_i)
|
86
98
|
end
|
87
|
-
reassigner =
|
88
|
-
execute_reassignment(reassigner, plan)
|
99
|
+
reassigner = create_reassigner(zk_client, options)
|
100
|
+
execute_reassignment(reassigner, plan, options)
|
89
101
|
end
|
90
102
|
end
|
91
103
|
|
@@ -101,8 +113,16 @@ module Ktl
|
|
101
113
|
|
102
114
|
private
|
103
115
|
|
104
|
-
def execute_reassignment(reassigner, plan,
|
105
|
-
ReassignmentTask.new(reassigner, plan, shell, logger: logger).execute(dryrun)
|
116
|
+
def execute_reassignment(reassigner, plan, options)
|
117
|
+
ReassignmentTask.new(reassigner, plan, shell, logger: logger).execute(options.dryrun)
|
118
|
+
end
|
119
|
+
|
120
|
+
def create_reassigner(zk_client, options)
|
121
|
+
if options.wait?
|
122
|
+
ContinousReassigner.new(zk_client, limit: options.limit, logger: logger, log_assignments: options.verbose, delay: options.delay, shell: shell, multi_step_migration: options.multi_step_migration)
|
123
|
+
else
|
124
|
+
Reassigner.new(zk_client, limit: options.limit, logger: logger, log_assignments: options.verbose, multi_step_migration: options.multi_step_migration)
|
125
|
+
end
|
106
126
|
end
|
107
127
|
end
|
108
128
|
end
|
@@ -19,7 +19,7 @@ module Ktl
|
|
19
19
|
brokers.foreach do |broker|
|
20
20
|
leader_for = ownership[broker.id]
|
21
21
|
share = leader_for.fdiv(partitions.size.to_f) * 100
|
22
|
-
@shell.say ' - %
|
22
|
+
@shell.say ' - %s leader for %d partitions (%.2f %%)' % [broker.to_s, leader_for, share]
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Ktl
|
4
|
+
class ContinousReassigner < Reassigner
|
5
|
+
include ZkClient::IZkDataListener
|
6
|
+
|
7
|
+
def initialize(zk_client, options={})
|
8
|
+
super(zk_client, options)
|
9
|
+
@latch = JavaConcurrent::CountDownLatch.new(1)
|
10
|
+
@sleeper = options[:sleeper] || java.lang.Thread
|
11
|
+
@delay = options[:delay] || 5
|
12
|
+
@shell = options[:shell]
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute(reassignment)
|
16
|
+
Signal.trap('SIGINT', proc { @logger.info 'Exiting due to Ctrl-C'; @latch.count_down })
|
17
|
+
@zk_client.watch_data(zk_utils.class.reassign_partitions_path, self)
|
18
|
+
if reassignment_in_progress?
|
19
|
+
@logger.info 'reassignment already in progress, watching for changes...'
|
20
|
+
progress = ReassignmentProgress.new(@zk_client, logger: @logger, verbose: true)
|
21
|
+
progress.display(@shell)
|
22
|
+
else
|
23
|
+
reassign(reassignment)
|
24
|
+
end
|
25
|
+
@latch.await
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle_data_change(path, data)
|
29
|
+
parsed_data = JSON.parse(data)
|
30
|
+
if (partitions = parsed_data['partitions'])
|
31
|
+
partitions = partitions.map { |r| r.values_at('topic', 'partition').join(':') }
|
32
|
+
@logger.debug sprintf('%d partitions left to reassign (%p)', partitions.size, partitions.size <= 5 ? partitions : '...')
|
33
|
+
else
|
34
|
+
@logger.info sprintf('Data without `partitions` key: %p', parsed_data)
|
35
|
+
end
|
36
|
+
rescue => e
|
37
|
+
@logger.error sprintf('Bad data: %p', data)
|
38
|
+
end
|
39
|
+
|
40
|
+
def handle_data_deleted(path)
|
41
|
+
reassignment = load_overflow
|
42
|
+
if reassignment.empty?
|
43
|
+
@zk_client.unsubscribe_data(zk_utils.class.reassign_partitions_path, self)
|
44
|
+
delete_previous_state
|
45
|
+
@latch.count_down
|
46
|
+
else
|
47
|
+
@logger.info sprintf('Waiting %ds before next assignment', @delay)
|
48
|
+
@sleeper.sleep(@delay * 1000)
|
49
|
+
reassign(reassignment)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/ktl/migration_plan.rb
CHANGED
@@ -2,10 +2,22 @@
|
|
2
2
|
|
3
3
|
module Ktl
|
4
4
|
class MigrationPlan
|
5
|
-
def initialize(zk_client,
|
5
|
+
def initialize(zk_client, from_brokers, to_brokers, options = {})
|
6
6
|
@zk_client = zk_client
|
7
|
-
@
|
8
|
-
@
|
7
|
+
@from_brokers = from_brokers
|
8
|
+
@to_brokers = to_brokers
|
9
|
+
if @from_brokers.length != @to_brokers.length
|
10
|
+
raise ArgumentError, "Both brokers lists must be of equal length. From: #{@from_brokers}, To: #{@to_brokers}"
|
11
|
+
elsif !(@from_brokers & @to_brokers).empty?
|
12
|
+
raise ArgumentError, "Broker lists must be mutually exclusive. From: #{@from_brokers}, To: #{@to_brokers}"
|
13
|
+
end
|
14
|
+
from_racks = from_brokers.map {|broker_id| Kafka::Admin.get_broker_rack(zk_client, broker_id)}
|
15
|
+
to_racks = to_brokers.map {|broker_id| Kafka::Admin.get_broker_rack(zk_client, broker_id)}
|
16
|
+
if from_racks != to_racks && from_racks.compact.any?
|
17
|
+
raise ArgumentError, "Both broker lists must have the same rack setup. From: #{from_racks}, To: #{to_racks}"
|
18
|
+
end
|
19
|
+
@logger = options[:logger] || NullLogger.new
|
20
|
+
@log_plan = !!options[:log_plan]
|
9
21
|
end
|
10
22
|
|
11
23
|
def generate
|
@@ -15,9 +27,16 @@ module Ktl
|
|
15
27
|
assignments.each do |item|
|
16
28
|
topic_partition = item.first
|
17
29
|
replicas = item.last
|
18
|
-
|
19
|
-
|
20
|
-
|
30
|
+
new_replicas = replicas
|
31
|
+
@from_brokers.each_with_index do |from_broker, index|
|
32
|
+
to_broker = @to_brokers[index]
|
33
|
+
if new_replicas.contains?(from_broker)
|
34
|
+
replacement_index = new_replicas.index_of(from_broker)
|
35
|
+
new_replicas = new_replicas.updated(replacement_index, to_broker, CanBuildFrom)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
if replicas != new_replicas
|
39
|
+
@logger.debug "Moving #{topic_partition.topic},#{topic_partition.partition} from #{replicas} to #{new_replicas}" if @log_plan
|
21
40
|
plan += Scala::Tuple.new(topic_partition, new_replicas)
|
22
41
|
end
|
23
42
|
end
|
data/lib/ktl/reassigner.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
module Ktl
|
4
4
|
class Reassigner
|
5
|
+
|
6
|
+
attr_reader :limit
|
7
|
+
|
5
8
|
def initialize(zk_client, options={})
|
6
9
|
@zk_client = zk_client
|
7
10
|
@limit = options[:limit]
|
@@ -9,6 +12,7 @@ module Ktl
|
|
9
12
|
@state_path = '/ktl/reassign'
|
10
13
|
@logger = options[:logger] || NullLogger.new
|
11
14
|
@log_assignments = !!options[:log_assignments]
|
15
|
+
@multi_step_migration = options[:multi_step_migration]
|
12
16
|
end
|
13
17
|
|
14
18
|
def reassignment_in_progress?
|
@@ -31,29 +35,72 @@ module Ktl
|
|
31
35
|
data = parse_reassignment_json(overflow_json)
|
32
36
|
overflow = overflow.send('++', data)
|
33
37
|
end
|
34
|
-
delete_previous_overflow
|
35
38
|
overflow
|
39
|
+
rescue ZkClient::Exception::ZkNoNodeException
|
40
|
+
Scala::Collection::Map.empty
|
36
41
|
end
|
37
42
|
|
38
43
|
def execute(reassignment)
|
44
|
+
reassign(reassignment)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
JSON_MAX_SIZE = 1024**2
|
50
|
+
|
51
|
+
def reassign(reassignment)
|
52
|
+
if (limit)
|
53
|
+
@logger.info 'reassigning %d of %d partitions' % [limit, reassignment.size]
|
54
|
+
else
|
55
|
+
@logger.info 'reassigning %d partitions' % reassignment.size
|
56
|
+
end
|
57
|
+
|
39
58
|
reassignments = split(reassignment, @limit)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
59
|
+
reassignment_candidates = reassignments.shift
|
60
|
+
actual_reassignment = Scala::Collection::Map.empty
|
61
|
+
next_step_assignments = Scala::Collection::Map.empty
|
62
|
+
Scala::Collection::JavaConversions.as_java_iterable(reassignment_candidates).each do |pr|
|
63
|
+
topic_and_partition, replicas = pr.elements
|
64
|
+
if @multi_step_migration && step1_replicas = is_two_step_operation(topic_and_partition, replicas)
|
65
|
+
if step1_replicas.uniq != step1_replicas
|
66
|
+
raise "Multiple replicas on the same broker, this should not happen... #{step1_replicas}"
|
67
|
+
end
|
68
|
+
step1_replicas = Scala::Collection::JavaConversions.as_scala_iterable(step1_replicas)
|
69
|
+
next_step_assignments += pr
|
70
|
+
actual_reassignment += Scala::Tuple.new(topic_and_partition, step1_replicas)
|
71
|
+
brokers = Scala::Collection::JavaConversions.as_java_iterable(step1_replicas).to_a
|
72
|
+
eventual_brokers = Scala::Collection::JavaConversions.as_java_iterable(replicas).to_a
|
73
|
+
@logger.debug "Mirroring #{topic_and_partition.topic},#{topic_and_partition.partition} to #{brokers.join(',')} for eventual transition to #{eventual_brokers.join(',')}" if @log_assignments
|
74
|
+
else
|
75
|
+
actual_reassignment += pr
|
44
76
|
brokers = Scala::Collection::JavaConversions.as_java_iterable(replicas).to_a
|
45
|
-
@logger.
|
77
|
+
@logger.debug "Assigning #{topic_and_partition.topic},#{topic_and_partition.partition} to #{brokers.join(',')}" if @log_assignments
|
46
78
|
end
|
47
79
|
end
|
48
80
|
json = reassignment_json(actual_reassignment)
|
49
81
|
@zk_client.reassign_partitions(json)
|
50
|
-
manage_overflow(reassignments)
|
82
|
+
manage_overflow(split(next_step_assignments, nil) + reassignments)
|
51
83
|
manage_progress_state(actual_reassignment)
|
52
84
|
end
|
53
85
|
|
54
|
-
|
86
|
+
def is_two_step_operation(topic_and_partition, final_replicas)
|
87
|
+
replicas = Scala::Collection::JavaConversions.as_java_iterable(final_replicas).to_a.uniq
|
88
|
+
topic_list = Scala::Collection::JavaConversions.as_scala_iterable([topic_and_partition.topic])
|
89
|
+
assignments = ScalaEnumerable.new(@zk_client.replica_assignment_for_topics(topic_list))
|
90
|
+
assignments.each do |item|
|
91
|
+
item_topic_partition = item.first
|
92
|
+
if item_topic_partition.partition == topic_and_partition.partition
|
93
|
+
item_replicas = Scala::Collection::JavaConversions.as_java_iterable(item.last).to_a.uniq
|
94
|
+
diff_replicas = replicas - item_replicas
|
95
|
+
unless diff_replicas.empty?
|
96
|
+
transition_replicas = item_replicas + diff_replicas
|
97
|
+
return transition_replicas
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
55
101
|
|
56
|
-
|
102
|
+
false
|
103
|
+
end
|
57
104
|
|
58
105
|
def manage_progress_state(reassignment)
|
59
106
|
delete_previous_state
|
@@ -73,6 +120,9 @@ module Ktl
|
|
73
120
|
@zk_client.delete_znode(overflow_path(index))
|
74
121
|
end
|
75
122
|
rescue ZkClient::Exception::ZkNoNodeException
|
123
|
+
# no-op
|
124
|
+
rescue => e
|
125
|
+
puts e.backtrace.join($/)
|
76
126
|
end
|
77
127
|
|
78
128
|
def manage_overflow(reassignments)
|
@@ -11,7 +11,12 @@ module Ktl
|
|
11
11
|
|
12
12
|
def execute(dryrun = false)
|
13
13
|
if @reassigner.reassignment_in_progress?
|
14
|
-
@
|
14
|
+
if @reassigner.is_a?(ContinousReassigner)
|
15
|
+
reassignment = @reassigner.load_overflow
|
16
|
+
@reassigner.execute(reassignment)
|
17
|
+
else
|
18
|
+
@logger.warn 'reassignment already in progress, exiting'
|
19
|
+
end
|
15
20
|
else
|
16
21
|
if use_overflow?
|
17
22
|
@logger.info 'loading overflow data'
|
@@ -21,7 +26,6 @@ module Ktl
|
|
21
26
|
reassignment = @plan.generate
|
22
27
|
end
|
23
28
|
if reassignment.size > 0
|
24
|
-
@logger.info 'reassigning %d partitions' % reassignment.size
|
25
29
|
if dryrun
|
26
30
|
@logger.info 'dryrun detected, skipping reassignment'
|
27
31
|
else
|
@@ -43,4 +47,3 @@ module Ktl
|
|
43
47
|
end
|
44
48
|
end
|
45
49
|
end
|
46
|
-
|
data/lib/ktl/shuffle_plan.rb
CHANGED
@@ -55,9 +55,11 @@ module Ktl
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def assign_replicas_to_brokers(topic, brokers, partition_count, replica_count)
|
58
|
-
broker_metadatas
|
59
|
-
|
60
|
-
|
58
|
+
@broker_metadatas ||= begin
|
59
|
+
broker_metadatas = Kafka::Admin.get_broker_metadatas(@zk_client, brokers)
|
60
|
+
Scala::Collection::JavaConversions.as_scala_iterable(broker_metadatas).to_seq
|
61
|
+
end
|
62
|
+
Kafka::Admin.assign_replicas_to_brokers(@broker_metadatas, partition_count, replica_count)
|
61
63
|
rescue Kafka::Admin::AdminOperationException => e
|
62
64
|
raise ArgumentError, sprintf('%s (%s)', e.message, e.class.name), e.backtrace
|
63
65
|
end
|
@@ -125,21 +127,7 @@ module Ktl
|
|
125
127
|
private
|
126
128
|
|
127
129
|
def rack_for(broker_id)
|
128
|
-
|
129
|
-
broker_metadata = Kafka::Admin.get_broker_metadatas(@zk_client, [broker_id]).first
|
130
|
-
rack = broker_metadata.rack
|
131
|
-
unless rack.isDefined
|
132
|
-
raise "Broker #{broker_metadata.id} is missing rack information, unable to create rack aware shuffle plan."
|
133
|
-
end
|
134
|
-
@rack_mappings[broker_id] = rack.get
|
135
|
-
end
|
136
|
-
@rack_mappings[broker_id]
|
137
|
-
rescue Java::KafkaAdmin::AdminOperationException => e
|
138
|
-
if e.message.match '--disable-rack-aware'
|
139
|
-
raise "Not all brokers have rack information. Unable to create rack aware shuffle plan."
|
140
|
-
else
|
141
|
-
raise e
|
142
|
-
end
|
130
|
+
@rack_mappings[broker_id] ||= Kafka::Admin.get_broker_rack(@zk_client, broker_id)
|
143
131
|
end
|
144
132
|
end
|
145
133
|
end
|
data/lib/ktl/version.rb
CHANGED
data/lib/ktl/zookeeper_client.rb
CHANGED
@@ -84,6 +84,22 @@ module Ktl
|
|
84
84
|
@utils.path_exists(path)
|
85
85
|
end
|
86
86
|
|
87
|
+
def watch_state(path, listener)
|
88
|
+
zk_client.subscribe_state_changes(path, listener)
|
89
|
+
end
|
90
|
+
|
91
|
+
def watch_data(path, listener)
|
92
|
+
zk_client.subscribe_data_changes(path, listener)
|
93
|
+
end
|
94
|
+
|
95
|
+
def watch_child(path, listener)
|
96
|
+
zk_client.subscribe_child_changes(path, listener)
|
97
|
+
end
|
98
|
+
|
99
|
+
def unsubscribe_data(path, listener)
|
100
|
+
zk_client.unsubscribe_data_changes(path, listener)
|
101
|
+
end
|
102
|
+
|
87
103
|
private
|
88
104
|
|
89
105
|
CONCURRENCY = 8
|
@@ -107,5 +123,9 @@ module Ktl
|
|
107
123
|
acc.send('++', v)
|
108
124
|
end
|
109
125
|
end
|
126
|
+
|
127
|
+
def zk_client
|
128
|
+
@zk_client ||= @utils.class.create_zk_client(@uri, 5_000, 5_000)
|
129
|
+
end
|
110
130
|
end
|
111
131
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ktl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Burt Platform Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -64,6 +64,7 @@ files:
|
|
64
64
|
- lib/ktl/cluster.rb
|
65
65
|
- lib/ktl/cluster_stats_task.rb
|
66
66
|
- lib/ktl/command.rb
|
67
|
+
- lib/ktl/continous_reassigner.rb
|
67
68
|
- lib/ktl/decommission_plan.rb
|
68
69
|
- lib/ktl/migration_plan.rb
|
69
70
|
- lib/ktl/reassigner.rb
|