This is an automated email from the ASF dual-hosted git repository.
alexstocks pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git
The following commit(s) were added to refs/heads/3.0 by this push:
new 0f83b1a make cluster interceptor a chain (#1211)
0f83b1a is described below
commit 0f83b1a55ccfa89acd88db8d0002e92ad1417673
Author: Ian Luo <[email protected]>
AuthorDate: Thu May 20 22:56:27 2021 +0800
make cluster interceptor a chain (#1211)
---
cluster/cluster_impl/available_cluster.go | 2 +-
cluster/cluster_impl/base_cluster_invoker.go | 19 ------
cluster/cluster_impl/broadcast_cluster.go | 2 +-
cluster/cluster_impl/failback_cluster.go | 2 +-
cluster/cluster_impl/failfast_cluster.go | 2 +-
cluster/cluster_impl/failover_cluster.go | 2 +-
cluster/cluster_impl/failsafe_cluster.go | 2 +-
cluster/cluster_impl/forking_cluster.go | 2 +-
cluster/cluster_impl/interceptor_invoker.go | 76 ++++++++++++++++++++++
cluster/cluster_impl/mock_cluster.go | 2 +-
cluster/cluster_impl/zone_aware_cluster.go | 2 +-
...luster.go => zone_aware_cluster_interceptor.go} | 42 +++++++-----
cluster/cluster_impl/zone_aware_cluster_invoker.go | 31 +--------
cluster/cluster_interceptor.go | 16 ++---
common/extension/cluster_interceptor.go | 60 +++++++++++++++++
15 files changed, 180 insertions(+), 82 deletions(-)
diff --git a/cluster/cluster_impl/available_cluster.go
b/cluster/cluster_impl/available_cluster.go
index 1038812..23a535e 100644
--- a/cluster/cluster_impl/available_cluster.go
+++ b/cluster/cluster_impl/available_cluster.go
@@ -40,5 +40,5 @@ func NewAvailableCluster() cluster.Cluster {
// Join returns a baseClusterInvoker instance
func (cluster *availableCluster) Join(directory cluster.Directory)
protocol.Invoker {
- return NewAvailableClusterInvoker(directory)
+ return buildInterceptorChain(NewAvailableClusterInvoker(directory))
}
diff --git a/cluster/cluster_impl/base_cluster_invoker.go
b/cluster/cluster_impl/base_cluster_invoker.go
index 7231ea1..925a039 100644
--- a/cluster/cluster_impl/base_cluster_invoker.go
+++ b/cluster/cluster_impl/base_cluster_invoker.go
@@ -18,10 +18,6 @@
package cluster_impl
import (
- "context"
-)
-
-import (
perrors "github.com/pkg/errors"
"go.uber.org/atomic"
)
@@ -40,7 +36,6 @@ type baseClusterInvoker struct {
availablecheck bool
destroyed *atomic.Bool
stickyInvoker protocol.Invoker
- interceptor cluster.ClusterInterceptor
}
func newBaseClusterInvoker(directory cluster.Directory) baseClusterInvoker {
@@ -165,20 +160,6 @@ func (invoker *baseClusterInvoker) doSelectInvoker(lb
cluster.LoadBalance, invoc
return nil
}
-func (invoker *baseClusterInvoker) Invoke(ctx context.Context, invocation
protocol.Invocation) protocol.Result {
- if invoker.interceptor != nil {
- invoker.interceptor.BeforeInvoker(ctx, invocation)
-
- result := invoker.interceptor.DoInvoke(ctx, invocation)
-
- invoker.interceptor.AfterInvoker(ctx, invocation)
-
- return result
- }
-
- return nil
-}
-
func isInvoked(selectedInvoker protocol.Invoker, invoked []protocol.Invoker)
bool {
for _, i := range invoked {
if i == selectedInvoker {
diff --git a/cluster/cluster_impl/broadcast_cluster.go
b/cluster/cluster_impl/broadcast_cluster.go
index e4ca54e..c2e8955 100644
--- a/cluster/cluster_impl/broadcast_cluster.go
+++ b/cluster/cluster_impl/broadcast_cluster.go
@@ -41,5 +41,5 @@ func NewBroadcastCluster() cluster.Cluster {
// Join returns a baseClusterInvoker instance
func (cluster *broadcastCluster) Join(directory cluster.Directory)
protocol.Invoker {
- return newBroadcastClusterInvoker(directory)
+ return buildInterceptorChain(newBroadcastClusterInvoker(directory))
}
diff --git a/cluster/cluster_impl/failback_cluster.go
b/cluster/cluster_impl/failback_cluster.go
index 4992c2b..7666570 100644
--- a/cluster/cluster_impl/failback_cluster.go
+++ b/cluster/cluster_impl/failback_cluster.go
@@ -41,5 +41,5 @@ func NewFailbackCluster() cluster.Cluster {
// Join returns a baseClusterInvoker instance
func (cluster *failbackCluster) Join(directory cluster.Directory)
protocol.Invoker {
- return newFailbackClusterInvoker(directory)
+ return buildInterceptorChain(newFailbackClusterInvoker(directory))
}
diff --git a/cluster/cluster_impl/failfast_cluster.go
b/cluster/cluster_impl/failfast_cluster.go
index af38666..a8022d5 100644
--- a/cluster/cluster_impl/failfast_cluster.go
+++ b/cluster/cluster_impl/failfast_cluster.go
@@ -41,5 +41,5 @@ func NewFailFastCluster() cluster.Cluster {
// Join returns a baseClusterInvoker instance
func (cluster *failfastCluster) Join(directory cluster.Directory)
protocol.Invoker {
- return newFailFastClusterInvoker(directory)
+ return buildInterceptorChain(newFailFastClusterInvoker(directory))
}
diff --git a/cluster/cluster_impl/failover_cluster.go
b/cluster/cluster_impl/failover_cluster.go
index 0ddeb7a..84dee3a 100644
--- a/cluster/cluster_impl/failover_cluster.go
+++ b/cluster/cluster_impl/failover_cluster.go
@@ -41,5 +41,5 @@ func NewFailoverCluster() cluster.Cluster {
// Join returns a baseClusterInvoker instance
func (cluster *failoverCluster) Join(directory cluster.Directory)
protocol.Invoker {
- return newFailoverClusterInvoker(directory)
+ return buildInterceptorChain(newFailoverClusterInvoker(directory))
}
diff --git a/cluster/cluster_impl/failsafe_cluster.go
b/cluster/cluster_impl/failsafe_cluster.go
index 2cbeef2..ac55e44 100644
--- a/cluster/cluster_impl/failsafe_cluster.go
+++ b/cluster/cluster_impl/failsafe_cluster.go
@@ -41,5 +41,5 @@ func NewFailsafeCluster() cluster.Cluster {
// Join returns a baseClusterInvoker instance
func (cluster *failsafeCluster) Join(directory cluster.Directory)
protocol.Invoker {
- return newFailsafeClusterInvoker(directory)
+ return buildInterceptorChain(newFailsafeClusterInvoker(directory))
}
diff --git a/cluster/cluster_impl/forking_cluster.go
b/cluster/cluster_impl/forking_cluster.go
index c88cd5b..7221d2d 100644
--- a/cluster/cluster_impl/forking_cluster.go
+++ b/cluster/cluster_impl/forking_cluster.go
@@ -41,5 +41,5 @@ func NewForkingCluster() cluster.Cluster {
// Join returns a baseClusterInvoker instance
func (cluster *forkingCluster) Join(directory cluster.Directory)
protocol.Invoker {
- return newForkingClusterInvoker(directory)
+ return buildInterceptorChain(newForkingClusterInvoker(directory))
}
diff --git a/cluster/cluster_impl/interceptor_invoker.go
b/cluster/cluster_impl/interceptor_invoker.go
new file mode 100644
index 0000000..a22695d
--- /dev/null
+++ b/cluster/cluster_impl/interceptor_invoker.go
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package cluster_impl
+
+import (
+ "context"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/cluster"
+ "dubbo.apache.org/dubbo-go/v3/common"
+ "dubbo.apache.org/dubbo-go/v3/common/extension"
+ "dubbo.apache.org/dubbo-go/v3/protocol"
+)
+
+// InterceptorInvoker mocks cluster interceptor as an invoker
+type InterceptorInvoker struct {
+ next protocol.Invoker
+ interceptor cluster.Interceptor
+}
+
+// GetURL is used to get url from InterceptorInvoker
+func (i *InterceptorInvoker) GetURL() *common.URL {
+ return i.next.GetURL()
+}
+
+// IsAvailable is used to get available status
+func (i *InterceptorInvoker) IsAvailable() bool {
+ return i.next.IsAvailable()
+}
+
+// Invoke is used to call service method by invocation
+func (i *InterceptorInvoker) Invoke(ctx context.Context, invocation
protocol.Invocation) protocol.Result {
+ return i.interceptor.Invoke(ctx, i.next, invocation)
+}
+
+// Destroy will destroy invoker
+func (i *InterceptorInvoker) Destroy() {
+ i.next.Destroy()
+}
+
+func buildInterceptorChain(invoker protocol.Invoker, builtins
...cluster.Interceptor) protocol.Invoker {
+ // The order of interceptors is from left to right, so loading from
right to left
+ next := invoker
+ interceptors := extension.GetClusterInterceptors()
+ if len(interceptors) != 0 {
+ for i := len(interceptors) - 1; i >= 0; i-- {
+ v := &InterceptorInvoker{next: next, interceptor:
interceptors[i]}
+ next = v
+ }
+ }
+
+ if builtins != nil && len(builtins) > 0 {
+ for i := len(builtins) - 1; i >= 0; i-- {
+ v := &InterceptorInvoker{next: next, interceptor:
builtins[i]}
+ next = v
+ }
+ }
+
+ return next
+}
diff --git a/cluster/cluster_impl/mock_cluster.go
b/cluster/cluster_impl/mock_cluster.go
index 7a243d8..40d1c2b 100644
--- a/cluster/cluster_impl/mock_cluster.go
+++ b/cluster/cluster_impl/mock_cluster.go
@@ -35,5 +35,5 @@ func NewMockCluster() cluster.Cluster {
// nolint
func (cluster *mockCluster) Join(directory cluster.Directory) protocol.Invoker
{
- return protocol.NewBaseInvoker(directory.GetURL())
+ return
buildInterceptorChain(protocol.NewBaseInvoker(directory.GetURL()))
}
diff --git a/cluster/cluster_impl/zone_aware_cluster.go
b/cluster/cluster_impl/zone_aware_cluster.go
index fed551a..a280ba9 100644
--- a/cluster/cluster_impl/zone_aware_cluster.go
+++ b/cluster/cluster_impl/zone_aware_cluster.go
@@ -40,5 +40,5 @@ func NewZoneAwareCluster() cluster.Cluster {
// Join returns a zoneAwareClusterInvoker instance
func (cluster *zoneAwareCluster) Join(directory cluster.Directory)
protocol.Invoker {
- return newZoneAwareClusterInvoker(directory)
+ return buildInterceptorChain(newZoneAwareClusterInvoker(directory),
getZoneAwareInterceptor())
}
diff --git a/cluster/cluster_impl/failover_cluster.go
b/cluster/cluster_impl/zone_aware_cluster_interceptor.go
similarity index 59%
copy from cluster/cluster_impl/failover_cluster.go
copy to cluster/cluster_impl/zone_aware_cluster_interceptor.go
index 0ddeb7a..ea26c2e 100644
--- a/cluster/cluster_impl/failover_cluster.go
+++ b/cluster/cluster_impl/zone_aware_cluster_interceptor.go
@@ -18,28 +18,40 @@
package cluster_impl
import (
+ "context"
+)
+
+import (
"dubbo.apache.org/dubbo-go/v3/cluster"
"dubbo.apache.org/dubbo-go/v3/common/constant"
- "dubbo.apache.org/dubbo-go/v3/common/extension"
"dubbo.apache.org/dubbo-go/v3/protocol"
)
-type failoverCluster struct{}
-
-func init() {
- extension.SetCluster(constant.FAILOVER_CLUSTER_NAME, NewFailoverCluster)
+type zoneAwareInterceptor struct {
}
-// NewFailoverCluster returns a failover cluster instance
-//
-// Failure automatically switch, when there is a failure,
-// retry the other server (default). Usually used for read operations,
-// but retries can result in longer delays.
-func NewFailoverCluster() cluster.Cluster {
- return &failoverCluster{}
+func (z *zoneAwareInterceptor) Invoke(ctx context.Context, invoker
protocol.Invoker, invocation protocol.Invocation) protocol.Result {
+ key := constant.REGISTRY_KEY + "." + constant.ZONE_FORCE_KEY
+ force := ctx.Value(key)
+
+ if force != nil {
+ switch value := force.(type) {
+ case bool:
+ if value {
+ invocation.SetAttachments(key, "true")
+ }
+ case string:
+ if "true" == value {
+ invocation.SetAttachments(key, "true")
+ }
+ default:
+ // ignore
+ }
+ }
+
+ return invoker.Invoke(ctx, invocation)
}
-// Join returns a baseClusterInvoker instance
-func (cluster *failoverCluster) Join(directory cluster.Directory)
protocol.Invoker {
- return newFailoverClusterInvoker(directory)
+func getZoneAwareInterceptor() cluster.Interceptor {
+ return &zoneAwareInterceptor{}
}
diff --git a/cluster/cluster_impl/zone_aware_cluster_invoker.go
b/cluster/cluster_impl/zone_aware_cluster_invoker.go
index 9d57133..1e04da5 100644
--- a/cluster/cluster_impl/zone_aware_cluster_invoker.go
+++ b/cluster/cluster_impl/zone_aware_cluster_invoker.go
@@ -40,16 +40,14 @@ type zoneAwareClusterInvoker struct {
}
func newZoneAwareClusterInvoker(directory cluster.Directory) protocol.Invoker {
- invoke := &zoneAwareClusterInvoker{
+ invoker := &zoneAwareClusterInvoker{
baseClusterInvoker: newBaseClusterInvoker(directory),
}
- // add local to interceptor
- invoke.interceptor = invoke
- return invoke
+ return invoker
}
// nolint
-func (invoker *zoneAwareClusterInvoker) DoInvoke(ctx context.Context,
invocation protocol.Invocation) protocol.Result {
+func (invoker *zoneAwareClusterInvoker) Invoke(ctx context.Context, invocation
protocol.Invocation) protocol.Result {
invokers := invoker.directory.List(invocation)
err := invoker.checkInvokers(invokers, invocation)
@@ -104,29 +102,6 @@ func (invoker *zoneAwareClusterInvoker) DoInvoke(ctx
context.Context, invocation
}
}
-func (invoker *zoneAwareClusterInvoker) BeforeInvoker(ctx context.Context,
invocation protocol.Invocation) {
- key := constant.REGISTRY_KEY + "." + constant.ZONE_FORCE_KEY
- force := ctx.Value(key)
-
- if force != nil {
- switch value := force.(type) {
- case bool:
- if value {
- invocation.SetAttachments(key, "true")
- }
- case string:
- if "true" == value {
- invocation.SetAttachments(key, "true")
- }
- default:
- // ignore
- }
- }
-}
-
-func (invoker *zoneAwareClusterInvoker) AfterInvoker(ctx context.Context,
invocation protocol.Invocation) {
-}
-
func matchParam(target, key, def string, invoker protocol.Invoker) bool {
return target == invoker.GetURL().GetParam(key, def)
}
diff --git a/cluster/cluster_interceptor.go b/cluster/cluster_interceptor.go
index dae7ff2..9f66d89 100644
--- a/cluster/cluster_interceptor.go
+++ b/cluster/cluster_interceptor.go
@@ -25,15 +25,9 @@ import (
"dubbo.apache.org/dubbo-go/v3/protocol"
)
-// ClusterInterceptor
-// Extension - ClusterInterceptor
-type ClusterInterceptor interface {
- // Before DoInvoke method
- BeforeInvoker(ctx context.Context, invocation protocol.Invocation)
-
- // After DoInvoke method
- AfterInvoker(ctx context.Context, invocation protocol.Invocation)
-
- // Corresponding cluster invoke
- DoInvoke(ctx context.Context, invocation protocol.Invocation)
protocol.Result
+// Interceptor
+// Extension - Interceptor
+type Interceptor interface {
+ // Invoke is the core function of a cluster interceptor, it determines
the process of the interceptor
+ Invoke(context.Context, protocol.Invoker, protocol.Invocation)
protocol.Result
}
diff --git a/common/extension/cluster_interceptor.go
b/common/extension/cluster_interceptor.go
new file mode 100644
index 0000000..e437259
--- /dev/null
+++ b/common/extension/cluster_interceptor.go
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package extension
+
+import (
+ "sync"
+)
+
+import (
+ "dubbo.apache.org/dubbo-go/v3/cluster"
+)
+
+var (
+ lock sync.RWMutex
+ interceptors = make(map[string]func() cluster.Interceptor)
+)
+
+// SetClusterInterceptor sets cluster interceptor so that user has chance to
inject extra logics before and after
+// cluster invoker
+func SetClusterInterceptor(name string, fun func() cluster.Interceptor) {
+ lock.Lock()
+ defer lock.Unlock()
+ interceptors[name] = fun
+}
+
+// GetClusterInterceptor returns the cluster interceptor instance with the
given name
+func GetClusterInterceptor(name string) cluster.Interceptor {
+ lock.RLock()
+ defer lock.RUnlock()
+ if interceptors[name] == nil {
+ panic("cluster_interceptor for " + name + " doesn't exist, make
sure the corresponding package is imported")
+ }
+ return interceptors[name]()
+}
+
+// GetClusterInterceptors returns all instances of registered cluster
interceptors
+func GetClusterInterceptors() []cluster.Interceptor {
+ lock.RLock()
+ defer lock.RUnlock()
+ ret := make([]cluster.Interceptor, 0, len(interceptors))
+ for _, f := range interceptors {
+ ret = append(ret, f())
+ }
+ return ret
+}