Ejemplo n.º 1
0
func withRetry(
	b *sarama.Broker,
	cfg *sarama.Config,
	f func() error,
) error {
	var err error
	for max := 0; max < cfg.Metadata.Retry.Max; max++ {
		if ok, _ := b.Connected(); !ok {
			if err = b.Open(cfg); err == nil {
				err = f()
			}
		} else {
			err = f()
		}

		if err == nil {
			return nil
		}

		retry, reconnect := checkRetryQuery(err)
		if !retry {
			return err
		}

		time.Sleep(cfg.Metadata.Retry.Backoff)
		if reconnect {
			closeBroker(b)
		}
	}
	return err
}
Ejemplo n.º 2
0
// Start a rebalance cycle
func (cg *ConsumerGroup) rebalance() (err error) {
	var cids []string
	var pids []int32

	// Fetch a list of consumers and listen for changes
	if cids, cg.zkchange, err = cg.zoo.Consumers(cg.name); err != nil {
		cg.zkchange = nil
		return
	}

	// Fetch a list of partition IDs
	if pids, err = cg.client.Partitions(cg.topic); err != nil {
		cg.zkchange = nil
		return
	}

	// Get leaders for each partition ID
	parts := make(PartitionSlice, len(pids))
	for i, pid := range pids {
		var broker *sarama.Broker
		if broker, err = cg.client.Leader(cg.topic, pid); err != nil {
			cg.zkchange = nil
			return
		}
		defer broker.Close()
		parts[i] = Partition{Id: pid, Addr: broker.Addr()}
	}

	if err = cg.makeClaims(cids, parts); err != nil {
		cg.zkchange = nil
		cg.releaseClaims()
		return
	}
	return
}
Ejemplo n.º 3
0
Archivo: offset.go Proyecto: fgeller/kt
// commitOffset sends an offset message to kafka for the given consumer group
func commitOffset(broker *sarama.Broker, topic string, partition int32, group string, offset int64, generationID int32, memberID string) {

	v := int16(0)
	if config.offset.version.IsAtLeast(sarama.V0_8_2_0) {
		v = 1
	}
	if config.offset.version.IsAtLeast(sarama.V0_9_0_0) {
		v = 2
	}

	req := &sarama.OffsetCommitRequest{
		Version:                 v,
		ConsumerGroup:           group,
		ConsumerGroupGeneration: generationID,
		ConsumerID:              memberID,
		RetentionTime:           -1,
	}
	req.AddBlock(topic, partition, offset, 0, "")

	offsetResp, err := broker.CommitOffset(req)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to commit offsets. err=%v\n", err)
		os.Exit(1)
	} else if len(offsetResp.Errors) > 0 {
		for topic, perrs := range offsetResp.Errors {
			for partition, kerr := range perrs {
				if kerr != sarama.ErrNoError {
					fmt.Fprintf(os.Stderr, "Failed to commit offsets topic=%s, partition=%s. err=%v\n", topic, partition, err)
					os.Exit(1)
				}
			}
		}
	}
}
Ejemplo n.º 4
0
Archivo: offset.go Proyecto: fgeller/kt
// joinGroup joins a consumer group and returns the group memberID and generationID
func joinGroup(broker *sarama.Broker, group string, topic string) (string, int32) {
	joinGroupReq := &sarama.JoinGroupRequest{
		GroupId:        group,
		SessionTimeout: int32((30 * time.Second) / time.Millisecond),
		ProtocolType:   "consumer",
	}

	meta := &sarama.ConsumerGroupMemberMetadata{
		Version: 1,
		Topics:  []string{topic},
	}
	err := joinGroupReq.AddGroupProtocolMetadata("range", meta)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to add meta data err=%v\n", err)
		os.Exit(1)
	}
	err = joinGroupReq.AddGroupProtocolMetadata("roundrobin", meta)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to add meta data err=%v\n", err)
		os.Exit(1)
	}

	resp, err := broker.JoinGroup(joinGroupReq)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to join consumer group err=%v\n", err)
		os.Exit(1)
	} else if resp.Err != sarama.ErrNoError {
		fmt.Fprintf(os.Stderr, "Failed to join consumer group err=%v\n", resp.Err)
		os.Exit(1)
	}

	return resp.MemberId, resp.GenerationId
}
Ejemplo n.º 5
0
func queryMetadataWithRetry(
	b *sarama.Broker,
	cfg *sarama.Config,
	topics []string,
) (r *sarama.MetadataResponse, err error) {
	err = withRetry(b, cfg, func() (e error) {
		r, e = b.GetMetadata(&sarama.MetadataRequest{topics})
		return
	})
	return
}
Ejemplo n.º 6
0
func queryOffset(
	b *sarama.Broker,
	replicaID int32,
	topic string,
	partition int32,
	time int64,
) (int64, bool, error) {
	req := &sarama.OffsetRequest{}
	if replicaID != noID {
		req.SetReplicaID(replicaID)
	}
	req.AddBlock(topic, partition, time, 1)
	resp, err := b.GetAvailableOffsets(req)
	if err != nil {
		return -1, false, err
	}

	block := resp.GetBlock(topic, partition)
	if len(block.Offsets) == 0 {
		return -1, false, nil
	}

	return block.Offsets[0], true, nil
}
Ejemplo n.º 7
0
// Connects to the broker that handles all produce and consume
// requests for the given chain (Partition Leader Replica)
func newBroker(brokers []string, cp ChainPartition) (Broker, error) {
	var candidateBroker, connectedBroker, leaderBroker *sarama.Broker

	// Connect to one of the given brokers
	for _, hostPort := range brokers {
		candidateBroker = sarama.NewBroker(hostPort)
		if err := candidateBroker.Open(nil); err != nil {
			logger.Warningf("Failed to connect to broker %s: %s", hostPort, err)
			continue
		}
		if connected, err := candidateBroker.Connected(); !connected {
			logger.Warningf("Failed to connect to broker %s: %s", hostPort, err)
			continue
		}
		connectedBroker = candidateBroker
		break
	}

	if connectedBroker == nil {
		return nil, fmt.Errorf("Failed to connect to any of the given brokers (%v) for metadata request", brokers)
	}
	logger.Debugf("Connected to broker %s", connectedBroker.Addr())

	// Get metadata for the topic that corresponds to this chain
	metadata, err := connectedBroker.GetMetadata(&sarama.MetadataRequest{Topics: []string{cp.Topic()}})
	if err != nil {
		return nil, fmt.Errorf("Failed to get metadata for topic %s: %s", cp, err)
	}

	// Get the leader broker for this chain partition
	if (cp.Partition() >= 0) && (cp.Partition() < int32(len(metadata.Topics[0].Partitions))) {
		leaderBrokerID := metadata.Topics[0].Partitions[cp.Partition()].Leader
		logger.Debugf("Leading broker for chain %s is broker ID %d", cp, leaderBrokerID)
		for _, availableBroker := range metadata.Brokers {
			if availableBroker.ID() == leaderBrokerID {
				leaderBroker = availableBroker
				break
			}
		}
	}

	if leaderBroker == nil {
		return nil, fmt.Errorf("Can't find leader for chain %s", cp)
	}

	// Connect to broker
	if err := leaderBroker.Open(nil); err != nil {
		return nil, fmt.Errorf("Failed to connect ho Kafka broker: %s", err)
	}
	if connected, err := leaderBroker.Connected(); !connected {
		return nil, fmt.Errorf("Failed to connect to Kafka broker: %s", err)
	}

	return &brokerImpl{broker: leaderBroker}, nil
}
Ejemplo n.º 8
0
func closeBroker(b *sarama.Broker) {
	if ok, _ := b.Connected(); ok {
		b.Close()
	}
}
Ejemplo n.º 9
0
func brokerAddress(b *sarama.Broker) string {
	return strings.ToLower(b.Addr())
}