Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions client/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ func (refOpts *ReferenceOptions) init(opts ...ReferenceOption) error {
}

// init protocol
// The default protocol is Triple ("tri"). Before the fix for issue #3173,
// this default caused the discovery-phase protocol guard in cacheInvoker to
// silently discard Java Dubbo 2.x providers (which register with
// protocol="dubbo"), resulting in "No provider available". Callers targeting
// Java Dubbo 2.x providers should use WithClientProtocolDubbo() to set the
// protocol explicitly.
if refConf.Protocol == "" {
refConf.Protocol = constant.TriProtocol
if refOpts.Consumer != nil && refOpts.Consumer.Protocol != "" {
Expand Down
25 changes: 17 additions & 8 deletions registry/directory/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,14 +476,23 @@ func (dir *RegistryDirectory) cacheInvoker(url *common.URL, event *registry.Serv
logger.Error("URL is nil ,pls check if service url is subscribe successfully!")
return nil
}
// check the url's protocol is equal to the protocol which is configured in reference config or referenceUrl is not care about protocol
if url.Protocol == referenceUrl.Protocol || referenceUrl.Protocol == "" {
newUrl := url.MergeURL(referenceUrl)
dir.overrideUrl(newUrl)
event.Update(newUrl)
if v, ok := dir.doCacheInvoker(newUrl, event); ok {
return v
}
// Protocol filtering at this layer is intentionally removed.
//
// Registry-based discovery (ZooKeeper, Nacos, …) already scopes provider
// lookup to interface + group + version. Filtering by protocol here caused
// a silent mismatch: when a Go consumer is created with client.NewClient the
// reference protocol defaults to "tri" (Triple), but Java Dubbo 2.x providers
// register in ZooKeeper with protocol="dubbo". The old guard therefore
// discarded every Java provider and the consumer always saw "No provider
// available" (see GitHub issue #3173).
//
// Protocol selection is correctly handled later in the invoker/protocol
// layer via the merged URL, so there is no need to pre-filter here.
newUrl := url.MergeURL(referenceUrl)
dir.overrideUrl(newUrl)
event.Update(newUrl)
if v, ok := dir.doCacheInvoker(newUrl, event); ok {
return v
}
return nil
}
Expand Down
49 changes: 49 additions & 0 deletions registry/directory/directory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
}

func TestSubscribe_InvalidUrl(t *testing.T) {
url, _ := common.NewURL("mock://127.0.0.1:1111")

Check failure on line 52 in registry/directory/directory_test.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal "mock://127.0.0.1:1111" 3 times.

See more on https://sonarcloud.io/project/issues?id=apache_dubbo-go&issues=AZz6rqrWvjDTsnvOIQNM&open=AZz6rqrWvjDTsnvOIQNM&pullRequest=3263
mockRegistry, _ := registry.NewMockRegistry(&common.URL{})
_, err := NewRegistryDirectory(url, mockRegistry)
require.Error(t, err)
Expand Down Expand Up @@ -187,6 +187,55 @@
return dir.(*RegistryDirectory), mockRegistry.(*registry.MockRegistry)
}

// TestCrossProtocolProviderDiscoveryIssue3173 is a regression test for
// https://github.com/apache/dubbo-go/issues/3173.
// A Go consumer configured with "tri" (the default for client.NewClient) must
// be able to discover and cache a Java Dubbo 2.x provider that registered in
// ZooKeeper with protocol="dubbo". Before the fix, the protocol guard in
// cacheInvoker silently dropped the provider and the consumer always received
// "No provider available".
func TestCrossProtocolProviderDiscoveryIssue3173(t *testing.T) {
extension.SetProtocol(protocolwrapper.FILTER, protocolwrapper.NewMockProtocolFilter)

applicationConfig := &global.ApplicationConfig{Name: "test-application"}
url, _ := common.NewURL("mock://127.0.0.1:1111")
// Consumer uses "tri" — the default protocol when using client.NewClient().
suburl, _ := common.NewURL(
"tri://127.0.0.1:20000/org.apache.dubbo-go.mockService",
common.WithParamsValue(constant.ClusterKey, "mock"),
common.WithParamsValue(constant.GroupKey, "group"),
common.WithParamsValue(constant.VersionKey, "1.0.0"),
common.WithParamsValue(constant.ApplicationKey, applicationConfig.Name),
)
url.SubURL = suburl
mockRegistry, _ := registry.NewMockRegistry(&common.URL{})
dir, _ := NewRegistryDirectory(url, mockRegistry)
go dir.(*RegistryDirectory).Subscribe(suburl)

// Java Dubbo 2.x provider registers in ZooKeeper with protocol="dubbo".
providerUrl, _ := common.NewURL(
"dubbo://0.0.0.0:20880/org.apache.dubbo-go.mockService",
common.WithParamsValue(constant.GroupKey, "group"),
common.WithParamsValue(constant.VersionKey, "1.0.0"),
)
mockRegistry.(*registry.MockRegistry).MockEvent(
&registry.ServiceEvent{Action: remoting.EventTypeAdd, Service: providerUrl},
)
time.Sleep(1e9)

registryDirectory := dir.(*RegistryDirectory)
// Provider must be discovered — cacheInvokers must not be empty.
assert.Len(t, registryDirectory.cacheInvokers, 1,
"Java dubbo provider must be discoverable by a tri consumer (issue #3173)")
// The invoker's URL must retain the provider's "dubbo" protocol so that the
// actual RPC connection is established over the dubbo protocol.
if len(registryDirectory.cacheInvokers) > 0 {
assert.Equal(t, constant.DubboProtocol,
registryDirectory.cacheInvokers[0].GetURL().Protocol,
"merged URL must retain the provider's dubbo protocol for correct invocation")
}
}

func TestToGroupInvokers(t *testing.T) {
t.Run("SameGroup", func(t *testing.T) {
registryDirectory, mockRegistry := normalRegistryDir(true)
Expand Down
Loading