github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/config/messages.go (about)

     1  // Copyright 2021 PingCAP, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package config
    15  
    16  import (
    17  	"time"
    18  
    19  	cerrors "github.com/pingcap/tiflow/pkg/errors"
    20  	"github.com/pingcap/tiflow/pkg/p2p"
    21  )
    22  
    23  const defaultMaxRecvMsgSize = 256 * 1024 * 1024 // 256MB
    24  
    25  // MessagesConfig configs MessageServer and MessageClient.
    26  type MessagesConfig struct {
    27  	ClientMaxBatchInterval TomlDuration `toml:"client-max-batch-interval" json:"client-max-batch-interval"`
    28  	ClientMaxBatchSize     int          `toml:"client-max-batch-size" json:"client-max-batch-size"`
    29  	ClientMaxBatchCount    int          `toml:"client-max-batch-count" json:"client-max-batch-count"`
    30  	ClientRetryRateLimit   float64      `toml:"client-retry-rate-limit" json:"client-retry-rate-limit"`
    31  
    32  	ServerMaxPendingMessageCount int          `toml:"server-max-pending-message-count" json:"server-max-pending-message-count"`
    33  	ServerAckInterval            TomlDuration `toml:"server-ack-interval" json:"server-ack-interval"`
    34  	ServerWorkerPoolSize         int          `toml:"server-worker-pool-size" json:"server-worker-pool-size"`
    35  
    36  	// MaxRecvMsgSize is the maximum message size in bytes TiCDC can receive.
    37  	MaxRecvMsgSize int `toml:"max-recv-msg-size" json:"max-recv-msg-size"`
    38  
    39  	// After a duration of this time if the server doesn't see any activity it
    40  	// pings the client to see if the transport is still alive.
    41  	KeepAliveTime TomlDuration `toml:"keep-alive-time" json:"keep-alive-time"`
    42  	// After having pinged for keepalive check, the server waits for a duration
    43  	// of Timeout and if no activity is seen even after that the connection is
    44  	// closed.
    45  	KeepAliveTimeout TomlDuration `toml:"keep-alive-timeout" json:"keep-alive-timeout"`
    46  }
    47  
    48  // read only
    49  var defaultMessageConfig = &MessagesConfig{
    50  	// Note that ClientMaxBatchInterval may increase the checkpoint latency.
    51  	ClientMaxBatchInterval:       TomlDuration(time.Millisecond * 10),
    52  	ClientMaxBatchSize:           8 * 1024 * 1024, // 8MB
    53  	ClientMaxBatchCount:          128,
    54  	ClientRetryRateLimit:         1.0, // Once per second
    55  	ServerMaxPendingMessageCount: 102400,
    56  	ServerAckInterval:            TomlDuration(time.Millisecond * 100),
    57  	ServerWorkerPoolSize:         4,
    58  	MaxRecvMsgSize:               defaultMaxRecvMsgSize,
    59  	KeepAliveTime:                TomlDuration(time.Second * 30),
    60  	KeepAliveTimeout:             TomlDuration(time.Second * 10),
    61  }
    62  
    63  const (
    64  	// These values are advanced parameters to MessageServer and MessageClient,
    65  	// and it is not necessary for users to modify them.
    66  
    67  	// clientSendChannelSize represents the size of an internal channel used to buffer
    68  	// unsent messages.
    69  	clientSendChannelSize = 128
    70  
    71  	// clientDialTimeout represents the timeout given to gRPC to dial. 5 seconds seems reasonable
    72  	// because it is unlikely that the latency between TiCDC nodes is larger than 5 seconds.
    73  	clientDialTimeout = time.Second * 5
    74  
    75  	// maxTopicPendingCount is the max allowed number of unhandled message for a message topic
    76  	// ** if there is NO registered handler for it **.
    77  	maxTopicPendingCount = 256
    78  
    79  	// serverSendChannelSize is the size of a channel used to buffer messages to be sent back to
    80  	// the client. Note that the traffic from the server to the client is minimal, as it consists
    81  	// only of ACK messages.
    82  	serverSendChannelSize = 16
    83  
    84  	// maxPeerCount is the maximum number of peers that can be connected to the server.
    85  	// 1024 is reasonable given the current scalability of TiCDC.
    86  	maxPeerCount = 1024
    87  
    88  	// unregisterHandleTimeout is the time to wait for a message handler to unregister.
    89  	// Only in extreme situations can unregistering take more than a second. We use a timeout
    90  	// to make deadlocking more detectable.
    91  	unregisterHandleTimeout = time.Second * 10
    92  
    93  	// serverSendRateLimit is the rate limit of sending messages from the server to the client.
    94  	// Since ACK messages are batched, 1024 should be more than enough.
    95  	serverSendRateLimit = 1024.0
    96  )
    97  
    98  // ValidateAndAdjust validates and adjusts the configs.
    99  func (c *MessagesConfig) ValidateAndAdjust() error {
   100  	if c.ClientMaxBatchInterval == 0 {
   101  		c.ClientMaxBatchInterval = defaultMessageConfig.ClientMaxBatchInterval
   102  	}
   103  	if time.Duration(c.ClientMaxBatchInterval) > 10*time.Second {
   104  		return cerrors.ErrInvalidServerOption.GenWithStackByArgs("client-max-batch-interval is larger than 10s")
   105  	}
   106  
   107  	// We do not impose an upper limit on ClientMaxBatchSize and ClientMaxBatchCount
   108  	// to allow some flexibility in tuning and debugging.
   109  	if c.ClientMaxBatchSize <= 0 {
   110  		c.ClientMaxBatchSize = defaultMessageConfig.ClientMaxBatchSize
   111  	}
   112  
   113  	if c.ClientMaxBatchCount <= 0 {
   114  		c.ClientMaxBatchCount = defaultMessageConfig.ClientMaxBatchCount
   115  	}
   116  
   117  	if c.ClientRetryRateLimit <= 0.0 {
   118  		c.ClientRetryRateLimit = defaultMessageConfig.ClientRetryRateLimit
   119  	}
   120  
   121  	if c.ServerMaxPendingMessageCount <= 0 {
   122  		c.ServerMaxPendingMessageCount = defaultMessageConfig.ServerMaxPendingMessageCount
   123  	}
   124  
   125  	if c.ServerAckInterval == 0 {
   126  		c.ServerAckInterval = defaultMessageConfig.ServerAckInterval
   127  	}
   128  	if c.KeepAliveTime == 0 {
   129  		c.KeepAliveTime = defaultMessageConfig.KeepAliveTime
   130  	}
   131  	if c.KeepAliveTimeout == 0 {
   132  		c.KeepAliveTimeout = defaultMessageConfig.KeepAliveTimeout
   133  	}
   134  	if time.Duration(c.ServerAckInterval) > 10*time.Second {
   135  		return cerrors.ErrInvalidServerOption.GenWithStackByArgs("server-ack-interval is larger than 10s")
   136  	}
   137  
   138  	if c.ServerWorkerPoolSize <= 0 {
   139  		c.ServerWorkerPoolSize = defaultMessageConfig.ServerWorkerPoolSize
   140  	}
   141  	// We put an upper limit on ServerWorkerPoolSize to avoid having to create many goroutines.
   142  	if c.ServerWorkerPoolSize > 32 {
   143  		return cerrors.ErrInvalidServerOption.GenWithStackByArgs("server-worker-pool-size is larger than 32")
   144  	}
   145  
   146  	if c.MaxRecvMsgSize == 0 {
   147  		c.MaxRecvMsgSize = defaultMaxRecvMsgSize
   148  	}
   149  	if c.MaxRecvMsgSize < 0 {
   150  		return cerrors.ErrInvalidServerOption.GenWithStackByArgs(
   151  			"max-recv-msg-size must be larger than 0")
   152  	}
   153  
   154  	return nil
   155  }
   156  
   157  // Clone returns a deep copy of the configuration.
   158  func (c *MessagesConfig) Clone() *MessagesConfig {
   159  	return &MessagesConfig{
   160  		ClientMaxBatchInterval:       c.ClientMaxBatchInterval,
   161  		ClientMaxBatchSize:           c.ClientMaxBatchSize,
   162  		ClientMaxBatchCount:          c.ClientMaxBatchCount,
   163  		ClientRetryRateLimit:         c.ClientRetryRateLimit,
   164  		ServerMaxPendingMessageCount: c.ServerMaxPendingMessageCount,
   165  		ServerAckInterval:            c.ServerAckInterval,
   166  		ServerWorkerPoolSize:         c.ServerWorkerPoolSize,
   167  		MaxRecvMsgSize:               c.MaxRecvMsgSize,
   168  		KeepAliveTime:                c.KeepAliveTime,
   169  		KeepAliveTimeout:             c.KeepAliveTimeout,
   170  	}
   171  }
   172  
   173  // ToMessageClientConfig converts the MessagesConfig to a MessageClientConfig.
   174  func (c *MessagesConfig) ToMessageClientConfig() *p2p.MessageClientConfig {
   175  	return &p2p.MessageClientConfig{
   176  		SendChannelSize:         clientSendChannelSize,
   177  		BatchSendInterval:       time.Duration(c.ClientMaxBatchInterval),
   178  		MaxBatchBytes:           c.ClientMaxBatchSize,
   179  		MaxBatchCount:           c.ClientMaxBatchCount,
   180  		RetryRateLimitPerSecond: c.ClientRetryRateLimit,
   181  		DialTimeout:             clientDialTimeout,
   182  		MaxRecvMsgSize:          c.MaxRecvMsgSize,
   183  	}
   184  }
   185  
   186  // ToMessageServerConfig returns a MessageServerConfig that can be used to create a MessageServer.
   187  func (c *MessagesConfig) ToMessageServerConfig() *p2p.MessageServerConfig {
   188  	return &p2p.MessageServerConfig{
   189  		MaxPendingMessageCountPerTopic:       maxTopicPendingCount,
   190  		MaxPendingTaskCount:                  c.ServerMaxPendingMessageCount,
   191  		SendChannelSize:                      serverSendChannelSize,
   192  		AckInterval:                          time.Duration(c.ServerAckInterval),
   193  		WorkerPoolSize:                       c.ServerWorkerPoolSize,
   194  		MaxPeerCount:                         maxPeerCount,
   195  		WaitUnregisterHandleTimeoutThreshold: unregisterHandleTimeout,
   196  		SendRateLimitPerStream:               serverSendRateLimit,
   197  		MaxRecvMsgSize:                       c.MaxRecvMsgSize,
   198  		KeepAliveTimeout:                     time.Duration(c.KeepAliveTimeout),
   199  		KeepAliveTime:                        time.Duration(c.KeepAliveTime),
   200  	}
   201  }