@@ -169,6 +169,10 @@ func (c *EventCollector) Run(ctx context.Context) {
169169 return c .processDSFeedback (ctx )
170170 })
171171
172+ g .Go (func () error {
173+ return c .controlCongestion (ctx )
174+ })
175+
172176 g .Go (func () error {
173177 return c .sendDispatcherRequests (ctx )
174178 })
@@ -219,7 +223,9 @@ func (c *EventCollector) PrepareAddDispatcher(
219223) {
220224 log .Info ("add dispatcher" , zap .Stringer ("dispatcher" , target .GetId ()))
221225 defer func () {
222- log .Info ("add dispatcher done" , zap .Stringer ("dispatcher" , target .GetId ()), zap .Int ("type" , target .GetType ()))
226+ log .Info ("add dispatcher done" ,
227+ zap .Stringer ("dispatcherID" , target .GetId ()), zap .Int64 ("tableID" , target .GetTableSpan ().GetTableID ()),
228+ zap .Uint64 ("startTs" , target .GetStartTs ()), zap .Int ("type" , target .GetType ()))
223229 }()
224230 metrics .EventCollectorRegisteredDispatcherCount .Inc ()
225231
@@ -238,11 +244,12 @@ func (c *EventCollector) PrepareAddDispatcher(
238244
239245// CommitAddDispatcher notify local event service that the dispatcher is ready to receive events.
240246func (c * EventCollector ) CommitAddDispatcher (target dispatcher.Dispatcher , startTs uint64 ) {
241- log .Info ("commit add dispatcher" , zap .Stringer ("dispatcher" , target .GetId ()), zap .Uint64 ("startTs" , startTs ))
247+ log .Info ("commit add dispatcher" , zap .Stringer ("dispatcherID" , target .GetId ()),
248+ zap .Int64 ("tableID" , target .GetTableSpan ().GetTableID ()), zap .Uint64 ("startTs" , startTs ))
242249 value , ok := c .dispatcherMap .Load (target .GetId ())
243250 if ! ok {
244251 log .Warn ("dispatcher not found when commit add dispatcher" ,
245- zap .Stringer ("dispatcher " , target .GetId ()),
252+ zap .Stringer ("dispatcherID " , target .GetId ()), zap . Int64 ( "tableID" , target . GetTableSpan (). GetTableID ()),
246253 zap .Uint64 ("startTs" , startTs ))
247254 return
248255 }
@@ -251,9 +258,10 @@ func (c *EventCollector) CommitAddDispatcher(target dispatcher.Dispatcher, start
251258}
252259
253260func (c * EventCollector ) RemoveDispatcher (target dispatcher.Dispatcher ) {
254- log .Info ("remove dispatcher" , zap .Stringer ("dispatcher " , target .GetId ()))
261+ log .Info ("remove dispatcher" , zap .Stringer ("dispatcherID " , target .GetId ()))
255262 defer func () {
256- log .Info ("remove dispatcher done" , zap .Stringer ("dispatcher" , target .GetId ()))
263+ log .Info ("remove dispatcher done" , zap .Stringer ("dispatcherID" , target .GetId ()),
264+ zap .Int64 ("tableID" , target .GetTableSpan ().GetTableID ()))
257265 }()
258266 isRedo := dispatcher .IsRedoDispatcher (target )
259267 value , ok := c .dispatcherMap .Load (target .GetId ())
@@ -512,6 +520,90 @@ func (c *EventCollector) runDispatchMessage(ctx context.Context, inCh <-chan *me
512520 }
513521}
514522
523+ func (c * EventCollector ) controlCongestion (ctx context.Context ) error {
524+ ticker := time .NewTicker (time .Second )
525+ defer ticker .Stop ()
526+
527+ for {
528+ select {
529+ case <- ctx .Done ():
530+ return context .Cause (ctx )
531+ case <- ticker .C :
532+ messages := c .newCongestionControlMessages ()
533+ for serverID , m := range messages {
534+ if len (m .GetAvailables ()) != 0 {
535+ msg := messaging .NewSingleTargetMessage (serverID , messaging .EventServiceTopic , m )
536+ if err := c .mc .SendCommand (msg ); err != nil {
537+ log .Warn ("send congestion control message failed" , zap .Error (err ))
538+ }
539+ }
540+ }
541+ }
542+ }
543+ }
544+
545+ func (c * EventCollector ) newCongestionControlMessages () map [node.ID ]* event.CongestionControl {
546+ // collect all changefeeds' available memory quota
547+ availables := make (map [common.ChangeFeedID ]uint64 )
548+ for _ , quota := range c .ds .GetMetrics ().MemoryControl .AreaMemoryMetrics {
549+ changefeedID , ok := c .changefeedIDMap .Load (quota .Area ())
550+ if ! ok {
551+ continue
552+ }
553+ availables [changefeedID .(common.ChangeFeedID )] = uint64 (quota .AvailableMemory ())
554+ }
555+ if len (availables ) == 0 {
556+ return nil
557+ }
558+
559+ // calculate each changefeed's available memory quota for each node
560+ // by the proportion of the dispatcher on each node.
561+ // this is not accurate, we should also consider each node's workload distribution.
562+ proportions := make (map [common.ChangeFeedID ]map [node.ID ]uint64 )
563+ c .dispatcherMap .Range (func (k , v interface {}) bool {
564+ stat := v .(* dispatcherStat )
565+ eventServiceID := stat .connState .getEventServiceID ()
566+ if eventServiceID == "" {
567+ return true
568+ }
569+
570+ changefeedID := stat .target .GetChangefeedID ()
571+ holder , ok := proportions [changefeedID ]
572+ if ! ok {
573+ holder = make (map [node.ID ]uint64 )
574+ proportions [changefeedID ] = holder
575+ }
576+ holder [eventServiceID ]++
577+ return true
578+ })
579+
580+ // group the available memory quota by nodeID
581+ result := make (map [node.ID ]* event.CongestionControl )
582+ for changefeedID , total := range availables {
583+ proportion := proportions [changefeedID ]
584+ var sum uint64
585+ for _ , portion := range proportion {
586+ sum += portion
587+ }
588+ if sum == 0 {
589+ continue
590+ }
591+
592+ for nodeID , portion := range proportion {
593+ ratio := float64 (portion ) / float64 (sum )
594+ quota := uint64 (float64 (total ) * ratio )
595+
596+ m , ok := result [nodeID ]
597+ if ! ok {
598+ m = event .NewCongestionControl ()
599+ result [nodeID ] = m
600+ }
601+ m .AddAvailableMemory (changefeedID .ID (), quota )
602+ }
603+ }
604+ return result
605+ }
606+
515607func (c * EventCollector ) updateMetrics (ctx context.Context ) error {
516608 ticker := time .NewTicker (5 * time .Second )
517609 defer ticker .Stop ()
0 commit comments