github.com/milvus-io/milvus-sdk-go/v2@v2.4.1/client/config.go (about) 1 package client 2 3 import ( 4 "context" 5 "crypto/tls" 6 "fmt" 7 "math" 8 "net/url" 9 "regexp" 10 "strings" 11 "time" 12 13 "github.com/cockroachdb/errors" 14 grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry" 15 "google.golang.org/grpc" 16 "google.golang.org/grpc/backoff" 17 "google.golang.org/grpc/codes" 18 "google.golang.org/grpc/credentials" 19 "google.golang.org/grpc/credentials/insecure" 20 "google.golang.org/grpc/keepalive" 21 ) 22 23 const ( 24 disableDatabase uint64 = 1 << iota 25 disableJSON 26 disableDynamicSchema 27 disableParitionKey 28 ) 29 30 var regexValidScheme = regexp.MustCompile(`^https?:\/\/`) 31 32 // DefaultGrpcOpts is GRPC options for milvus client. 33 var DefaultGrpcOpts = []grpc.DialOption{ 34 grpc.WithBlock(), 35 grpc.WithKeepaliveParams(keepalive.ClientParameters{ 36 Time: 5 * time.Second, 37 Timeout: 10 * time.Second, 38 PermitWithoutStream: true, 39 }), 40 grpc.WithConnectParams(grpc.ConnectParams{ 41 Backoff: backoff.Config{ 42 BaseDelay: 100 * time.Millisecond, 43 Multiplier: 1.6, 44 Jitter: 0.2, 45 MaxDelay: 3 * time.Second, 46 }, 47 MinConnectTimeout: 3 * time.Second, 48 }), 49 } 50 51 // Config for milvus client. 52 type Config struct { 53 Address string // Remote address, "localhost:19530". 54 Username string // Username for auth. 55 Password string // Password for auth. 56 DBName string // DBName for this client. 57 Identifier string // Identifier for this connection 58 EnableTLSAuth bool // Enable TLS Auth for transport security. 59 APIKey string // API key 60 ServerVersion string // ServerVersion 61 62 DialOptions []grpc.DialOption // Dial options for GRPC. 63 64 parsedAddress *url.URL 65 66 RetryRateLimit *RetryRateLimitOption // option for retry on rate limit inteceptor 67 68 DisableConn bool 69 70 flags uint64 // internal flags 71 } 72 73 type RetryRateLimitOption struct { 74 MaxRetry uint 75 MaxBackoff time.Duration 76 } 77 78 // Copy a new config, dialOption may shared with old config. 79 func (c *Config) Copy() Config { 80 newConfig := Config{ 81 Address: c.Address, 82 Username: c.Username, 83 Password: c.Password, 84 DBName: c.DBName, 85 EnableTLSAuth: c.EnableTLSAuth, 86 } 87 newConfig.DialOptions = make([]grpc.DialOption, 0, len(c.DialOptions)) 88 newConfig.DialOptions = append(newConfig.DialOptions, c.DialOptions...) 89 return newConfig 90 } 91 92 func (c *Config) parse() error { 93 // Prepend default fake tcp:// scheme for remote address. 94 address := c.Address 95 if !regexValidScheme.MatchString(address) { 96 address = fmt.Sprintf("tcp://%s", address) 97 } 98 99 remoteURL, err := url.Parse(address) 100 if err != nil { 101 return errors.Wrap(err, "milvus address parse fail") 102 } 103 // Remote Host should never be empty. 104 if remoteURL.Host == "" { 105 return errors.New("empty remote host of milvus address") 106 } 107 // Use DBName in remote url path. 108 if c.DBName == "" { 109 c.DBName = strings.TrimLeft(remoteURL.Path, "/") 110 } 111 // Always enable tls auth for https remote url. 112 if remoteURL.Scheme == "https" { 113 c.EnableTLSAuth = true 114 } 115 if remoteURL.Port() == "" && c.EnableTLSAuth { 116 remoteURL.Host += ":443" 117 } 118 c.parsedAddress = remoteURL 119 return nil 120 } 121 122 // Get parsed remote milvus address, should be called after parse was called. 123 func (c *Config) getParsedAddress() string { 124 return c.parsedAddress.Host 125 } 126 127 // useDatabase change the inner db name. 128 func (c *Config) useDatabase(dbName string) { 129 c.DBName = dbName 130 } 131 132 // useDatabase change the inner db name. 133 func (c *Config) setIdentifier(identifier string) { 134 c.Identifier = identifier 135 } 136 137 // Get parsed grpc dial options, should be called after parse was called. 138 func (c *Config) getDialOption() []grpc.DialOption { 139 var options []grpc.DialOption 140 // Construct dial option. 141 if c.EnableTLSAuth { 142 options = append(options, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{}))) 143 } else { 144 options = append(options, grpc.WithTransportCredentials(insecure.NewCredentials())) 145 } 146 147 if c.DialOptions == nil { 148 // Add default connection options. 149 options = append(options, DefaultGrpcOpts...) 150 } else { 151 options = append(options, c.DialOptions...) 152 } 153 154 options = append(options, 155 grpc.WithChainUnaryInterceptor(grpc_retry.UnaryClientInterceptor( 156 grpc_retry.WithMax(6), 157 grpc_retry.WithBackoff(func(attempt uint) time.Duration { 158 return 60 * time.Millisecond * time.Duration(math.Pow(3, float64(attempt))) 159 }), 160 grpc_retry.WithCodes(codes.Unavailable, codes.ResourceExhausted)), 161 c.getRetryOnRateLimitInterceptor(), 162 )) 163 164 options = append(options, grpc.WithChainUnaryInterceptor( 165 createMetaDataUnaryInterceptor(c), 166 )) 167 return options 168 } 169 170 func (c *Config) getRetryOnRateLimitInterceptor() grpc.UnaryClientInterceptor { 171 if c.RetryRateLimit == nil { 172 c.RetryRateLimit = c.defaultRetryRateLimitOption() 173 } 174 175 return RetryOnRateLimitInterceptor(c.RetryRateLimit.MaxRetry, c.RetryRateLimit.MaxBackoff, func(ctx context.Context, attempt uint) time.Duration { 176 return 10 * time.Millisecond * time.Duration(math.Pow(3, float64(attempt))) 177 }) 178 } 179 180 func (c *Config) defaultRetryRateLimitOption() *RetryRateLimitOption { 181 return &RetryRateLimitOption{ 182 MaxRetry: 75, 183 MaxBackoff: 3 * time.Second, 184 } 185 } 186 187 // addFlags set internal flags 188 func (c *Config) addFlags(flags uint64) { 189 c.flags |= flags 190 } 191 192 // hasFlags check flags is set 193 func (c *Config) hasFlags(flags uint64) bool { 194 return (c.flags & flags) > 0 195 } 196 197 func (c *Config) resetFlags(flags uint64) { 198 c.flags &= ^flags 199 }