Skip to content

Commit 4084688

Browse files
author
Luis Sanchez
committed
[FAB-1164] Create broker connection to partion leader
Subtask of FAB-890 Changed newBroker to: - bootstrap from any of the bootstrap servers specifed. - return the leader for the topic/partition specified by config.Kafka.Topic and config.Kafka.PartitionID Added TestNewBrokerReturnsPartitionLeader unit test. Change-Id: Ib8b5de11c6822307aef6c127c5bd7074e18329ab Signed-off-by: Luis Sanchez <[email protected]>
1 parent af0cd3e commit 4084688

File tree

2 files changed

+109
-2
lines changed

2 files changed

+109
-2
lines changed

orderer/kafka/broker.go

+51-2
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,59 @@ type brokerImpl struct {
3535
}
3636

3737
func newBroker(conf *config.TopLevel) Broker {
38-
broker := sarama.NewBroker(conf.Kafka.Brokers[0])
38+
39+
// connect to one of the bootstrap servers
40+
var bootstrapServer *sarama.Broker
41+
for _, hostPort := range conf.Kafka.Brokers {
42+
broker := sarama.NewBroker(hostPort)
43+
if err := broker.Open(nil); err != nil {
44+
logger.Warningf("Failed to connect to bootstrap server at %s: %v.", hostPort, err)
45+
continue
46+
}
47+
if connected, err := broker.Connected(); !connected {
48+
logger.Warningf("Failed to connect to bootstrap server at %s: %v.", hostPort, err)
49+
continue
50+
}
51+
bootstrapServer = broker
52+
break
53+
}
54+
if bootstrapServer == nil {
55+
panic(fmt.Errorf("Failed to connect to any of the bootstrap servers (%v) for metadata request.", conf.Kafka.Brokers))
56+
}
57+
logger.Debugf("Connected to bootstrap server at %s.", bootstrapServer.Addr())
58+
59+
// get metadata for topic
60+
topic := conf.Kafka.Topic
61+
metadata, err := bootstrapServer.GetMetadata(&sarama.MetadataRequest{Topics: []string{topic}})
62+
if err != nil {
63+
panic(fmt.Errorf("GetMetadata failed for topic %s: %v", topic, err))
64+
}
65+
66+
// get leader broker for given topic/partition
67+
var broker *sarama.Broker
68+
partitionID := conf.Kafka.PartitionID
69+
if (partitionID >= 0) && (partitionID < int32(len(metadata.Topics[0].Partitions))) {
70+
leader := metadata.Topics[0].Partitions[partitionID].Leader
71+
logger.Debugf("Leading broker for topic %s/partition %d is broker ID %d", topic, partitionID, leader)
72+
for _, b := range metadata.Brokers {
73+
if b.ID() == leader {
74+
broker = b
75+
break
76+
}
77+
}
78+
}
79+
if broker == nil {
80+
panic(fmt.Errorf("Can't find leader for topic %s/partition %d", topic, partitionID))
81+
}
82+
83+
// connect to broker
3984
if err := broker.Open(nil); err != nil {
40-
panic(fmt.Errorf("Failed to create Kafka broker: %v", err))
85+
panic(fmt.Errorf("Failed to open Kafka broker: %v", err))
86+
}
87+
if connected, err := broker.Connected(); !connected {
88+
panic(fmt.Errorf("Failed to open Kafka broker: %v", err))
4189
}
90+
4291
return &brokerImpl{
4392
broker: broker,
4493
config: conf,

orderer/kafka/broker_test.go

+58
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,61 @@ func testBrokerGetOffsetFunc(given, expected int64) func(t *testing.T) {
3838
}
3939
}
4040
}
41+
42+
func TestNewBrokerReturnsPartitionLeader(t *testing.T) {
43+
44+
// sarama.Logger = log.New(os.Stdout, "[sarama] ", log.Lshortfile)
45+
// SetLogLevel("debug")
46+
47+
broker1 := sarama.NewMockBroker(t, 1001)
48+
broker2 := sarama.NewMockBroker(t, 1002)
49+
broker3 := sarama.NewMockBroker(t, 1003)
50+
51+
// shutdown broker1
52+
broker1.Close()
53+
54+
// update list of bootstrap brokers in config
55+
originalKafkaBrokers := testConf.Kafka.Brokers
56+
defer func() {
57+
testConf.Kafka.Brokers = originalKafkaBrokers
58+
}()
59+
// add broker1, and broker2 to list of bootstrap brokers
60+
// broker1 is 'down'
61+
// broker3 will be discovered via a metadata request
62+
testConf.Kafka.Brokers = []string{broker1.Addr(), broker2.Addr()}
63+
64+
// handy references
65+
topic := testConf.Kafka.Topic
66+
partition := testConf.Kafka.PartitionID
67+
68+
// add expectation that broker2 will return a metadata response that
69+
// identifies broker3 as the topic partition leader
70+
broker2.SetHandlerByMap(map[string]sarama.MockResponse{
71+
"MetadataRequest": sarama.NewMockMetadataResponse(t).
72+
SetBroker(broker1.Addr(), broker1.BrokerID()).
73+
SetBroker(broker2.Addr(), broker2.BrokerID()).
74+
SetBroker(broker3.Addr(), broker3.BrokerID()).
75+
SetLeader(topic, partition, broker3.BrokerID()),
76+
})
77+
78+
// add expectation that broker3 respond to an offset request
79+
broker3.SetHandlerByMap(map[string]sarama.MockResponse{
80+
"OffsetRequest": sarama.NewMockOffsetResponse(t).
81+
SetOffset(topic, partition, sarama.OffsetOldest, 0).
82+
SetOffset(topic, partition, sarama.OffsetNewest, 42),
83+
})
84+
85+
// get leader for topic partition
86+
broker := newBroker(testConf)
87+
88+
// only broker3 will respond successfully to an offset request
89+
offsetRequest := new(sarama.OffsetRequest)
90+
offsetRequest.AddBlock(topic, partition, -1, 1)
91+
if _, err := broker.GetOffset(offsetRequest); err != nil {
92+
t.Fatal(err)
93+
}
94+
95+
broker2.Close()
96+
broker3.Close()
97+
98+
}

0 commit comments

Comments
 (0)