ktl 1.0.0-java → 1.1.0-java
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.
- 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
|