Skip to content

Commit ccaf552

Browse files
authored
[improve] PIP-368: Support lookup based on the lookup properties (#1303)
1 parent 8c193de commit ccaf552

File tree

9 files changed

+1299
-1202
lines changed

9 files changed

+1299
-1202
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ lint: bin/golangci-lint
3636
bin/golangci-lint run
3737

3838
bin/golangci-lint:
39-
GOBIN=$(shell pwd)/bin go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.2
39+
GOBIN=$(shell pwd)/bin go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0
4040

4141
# an alternative to above `make lint` command
4242
# use golangCi-lint docker to avoid local golang env issues

pulsar/client.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ type ClientOptions struct {
163163
// Limit of client memory usage (in byte). The 64M default can guarantee a high producer throughput.
164164
// Config less than 0 indicates off memory limit.
165165
MemoryLimitBytes int64
166+
167+
// Set the properties used for topic lookup.
168+
// When the broker performs topic lookup, these lookup properties will be taken into consideration in a customized
169+
// load manager.
170+
// Note: The lookup properties are only used in topic lookup when:
171+
// The protocol is binary protocol, i.e. the service URL starts with "pulsar://" or "pulsar+ssl://"
172+
// The `loadManagerClassName` config in broker is a class that implements the `ExtensibleLoadManager` interface
173+
LookupProperties map[string]string
166174
}
167175

168176
// Client represents a pulsar client

pulsar/client_impl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ func newClient(options ClientOptions) (Client, error) {
172172
}
173173

174174
c.rpcClient = internal.NewRPCClient(url, c.cnxPool, operationTimeout, logger, metrics,
175-
options.ListenerName, tlsConfig, authProvider)
175+
options.ListenerName, tlsConfig, authProvider, toKeyValues(options.LookupProperties))
176176

177177
c.lookupService = c.rpcClient.LookupService("")
178178

pulsar/consumer_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4691,3 +4691,57 @@ func TestPartitionConsumerGetLastMessageIDs(t *testing.T) {
46914691
}
46924692

46934693
}
4694+
4695+
func TestLookupConsumer(t *testing.T) {
4696+
client, err := NewClient(ClientOptions{
4697+
URL: lookupURL,
4698+
LookupProperties: map[string]string{
4699+
"broker.id": "1",
4700+
},
4701+
})
4702+
4703+
assert.Nil(t, err)
4704+
defer client.Close()
4705+
4706+
topic := newTopicName()
4707+
ctx := context.Background()
4708+
4709+
// create consumer
4710+
consumer, err := client.Subscribe(ConsumerOptions{
4711+
Topic: topic,
4712+
SubscriptionName: "my-sub",
4713+
Type: Exclusive,
4714+
})
4715+
assert.Nil(t, err)
4716+
defer consumer.Close()
4717+
4718+
// create producer
4719+
producer, err := client.CreateProducer(ProducerOptions{
4720+
Topic: topic,
4721+
DisableBatching: false,
4722+
})
4723+
assert.Nil(t, err)
4724+
defer producer.Close()
4725+
4726+
// send 10 messages
4727+
for i := 0; i < 10; i++ {
4728+
if _, err := producer.Send(ctx, &ProducerMessage{
4729+
Payload: []byte(fmt.Sprintf("hello-%d", i)),
4730+
}); err != nil {
4731+
log.Fatal(err)
4732+
}
4733+
}
4734+
4735+
// receive 10 messages
4736+
for i := 0; i < 10; i++ {
4737+
msg, err := consumer.Receive(context.Background())
4738+
if err != nil {
4739+
log.Fatal(err)
4740+
}
4741+
4742+
expectMsg := fmt.Sprintf("hello-%d", i)
4743+
assert.Equal(t, []byte(expectMsg), msg.Payload())
4744+
// ack message
4745+
consumer.Ack(msg)
4746+
}
4747+
}

pulsar/internal/lookup_service.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,21 @@ type lookupService struct {
7777
serviceNameResolver ServiceNameResolver
7878
tlsEnabled bool
7979
listenerName string
80+
lookupProperties []*pb.KeyValue
8081
log log.Logger
8182
metrics *Metrics
8283
}
8384

8485
// NewLookupService init a lookup service struct and return an object of LookupService.
8586
func NewLookupService(rpcClient RPCClient, serviceURL *url.URL, serviceNameResolver ServiceNameResolver,
86-
tlsEnabled bool, listenerName string, logger log.Logger, metrics *Metrics) LookupService {
87+
tlsEnabled bool, listenerName string,
88+
lookupProperties []*pb.KeyValue, logger log.Logger, metrics *Metrics) LookupService {
8789
return &lookupService{
8890
rpcClient: rpcClient,
8991
serviceNameResolver: serviceNameResolver,
9092
tlsEnabled: tlsEnabled,
9193
log: logger.SubLogger(log.Fields{"serviceURL": serviceURL}),
94+
lookupProperties: lookupProperties,
9295
metrics: metrics,
9396
listenerName: listenerName,
9497
}
@@ -146,6 +149,7 @@ func (ls *lookupService) Lookup(topic string) (*LookupResult, error) {
146149
Topic: &topic,
147150
Authoritative: proto.Bool(false),
148151
AdvertisedListenerName: proto.String(ls.listenerName),
152+
Properties: ls.lookupProperties,
149153
})
150154
if err != nil {
151155
return nil, err

pulsar/internal/lookup_service_test.go

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func TestLookupSuccess(t *testing.T) {
128128
url, err := url.Parse("pulsar://example:6650")
129129
assert.NoError(t, err)
130130
serviceNameResolver := NewPulsarServiceNameResolver(url)
131-
131+
kvs := make([]*pb.KeyValue, 0)
132132
mockedClient := &mockedLookupRPCClient{
133133
t: t,
134134

@@ -138,6 +138,7 @@ func TestLookupSuccess(t *testing.T) {
138138
Topic: proto.String("my-topic"),
139139
Authoritative: proto.Bool(false),
140140
AdvertisedListenerName: proto.String(""),
141+
Properties: kvs,
141142
},
142143
},
143144
mockedResponses: []pb.CommandLookupTopicResponse{
@@ -149,9 +150,8 @@ func TestLookupSuccess(t *testing.T) {
149150
},
150151
},
151152
}
152-
153153
metricsProvider := NewMetricsProvider(4, map[string]string{}, prometheus.DefaultRegisterer)
154-
ls := NewLookupService(mockedClient, url, serviceNameResolver, false, "", log.DefaultNopLogger(), metricsProvider)
154+
ls := NewLookupService(mockedClient, url, serviceNameResolver, false, "", kvs, log.DefaultNopLogger(), metricsProvider)
155155

156156
lr, err := ls.Lookup("my-topic")
157157
assert.NoError(t, err)
@@ -165,6 +165,7 @@ func TestTlsLookupSuccess(t *testing.T) {
165165
url, err := url.Parse("pulsar+ssl://example:6651")
166166
assert.NoError(t, err)
167167
serviceNameResolver := NewPulsarServiceNameResolver(url)
168+
kvs := make([]*pb.KeyValue, 0)
168169
mockedClient := &mockedLookupRPCClient{
169170
t: t,
170171

@@ -174,6 +175,7 @@ func TestTlsLookupSuccess(t *testing.T) {
174175
Topic: proto.String("my-topic"),
175176
Authoritative: proto.Bool(false),
176177
AdvertisedListenerName: proto.String(""),
178+
Properties: kvs,
177179
},
178180
},
179181
mockedResponses: []pb.CommandLookupTopicResponse{
@@ -187,7 +189,7 @@ func TestTlsLookupSuccess(t *testing.T) {
187189
}
188190
metricsProvider := NewMetricsProvider(4, map[string]string{}, prometheus.DefaultRegisterer)
189191

190-
ls := NewLookupService(mockedClient, url, serviceNameResolver, true, "", log.DefaultNopLogger(), metricsProvider)
192+
ls := NewLookupService(mockedClient, url, serviceNameResolver, true, "", kvs, log.DefaultNopLogger(), metricsProvider)
191193

192194
lr, err := ls.Lookup("my-topic")
193195
assert.NoError(t, err)
@@ -201,6 +203,7 @@ func TestLookupWithProxy(t *testing.T) {
201203
url, err := url.Parse("pulsar://example:6650")
202204
assert.NoError(t, err)
203205
serviceNameResolver := NewPulsarServiceNameResolver(url)
206+
kvs := make([]*pb.KeyValue, 0)
204207
mockedClient := &mockedLookupRPCClient{
205208
t: t,
206209

@@ -210,6 +213,7 @@ func TestLookupWithProxy(t *testing.T) {
210213
Topic: proto.String("my-topic"),
211214
Authoritative: proto.Bool(false),
212215
AdvertisedListenerName: proto.String(""),
216+
Properties: kvs,
213217
},
214218
},
215219
mockedResponses: []pb.CommandLookupTopicResponse{
@@ -223,7 +227,7 @@ func TestLookupWithProxy(t *testing.T) {
223227
},
224228
}
225229
metricsProvider := NewMetricsProvider(4, map[string]string{}, prometheus.DefaultRegisterer)
226-
ls := NewLookupService(mockedClient, url, serviceNameResolver, false, "", log.DefaultNopLogger(), metricsProvider)
230+
ls := NewLookupService(mockedClient, url, serviceNameResolver, false, "", kvs, log.DefaultNopLogger(), metricsProvider)
227231

228232
lr, err := ls.Lookup("my-topic")
229233
assert.NoError(t, err)
@@ -236,7 +240,7 @@ func TestLookupWithProxy(t *testing.T) {
236240
func TestTlsLookupWithProxy(t *testing.T) {
237241
url, err := url.Parse("pulsar+ssl://example:6651")
238242
assert.NoError(t, err)
239-
243+
kvs := make([]*pb.KeyValue, 0)
240244
mockedClient := &mockedLookupRPCClient{
241245
t: t,
242246

@@ -246,6 +250,7 @@ func TestTlsLookupWithProxy(t *testing.T) {
246250
Topic: proto.String("my-topic"),
247251
Authoritative: proto.Bool(false),
248252
AdvertisedListenerName: proto.String(""),
253+
Properties: kvs,
249254
},
250255
},
251256
mockedResponses: []pb.CommandLookupTopicResponse{
@@ -260,7 +265,7 @@ func TestTlsLookupWithProxy(t *testing.T) {
260265
}
261266
resolver := NewPulsarServiceNameResolver(url)
262267
metricsProvider := NewMetricsProvider(4, map[string]string{}, prometheus.DefaultRegisterer)
263-
ls := NewLookupService(mockedClient, url, resolver, true, "", log.DefaultNopLogger(), metricsProvider)
268+
ls := NewLookupService(mockedClient, url, resolver, true, "", kvs, log.DefaultNopLogger(), metricsProvider)
264269

265270
lr, err := ls.Lookup("my-topic")
266271
assert.NoError(t, err)
@@ -273,7 +278,7 @@ func TestTlsLookupWithProxy(t *testing.T) {
273278
func TestLookupWithRedirect(t *testing.T) {
274279
url, err := url.Parse("pulsar://example:6650")
275280
assert.NoError(t, err)
276-
281+
kvs := make([]*pb.KeyValue, 0)
277282
mockedClient := &mockedLookupRPCClient{
278283
t: t,
279284
expectedURL: "pulsar://broker-2:6650",
@@ -284,6 +289,7 @@ func TestLookupWithRedirect(t *testing.T) {
284289
Topic: proto.String("my-topic"),
285290
Authoritative: proto.Bool(false),
286291
AdvertisedListenerName: proto.String(""),
292+
Properties: kvs,
287293
},
288294
{
289295
RequestId: proto.Uint64(2),
@@ -309,7 +315,7 @@ func TestLookupWithRedirect(t *testing.T) {
309315
}
310316
resolver := NewPulsarServiceNameResolver(url)
311317
metricsProvider := NewMetricsProvider(4, map[string]string{}, prometheus.DefaultRegisterer)
312-
ls := NewLookupService(mockedClient, url, resolver, false, "", log.DefaultNopLogger(), metricsProvider)
318+
ls := NewLookupService(mockedClient, url, resolver, false, "", kvs, log.DefaultNopLogger(), metricsProvider)
313319

314320
lr, err := ls.Lookup("my-topic")
315321
assert.NoError(t, err)
@@ -322,7 +328,7 @@ func TestLookupWithRedirect(t *testing.T) {
322328
func TestTlsLookupWithRedirect(t *testing.T) {
323329
url, err := url.Parse("pulsar+ssl://example:6651")
324330
assert.NoError(t, err)
325-
331+
kvs := make([]*pb.KeyValue, 0)
326332
mockedClient := &mockedLookupRPCClient{
327333
t: t,
328334
expectedURL: "pulsar+ssl://broker-2:6651",
@@ -333,6 +339,7 @@ func TestTlsLookupWithRedirect(t *testing.T) {
333339
Topic: proto.String("my-topic"),
334340
Authoritative: proto.Bool(false),
335341
AdvertisedListenerName: proto.String(""),
342+
Properties: kvs,
336343
},
337344
{
338345
RequestId: proto.Uint64(2),
@@ -359,7 +366,7 @@ func TestTlsLookupWithRedirect(t *testing.T) {
359366

360367
resolver := NewPulsarServiceNameResolver(url)
361368
metricsProvider := NewMetricsProvider(4, map[string]string{}, prometheus.DefaultRegisterer)
362-
ls := NewLookupService(mockedClient, url, resolver, true, "", log.DefaultNopLogger(), metricsProvider)
369+
ls := NewLookupService(mockedClient, url, resolver, true, "", kvs, log.DefaultNopLogger(), metricsProvider)
363370

364371
lr, err := ls.Lookup("my-topic")
365372
assert.NoError(t, err)
@@ -372,7 +379,7 @@ func TestTlsLookupWithRedirect(t *testing.T) {
372379
func TestLookupWithInvalidUrlResponse(t *testing.T) {
373380
url, err := url.Parse("pulsar://example:6650")
374381
assert.NoError(t, err)
375-
382+
kvs := make([]*pb.KeyValue, 0)
376383
mockedClient := &mockedLookupRPCClient{
377384
t: t,
378385

@@ -382,6 +389,7 @@ func TestLookupWithInvalidUrlResponse(t *testing.T) {
382389
Topic: proto.String("my-topic"),
383390
Authoritative: proto.Bool(false),
384391
AdvertisedListenerName: proto.String(""),
392+
Properties: kvs,
385393
},
386394
},
387395
mockedResponses: []pb.CommandLookupTopicResponse{
@@ -396,7 +404,7 @@ func TestLookupWithInvalidUrlResponse(t *testing.T) {
396404
}
397405
resolver := NewPulsarServiceNameResolver(url)
398406
metricsProvider := NewMetricsProvider(4, map[string]string{}, prometheus.DefaultRegisterer)
399-
ls := NewLookupService(mockedClient, url, resolver, false, "", log.DefaultNopLogger(), metricsProvider)
407+
ls := NewLookupService(mockedClient, url, resolver, false, "", kvs, log.DefaultNopLogger(), metricsProvider)
400408

401409
lr, err := ls.Lookup("my-topic")
402410
assert.Error(t, err)
@@ -406,7 +414,7 @@ func TestLookupWithInvalidUrlResponse(t *testing.T) {
406414
func TestLookupWithLookupFailure(t *testing.T) {
407415
url, err := url.Parse("pulsar://example:6650")
408416
assert.NoError(t, err)
409-
417+
kvs := make([]*pb.KeyValue, 0)
410418
mockedClient := &mockedLookupRPCClient{
411419
t: t,
412420

@@ -416,6 +424,7 @@ func TestLookupWithLookupFailure(t *testing.T) {
416424
Topic: proto.String("my-topic"),
417425
Authoritative: proto.Bool(false),
418426
AdvertisedListenerName: proto.String(""),
427+
Properties: kvs,
419428
},
420429
},
421430
mockedResponses: []pb.CommandLookupTopicResponse{
@@ -429,7 +438,7 @@ func TestLookupWithLookupFailure(t *testing.T) {
429438

430439
resolver := NewPulsarServiceNameResolver(url)
431440
metricsProvider := NewMetricsProvider(4, map[string]string{}, prometheus.DefaultRegisterer)
432-
ls := NewLookupService(mockedClient, url, resolver, false, "", log.DefaultNopLogger(), metricsProvider)
441+
ls := NewLookupService(mockedClient, url, resolver, false, "", kvs, log.DefaultNopLogger(), metricsProvider)
433442

434443
lr, err := ls.Lookup("my-topic")
435444
assert.Error(t, err)
@@ -509,6 +518,7 @@ func TestGetPartitionedTopicMetadataSuccess(t *testing.T) {
509518
assert.NoError(t, err)
510519
serviceNameResolver := NewPulsarServiceNameResolver(url)
511520

521+
kvs := make([]*pb.KeyValue, 0)
512522
ls := NewLookupService(&mockedPartitionedTopicMetadataRPCClient{
513523
t: t,
514524

@@ -525,7 +535,7 @@ func TestGetPartitionedTopicMetadataSuccess(t *testing.T) {
525535
Response: pb.CommandPartitionedTopicMetadataResponse_Success.Enum(),
526536
},
527537
},
528-
}, url, serviceNameResolver, false, "", log.DefaultNopLogger(),
538+
}, url, serviceNameResolver, false, "", kvs, log.DefaultNopLogger(),
529539
NewMetricsProvider(4, map[string]string{}, prometheus.DefaultRegisterer))
530540

531541
metadata, err := ls.GetPartitionedTopicMetadata("my-topic")
@@ -539,6 +549,7 @@ func TestLookupSuccessWithMultipleHosts(t *testing.T) {
539549
assert.NoError(t, err)
540550
serviceNameResolver := NewPulsarServiceNameResolver(url)
541551

552+
kvs := make([]*pb.KeyValue, 0)
542553
ls := NewLookupService(&mockedLookupRPCClient{
543554
t: t,
544555

@@ -548,6 +559,7 @@ func TestLookupSuccessWithMultipleHosts(t *testing.T) {
548559
Topic: proto.String("my-topic"),
549560
AdvertisedListenerName: proto.String(""),
550561
Authoritative: proto.Bool(false),
562+
Properties: kvs,
551563
},
552564
},
553565
mockedResponses: []pb.CommandLookupTopicResponse{
@@ -558,7 +570,7 @@ func TestLookupSuccessWithMultipleHosts(t *testing.T) {
558570
BrokerServiceUrl: proto.String("pulsar://broker-1:6650"),
559571
},
560572
},
561-
}, url, serviceNameResolver, false, "", log.DefaultNopLogger(),
573+
}, url, serviceNameResolver, false, "", kvs, log.DefaultNopLogger(),
562574
NewMetricsProvider(4, map[string]string{}, prometheus.DefaultRegisterer))
563575

564576
lr, err := ls.Lookup("my-topic")

0 commit comments

Comments
 (0)