|
@@ -9,10 +9,6 @@ import (
|
|
|
"github.com/eapache/queue"
|
|
|
)
|
|
|
|
|
|
-func forceFlushThreshold() int {
|
|
|
- return int(MaxRequestSize - (10 * 1024))
|
|
|
-}
|
|
|
-
|
|
|
|
|
|
|
|
|
|
|
@@ -491,6 +487,7 @@ func (pp *partitionProducer) updateLeader() error {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+
|
|
|
func (p *asyncProducer) newBrokerProducer(broker *Broker) chan<- *ProducerMessage {
|
|
|
input := make(chan *ProducerMessage)
|
|
|
bridge := make(chan []*ProducerMessage)
|
|
@@ -514,7 +511,6 @@ func (p *asyncProducer) newBrokerProducer(broker *Broker) chan<- *ProducerMessag
|
|
|
return input
|
|
|
}
|
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
type aggregator struct {
|
|
@@ -522,20 +518,14 @@ type aggregator struct {
|
|
|
broker *Broker
|
|
|
input <-chan *ProducerMessage
|
|
|
output chan<- []*ProducerMessage
|
|
|
+
|
|
|
+ buffer []*ProducerMessage
|
|
|
+ bufferBytes int
|
|
|
+ timer <-chan time.Time
|
|
|
}
|
|
|
|
|
|
func (a *aggregator) run() {
|
|
|
- var (
|
|
|
- timer <-chan time.Time
|
|
|
- buffer []*ProducerMessage
|
|
|
- flushTriggered chan<- []*ProducerMessage
|
|
|
- bytesAccumulated int
|
|
|
- defaultFlush bool
|
|
|
- )
|
|
|
-
|
|
|
- if a.parent.conf.Producer.Flush.Frequency == 0 && a.parent.conf.Producer.Flush.Bytes == 0 && a.parent.conf.Producer.Flush.Messages == 0 {
|
|
|
- defaultFlush = true
|
|
|
- }
|
|
|
+ var output chan<- []*ProducerMessage
|
|
|
|
|
|
for {
|
|
|
select {
|
|
@@ -544,45 +534,77 @@ func (a *aggregator) run() {
|
|
|
goto shutdown
|
|
|
}
|
|
|
|
|
|
- if (bytesAccumulated+msg.byteSize() >= forceFlushThreshold()) ||
|
|
|
- (a.parent.conf.Producer.Compression != CompressionNone && bytesAccumulated+msg.byteSize() >= a.parent.conf.Producer.MaxMessageBytes) ||
|
|
|
- (a.parent.conf.Producer.Flush.MaxMessages > 0 && len(buffer) >= a.parent.conf.Producer.Flush.MaxMessages) {
|
|
|
+ if a.wouldOverflow(msg) {
|
|
|
Logger.Printf("producer/aggregator/%d maximum request accumulated, forcing blocking flush\n", a.broker.ID())
|
|
|
- a.output <- buffer
|
|
|
- timer = nil
|
|
|
- buffer = nil
|
|
|
- flushTriggered = nil
|
|
|
- bytesAccumulated = 0
|
|
|
+ a.output <- a.buffer
|
|
|
+ a.reset()
|
|
|
+ output = nil
|
|
|
}
|
|
|
|
|
|
- buffer = append(buffer, msg)
|
|
|
- bytesAccumulated += msg.byteSize()
|
|
|
+ a.buffer = append(a.buffer, msg)
|
|
|
+ a.bufferBytes += msg.byteSize()
|
|
|
|
|
|
- if defaultFlush ||
|
|
|
- msg.flags&chaser == chaser ||
|
|
|
- (a.parent.conf.Producer.Flush.Messages > 0 && len(buffer) >= a.parent.conf.Producer.Flush.Messages) ||
|
|
|
- (a.parent.conf.Producer.Flush.Bytes > 0 && bytesAccumulated >= a.parent.conf.Producer.Flush.Bytes) {
|
|
|
- flushTriggered = a.output
|
|
|
- } else if a.parent.conf.Producer.Flush.Frequency > 0 && timer == nil {
|
|
|
- timer = time.After(a.parent.conf.Producer.Flush.Frequency)
|
|
|
+ if a.readyToFlush(msg) {
|
|
|
+ output = a.output
|
|
|
+ } else if a.parent.conf.Producer.Flush.Frequency > 0 && a.timer == nil {
|
|
|
+ a.timer = time.After(a.parent.conf.Producer.Flush.Frequency)
|
|
|
}
|
|
|
- case <-timer:
|
|
|
- flushTriggered = a.output
|
|
|
- case flushTriggered <- buffer:
|
|
|
- timer = nil
|
|
|
- buffer = nil
|
|
|
- flushTriggered = nil
|
|
|
- bytesAccumulated = 0
|
|
|
+ case <-a.timer:
|
|
|
+ output = a.output
|
|
|
+ case output <- a.buffer:
|
|
|
+ a.reset()
|
|
|
+ output = nil
|
|
|
}
|
|
|
}
|
|
|
|
|
|
shutdown:
|
|
|
- if len(buffer) > 0 {
|
|
|
- a.output <- buffer
|
|
|
+ if len(a.buffer) > 0 {
|
|
|
+ a.output <- a.buffer
|
|
|
}
|
|
|
close(a.output)
|
|
|
}
|
|
|
|
|
|
+func (a *aggregator) wouldOverflow(msg *ProducerMessage) bool {
|
|
|
+ switch {
|
|
|
+
|
|
|
+ case a.bufferBytes+msg.byteSize() >= int(MaxRequestSize-(10*1024)):
|
|
|
+ return true
|
|
|
+
|
|
|
+ case a.parent.conf.Producer.Compression != CompressionNone && a.bufferBytes+msg.byteSize() >= a.parent.conf.Producer.MaxMessageBytes:
|
|
|
+ return true
|
|
|
+
|
|
|
+ case a.parent.conf.Producer.Flush.MaxMessages > 0 && len(a.buffer) >= a.parent.conf.Producer.Flush.MaxMessages:
|
|
|
+ return true
|
|
|
+ default:
|
|
|
+ return false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (a *aggregator) readyToFlush(msg *ProducerMessage) bool {
|
|
|
+ switch {
|
|
|
+
|
|
|
+ case a.parent.conf.Producer.Flush.Frequency == 0 && a.parent.conf.Producer.Flush.Bytes == 0 && a.parent.conf.Producer.Flush.Messages == 0:
|
|
|
+ return true
|
|
|
+
|
|
|
+ case msg.flags&chaser == chaser:
|
|
|
+ return true
|
|
|
+
|
|
|
+ case a.parent.conf.Producer.Flush.Messages > 0 && len(a.buffer) >= a.parent.conf.Producer.Flush.Messages:
|
|
|
+ return true
|
|
|
+
|
|
|
+ case a.parent.conf.Producer.Flush.Bytes > 0 && a.bufferBytes >= a.parent.conf.Producer.Flush.Bytes:
|
|
|
+ return true
|
|
|
+ default:
|
|
|
+ return false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (a *aggregator) reset() {
|
|
|
+ a.timer = nil
|
|
|
+ a.buffer = nil
|
|
|
+ a.bufferBytes = 0
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
type flusher struct {
|
|
|
parent *asyncProducer
|