github.com/lzy4123/fabric@v2.1.1+incompatible/orderer/consensus/kafka/consenter.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package kafka 8 9 import ( 10 "github.com/Shopify/sarama" 11 "github.com/hyperledger/fabric-lib-go/healthz" 12 cb "github.com/hyperledger/fabric-protos-go/common" 13 "github.com/hyperledger/fabric/common/flogging" 14 "github.com/hyperledger/fabric/common/metrics" 15 "github.com/hyperledger/fabric/orderer/common/localconfig" 16 "github.com/hyperledger/fabric/orderer/consensus" 17 "github.com/hyperledger/fabric/orderer/consensus/inactive" 18 "github.com/pkg/errors" 19 ) 20 21 //go:generate counterfeiter -o mock/health_checker.go -fake-name HealthChecker . healthChecker 22 23 // healthChecker defines the contract for health checker 24 type healthChecker interface { 25 RegisterChecker(component string, checker healthz.HealthChecker) error 26 } 27 28 // New creates a Kafka-based consenter. Called by orderer's main.go. 29 func New(config localconfig.Kafka, mp metrics.Provider, healthChecker healthChecker, icr InactiveChainRegistry, mkChain func(string)) (consensus.Consenter, *Metrics) { 30 if config.Verbose { 31 flogging.ActivateSpec(flogging.Global.Spec() + ":orderer.consensus.kafka.sarama=debug") 32 } 33 34 brokerConfig := newBrokerConfig( 35 config.TLS, 36 config.SASLPlain, 37 config.Retry, 38 config.Version, 39 defaultPartition) 40 41 metrics := NewMetrics(mp, brokerConfig.MetricRegistry) 42 43 return &consenterImpl{ 44 mkChain: mkChain, 45 inactiveChainRegistry: icr, 46 brokerConfigVal: brokerConfig, 47 tlsConfigVal: config.TLS, 48 retryOptionsVal: config.Retry, 49 kafkaVersionVal: config.Version, 50 topicDetailVal: &sarama.TopicDetail{ 51 NumPartitions: 1, 52 ReplicationFactor: config.Topic.ReplicationFactor, 53 }, 54 healthChecker: healthChecker, 55 metrics: metrics, 56 }, metrics 57 } 58 59 // InactiveChainRegistry registers chains that are inactive 60 type InactiveChainRegistry interface { 61 // TrackChain tracks a chain with the given name, and calls the given callback 62 // when this chain should be created. 63 TrackChain(chainName string, genesisBlock *cb.Block, createChain func()) 64 } 65 66 // consenterImpl holds the implementation of type that satisfies the 67 // consensus.Consenter interface --as the HandleChain contract requires-- and 68 // the commonConsenter one. 69 type consenterImpl struct { 70 mkChain func(string) 71 brokerConfigVal *sarama.Config 72 tlsConfigVal localconfig.TLS 73 retryOptionsVal localconfig.Retry 74 kafkaVersionVal sarama.KafkaVersion 75 topicDetailVal *sarama.TopicDetail 76 healthChecker healthChecker 77 metrics *Metrics 78 inactiveChainRegistry InactiveChainRegistry 79 } 80 81 // HandleChain creates/returns a reference to a consensus.Chain object for the 82 // given set of support resources. Implements the consensus.Consenter 83 // interface. Called by consensus.newChainSupport(), which is itself called by 84 // multichannel.NewManagerImpl() when ranging over the ledgerFactory's 85 // existingChains. 86 func (consenter *consenterImpl) HandleChain(support consensus.ConsenterSupport, metadata *cb.Metadata) (consensus.Chain, error) { 87 88 // Check if this node was migrated from Raft 89 if consenter.inactiveChainRegistry != nil { 90 logger.Infof("This node was migrated from Kafka to Raft, skipping activation of Kafka chain") 91 consenter.inactiveChainRegistry.TrackChain(support.ChannelID(), support.Block(0), func() { 92 consenter.mkChain(support.ChannelID()) 93 }) 94 return &inactive.Chain{Err: errors.Errorf("channel %s is not serviced by me", support.ChannelID())}, nil 95 } 96 97 lastOffsetPersisted, lastOriginalOffsetProcessed, lastResubmittedConfigOffset := getOffsets(metadata.Value, support.ChannelID()) 98 ch, err := newChain(consenter, support, lastOffsetPersisted, lastOriginalOffsetProcessed, lastResubmittedConfigOffset) 99 if err != nil { 100 return nil, err 101 } 102 consenter.healthChecker.RegisterChecker(ch.channel.String(), ch) 103 return ch, nil 104 } 105 106 // commonConsenter allows us to retrieve the configuration options set on the 107 // consenter object. These will be common across all chain objects derived by 108 // this consenter. They are set using local configuration settings. This 109 // interface is satisfied by consenterImpl. 110 type commonConsenter interface { 111 brokerConfig() *sarama.Config 112 retryOptions() localconfig.Retry 113 topicDetail() *sarama.TopicDetail 114 Metrics() *Metrics 115 } 116 117 func (consenter *consenterImpl) Metrics() *Metrics { 118 return consenter.metrics 119 } 120 121 func (consenter *consenterImpl) brokerConfig() *sarama.Config { 122 return consenter.brokerConfigVal 123 } 124 125 func (consenter *consenterImpl) retryOptions() localconfig.Retry { 126 return consenter.retryOptionsVal 127 } 128 129 func (consenter *consenterImpl) topicDetail() *sarama.TopicDetail { 130 return consenter.topicDetailVal 131 }