diff --git a/.gitignore b/.gitignore index 0b3673bf316a409b5caadf09f3fa58d42ad8f968..3769d10aa12348464cb315fd336bf6b7234069cc 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out +coverage.txt *.idea *.iml @@ -22,3 +23,4 @@ vendor/ logs/ .vscode/ +coverage.txt diff --git a/.travis.yml b/.travis.yml index 2038d8ecc81ce319906b66333458eb6eda9afc30..ea6b2035584ba07ae7caa709f83be59cf20c730e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: go go: - - "1.11" - "1.12" env: @@ -11,6 +10,10 @@ install: true script: - go fmt ./... && [[ -z `git status -s` ]] + - mkdir -p remoting/zookeeper/zookeeper-4unittest/contrib/fatjar config_center/zookeeper/zookeeper-4unittest/contrib/fatjar registry/zookeeper/zookeeper-4unittest/contrib/fatjar + - wget -P "remoting/zookeeper/zookeeper-4unittest/contrib/fatjar" https://github.com/dubbogo/resources/raw/master/zookeeper-4unitest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar + - cp remoting/zookeeper/zookeeper-4unittest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar config_center/zookeeper/zookeeper-4unittest/contrib/fatjar/ + - cp remoting/zookeeper/zookeeper-4unittest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar registry/zookeeper/zookeeper-4unittest/contrib/fatjar/ - go mod vendor && go test ./... -coverprofile=coverage.txt -covermode=atomic after_success: diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000000000000000000000000000000000000..a9bd809c5c43a9d88a773b5f0c421b252abf38de --- /dev/null +++ b/NOTICE @@ -0,0 +1,5 @@ +Apache Dubbo Go +Copyright 2018-2019 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/README.md b/README.md index 245b693fb3dac5c7d6058a2d57dcc33c1d41e309..ccc6ae52edf5f5086213feb3d3d0823ed46e0b96 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,10 @@ --- Apache Dubbo Go Implementation. + + +Apache/Dubbo-go image, licensed under [Creative Commons 3.0 Attributions license](https://creativecommons.org/licenses/by/3.0/). + ## License Apache License, Version 2.0 @@ -29,19 +33,19 @@ Finished List: - Role: Consumer, Provider - Transport: HTTP, TCP - Codec: JsonRPC v2, Hessian v2 -- Registry: ZooKeeper -- Routing: Rule(dubbo v2.6.x) +- Registry: ZooKeeper/[etcd](https://github.com/apache/dubbo-go/pull/148)/[nacos](https://github.com/apache/dubbo-go/pull/151) - Configure Center: Zookeeper -- Cluster Strategy: Failover -- Load Balance: Random, RoundRobin, LeastActive +- Cluster Strategy: Failover/[Failfast](https://github.com/apache/dubbo-go/pull/140)/[Failsafe/Failback](https://github.com/apache/dubbo-go/pull/136)/Available/Broadcast +- Load Balance: Random/[RoundRobin](https://github.com/apache/dubbo-go/pull/66)/[LeastActive](https://github.com/apache/dubbo-go/pull/65) - Filter: Echo Health Check +- Other feature: [generic invoke](https://github.com/apache/dubbo-go/pull/122)/start check/connecting certain provider/multi-protocols/multi-registries/multi-versions/service group Working List: -- Cluster Strategy: Failfast/Failsafe/Failback/Forking +- Cluster Strategy: Forking - Load Balance: ConsistentHash -- Filter: TokenFilter/AccessLogFilter/CountFilter/ActiveLimitFilter/ExecuteLimitFilter/GenericFilter/TpsLimitFilter -- Registry: etcd/k8s/consul/nacos +- Filter: TokenFilter/AccessLogFilter/CountFilter/ExecuteLimitFilter/TpsLimitFilter +- Registry: k8s/consul - Configure Center: apollo - Dynamic Configuration Center & Metadata Center (dubbo v2.7.x) - Metrics: Promethus(dubbo v2.7.x) @@ -54,12 +58,23 @@ Todo List: You can know more about dubbo-go by its [roadmap](https://github.com/apache/dubbo-go/wiki/Roadmap). +## Document +TODO ## Quick Start The subdirectory examples shows how to use dubbo-go. Please read the [examples/README.md](https://github.com/apache/dubbo-go/blob/develop/examples/README.md) carefully to learn how to dispose the configuration and compile the program. +## Running unit tests + +```bash +go test ./... + +# coverage +go test ./... -coverprofile=coverage.txt -covermode=atomic +``` + ## Contributing If you are willing to do some code contributions and document contributions to [Apache/dubbo-go](https://github.com/apache/dubbo-go), please visit [contribution intro](https://github.com/apache/dubbo-go/blob/master/cg.md). diff --git a/README_CN.md b/README_CN.md index a5502d1379ac4e3ba977ac1727c1c30f9ce488b2..e021be55765241be93f4c9c66cca1beb573cc1bb 100644 --- a/README_CN.md +++ b/README_CN.md @@ -5,6 +5,9 @@ --- Apache Dubbo Go 语言实现 + + +Apache/Dubbo-go image, licensed under [Creative Commons 3.0 Attributions license](https://creativecommons.org/licenses/by/3.0/). ## 证书 ## @@ -26,38 +29,51 @@ Apache License, Version 2.0 实现列表: -- Role: Consumer, Provider -- Transport: HTTP, TCP -- Codec: JsonRPC v2, Hessian v2 -- Registry: ZooKeeper -- Routing: Rule(dubbo v2.6.x) -- Configure Center: Zookeeper -- Cluster Strategy: Failover -- Load Balance: Random, RoundRobin, LeastActive -- Filter: Echo Health Check +- 角色端: Consumer, Provider +- 传输协议: HTTP, TCP +- 序列化协议: JsonRPC v2, Hessian v2 +- 注册中心: ZooKeeper/[etcd](https://github.com/apache/dubbo-go/pull/148)/[nacos](https://github.com/apache/dubbo-go/pull/151) +- 配置中心: Zookeeper +- 集群策略: Failover/[Failfast](https://github.com/apache/dubbo-go/pull/140)/[Failsafe/Failback](https://github.com/apache/dubbo-go/pull/136)/Available/Broadcast +- 负载均衡策略: Random/[RoundRobin](https://github.com/apache/dubbo-go/pull/66)/[LeastActive](https://github.com/apache/dubbo-go/pull/65) +- 过滤器: Echo Health Check +- 其他功能支持: [泛化调用](https://github.com/apache/dubbo-go/pull/122)/启动时检查/服务直连/多服务协议/多注册中心/多服务版本/服务分组 开发中列表: -- Cluster Strategy: Failfast/Failsafe/Failback/Forking -- Load Balance: ConsistentHash -- Filter: TokenFilter/AccessLogFilter/CountFilter/ActiveLimitFilter/ExecuteLimitFilter/GenericFilter/TpsLimitFilter -- Registry: etcd/k8s/consul/nacos -- Configure Center: apollo -- Dynamic Configuration Center & Metadata Center (dubbo v2.7.x) +- 集群策略: Forking +- 负载均衡策略: ConsistentHash +- 过滤器: TokenFilter/AccessLogFilter/CountFilter/ExecuteLimitFilter/TpsLimitFilter +- 注册中心: etcd/k8s/consul/nacos +- 配置中心: apollo +- 动态配置中心 & 元数据中心 (dubbo v2.7.x) - Metrics: Promethus(dubbo v2.7.x) 任务列表: -- Registry: kubernetes +- 注册中心: kubernetes - Routing: istio - tracing (dubbo ecosystem) 你可以通过访问 [roadmap](https://github.com/apache/dubbo-go/wiki/Roadmap) 知道更多关于 dubbo-go 的信息 +## 文档 + +TODO + ## 快速开始 ## 这个子目录下的例子展示了如何使用 dubbo-go 。请仔细阅读 [examples/README.md](https://github.com/apache/dubbo-go/blob/develop/examples/README.md) 学习如何处理配置并编译程序。 +## 运行单测 + +```bash +go test ./... + +# 覆盖率 +go test ./... -coverprofile=coverage.txt -covermode=atomic +``` + ## 如何贡献 如果您愿意给 [Apache/dubbo-go](https://github.com/apache/dubbo-go) 贡献代码或者文档,我们都热烈欢迎。具体请参考 [contribution intro](https://github.com/apache/dubbo-go/blob/master/cg.md)。 diff --git a/cluster/cluster_impl/available_cluster.go b/cluster/cluster_impl/available_cluster.go new file mode 100644 index 0000000000000000000000000000000000000000..7e748cd938319ff437bb3fb6c7945b857d316069 --- /dev/null +++ b/cluster/cluster_impl/available_cluster.go @@ -0,0 +1,40 @@ +/* +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 ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" +) + +type availableCluster struct{} + +const available = "available" + +func init() { + extension.SetCluster(available, NewAvailableCluster) +} + +func NewAvailableCluster() cluster.Cluster { + return &availableCluster{} +} + +func (cluser *availableCluster) Join(directory cluster.Directory) protocol.Invoker { + return NewAvailableClusterInvoker(directory) +} diff --git a/cluster/cluster_impl/available_cluster_invoker.go b/cluster/cluster_impl/available_cluster_invoker.go new file mode 100644 index 0000000000000000000000000000000000000000..c59c0702c216fe5c58d190a023322aaa00ac9c17 --- /dev/null +++ b/cluster/cluster_impl/available_cluster_invoker.go @@ -0,0 +1,61 @@ +/* +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 ( + "fmt" +) + +import ( + "github.com/pkg/errors" +) + +import ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/protocol" +) + +type availableClusterInvoker struct { + baseClusterInvoker +} + +func NewAvailableClusterInvoker(directory cluster.Directory) protocol.Invoker { + return &availableClusterInvoker{ + baseClusterInvoker: newBaseClusterInvoker(directory), + } +} + +func (invoker *availableClusterInvoker) Invoke(invocation protocol.Invocation) protocol.Result { + invokers := invoker.directory.List(invocation) + err := invoker.checkInvokers(invokers, invocation) + if err != nil { + return &protocol.RPCResult{Err: err} + } + + err = invoker.checkWhetherDestroyed() + if err != nil { + return &protocol.RPCResult{Err: err} + } + + for _, ivk := range invokers { + if ivk.IsAvailable() { + return ivk.Invoke(invocation) + } + } + return &protocol.RPCResult{Err: errors.New(fmt.Sprintf("no provider available in %v", invokers))} +} diff --git a/cluster/cluster_impl/available_cluster_invoker_test.go b/cluster/cluster_impl/available_cluster_invoker_test.go new file mode 100644 index 0000000000000000000000000000000000000000..04032a7f24dec0e73acb15921f753921391f1515 --- /dev/null +++ b/cluster/cluster_impl/available_cluster_invoker_test.go @@ -0,0 +1,88 @@ +/* +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" + "strings" + "testing" +) + +import ( + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +import ( + "github.com/apache/dubbo-go/cluster/directory" + "github.com/apache/dubbo-go/cluster/loadbalance" + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/apache/dubbo-go/protocol/mock" +) + +var ( + availableUrl, _ = common.NewURL(context.Background(), "dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider") +) + +func registerAvailable(t *testing.T, invoker *mock.MockInvoker) protocol.Invoker { + extension.SetLoadbalance("random", loadbalance.NewRandomLoadBalance) + availableCluster := NewAvailableCluster() + + invokers := []protocol.Invoker{} + invokers = append(invokers, invoker) + invoker.EXPECT().GetUrl().Return(availableUrl) + + staticDir := directory.NewStaticDirectory(invokers) + clusterInvoker := availableCluster.Join(staticDir) + return clusterInvoker +} + +func TestAvailableClusterInvokerSuccess(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invoker := mock.NewMockInvoker(ctrl) + clusterInvoker := registerAvailable(t, invoker) + + mockResult := &protocol.RPCResult{Rest: rest{tried: 0, success: true}} + invoker.EXPECT().IsAvailable().Return(true) + invoker.EXPECT().Invoke(gomock.Any()).Return(mockResult) + + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + + assert.Equal(t, mockResult, result) +} + +func TestAvailableClusterInvokerNoAvail(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invoker := mock.NewMockInvoker(ctrl) + clusterInvoker := registerAvailable(t, invoker) + + invoker.EXPECT().IsAvailable().Return(false) + + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + + assert.NotNil(t, result.Error()) + assert.True(t, strings.Contains(result.Error().Error(), "no provider available")) + assert.Nil(t, result.Result()) +} diff --git a/cluster/cluster_impl/base_cluster_invoker.go b/cluster/cluster_impl/base_cluster_invoker.go index 6cbed7748e496afb37f9a1e93dbc40e845c62b06..52e2156885a2e6cc3c35da75a1d0db8bcfcabec0 100644 --- a/cluster/cluster_impl/base_cluster_invoker.go +++ b/cluster/cluster_impl/base_cluster_invoker.go @@ -25,9 +25,10 @@ import ( import ( "github.com/apache/dubbo-go/cluster" "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/extension" "github.com/apache/dubbo-go/common/utils" "github.com/apache/dubbo-go/protocol" - "github.com/apache/dubbo-go/version" ) type baseClusterInvoker struct { @@ -65,7 +66,7 @@ func (invoker *baseClusterInvoker) checkInvokers(invokers []protocol.Invoker, in ip, _ := utils.GetLocalIP() return perrors.Errorf("Failed to invoke the method %v. No provider available for the service %v from "+ "registry %v on the consumer %v using the dubbo version %v .Please check if the providers have been started and registered.", - invocation.MethodName(), invoker.directory.GetUrl().SubURL.Key(), invoker.directory.GetUrl().String(), ip, version.Version) + invocation.MethodName(), invoker.directory.GetUrl().SubURL.Key(), invoker.directory.GetUrl().String(), ip, constant.Version) } return nil @@ -76,13 +77,13 @@ func (invoker *baseClusterInvoker) checkWhetherDestroyed() error { if invoker.destroyed.Load() { ip, _ := utils.GetLocalIP() return perrors.Errorf("Rpc cluster invoker for %v on consumer %v use dubbo version %v is now destroyed! can not invoke any more. ", - invoker.directory.GetUrl().Service(), ip, version.Version) + invoker.directory.GetUrl().Service(), ip, constant.Version) } return nil } func (invoker *baseClusterInvoker) doSelect(lb cluster.LoadBalance, invocation protocol.Invocation, invokers []protocol.Invoker, invoked []protocol.Invoker) protocol.Invoker { - //todo:ticky connect 粘纸连接 + //todo:sticky connect if len(invokers) == 1 { return invokers[0] } @@ -115,12 +116,24 @@ func (invoker *baseClusterInvoker) doSelect(lb cluster.LoadBalance, invocation p } func isInvoked(selectedInvoker protocol.Invoker, invoked []protocol.Invoker) bool { - if len(invoked) > 0 { - for _, i := range invoked { - if i == selectedInvoker { - return true - } + for _, i := range invoked { + if i == selectedInvoker { + return true } } return false } + +func getLoadBalance(invoker protocol.Invoker, invocation protocol.Invocation) cluster.LoadBalance { + url := invoker.GetUrl() + + methodName := invocation.MethodName() + //Get the service loadbalance config + lb := url.GetParam(constant.LOADBALANCE_KEY, constant.DEFAULT_LOADBALANCE) + + //Get the service method loadbalance config if have + if v := url.GetMethodParam(methodName, constant.LOADBALANCE_KEY, ""); len(v) > 0 { + lb = v + } + return extension.GetLoadbalance(lb) +} diff --git a/cluster/cluster_impl/broadcast_cluster.go b/cluster/cluster_impl/broadcast_cluster.go new file mode 100644 index 0000000000000000000000000000000000000000..50aae3cfab8d67570b50dcab4e53bbfad29d6d30 --- /dev/null +++ b/cluster/cluster_impl/broadcast_cluster.go @@ -0,0 +1,40 @@ +/* +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 ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" +) + +type broadcastCluster struct{} + +const broadcast = "broadcast" + +func init() { + extension.SetCluster(broadcast, NewBroadcastCluster) +} + +func NewBroadcastCluster() cluster.Cluster { + return &broadcastCluster{} +} + +func (cluster *broadcastCluster) Join(directory cluster.Directory) protocol.Invoker { + return newBroadcastClusterInvoker(directory) +} diff --git a/cluster/cluster_impl/broadcast_cluster_invoker.go b/cluster/cluster_impl/broadcast_cluster_invoker.go new file mode 100644 index 0000000000000000000000000000000000000000..238df0acfa7fb946e38bfbfd490bce7c0bb34e60 --- /dev/null +++ b/cluster/cluster_impl/broadcast_cluster_invoker.go @@ -0,0 +1,59 @@ +/* +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 ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/common/logger" + "github.com/apache/dubbo-go/protocol" +) + +type broadcastClusterInvoker struct { + baseClusterInvoker +} + +func newBroadcastClusterInvoker(directory cluster.Directory) protocol.Invoker { + return &broadcastClusterInvoker{ + baseClusterInvoker: newBaseClusterInvoker(directory), + } +} + +func (invoker *broadcastClusterInvoker) Invoke(invocation protocol.Invocation) protocol.Result { + invokers := invoker.directory.List(invocation) + err := invoker.checkInvokers(invokers, invocation) + if err != nil { + return &protocol.RPCResult{Err: err} + } + err = invoker.checkWhetherDestroyed() + if err != nil { + return &protocol.RPCResult{Err: err} + } + + var result protocol.Result + for _, ivk := range invokers { + result = ivk.Invoke(invocation) + if result.Error() != nil { + logger.Warnf("broadcast invoker invoke err: %v when use invoker: %v\n", result.Error(), ivk) + err = result.Error() + } + } + if err != nil { + return &protocol.RPCResult{Err: err} + } + return result +} diff --git a/cluster/cluster_impl/broadcast_cluster_invoker_test.go b/cluster/cluster_impl/broadcast_cluster_invoker_test.go new file mode 100644 index 0000000000000000000000000000000000000000..565684a8ae25c648ff77aef71d2ced0665202fe7 --- /dev/null +++ b/cluster/cluster_impl/broadcast_cluster_invoker_test.go @@ -0,0 +1,109 @@ +/* +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" + "errors" + "testing" +) + +import ( + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +import ( + "github.com/apache/dubbo-go/cluster/directory" + "github.com/apache/dubbo-go/cluster/loadbalance" + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/apache/dubbo-go/protocol/mock" +) + +var ( + broadcastUrl, _ = common.NewURL(context.TODO(), "dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider") +) + +func registerBroadcast(t *testing.T, mockInvokers ...*mock.MockInvoker) protocol.Invoker { + extension.SetLoadbalance("random", loadbalance.NewRandomLoadBalance) + + invokers := []protocol.Invoker{} + for i, ivk := range mockInvokers { + invokers = append(invokers, ivk) + if i == 0 { + ivk.EXPECT().GetUrl().Return(broadcastUrl) + } + } + staticDir := directory.NewStaticDirectory(invokers) + + broadcastCluster := NewBroadcastCluster() + clusterInvoker := broadcastCluster.Join(staticDir) + return clusterInvoker +} + +func Test_BroadcastInvokeSuccess(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invokers := make([]*mock.MockInvoker, 0) + + mockResult := &protocol.RPCResult{Rest: rest{tried: 0, success: true}} + for i := 0; i < 3; i++ { + invoker := mock.NewMockInvoker(ctrl) + invokers = append(invokers, invoker) + invoker.EXPECT().Invoke(gomock.Any()).Return(mockResult) + } + + clusterInvoker := registerBroadcast(t, invokers...) + + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + assert.Equal(t, mockResult, result) +} + +func Test_BroadcastInvokeFailed(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invokers := make([]*mock.MockInvoker, 0) + + mockResult := &protocol.RPCResult{Rest: rest{tried: 0, success: true}} + mockFailedResult := &protocol.RPCResult{Err: errors.New("just failed")} + for i := 0; i < 10; i++ { + invoker := mock.NewMockInvoker(ctrl) + invokers = append(invokers, invoker) + invoker.EXPECT().Invoke(gomock.Any()).Return(mockResult) + } + { + invoker := mock.NewMockInvoker(ctrl) + invokers = append(invokers, invoker) + invoker.EXPECT().Invoke(gomock.Any()).Return(mockFailedResult) + } + for i := 0; i < 10; i++ { + invoker := mock.NewMockInvoker(ctrl) + invokers = append(invokers, invoker) + invoker.EXPECT().Invoke(gomock.Any()).Return(mockResult) + } + + clusterInvoker := registerBroadcast(t, invokers...) + + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + assert.Equal(t, mockFailedResult.Err, result.Error()) +} diff --git a/cluster/cluster_impl/failback_cluster.go b/cluster/cluster_impl/failback_cluster.go new file mode 100644 index 0000000000000000000000000000000000000000..de22c78e947d0b8124add721ab7ff42efebcdbe4 --- /dev/null +++ b/cluster/cluster_impl/failback_cluster.go @@ -0,0 +1,40 @@ +/* + * 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 ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" +) + +type failbackCluster struct{} + +const failback = "failback" + +func init() { + extension.SetCluster(failback, NewFailbackCluster) +} + +func NewFailbackCluster() cluster.Cluster { + return &failbackCluster{} +} + +func (cluster *failbackCluster) Join(directory cluster.Directory) protocol.Invoker { + return newFailbackClusterInvoker(directory) +} diff --git a/cluster/cluster_impl/failback_cluster_invoker.go b/cluster/cluster_impl/failback_cluster_invoker.go new file mode 100644 index 0000000000000000000000000000000000000000..027461ccb7f32d6383d756ac986295b6300f249c --- /dev/null +++ b/cluster/cluster_impl/failback_cluster_invoker.go @@ -0,0 +1,203 @@ +/* + * 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 ( + "sync" + "time" +) + +import ( + "github.com/Workiva/go-datastructures/queue" +) + +import ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/common/logger" + "github.com/apache/dubbo-go/protocol" +) + +/** + * When fails, record failure requests and schedule for retry on a regular interval. + * Especially useful for services of notification. + * + * <a href="http://en.wikipedia.org/wiki/Failback">Failback</a> + */ +type failbackClusterInvoker struct { + baseClusterInvoker + + once sync.Once + ticker *time.Ticker + maxRetries int64 + failbackTasks int64 + taskList *queue.Queue +} + +func newFailbackClusterInvoker(directory cluster.Directory) protocol.Invoker { + invoker := &failbackClusterInvoker{ + baseClusterInvoker: newBaseClusterInvoker(directory), + } + retriesConfig := invoker.GetUrl().GetParamInt(constant.RETRIES_KEY, constant.DEFAULT_FAILBACK_TIMES) + if retriesConfig <= 0 { + retriesConfig = constant.DEFAULT_FAILBACK_TIMES + } + failbackTasksConfig := invoker.GetUrl().GetParamInt(constant.FAIL_BACK_TASKS_KEY, constant.DEFAULT_FAILBACK_TASKS) + if failbackTasksConfig <= 0 { + failbackTasksConfig = constant.DEFAULT_FAILBACK_TASKS + } + invoker.maxRetries = retriesConfig + invoker.failbackTasks = failbackTasksConfig + return invoker +} + +func (invoker *failbackClusterInvoker) process() { + invoker.ticker = time.NewTicker(time.Second * 1) + for range invoker.ticker.C { + // check each timeout task and re-run + for { + value, err := invoker.taskList.Peek() + if err == queue.ErrDisposed { + return + } + if err == queue.ErrEmptyQueue { + break + } + + retryTask := value.(*retryTimerTask) + if time.Since(retryTask.lastT).Seconds() < 5 { + break + } + + // ignore return. the get must success. + _, err = invoker.taskList.Get(1) + if err != nil { + logger.Warnf("get task found err: %v\n", err) + break + } + + go func(retryTask *retryTimerTask) { + invoked := make([]protocol.Invoker, 0) + invoked = append(invoked, retryTask.lastInvoker) + + retryInvoker := invoker.doSelect(retryTask.loadbalance, retryTask.invocation, retryTask.invokers, invoked) + var result protocol.Result + result = retryInvoker.Invoke(retryTask.invocation) + if result.Error() != nil { + retryTask.lastInvoker = retryInvoker + invoker.checkRetry(retryTask, result.Error()) + } + }(retryTask) + + } + } +} + +func (invoker *failbackClusterInvoker) checkRetry(retryTask *retryTimerTask, err error) { + logger.Errorf("Failed retry to invoke the method %v in the service %v, wait again. The exception: %v.\n", + retryTask.invocation.MethodName(), invoker.GetUrl().Service(), err.Error()) + retryTask.retries++ + retryTask.lastT = time.Now() + if retryTask.retries > invoker.maxRetries { + logger.Errorf("Failed retry times exceed threshold (%v), We have to abandon, invocation-> %v.\n", + retryTask.retries, retryTask.invocation) + } else { + invoker.taskList.Put(retryTask) + } +} + +func (invoker *failbackClusterInvoker) Invoke(invocation protocol.Invocation) protocol.Result { + invokers := invoker.directory.List(invocation) + err := invoker.checkInvokers(invokers, invocation) + if err != nil { + logger.Errorf("Failed to invoke the method %v in the service %v, wait for retry in background. Ignored exception: %v.\n", + invocation.MethodName(), invoker.GetUrl().Service(), err) + return &protocol.RPCResult{} + } + url := invokers[0].GetUrl() + methodName := invocation.MethodName() + //Get the service loadbalance config + lb := url.GetParam(constant.LOADBALANCE_KEY, constant.DEFAULT_LOADBALANCE) + + //Get the service method loadbalance config if have + if v := url.GetMethodParam(methodName, constant.LOADBALANCE_KEY, ""); v != "" { + lb = v + } + loadbalance := extension.GetLoadbalance(lb) + + invoked := make([]protocol.Invoker, 0, len(invokers)) + var result protocol.Result + + ivk := invoker.doSelect(loadbalance, invocation, invokers, invoked) + //DO INVOKE + result = ivk.Invoke(invocation) + if result.Error() != nil { + invoker.once.Do(func() { + invoker.taskList = queue.New(invoker.failbackTasks) + go invoker.process() + }) + + taskLen := invoker.taskList.Len() + if taskLen >= invoker.failbackTasks { + logger.Warnf("tasklist is too full > %d.\n", taskLen) + return &protocol.RPCResult{} + } + + timerTask := newRetryTimerTask(loadbalance, invocation, invokers, ivk) + invoker.taskList.Put(timerTask) + + logger.Errorf("Failback to invoke the method %v in the service %v, wait for retry in background. Ignored exception: %v.\n", + methodName, url.Service(), result.Error().Error()) + // ignore + return &protocol.RPCResult{} + } + + return result +} + +func (invoker *failbackClusterInvoker) Destroy() { + invoker.baseClusterInvoker.Destroy() + + // stop ticker + if invoker.ticker != nil { + invoker.ticker.Stop() + } + + _ = invoker.taskList.Dispose() +} + +type retryTimerTask struct { + loadbalance cluster.LoadBalance + invocation protocol.Invocation + invokers []protocol.Invoker + lastInvoker protocol.Invoker + retries int64 + lastT time.Time +} + +func newRetryTimerTask(loadbalance cluster.LoadBalance, invocation protocol.Invocation, invokers []protocol.Invoker, + lastInvoker protocol.Invoker) *retryTimerTask { + return &retryTimerTask{ + loadbalance: loadbalance, + invocation: invocation, + invokers: invokers, + lastInvoker: lastInvoker, + lastT: time.Now(), + } +} diff --git a/cluster/cluster_impl/failback_cluster_test.go b/cluster/cluster_impl/failback_cluster_test.go new file mode 100644 index 0000000000000000000000000000000000000000..c94347a1251a69a10c0a4d50007ef569bd6dd996 --- /dev/null +++ b/cluster/cluster_impl/failback_cluster_test.go @@ -0,0 +1,242 @@ +/* +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" + "sync" + "testing" + "time" +) + +import ( + "github.com/golang/mock/gomock" + perrors "github.com/pkg/errors" + "github.com/stretchr/testify/assert" +) + +import ( + "github.com/apache/dubbo-go/cluster/directory" + "github.com/apache/dubbo-go/cluster/loadbalance" + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/apache/dubbo-go/protocol/mock" +) + +var ( + failbackUrl, _ = common.NewURL(context.TODO(), "dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider") +) + +// registerFailback register failbackCluster to cluster extension. +func registerFailback(t *testing.T, invoker *mock.MockInvoker) protocol.Invoker { + extension.SetLoadbalance("random", loadbalance.NewRandomLoadBalance) + failbackCluster := NewFailbackCluster() + + invokers := []protocol.Invoker{} + invokers = append(invokers, invoker) + + invoker.EXPECT().GetUrl().Return(failbackUrl) + + staticDir := directory.NewStaticDirectory(invokers) + clusterInvoker := failbackCluster.Join(staticDir) + return clusterInvoker +} + +// success firstly, failback should return origin invoke result. +func Test_FailbackSuceess(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invoker := mock.NewMockInvoker(ctrl) + clusterInvoker := registerFailback(t, invoker).(*failbackClusterInvoker) + + invoker.EXPECT().GetUrl().Return(failbackUrl).Times(1) + + mockResult := &protocol.RPCResult{Rest: rest{tried: 0, success: true}} + invoker.EXPECT().Invoke(gomock.Any()).Return(mockResult) + + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + assert.Equal(t, mockResult, result) +} + +// failed firstly, success later after one retry. +func Test_FailbackRetryOneSuccess(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invoker := mock.NewMockInvoker(ctrl) + clusterInvoker := registerFailback(t, invoker).(*failbackClusterInvoker) + + invoker.EXPECT().GetUrl().Return(failbackUrl).AnyTimes() + + // failed at first + mockFailedResult := &protocol.RPCResult{Err: perrors.New("error")} + invoker.EXPECT().Invoke(gomock.Any()).Return(mockFailedResult) + + // success second + var wg sync.WaitGroup + wg.Add(1) + now := time.Now() + mockSuccResult := &protocol.RPCResult{Rest: rest{tried: 0, success: true}} + invoker.EXPECT().Invoke(gomock.Any()).DoAndReturn(func(invocation protocol.Invocation) protocol.Result { + delta := time.Since(now).Nanoseconds() / int64(time.Second) + assert.True(t, delta >= 5) + wg.Done() + return mockSuccResult + }) + + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + assert.Nil(t, result.Error()) + assert.Nil(t, result.Result()) + assert.Equal(t, 0, len(result.Attachments())) + + // ensure the retry task has been executed + assert.Equal(t, int64(1), clusterInvoker.taskList.Len()) + // wait until the retry task is executed, the taskList will be empty. + wg.Wait() + assert.Equal(t, int64(0), clusterInvoker.taskList.Len()) + + invoker.EXPECT().Destroy().Return() + clusterInvoker.Destroy() + + assert.Equal(t, int64(0), clusterInvoker.taskList.Len()) +} + +// failed firstly, and failed again after ech retry time. +func Test_FailbackRetryFailed(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invoker := mock.NewMockInvoker(ctrl) + clusterInvoker := registerFailback(t, invoker).(*failbackClusterInvoker) + + invoker.EXPECT().GetUrl().Return(failbackUrl).AnyTimes() + + mockFailedResult := &protocol.RPCResult{Err: perrors.New("error")} + invoker.EXPECT().Invoke(gomock.Any()).Return(mockFailedResult) + + // + var wg sync.WaitGroup + retries := 2 + wg.Add(retries) + now := time.Now() + + // add retry call that eventually failed. + for i := 0; i < retries; i++ { + j := i + 1 + invoker.EXPECT().Invoke(gomock.Any()).DoAndReturn(func(invocation protocol.Invocation) protocol.Result { + delta := time.Since(now).Nanoseconds() / int64(time.Second) + assert.True(t, delta >= int64(5*j)) + wg.Done() + return mockFailedResult + }) + } + + // first call should failed. + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + assert.Nil(t, result.Error()) + assert.Nil(t, result.Result()) + assert.Equal(t, 0, len(result.Attachments())) + + wg.Wait() + time.Sleep(time.Second) + assert.Equal(t, int64(1), clusterInvoker.taskList.Len()) + + invoker.EXPECT().Destroy().Return() + clusterInvoker.Destroy() + // after destroy, the taskList will be empty + assert.Equal(t, int64(0), clusterInvoker.taskList.Len()) +} + +// add 10 tasks but all failed firstly, and failed again with one retry. +func Test_FailbackRetryFailed10Times(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invoker := mock.NewMockInvoker(ctrl) + clusterInvoker := registerFailback(t, invoker).(*failbackClusterInvoker) + clusterInvoker.maxRetries = 10 + + invoker.EXPECT().GetUrl().Return(failbackUrl).AnyTimes() + + // 10 task should failed firstly. + mockFailedResult := &protocol.RPCResult{Err: perrors.New("error")} + invoker.EXPECT().Invoke(gomock.Any()).Return(mockFailedResult).Times(10) + + // 10 task should retry and failed. + var wg sync.WaitGroup + wg.Add(10) + now := time.Now() + invoker.EXPECT().Invoke(gomock.Any()).DoAndReturn(func(invocation protocol.Invocation) protocol.Result { + delta := time.Since(now).Nanoseconds() / int64(time.Second) + assert.True(t, delta >= 5) + wg.Done() + return mockFailedResult + }).Times(10) + + for i := 0; i < 10; i++ { + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + assert.Nil(t, result.Error()) + assert.Nil(t, result.Result()) + assert.Equal(t, 0, len(result.Attachments())) + } + + wg.Wait() + time.Sleep(time.Second) // in order to ensure checkRetry have done + assert.Equal(t, int64(10), clusterInvoker.taskList.Len()) + + invoker.EXPECT().Destroy().Return() + clusterInvoker.Destroy() + + assert.Equal(t, int64(0), clusterInvoker.taskList.Len()) +} + +func Test_FailbackOutOfLimit(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invoker := mock.NewMockInvoker(ctrl) + clusterInvoker := registerFailback(t, invoker).(*failbackClusterInvoker) + clusterInvoker.failbackTasks = 1 + + invoker.EXPECT().GetUrl().Return(failbackUrl).AnyTimes() + + mockFailedResult := &protocol.RPCResult{Err: perrors.New("error")} + invoker.EXPECT().Invoke(gomock.Any()).Return(mockFailedResult).Times(11) + + // reached limit + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + assert.Nil(t, result.Error()) + assert.Nil(t, result.Result()) + assert.Equal(t, 0, len(result.Attachments())) + + // all will be out of limit + for i := 0; i < 10; i++ { + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + assert.Nil(t, result.Error()) + assert.Nil(t, result.Result()) + assert.Equal(t, 0, len(result.Attachments())) + + assert.Equal(t, int64(1), clusterInvoker.taskList.Len()) + } + + invoker.EXPECT().Destroy().Return() + clusterInvoker.Destroy() +} diff --git a/cluster/cluster_impl/failfast_cluster.go b/cluster/cluster_impl/failfast_cluster.go new file mode 100644 index 0000000000000000000000000000000000000000..6301d945626103226132b433dd21e8647f53a38b --- /dev/null +++ b/cluster/cluster_impl/failfast_cluster.go @@ -0,0 +1,40 @@ +/* +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 ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" +) + +type failfastCluster struct{} + +const failfast = "failfast" + +func init() { + extension.SetCluster(failfast, NewFailFastCluster) +} + +func NewFailFastCluster() cluster.Cluster { + return &failfastCluster{} +} + +func (cluster *failfastCluster) Join(directory cluster.Directory) protocol.Invoker { + return newFailFastClusterInvoker(directory) +} diff --git a/cluster/cluster_impl/failfast_cluster_invoker.go b/cluster/cluster_impl/failfast_cluster_invoker.go new file mode 100644 index 0000000000000000000000000000000000000000..734ea2c6cb19bf54a338a76a10c9cfcc59d3954b --- /dev/null +++ b/cluster/cluster_impl/failfast_cluster_invoker.go @@ -0,0 +1,51 @@ +/* +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 ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/protocol" +) + +type failfastClusterInvoker struct { + baseClusterInvoker +} + +func newFailFastClusterInvoker(directory cluster.Directory) protocol.Invoker { + return &failfastClusterInvoker{ + baseClusterInvoker: newBaseClusterInvoker(directory), + } +} + +func (invoker *failfastClusterInvoker) Invoke(invocation protocol.Invocation) protocol.Result { + invokers := invoker.directory.List(invocation) + err := invoker.checkInvokers(invokers, invocation) + if err != nil { + return &protocol.RPCResult{Err: err} + } + + loadbalance := getLoadBalance(invokers[0], invocation) + + err = invoker.checkWhetherDestroyed() + if err != nil { + return &protocol.RPCResult{Err: err} + } + + ivk := invoker.doSelect(loadbalance, invocation, invokers, nil) + return ivk.Invoke(invocation) +} diff --git a/cluster/cluster_impl/failfast_cluster_test.go b/cluster/cluster_impl/failfast_cluster_test.go new file mode 100644 index 0000000000000000000000000000000000000000..7a19e80ccda15aa13a1c4fcf250e05a6effa7f0b --- /dev/null +++ b/cluster/cluster_impl/failfast_cluster_test.go @@ -0,0 +1,97 @@ +/* +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" + "testing" +) + +import ( + "github.com/golang/mock/gomock" + perrors "github.com/pkg/errors" + "github.com/stretchr/testify/assert" +) + +import ( + "github.com/apache/dubbo-go/cluster/directory" + "github.com/apache/dubbo-go/cluster/loadbalance" + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/apache/dubbo-go/protocol/mock" +) + +var ( + failfastUrl, _ = common.NewURL(context.TODO(), "dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider") +) + +// registerFailfast register failfastCluster to cluster extension. +func registerFailfast(t *testing.T, invoker *mock.MockInvoker) protocol.Invoker { + extension.SetLoadbalance("random", loadbalance.NewRandomLoadBalance) + failfastCluster := NewFailFastCluster() + + invokers := []protocol.Invoker{} + invokers = append(invokers, invoker) + + invoker.EXPECT().GetUrl().Return(failfastUrl) + + staticDir := directory.NewStaticDirectory(invokers) + clusterInvoker := failfastCluster.Join(staticDir) + return clusterInvoker +} + +func Test_FailfastInvokeSuccess(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invoker := mock.NewMockInvoker(ctrl) + clusterInvoker := registerFailfast(t, invoker) + + invoker.EXPECT().GetUrl().Return(failfastUrl) + + mockResult := &protocol.RPCResult{Rest: rest{tried: 0, success: true}} + + invoker.EXPECT().Invoke(gomock.Any()).Return(mockResult) + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + + assert.NoError(t, result.Error()) + res := result.Result().(rest) + assert.True(t, res.success) + assert.Equal(t, 0, res.tried) +} + +func Test_FailfastInvokeFail(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invoker := mock.NewMockInvoker(ctrl) + clusterInvoker := registerFailfast(t, invoker) + + invoker.EXPECT().GetUrl().Return(failfastUrl) + + mockResult := &protocol.RPCResult{Err: perrors.New("error")} + + invoker.EXPECT().Invoke(gomock.Any()).Return(mockResult) + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + + assert.NotNil(t, result.Error()) + assert.Equal(t, "error", result.Error().Error()) + assert.Nil(t, result.Result()) +} diff --git a/cluster/cluster_impl/failover_cluster_invoker.go b/cluster/cluster_impl/failover_cluster_invoker.go index cd17a85e00a1d4307b3b861467051e9719345d1a..3dd8c41dfb7b7512d7c81fa6d7f8a7c35cec0dcb 100644 --- a/cluster/cluster_impl/failover_cluster_invoker.go +++ b/cluster/cluster_impl/failover_cluster_invoker.go @@ -24,10 +24,8 @@ import ( import ( "github.com/apache/dubbo-go/cluster" "github.com/apache/dubbo-go/common/constant" - "github.com/apache/dubbo-go/common/extension" "github.com/apache/dubbo-go/common/utils" "github.com/apache/dubbo-go/protocol" - "github.com/apache/dubbo-go/version" ) type failoverClusterInvoker struct { @@ -48,17 +46,11 @@ func (invoker *failoverClusterInvoker) Invoke(invocation protocol.Invocation) pr if err != nil { return &protocol.RPCResult{Err: err} } - url := invokers[0].GetUrl() - methodName := invocation.MethodName() - //Get the service loadbalance config - lb := url.GetParam(constant.LOADBALANCE_KEY, constant.DEFAULT_LOADBALANCE) + loadbalance := getLoadBalance(invokers[0], invocation) - //Get the service method loadbalance config if have - if v := url.GetMethodParam(methodName, constant.LOADBALANCE_KEY, ""); v != "" { - lb = v - } - loadbalance := extension.GetLoadbalance(lb) + methodName := invocation.MethodName() + url := invokers[0].GetUrl() //get reties retries := url.GetParamInt(constant.RETRIES_KEY, constant.DEFAULT_RETRIES) @@ -98,6 +90,6 @@ func (invoker *failoverClusterInvoker) Invoke(invocation protocol.Invocation) pr ip, _ := utils.GetLocalIP() return &protocol.RPCResult{Err: perrors.Errorf("Failed to invoke the method %v in the service %v. Tried %v times of "+ "the providers %v (%v/%v)from the registry %v on the consumer %v using the dubbo version %v. Last error is %v.", - methodName, invoker.GetUrl().Service(), retries, providers, len(providers), len(invokers), invoker.directory.GetUrl(), ip, version.Version, result.Error().Error(), + methodName, invoker.GetUrl().Service(), retries, providers, len(providers), len(invokers), invoker.directory.GetUrl(), ip, constant.Version, result.Error().Error(), )} } diff --git a/cluster/cluster_impl/failover_cluster_test.go b/cluster/cluster_impl/failover_cluster_test.go index cc533ea098ee76488d2f76cbbe601b275274db83..dc039db8de41ab6722b20f99c5a0c5536a42a7e6 100644 --- a/cluster/cluster_impl/failover_cluster_test.go +++ b/cluster/cluster_impl/failover_cluster_test.go @@ -143,8 +143,7 @@ func Test_FailoverInvoke2(t *testing.T) { urlParams.Set(constant.RETRIES_KEY, "2") urlParams.Set("methods.test."+constant.RETRIES_KEY, "3") - ivc := &invocation.RPCInvocation{} - ivc.SetMethod("test") + ivc := invocation.NewRPCInvocationWithOptions(invocation.WithMethodName("test")) result := normalInvoke(t, 3, urlParams, ivc) assert.NoError(t, result.Error()) count = 0 diff --git a/cluster/cluster_impl/failsafe_cluster.go b/cluster/cluster_impl/failsafe_cluster.go new file mode 100644 index 0000000000000000000000000000000000000000..3ff97d25eae80980a90a03e71865bb8f9a63defe --- /dev/null +++ b/cluster/cluster_impl/failsafe_cluster.go @@ -0,0 +1,40 @@ +/* + * 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 ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" +) + +type failsafeCluster struct{} + +const failsafe = "failsafe" + +func init() { + extension.SetCluster(failsafe, NewFailsafeCluster) +} + +func NewFailsafeCluster() cluster.Cluster { + return &failsafeCluster{} +} + +func (cluster *failsafeCluster) Join(directory cluster.Directory) protocol.Invoker { + return newFailsafeClusterInvoker(directory) +} diff --git a/cluster/cluster_impl/failsafe_cluster_invoker.go b/cluster/cluster_impl/failsafe_cluster_invoker.go new file mode 100644 index 0000000000000000000000000000000000000000..b95f997fef87cf466f07c4e506e41758e7998e52 --- /dev/null +++ b/cluster/cluster_impl/failsafe_cluster_invoker.go @@ -0,0 +1,75 @@ +/* + * 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 ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/common/logger" + "github.com/apache/dubbo-go/protocol" +) + +/** + * When invoke fails, log the error message and ignore this error by returning an empty Result. + * Usually used to write audit logs and other operations + * + * <a href="http://en.wikipedia.org/wiki/Fail-safe">Fail-safe</a> + * + */ +type failsafeClusterInvoker struct { + baseClusterInvoker +} + +func newFailsafeClusterInvoker(directory cluster.Directory) protocol.Invoker { + return &failsafeClusterInvoker{ + baseClusterInvoker: newBaseClusterInvoker(directory), + } +} + +func (invoker *failsafeClusterInvoker) Invoke(invocation protocol.Invocation) protocol.Result { + invokers := invoker.directory.List(invocation) + + err := invoker.checkInvokers(invokers, invocation) + if err != nil { + return &protocol.RPCResult{} + } + + url := invokers[0].GetUrl() + methodName := invocation.MethodName() + //Get the service loadbalance config + lb := url.GetParam(constant.LOADBALANCE_KEY, constant.DEFAULT_LOADBALANCE) + //Get the service method loadbalance config if have + if v := url.GetMethodParam(methodName, constant.LOADBALANCE_KEY, ""); v != "" { + lb = v + } + loadbalance := extension.GetLoadbalance(lb) + + invoked := make([]protocol.Invoker, 0) + var result protocol.Result + + ivk := invoker.doSelect(loadbalance, invocation, invokers, invoked) + //DO INVOKE + result = ivk.Invoke(invocation) + if result.Error() != nil { + // ignore + logger.Errorf("Failsafe ignore exception: %v.\n", result.Error().Error()) + return &protocol.RPCResult{} + } + return result +} diff --git a/cluster/cluster_impl/failsafe_cluster_test.go b/cluster/cluster_impl/failsafe_cluster_test.go new file mode 100644 index 0000000000000000000000000000000000000000..9ee9d9fee31b0cb24d877ab3dc0e24fb552f5f11 --- /dev/null +++ b/cluster/cluster_impl/failsafe_cluster_test.go @@ -0,0 +1,95 @@ +/* +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" + "testing" +) + +import ( + "github.com/golang/mock/gomock" + perrors "github.com/pkg/errors" + "github.com/stretchr/testify/assert" +) + +import ( + "github.com/apache/dubbo-go/cluster/directory" + "github.com/apache/dubbo-go/cluster/loadbalance" + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/apache/dubbo-go/protocol/mock" +) + +var ( + failsafeUrl, _ = common.NewURL(context.TODO(), "dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider") +) + +// register_failsafe register failsafeCluster to cluster extension. +func register_failsafe(t *testing.T, invoker *mock.MockInvoker) protocol.Invoker { + extension.SetLoadbalance("random", loadbalance.NewRandomLoadBalance) + failsafeCluster := NewFailsafeCluster() + + invokers := []protocol.Invoker{} + invokers = append(invokers, invoker) + + invoker.EXPECT().GetUrl().Return(failbackUrl) + + staticDir := directory.NewStaticDirectory(invokers) + clusterInvoker := failsafeCluster.Join(staticDir) + return clusterInvoker +} + +func Test_FailSafeInvokeSuccess(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invoker := mock.NewMockInvoker(ctrl) + clusterInvoker := register_failsafe(t, invoker) + + invoker.EXPECT().GetUrl().Return(failsafeUrl) + + mockResult := &protocol.RPCResult{Rest: rest{tried: 0, success: true}} + + invoker.EXPECT().Invoke(gomock.Any()).Return(mockResult) + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + + assert.NoError(t, result.Error()) + res := result.Result().(rest) + assert.True(t, res.success) +} + +func Test_FailSafeInvokeFail(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invoker := mock.NewMockInvoker(ctrl) + clusterInvoker := register_failsafe(t, invoker) + + invoker.EXPECT().GetUrl().Return(failsafeUrl) + + mockResult := &protocol.RPCResult{Err: perrors.New("error")} + + invoker.EXPECT().Invoke(gomock.Any()).Return(mockResult) + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + + assert.NoError(t, result.Error()) + assert.Nil(t, result.Result()) +} diff --git a/cluster/cluster_impl/forking_cluster.go b/cluster/cluster_impl/forking_cluster.go new file mode 100644 index 0000000000000000000000000000000000000000..0a3c2b313ff3c4e89e592af9256fc42713419914 --- /dev/null +++ b/cluster/cluster_impl/forking_cluster.go @@ -0,0 +1,40 @@ +/* +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 ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" +) + +type forkingCluster struct{} + +const forking = "forking" + +func init() { + extension.SetCluster(forking, NewForkingCluster) +} + +func NewForkingCluster() cluster.Cluster { + return &forkingCluster{} +} + +func (cluster *forkingCluster) Join(directory cluster.Directory) protocol.Invoker { + return newForkingClusterInvoker(directory) +} diff --git a/cluster/cluster_impl/forking_cluster_invoker.go b/cluster/cluster_impl/forking_cluster_invoker.go new file mode 100644 index 0000000000000000000000000000000000000000..d6cf2f4b89ab4f322fa758deecae90c60742ef49 --- /dev/null +++ b/cluster/cluster_impl/forking_cluster_invoker.go @@ -0,0 +1,99 @@ +/* +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 ( + "errors" + "fmt" + "time" +) + +import ( + "github.com/Workiva/go-datastructures/queue" +) + +import ( + "github.com/apache/dubbo-go/cluster" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/logger" + "github.com/apache/dubbo-go/protocol" +) + +type forkingClusterInvoker struct { + baseClusterInvoker +} + +func newForkingClusterInvoker(directory cluster.Directory) protocol.Invoker { + return &forkingClusterInvoker{ + baseClusterInvoker: newBaseClusterInvoker(directory), + } +} + +func (invoker *forkingClusterInvoker) Invoke(invocation protocol.Invocation) protocol.Result { + err := invoker.checkWhetherDestroyed() + if err != nil { + return &protocol.RPCResult{Err: err} + } + + invokers := invoker.directory.List(invocation) + err = invoker.checkInvokers(invokers, invocation) + if err != nil { + return &protocol.RPCResult{Err: err} + } + + var selected []protocol.Invoker + forks := int(invoker.GetUrl().GetParamInt(constant.FORKS_KEY, constant.DEFAULT_FORKS)) + timeouts := invoker.GetUrl().GetParamInt(constant.TIMEOUT_KEY, constant.DEFAULT_TIMEOUT) + if forks < 0 || forks > len(invokers) { + selected = invokers + } else { + selected = make([]protocol.Invoker, 0) + loadbalance := getLoadBalance(invokers[0], invocation) + for i := 0; i < forks; i++ { + ivk := invoker.doSelect(loadbalance, invocation, invokers, selected) + if ivk != nil { + selected = append(selected, ivk) + } + } + } + + resultQ := queue.New(1) + for _, ivk := range selected { + go func(k protocol.Invoker) { + result := k.Invoke(invocation) + err := resultQ.Put(result) + if err != nil { + logger.Errorf("resultQ put failed with exception: %v.\n", err) + } + }(ivk) + } + + rsps, err := resultQ.Poll(1, time.Millisecond*time.Duration(timeouts)) + if err != nil { + return &protocol.RPCResult{ + Err: errors.New(fmt.Sprintf("failed to forking invoke provider %v, but no luck to perform the invocation. Last error is: %s", selected, err.Error()))} + } + if len(rsps) == 0 { + return &protocol.RPCResult{Err: errors.New(fmt.Sprintf("failed to forking invoke provider %v, but no resp", selected))} + } + result, ok := rsps[0].(protocol.Result) + if !ok { + return &protocol.RPCResult{Err: errors.New(fmt.Sprintf("failed to forking invoke provider %v, but not legal resp", selected))} + } + return result +} diff --git a/cluster/cluster_impl/forking_cluster_test.go b/cluster/cluster_impl/forking_cluster_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8603f8aedc4e28a3a4ca2f115355debc1a5ecc62 --- /dev/null +++ b/cluster/cluster_impl/forking_cluster_test.go @@ -0,0 +1,162 @@ +/* +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" + "strconv" + "sync" + "testing" + "time" +) + +import ( + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" +) + +import ( + "github.com/apache/dubbo-go/cluster/directory" + "github.com/apache/dubbo-go/cluster/loadbalance" + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/protocol" + "github.com/apache/dubbo-go/protocol/invocation" + "github.com/apache/dubbo-go/protocol/mock" +) + +var ( + forkingUrl, _ = common.NewURL(context.TODO(), "dubbo://192.168.1.1:20000/com.ikurento.user.UserProvider") +) + +func registerForking(t *testing.T, mockInvokers ...*mock.MockInvoker) protocol.Invoker { + extension.SetLoadbalance(loadbalance.RoundRobin, loadbalance.NewRoundRobinLoadBalance) + + invokers := []protocol.Invoker{} + for i, ivk := range mockInvokers { + invokers = append(invokers, ivk) + if i == 0 { + ivk.EXPECT().GetUrl().Return(forkingUrl) + } + } + staticDir := directory.NewStaticDirectory(invokers) + + forkingCluster := NewForkingCluster() + clusterInvoker := forkingCluster.Join(staticDir) + return clusterInvoker +} + +func Test_ForkingInvokeSuccess(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invokers := make([]*mock.MockInvoker, 0) + + mockResult := &protocol.RPCResult{Rest: rest{tried: 0, success: true}} + forkingUrl.AddParam(constant.FORKS_KEY, strconv.Itoa(3)) + //forkingUrl.AddParam(constant.TIMEOUT_KEY, strconv.Itoa(constant.DEFAULT_TIMEOUT)) + + var wg sync.WaitGroup + wg.Add(2) + for i := 0; i < 2; i++ { + invoker := mock.NewMockInvoker(ctrl) + invokers = append(invokers, invoker) + invoker.EXPECT().IsAvailable().Return(true).AnyTimes() + invoker.EXPECT().Invoke(gomock.Any()).DoAndReturn( + func(invocation protocol.Invocation) protocol.Result { + wg.Done() + return mockResult + }) + } + + clusterInvoker := registerForking(t, invokers...) + + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + assert.Equal(t, mockResult, result) + wg.Wait() +} + +func Test_ForkingInvokeTimeout(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invokers := make([]*mock.MockInvoker, 0) + + mockResult := &protocol.RPCResult{Rest: rest{tried: 0, success: true}} + forkingUrl.AddParam(constant.FORKS_KEY, strconv.Itoa(3)) + + var wg sync.WaitGroup + wg.Add(2) + for i := 0; i < 2; i++ { + invoker := mock.NewMockInvoker(ctrl) + invokers = append(invokers, invoker) + invoker.EXPECT().IsAvailable().Return(true).AnyTimes() + invoker.EXPECT().Invoke(gomock.Any()).DoAndReturn( + func(invocation protocol.Invocation) protocol.Result { + time.Sleep(2 * time.Second) + wg.Done() + return mockResult + }) + } + + clusterInvoker := registerForking(t, invokers...) + + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + assert.NotNil(t, result) + assert.NotNil(t, result.Error()) + wg.Wait() +} + +func Test_ForkingInvokeHalfTimeout(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + invokers := make([]*mock.MockInvoker, 0) + + mockResult := &protocol.RPCResult{Rest: rest{tried: 0, success: true}} + forkingUrl.AddParam(constant.FORKS_KEY, strconv.Itoa(3)) + + var wg sync.WaitGroup + wg.Add(2) + for i := 0; i < 2; i++ { + invoker := mock.NewMockInvoker(ctrl) + invokers = append(invokers, invoker) + invoker.EXPECT().IsAvailable().Return(true).AnyTimes() + if i == 1 { + invoker.EXPECT().Invoke(gomock.Any()).DoAndReturn( + func(invocation protocol.Invocation) protocol.Result { + wg.Done() + return mockResult + }) + } else { + invoker.EXPECT().Invoke(gomock.Any()).DoAndReturn( + func(invocation protocol.Invocation) protocol.Result { + time.Sleep(2 * time.Second) + wg.Done() + return mockResult + }) + } + } + + clusterInvoker := registerForking(t, invokers...) + + result := clusterInvoker.Invoke(&invocation.RPCInvocation{}) + assert.Equal(t, mockResult, result) + wg.Wait() +} diff --git a/cluster/loadbalance/least_active.go b/cluster/loadbalance/least_active.go index 695ca21b0ed53dcf94907223e4c222af17311db9..39c5620f02d607bb68430e17a206a1649ee31c54 100644 --- a/cluster/loadbalance/least_active.go +++ b/cluster/loadbalance/least_active.go @@ -1,14 +1,19 @@ -// Licensed 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. +/* + * 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. + */ // @author yiji@apache.org package loadbalance diff --git a/cluster/loadbalance/least_active_test.go b/cluster/loadbalance/least_active_test.go index c29a2092a19161d0dd75ee4098ee786b620880b0..7663ea3ce6252dcb7ddeaea92fb6bef8d95478d5 100644 --- a/cluster/loadbalance/least_active_test.go +++ b/cluster/loadbalance/least_active_test.go @@ -43,8 +43,7 @@ func TestLeastActiveByWeight(t *testing.T) { invokers = append(invokers, protocol.NewBaseInvoker(url)) } - inv := new(invocation.RPCInvocation) - inv.SetMethod("test") + inv := invocation.NewRPCInvocationWithOptions(invocation.WithMethodName("test")) protocol.BeginCount(invokers[2].GetUrl(), inv.MethodName()) loop = 10000 diff --git a/cluster/loadbalance/random_test.go b/cluster/loadbalance/random_test.go index 09d3d259a903693e9c0550965fc12d2089228662..ffe65d78ac61e5210d23e44c7f802597fed78f96 100644 --- a/cluster/loadbalance/random_test.go +++ b/cluster/loadbalance/random_test.go @@ -67,8 +67,7 @@ func Test_RandomlbSelectWeight(t *testing.T) { urlParams.Set("methods.test."+constant.WEIGHT_KEY, "10000000000000") urll, _ := common.NewURL(context.TODO(), fmt.Sprintf("dubbo://192.168.1.100:20000/com.ikurento.user.UserProvider"), common.WithParams(urlParams)) invokers = append(invokers, protocol.NewBaseInvoker(urll)) - ivc := &invocation.RPCInvocation{} - ivc.SetMethod("test") + ivc := invocation.NewRPCInvocationWithOptions(invocation.WithMethodName("test")) var selectedInvoker []protocol.Invoker var selected float64 @@ -99,8 +98,7 @@ func Test_RandomlbSelectWarmup(t *testing.T) { urlParams.Set(constant.REMOTE_TIMESTAMP_KEY, strconv.FormatInt(time.Now().Add(time.Minute*(-9)).Unix(), 10)) urll, _ := common.NewURL(context.TODO(), fmt.Sprintf("dubbo://192.168.1.100:20000/com.ikurento.user.UserProvider"), common.WithParams(urlParams)) invokers = append(invokers, protocol.NewBaseInvoker(urll)) - ivc := &invocation.RPCInvocation{} - ivc.SetMethod("test") + ivc := invocation.NewRPCInvocationWithOptions(invocation.WithMethodName("test")) var selectedInvoker []protocol.Invoker var selected float64 diff --git a/cluster/loadbalance/round_robin.go b/cluster/loadbalance/round_robin.go index e173e211c3630f4d4786edc2c1a09709fd7bf0a1..075acac7cdc60086ececb7b655dee86ec5198369 100644 --- a/cluster/loadbalance/round_robin.go +++ b/cluster/loadbalance/round_robin.go @@ -1,15 +1,19 @@ -// -// Licensed 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. +/* + * 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 loadbalance diff --git a/common/constant/default.go b/common/constant/default.go index 717b93163e347d345651319440a4b0504d31c980..e5c92fad4d3aa569b57e90d59f38c68834f4dba9 100644 --- a/common/constant/default.go +++ b/common/constant/default.go @@ -30,11 +30,13 @@ const ( ) const ( - DEFAULT_LOADBALANCE = "random" - DEFAULT_RETRIES = 2 - DEFAULT_PROTOCOL = "dubbo" - DEFAULT_REG_TIMEOUT = "10s" - DEFAULT_CLUSTER = "failover" + DEFAULT_LOADBALANCE = "random" + DEFAULT_RETRIES = 2 + DEFAULT_PROTOCOL = "dubbo" + DEFAULT_REG_TIMEOUT = "10s" + DEFAULT_CLUSTER = "failover" + DEFAULT_FAILBACK_TIMES = 3 + DEFAULT_FAILBACK_TASKS = 100 ) const ( @@ -42,6 +44,8 @@ const ( PREFIX_DEFAULT_KEY = "default." DEFAULT_SERVICE_FILTERS = "echo" DEFAULT_REFERENCE_FILTERS = "" + GENERIC_REFERENCE_FILTERS = "generic" + GENERIC = "$invoke" ECHO = "$echo" ) diff --git a/common/constant/key.go b/common/constant/key.go index f045bc8e95dee22462f979210327a2236699559c..13d65eb6f8d64f808d736566f4cc18c05cb9b1b4 100644 --- a/common/constant/key.go +++ b/common/constant/key.go @@ -34,6 +34,8 @@ const ( ENABLED_KEY = "enabled" SIDE_KEY = "side" OVERRIDE_PROVIDERS_KEY = "providerAddresses" + BEAN_NAME_KEY = "bean.name" + GENERIC_KEY = "generic" ) const ( @@ -50,6 +52,10 @@ const ( WARMUP_KEY = "warmup" RETRIES_KEY = "retries" BEAN_NAME = "bean.name" + FAIL_BACK_TASKS_KEY = "failbacktasks" + FORKS_KEY = "forks" + DEFAULT_FORKS = 2 + DEFAULT_TIMEOUT = 1000 ) const ( @@ -91,3 +97,15 @@ const ( ProviderConfigPrefix = "dubbo.provider." ConsumerConfigPrefix = "dubbo.consumer." ) + +const ( + NACOS_KEY = "nacos" + NACOS_DEFAULT_ROLETYPE = 3 + NACOS_CACHE_DIR_KEY = "cacheDir" + NACOS_LOG_DIR_KEY = "logDir" + NACOS_ENDPOINT = "endpoint" + NACOS_SERVICE_NAME_SEPARATOR = ":" + NACOS_CATEGORY_KEY = "category" + NACOS_PROTOCOL_KEY = "protocol" + NACOS_PATH_KEY = "path" +) diff --git a/version/version.go b/common/constant/version.go similarity index 98% rename from version/version.go rename to common/constant/version.go index b9a076e78cbf0c9c7b5172e1b30c84f60f250ea7..d4c6821e76894cbd82dc5fae09124263b5c6aa0f 100644 --- a/version/version.go +++ b/common/constant/version.go @@ -15,7 +15,7 @@ * limitations under the License. */ -package version +package constant const ( Version = "2.6.0" diff --git a/common/logger/logger.go b/common/logger/logger.go index e8dd5a608b68c7cbde0d8c6b85c1601c847fea01..f41e95744f954da69b0e3695c97ba3389c69160a 100644 --- a/common/logger/logger.go +++ b/common/logger/logger.go @@ -85,8 +85,6 @@ func InitLog(logConfFile string) error { InitLogger(conf) - // set getty log - getty.SetLogger(logger) return nil } @@ -112,9 +110,16 @@ func InitLogger(conf *zap.Config) { } zapLogger, _ := zapLoggerConfig.Build(zap.AddCallerSkip(1)) logger = zapLogger.Sugar() + + // set getty log + getty.SetLogger(logger) } func SetLogger(log Logger) { logger = log getty.SetLogger(logger) } + +func GetLogger() Logger { + return logger +} diff --git a/common/proxy/proxy.go b/common/proxy/proxy.go index 96d42eb21152e64d170f50276bbce88e1bf8db69..1c079f6bca52bf8f6e8c5ebb168da82ab8ccb5f2 100644 --- a/common/proxy/proxy.go +++ b/common/proxy/proxy.go @@ -116,7 +116,9 @@ func (p *Proxy) Implement(v common.RPCService) { } } - inv = invocation_impl.NewRPCInvocationForConsumer(methodName, nil, inArr, reply.Interface(), p.callBack, common.URL{}, nil) + inv = invocation_impl.NewRPCInvocationWithOptions(invocation_impl.WithMethodName(methodName), + invocation_impl.WithArguments(inArr), invocation_impl.WithReply(reply.Interface()), + invocation_impl.WithCallBack(p.callBack)) for k, value := range p.attachments { inv.SetAttachments(k, value) diff --git a/common/proxy/proxy_test.go b/common/proxy/proxy_test.go index 1cc30457c3b021ec139b57fe764d6ac6b9104dbc..8c1c0295d05135095b5be35b5b2b16428691d7f2 100644 --- a/common/proxy/proxy_test.go +++ b/common/proxy/proxy_test.go @@ -43,21 +43,15 @@ type TestService struct { Echo func(interface{}, *interface{}) error } -func (s *TestService) Service() string { +func (s *TestService) Reference() string { return "com.test.Path" } -func (s *TestService) Version() string { - return "" -} type TestServiceInt int -func (s *TestServiceInt) Service() string { +func (s *TestServiceInt) Reference() string { return "com.test.TestServiceInt" } -func (s *TestServiceInt) Version() string { - return "" -} func TestProxy_Implement(t *testing.T) { diff --git a/common/rpc_service.go b/common/rpc_service.go index 0444f0c17e7e9d96d1563c72fde2fd62b81fb744..4741a6fa3c0daef97f044f639a5e64a38fe4a187 100644 --- a/common/rpc_service.go +++ b/common/rpc_service.go @@ -36,8 +36,7 @@ import ( // rpc service interface type RPCService interface { - Service() string // Path InterfaceName - Version() string + Reference() string // rpc service id or reference id } // for lowercase func @@ -149,7 +148,7 @@ func (sm *serviceMap) Register(protocol string, rcvr RPCService) (string, error) return "", perrors.New(s) } - sname = rcvr.Service() + sname = rcvr.Reference() if server := sm.GetService(protocol, sname); server != nil { return "", perrors.New("service already defined: " + sname) } @@ -172,8 +171,8 @@ func (sm *serviceMap) Register(protocol string, rcvr RPCService) (string, error) return strings.TrimSuffix(methods, ","), nil } -func (sm *serviceMap) UnRegister(protocol, serviceName string) error { - if protocol == "" || serviceName == "" { +func (sm *serviceMap) UnRegister(protocol, serviceId string) error { + if protocol == "" || serviceId == "" { return perrors.New("protocol or serviceName is nil") } sm.mutex.RLock() @@ -182,16 +181,16 @@ func (sm *serviceMap) UnRegister(protocol, serviceName string) error { sm.mutex.RUnlock() return perrors.New("no services for " + protocol) } - _, ok = svcs[serviceName] + _, ok = svcs[serviceId] if !ok { sm.mutex.RUnlock() - return perrors.New("no service for " + serviceName) + return perrors.New("no service for " + serviceId) } sm.mutex.RUnlock() sm.mutex.Lock() defer sm.mutex.Unlock() - delete(svcs, serviceName) + delete(svcs, serviceId) delete(sm.serviceMap, protocol) return nil diff --git a/common/rpc_service_test.go b/common/rpc_service_test.go index 4232c9d90bee5a48ed988fa5449c3acbaf64f100..7df039b905d3cc064c5d6d9404fc874cf693dac9 100644 --- a/common/rpc_service_test.go +++ b/common/rpc_service_test.go @@ -39,12 +39,9 @@ func (s *TestService) MethodTwo(arg1, arg2, arg3 interface{}) (interface{}, erro func (s *TestService) MethodThree() error { return nil } -func (s *TestService) Service() string { +func (s *TestService) Reference() string { return "com.test.Path" } -func (s *TestService) Version() string { - return "" -} func (s *TestService) MethodMapper() map[string]string { return map[string]string{ "MethodTwo": "methodTwo", @@ -65,22 +62,16 @@ func (s *testService) Method3(ctx context.Context, args []interface{}, rsp *stru func (s *testService) Method4(ctx context.Context, args []interface{}, rsp *struct{}) *testService { return nil } -func (s *testService) Service() string { +func (s *testService) Reference() string { return "com.test.Path" } -func (s *testService) Version() string { - return "" -} type TestService1 struct { } -func (s *TestService1) Service() string { +func (s *TestService1) Reference() string { return "com.test.Path1" } -func (s *TestService1) Version() string { - return "" -} func TestServiceMap_Register(t *testing.T) { // lowercase @@ -181,7 +172,7 @@ func TestSuiteMethod(t *testing.T) { // wrong number of in return s1 := &testService{} - method, ok = reflect.TypeOf(s1).MethodByName("Version") + method, ok = reflect.TypeOf(s1).MethodByName("Reference") assert.True(t, ok) methodType = suiteMethod(method) assert.Nil(t, methodType) diff --git a/common/url.go b/common/url.go index 64c4274e6adc74228f7e856e00e40bbe05dd1d2d..52472d463a0784b0cb45e667c92cfc38f89e83d0 100644 --- a/common/url.go +++ b/common/url.go @@ -28,6 +28,7 @@ import ( "net/url" "strconv" "strings" + "sync" ) import ( @@ -67,11 +68,13 @@ func (t RoleType) Role() string { } type baseUrl struct { - Protocol string - Location string // ip+port - Ip string - Port string - Params url.Values + Protocol string + Location string // ip+port + Ip string + Port string + Params url.Values + //url.Values is not safe map, add to avoid concurrent map read and map write error + paramsLock sync.Mutex PrimitiveURL string ctx context.Context } @@ -139,6 +142,11 @@ func WithPath(path string) option { } } +func WithLocation(location string) option { + return func(url *URL) { + url.Location = location + } +} func NewURLWithOptions(opts ...option) *URL { url := &URL{} for _, opt := range opts { @@ -238,7 +246,7 @@ func isMatchCategory(category1 string, category2 string) bool { } else if strings.Contains(category2, constant.REMOVE_VALUE_PREFIX) { return !strings.Contains(category2, constant.REMOVE_VALUE_PREFIX+category1) } else { - strings.Contains(category2, category1) + return strings.Contains(category2, category1) } } func (c URL) String() string { @@ -298,14 +306,18 @@ func (c URL) Service() string { } func (c *URL) AddParam(key string, value string) { + c.paramsLock.Lock() c.Params.Add(key, value) + c.paramsLock.Unlock() } func (c URL) GetParam(s string, d string) string { var r string + c.paramsLock.Lock() if r = c.Params.Get(s); r == "" { r = d } + c.paramsLock.Unlock() return r } func (c URL) GetParamAndDecoded(key string) (string, error) { diff --git a/config/base_config_test.go b/config/base_config_test.go index 7676a11d025975b604ce3c493e7462a4bdba23f1..d07d983f64ed33fcac73f8430737dfb2f01c40c3 100644 --- a/config/base_config_test.go +++ b/config/base_config_test.go @@ -35,8 +35,8 @@ func Test_refresh(t *testing.T) { c := &BaseConfig{} mockMap := map[string]string{} mockMap["dubbo.registries.shanghai_reg1.protocol"] = "mock100" - mockMap["dubbo.reference.MockService.MockService.retries"] = "10" - mockMap["dubbo.MockService.MockService.GetUser.retries"] = "10" + mockMap["dubbo.reference.com.MockService.MockService.retries"] = "10" + mockMap["dubbo.com.MockService.MockService.GetUser.retries"] = "10" mockMap["dubbo.consumer.check"] = "false" mockMap["dubbo.application.name"] = "dubbo" @@ -88,7 +88,7 @@ func Test_refresh(t *testing.T) { }, References: map[string]*ReferenceConfig{ "MockService": { - InterfaceName: "MockService", + InterfaceName: "com.MockService", Protocol: "mock", Cluster: "failover", Loadbalance: "random", @@ -98,13 +98,14 @@ func Test_refresh(t *testing.T) { Methods: []*MethodConfig{ { InterfaceId: "MockService", - InterfaceName: "MockService", + InterfaceName: "com.MockService", Name: "GetUser", Retries: 2, Loadbalance: "random", }, - {InterfaceId: "MockService", - InterfaceName: "MockService", + { + InterfaceId: "MockService", + InterfaceName: "com.MockService", Name: "GetUser1", Retries: 2, Loadbalance: "random", @@ -128,8 +129,8 @@ func Test_refreshProvider(t *testing.T) { c := &BaseConfig{} mockMap := map[string]string{} mockMap["dubbo.registries.shanghai_reg1.protocol"] = "mock100" - mockMap["dubbo.service.MockService.MockService.retries"] = "10" - mockMap["dubbo.MockService.MockService.GetUser.retries"] = "10" + mockMap["dubbo.service.com.MockService.MockService.retries"] = "10" + mockMap["dubbo.com.MockService.MockService.GetUser.retries"] = "10" mockMap["dubbo.consumer.check"] = "false" mockMap["dubbo.application.name"] = "dubbo" mockMap["dubbo.protocols.jsonrpc1.name"] = "jsonrpc" @@ -183,7 +184,7 @@ func Test_refreshProvider(t *testing.T) { }, Services: map[string]*ServiceConfig{ "MockService": { - InterfaceName: "MockService", + InterfaceName: "com.MockService", Protocol: "mock", Cluster: "failover", Loadbalance: "random", @@ -193,13 +194,13 @@ func Test_refreshProvider(t *testing.T) { Methods: []*MethodConfig{ { InterfaceId: "MockService", - InterfaceName: "MockService", + InterfaceName: "com.MockService", Name: "GetUser", Retries: 2, Loadbalance: "random", }, {InterfaceId: "MockService", - InterfaceName: "MockService", + InterfaceName: "com.MockService", Name: "GetUser1", Retries: 2, Loadbalance: "random", diff --git a/config/config_loader.go b/config/config_loader.go index 86260c86734d88527ab03fede8286dd484953ba3..b033aced5365dc58b06887d95b15b24ec91980a9 100644 --- a/config/config_loader.go +++ b/config/config_loader.go @@ -28,7 +28,6 @@ import ( "github.com/apache/dubbo-go/common" "github.com/apache/dubbo-go/common/constant" "github.com/apache/dubbo-go/common/logger" - "github.com/apache/dubbo-go/version" ) var ( @@ -46,11 +45,11 @@ func init() { confConFile = os.Getenv(constant.CONF_CONSUMER_FILE_PATH) confProFile = os.Getenv(constant.CONF_PROVIDER_FILE_PATH) - if errCon := consumerInit(confConFile); errCon != nil { + if errCon := ConsumerInit(confConFile); errCon != nil { log.Printf("[consumerInit] %#v", errCon) consumerConfig = nil } - if errPro := providerInit(confProFile); errPro != nil { + if errPro := ProviderInit(confProFile); errPro != nil { log.Printf("[providerInit] %#v", errPro) providerConfig = nil } @@ -58,11 +57,6 @@ func init() { // Dubbo Init func Load() { - var ( - refMap map[string]*ReferenceConfig - srvMap map[string]*ServiceConfig - ) - // reference config if consumerConfig == nil { logger.Warnf("consumerConfig is nil!") @@ -70,18 +64,20 @@ func Load() { if err := configCenterRefreshConsumer(); err != nil { logger.Errorf("[consumer config center refresh] %#v", err) } - refMap = make(map[string]*ReferenceConfig) - for _, ref := range consumerConfig.References { - rpcService := GetConsumerService(ref.InterfaceName) + for key, ref := range consumerConfig.References { + if ref.Generic { + genericService := NewGenericService(key) + SetConsumerService(genericService) + } + rpcService := GetConsumerService(key) if rpcService == nil { - logger.Warnf("%s is not exsist!", ref.InterfaceName) + logger.Warnf("%s is not exsist!", key) continue } + ref.id = key ref.Refer() ref.Implement(rpcService) - refMap[ref.InterfaceName] = ref - } //wait for invoker is available, if wait over default 3s, then panic var count int @@ -97,7 +93,7 @@ func Load() { checkok = false count++ if count > maxWait { - panic(fmt.Sprintf("Failed to check the status of the service %v . No provider available for the service to the consumer use dubbo version %v", refconfig.InterfaceName, version.Version)) + panic(fmt.Sprintf("Failed to check the status of the service %v . No provider available for the service to the consumer use dubbo version %v", refconfig.InterfaceName, constant.Version)) } time.Sleep(time.Second * 1) break @@ -121,18 +117,17 @@ func Load() { if err := configCenterRefreshProvider(); err != nil { logger.Errorf("[provider config center refresh] %#v", err) } - srvMap = make(map[string]*ServiceConfig) - for _, svs := range providerConfig.Services { - rpcService := GetProviderService(svs.InterfaceName) + for key, svs := range providerConfig.Services { + rpcService := GetProviderService(key) if rpcService == nil { - logger.Warnf("%s is not exsist!", svs.InterfaceName) + logger.Warnf("%s is not exsist!", key) continue } + svs.id = key svs.Implement(rpcService) if err := svs.Export(); err != nil { - panic(fmt.Sprintf("service %s export failed! ", svs.InterfaceName)) + panic(fmt.Sprintf("service %s export failed! ", key)) } - srvMap[svs.InterfaceName] = svs } } } @@ -144,5 +139,5 @@ func GetRPCService(name string) common.RPCService { // create rpc service for consumer func RPCService(service common.RPCService) { - providerConfig.Services[service.Service()].Implement(service) + consumerConfig.References[service.Reference()].Implement(service) } diff --git a/config/config_loader_test.go b/config/config_loader_test.go index cbdc397c283f1e7948b42bbdd59b4f4a985671a6..107fea0b1d737f7be92d3e0042b6eebb7add78ed 100644 --- a/config/config_loader_test.go +++ b/config/config_loader_test.go @@ -45,9 +45,9 @@ func TestConfigLoader(t *testing.T) { assert.Nil(t, providerConfig) assert.Equal(t, ProviderConfig{}, GetProviderConfig()) - err = consumerInit(conPath) + err = ConsumerInit(conPath) assert.NoError(t, err) - err = providerInit(proPath) + err = ProviderInit(proPath) assert.NoError(t, err) assert.NotNil(t, consumerConfig) @@ -71,12 +71,12 @@ func TestLoad(t *testing.T) { Load() - assert.Equal(t, ms, GetRPCService(ms.Service())) + assert.Equal(t, ms, GetRPCService(ms.Reference())) ms2 := &struct { MockService }{} RPCService(ms2) - assert.NotEqual(t, ms2, GetRPCService(ms2.Service())) + assert.NotEqual(t, ms2, GetRPCService(ms2.Reference())) conServices = map[string]common.RPCService{} proServices = map[string]common.RPCService{} @@ -84,6 +84,7 @@ func TestLoad(t *testing.T) { consumerConfig = nil providerConfig = nil } + func TestWithNoRegLoad(t *testing.T) { doInit() doinit() @@ -99,12 +100,12 @@ func TestWithNoRegLoad(t *testing.T) { Load() - assert.Equal(t, ms, GetRPCService(ms.Service())) + assert.Equal(t, ms, GetRPCService(ms.Reference())) ms2 := &struct { MockService }{} RPCService(ms2) - assert.NotEqual(t, ms2, GetRPCService(ms2.Service())) + assert.NotEqual(t, ms2, GetRPCService(ms2.Reference())) conServices = map[string]common.RPCService{} proServices = map[string]common.RPCService{} @@ -112,6 +113,7 @@ func TestWithNoRegLoad(t *testing.T) { consumerConfig = nil providerConfig = nil } + func TestConfigLoaderWithConfigCenter(t *testing.T) { extension.SetConfigCenterFactory("mock", func() config_center.DynamicConfigurationFactory { return &config_center.MockDynamicConfigurationFactory{} @@ -127,10 +129,10 @@ func TestConfigLoaderWithConfigCenter(t *testing.T) { assert.Nil(t, providerConfig) assert.Equal(t, ProviderConfig{}, GetProviderConfig()) - err = consumerInit(conPath) + err = ConsumerInit(conPath) configCenterRefreshConsumer() assert.NoError(t, err) - err = providerInit(proPath) + err = ProviderInit(proPath) configCenterRefreshProvider() assert.NoError(t, err) diff --git a/config/consumer_config.go b/config/consumer_config.go index 5d3aec18e91ab3d9284c00fac3838d16414f2755..737339a0ad195201327eb4fac3445b18eb4bbf26 100644 --- a/config/consumer_config.go +++ b/config/consumer_config.go @@ -61,6 +61,7 @@ func (*ConsumerConfig) Prefix() string { func SetConsumerConfig(c ConsumerConfig) { consumerConfig = &c } + func GetConsumerConfig() ConsumerConfig { if consumerConfig == nil { logger.Warnf("consumerConfig is nil!") @@ -69,7 +70,7 @@ func GetConsumerConfig() ConsumerConfig { return *consumerConfig } -func consumerInit(confConFile string) error { +func ConsumerInit(confConFile string) error { if confConFile == "" { return perrors.Errorf("application configure(consumer) file name is nil") } diff --git a/config/generic_service.go b/config/generic_service.go new file mode 100644 index 0000000000000000000000000000000000000000..8a4e88df9788554bc4a5ee33884166e4ccede37f --- /dev/null +++ b/config/generic_service.go @@ -0,0 +1,30 @@ +/* + * 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 config + +type GenericService struct { + Invoke func(req []interface{}) (interface{}, error) `dubbo:"$invoke"` + referenceStr string +} + +func NewGenericService(referenceStr string) *GenericService { + return &GenericService{referenceStr: referenceStr} +} + +func (u *GenericService) Reference() string { + return u.referenceStr +} diff --git a/config/mock_rpcservice.go b/config/mock_rpcservice.go index 0b3b9f22b497c66067eff5969b8dca044a34735a..64d431ffb6dfbc7e25a988c6093cf0ab5cbd2db5 100644 --- a/config/mock_rpcservice.go +++ b/config/mock_rpcservice.go @@ -23,14 +23,10 @@ import ( type MockService struct{} -func (*MockService) Service() string { +func (*MockService) Reference() string { return "MockService" } -func (*MockService) Version() string { - return "1.0" -} - func (*MockService) GetUser(ctx context.Context, itf []interface{}, str *struct{}) error { return nil } diff --git a/config/provider_config.go b/config/provider_config.go index fc7a4d50d2ede6c3a64dade9c90914e3b5d51779..a504eea237dc47f66c4ed27d334ce5eea5c87d45 100644 --- a/config/provider_config.go +++ b/config/provider_config.go @@ -63,7 +63,7 @@ func GetProviderConfig() ProviderConfig { return *providerConfig } -func providerInit(confProFile string) error { +func ProviderInit(confProFile string) error { if len(confProFile) == 0 { return perrors.Errorf("application configure(provider) file name is nil") } diff --git a/config/reference_config.go b/config/reference_config.go index 835d17f0549045008a996a5756bb3dd772782612..f90e3aabd3a68b8dc7a7509331d301ea3a252f92 100644 --- a/config/reference_config.go +++ b/config/reference_config.go @@ -38,6 +38,7 @@ import ( type ReferenceConfig struct { context context.Context pxy *proxy.Proxy + id string InterfaceName string `required:"true" yaml:"interface" json:"interface,omitempty" property:"interface"` Check *bool `yaml:"check" json:"check,omitempty" property:"check"` Url string `yaml:"url" json:"url,omitempty" property:"url"` @@ -54,14 +55,16 @@ type ReferenceConfig struct { Params map[string]string `yaml:"params" json:"params,omitempty" property:"params"` invoker protocol.Invoker urls []*common.URL + Generic bool `yaml:"generic" json:"generic,omitempty" property:"generic"` } func (c *ReferenceConfig) Prefix() string { return constant.ReferenceConfigPrefix + c.InterfaceName + "." } -func NewReferenceConfig(ctx context.Context) *ReferenceConfig { - return &ReferenceConfig{context: ctx} +// The only way to get a new ReferenceConfig +func NewReferenceConfig(id string, ctx context.Context) *ReferenceConfig { + return &ReferenceConfig{id: id, context: ctx} } func (refconfig *ReferenceConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { @@ -76,7 +79,7 @@ func (refconfig *ReferenceConfig) UnmarshalYAML(unmarshal func(interface{}) erro } func (refconfig *ReferenceConfig) Refer() { - url := common.NewURLWithOptions(common.WithPath(refconfig.InterfaceName), common.WithProtocol(refconfig.Protocol), common.WithParams(refconfig.getUrlMap())) + url := common.NewURLWithOptions(common.WithPath(refconfig.id), common.WithProtocol(refconfig.Protocol), common.WithParams(refconfig.getUrlMap())) //1. user specified URL, could be peer-to-peer address, or register center's address. if refconfig.Url != "" { @@ -91,7 +94,7 @@ func (refconfig *ReferenceConfig) Refer() { refconfig.urls = append(refconfig.urls, &serviceUrl) } else { if serviceUrl.Path == "" { - serviceUrl.Path = "/" + refconfig.InterfaceName + serviceUrl.Path = "/" + refconfig.id } // merge url need to do newUrl := common.MergeUrl(serviceUrl, url) @@ -108,7 +111,6 @@ func (refconfig *ReferenceConfig) Refer() { regUrl.SubURL = url } } - if len(refconfig.urls) == 1 { refconfig.invoker = extension.GetProtocol(refconfig.urls[0].Protocol).Refer(*refconfig.urls[0]) } else { @@ -155,6 +157,8 @@ func (refconfig *ReferenceConfig) getUrlMap() url.Values { urlMap.Set(constant.RETRIES_KEY, strconv.FormatInt(refconfig.Retries, 10)) urlMap.Set(constant.GROUP_KEY, refconfig.Group) urlMap.Set(constant.VERSION_KEY, refconfig.Version) + urlMap.Set(constant.GENERIC_KEY, strconv.FormatBool(refconfig.Generic)) + urlMap.Set(constant.ROLE_KEY, strconv.Itoa(common.CONSUMER)) //getty invoke async or sync urlMap.Set(constant.ASYNC_KEY, strconv.FormatBool(refconfig.async)) @@ -168,7 +172,11 @@ func (refconfig *ReferenceConfig) getUrlMap() url.Values { urlMap.Set(constant.ENVIRONMENT_KEY, consumerConfig.ApplicationConfig.Environment) //filter - urlMap.Set(constant.REFERENCE_FILTER_KEY, mergeValue(consumerConfig.Filter, refconfig.Filter, constant.DEFAULT_REFERENCE_FILTERS)) + var defaultReferenceFilter = constant.DEFAULT_REFERENCE_FILTERS + if refconfig.Generic { + defaultReferenceFilter = constant.GENERIC_REFERENCE_FILTERS + defaultReferenceFilter + } + urlMap.Set(constant.REFERENCE_FILTER_KEY, mergeValue(consumerConfig.Filter, refconfig.Filter, defaultReferenceFilter)) for _, v := range refconfig.Methods { urlMap.Set("methods."+v.Name+"."+constant.LOADBALANCE_KEY, v.Loadbalance) @@ -178,3 +186,11 @@ func (refconfig *ReferenceConfig) getUrlMap() url.Values { return urlMap } +func (refconfig *ReferenceConfig) GenericLoad(id string) { + genericService := NewGenericService(refconfig.id) + SetConsumerService(genericService) + refconfig.id = id + refconfig.Refer() + refconfig.Implement(genericService) + return +} diff --git a/config/reference_config_test.go b/config/reference_config_test.go index 1a856872a63733866747a481e2a2e5d9295c46af..774fece29f5158b6840b3384b5c56846cc4da37b 100644 --- a/config/reference_config_test.go +++ b/config/reference_config_test.go @@ -20,6 +20,8 @@ package config import ( "sync" "testing" + + "github.com/apache/dubbo-go/common/constant" ) import ( @@ -82,9 +84,10 @@ func doInit() { "MockService": { Params: map[string]string{ "serviceid": "soa.mock", + "forks": "5", }, Registry: "shanghai_reg1,shanghai_reg2,hangzhou_reg1,hangzhou_reg2", - InterfaceName: "MockService", + InterfaceName: "com.MockService", Protocol: "mock", Cluster: "failover", Loadbalance: "random", @@ -147,6 +150,7 @@ func Test_ReferP2P(t *testing.T) { } consumerConfig = nil } + func Test_ReferMultiP2P(t *testing.T) { doInit() extension.SetProtocol("dubbo", GetProtocol) @@ -189,6 +193,23 @@ func Test_Implement(t *testing.T) { consumerConfig = nil } +func Test_Forking(t *testing.T) { + doInit() + extension.SetProtocol("dubbo", GetProtocol) + extension.SetProtocol("registry", GetProtocol) + m := consumerConfig.References["MockService"] + m.Url = "dubbo://127.0.0.1:20000;registry://127.0.0.2:20000" + + for _, reference := range consumerConfig.References { + reference.Refer() + forks := int(reference.invoker.GetUrl().GetParamInt(constant.FORKS_KEY, constant.DEFAULT_FORKS)) + assert.Equal(t, 5, forks) + assert.NotNil(t, reference.pxy) + assert.NotNil(t, reference.Cluster) + } + consumerConfig = nil +} + func GetProtocol() protocol.Protocol { if regProtocol != nil { return regProtocol diff --git a/config/registry_config.go b/config/registry_config.go index 1a926b459e598ff313e141a39956dc88cb3daad3..0abdab810f3cfa835f7d1f21e395cd2a2812a051 100644 --- a/config/registry_config.go +++ b/config/registry_config.go @@ -36,9 +36,10 @@ type RegistryConfig struct { TimeoutStr string `yaml:"timeout" default:"5s" json:"timeout,omitempty" property:"timeout"` // unit: second Group string `yaml:"group" json:"group,omitempty" property:"group"` //for registry - Address string `yaml:"address" json:"address,omitempty" property:"address"` - Username string `yaml:"username" json:"username,omitempty" property:"username"` - Password string `yaml:"password" json:"password,omitempty" property:"password"` + Address string `yaml:"address" json:"address,omitempty" property:"address"` + Username string `yaml:"username" json:"username,omitempty" property:"username"` + Password string `yaml:"password" json:"password,omitempty" property:"password"` + Params map[string]string `yaml:"params" json:"params,omitempty" property:"params"` } func (*RegistryConfig) Prefix() string { @@ -68,13 +69,28 @@ func loadRegistries(targetRegistries string, registries map[string]*RegistryConf } if target { - url, err := common.NewURL( - context.TODO(), - constant.REGISTRY_PROTOCOL+"://"+registryConf.Address, - common.WithParams(registryConf.getUrlMap(roleType)), - common.WithUsername(registryConf.Username), - common.WithPassword(registryConf.Password), + var ( + url common.URL + err error ) + if addresses := strings.Split(registryConf.Address, ","); len(addresses) > 1 { + url, err = common.NewURL( + context.Background(), + constant.REGISTRY_PROTOCOL+"://"+addresses[0], + common.WithParams(registryConf.getUrlMap(roleType)), + common.WithUsername(registryConf.Username), + common.WithPassword(registryConf.Password), + common.WithLocation(registryConf.Address), + ) + } else { + url, err = common.NewURL( + context.Background(), + constant.REGISTRY_PROTOCOL+"://"+registryConf.Address, + common.WithParams(registryConf.getUrlMap(roleType)), + common.WithUsername(registryConf.Username), + common.WithPassword(registryConf.Password), + ) + } if err != nil { logger.Errorf("The registry id:%s url is invalid ,and will skip the registry, error: %#v", k, err) @@ -94,6 +110,8 @@ func (regconfig *RegistryConfig) getUrlMap(roleType common.RoleType) url.Values urlMap.Set(constant.ROLE_KEY, strconv.Itoa(int(roleType))) urlMap.Set(constant.REGISTRY_KEY, regconfig.Protocol) urlMap.Set(constant.REGISTRY_TIMEOUT_KEY, regconfig.TimeoutStr) - + for k, v := range regconfig.Params { + urlMap.Set(k, v) + } return urlMap } diff --git a/config/registry_config_test.go b/config/registry_config_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f600a21a0117572349aaf4de1bdee5e1270f67b4 --- /dev/null +++ b/config/registry_config_test.go @@ -0,0 +1,61 @@ +/* + * 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 config + +import ( + "fmt" + "testing" +) +import ( + "github.com/apache/dubbo-go/common" + "github.com/stretchr/testify/assert" +) + +func Test_loadRegistries(t *testing.T) { + target := "shanghai1" + regs := map[string]*RegistryConfig{ + + "shanghai1": { + Protocol: "mock", + TimeoutStr: "2s", + Group: "shanghai_idc", + Address: "127.0.0.2:2181,128.0.0.1:2181", + Username: "user1", + Password: "pwd1", + }, + } + urls := loadRegistries(target, regs, common.CONSUMER) + fmt.Println(urls[0]) + assert.Equal(t, "127.0.0.2:2181,128.0.0.1:2181", urls[0].Location) +} +func Test_loadRegistries1(t *testing.T) { + target := "shanghai1" + regs := map[string]*RegistryConfig{ + + "shanghai1": { + Protocol: "mock", + TimeoutStr: "2s", + Group: "shanghai_idc", + Address: "127.0.0.2:2181", + Username: "user1", + Password: "pwd1", + }, + } + urls := loadRegistries(target, regs, common.CONSUMER) + fmt.Println(urls[0]) + assert.Equal(t, "127.0.0.2:2181", urls[0].Location) +} diff --git a/config/service.go b/config/service.go index 0f3356f710dc89f25db102d73026e2bde9b9f466..2bceac4a8c20bb598dc2607c90c8206e4a448808 100644 --- a/config/service.go +++ b/config/service.go @@ -28,12 +28,12 @@ var ( // SetConService is called by init() of implement of RPCService func SetConsumerService(service common.RPCService) { - conServices[service.Service()] = service + conServices[service.Reference()] = service } // SetProService is called by init() of implement of RPCService func SetProviderService(service common.RPCService) { - proServices[service.Service()] = service + proServices[service.Reference()] = service } func GetConsumerService(name string) common.RPCService { diff --git a/config/service_config.go b/config/service_config.go index 66386aec4e841f06478d3ee08d87c2c5f03487a8..5430f8a7c3c8702117cceefb10171e681a4f29d9 100644 --- a/config/service_config.go +++ b/config/service_config.go @@ -43,6 +43,7 @@ import ( type ServiceConfig struct { context context.Context + id string Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"` Protocol string `required:"true" yaml:"protocol" json:"protocol,omitempty" property:"protocol"` //multi protocol support, split by ',' InterfaceName string `required:"true" yaml:"interface" json:"interface,omitempty" property:"interface"` @@ -66,8 +67,12 @@ func (c *ServiceConfig) Prefix() string { return constant.ServiceConfigPrefix + c.InterfaceName + "." } -func NewServiceConfig() *ServiceConfig { +// The only way to get a new ServiceConfig +func NewServiceConfig(id string, context context.Context) *ServiceConfig { + return &ServiceConfig{ + context: context, + id: id, unexported: atomic.NewBool(false), exported: atomic.NewBool(false), } @@ -99,15 +104,12 @@ func (srvconfig *ServiceConfig) Export() error { logger.Errorf(err.Error()) return err } - //contextPath := proto.ContextPath - //if contextPath == "" { - // contextPath = providerConfig.Path - //} - url := common.NewURLWithOptions(common.WithPath(srvconfig.InterfaceName), + url := common.NewURLWithOptions(common.WithPath(srvconfig.id), common.WithProtocol(proto.Name), common.WithIp(proto.Ip), common.WithPort(proto.Port), common.WithParams(urlMap), + common.WithParamsValue(constant.BEAN_NAME_KEY, srvconfig.id), common.WithMethods(strings.Split(methods, ","))) if len(regUrls) > 0 { @@ -158,6 +160,7 @@ func (srvconfig *ServiceConfig) getUrlMap() url.Values { urlMap.Set(constant.RETRIES_KEY, strconv.FormatInt(srvconfig.Retries, 10)) urlMap.Set(constant.GROUP_KEY, srvconfig.Group) urlMap.Set(constant.VERSION_KEY, srvconfig.Version) + urlMap.Set(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER)) //application info urlMap.Set(constant.APPLICATION_KEY, providerConfig.ApplicationConfig.Name) urlMap.Set(constant.ORGANIZATION_KEY, providerConfig.ApplicationConfig.Organization) diff --git a/config/service_config_test.go b/config/service_config_test.go index 4e0b7f95d6b156eeda021e3c02e5457e8b52b244..e111c8d110a14a039f3ab1a6c14f8044847f87e5 100644 --- a/config/service_config_test.go +++ b/config/service_config_test.go @@ -74,7 +74,7 @@ func doinit() { }, Services: map[string]*ServiceConfig{ "MockService": { - InterfaceName: "MockService", + InterfaceName: "com.MockService", Protocol: "mock", Registry: "shanghai_reg1,shanghai_reg2,hangzhou_reg1,hangzhou_reg2", Cluster: "failover", diff --git a/config/testdata/consumer_config.yml b/config/testdata/consumer_config.yml index 68398623b6a2cbfe9fe9c255d3261c5a59b6af5e..372873abbb258e03acfe8e9e00d03aa2f77fb9a9 100644 --- a/config/testdata/consumer_config.yml +++ b/config/testdata/consumer_config.yml @@ -36,8 +36,10 @@ references: registry: "hangzhouzk,shanghaizk" filter: "" protocol : "dubbo" + version: "1.0" + group: "as" interface : "com.ikurento.user.UserProvider" - url: "dubbo://127.0.0.1:20000" + url: "dubbo://127.0.0.1:20000/UserProvider" cluster: "failover" methods : - name: "GetUser" @@ -45,6 +47,7 @@ references: params: "serviceid": "soa.com.ikurento.user.UserProvider" + "forks": 5 protocol_conf: dubbo: @@ -52,9 +55,14 @@ protocol_conf: connection_number: 2 heartbeat_period: "5s" session_timeout: "20s" - fail_fast_timeout: "5s" pool_size: 64 pool_ttl: 600 + # gr_pool_size is recommended to be set to [cpu core number] * 100 + gr_pool_size: 1200 + # queue_len is recommended to be set to 64 or 128 + queue_len: 64 + # queue_number is recommended to be set to gr_pool_size / 20 + queue_number: 60 getty_session_param: compress_encoding: false tcp_no_delay: true @@ -62,7 +70,6 @@ protocol_conf: keep_alive_period: "120s" tcp_r_buf_size: 262144 tcp_w_buf_size: 65536 - pkg_rq_size: 1024 pkg_wq_size: 512 tcp_read_timeout: "1s" tcp_write_timeout: "5s" diff --git a/config/testdata/consumer_config_with_configcenter.yml b/config/testdata/consumer_config_with_configcenter.yml index df896d2442ce6eb5cf0cc41bb92f39964325d885..c6505e4492887cc6602ab0b2ee9a9fbd9fdce9c9 100644 --- a/config/testdata/consumer_config_with_configcenter.yml +++ b/config/testdata/consumer_config_with_configcenter.yml @@ -9,7 +9,7 @@ references: filter: "" protocol : "dubbo" interface : "com.ikurento.user.UserProvider" - url: "dubbo://127.0.0.1:20000" + url: "dubbo://127.0.0.1:20000/UserProvider" cluster: "failover" methods : - name: "GetUser" @@ -21,7 +21,6 @@ protocol_conf: connection_number: 2 heartbeat_period: "5s" session_timeout: "20s" - fail_fast_timeout: "5s" pool_size: 64 pool_ttl: 600 getty_session_param: @@ -31,7 +30,6 @@ protocol_conf: keep_alive_period: "120s" tcp_r_buf_size: 262144 tcp_w_buf_size: 65536 - pkg_rq_size: 1024 pkg_wq_size: 512 tcp_read_timeout: "1s" tcp_write_timeout: "5s" diff --git a/config/testdata/provider_config.yml b/config/testdata/provider_config.yml index 38952220e270b2b0a929a7583d1f5650ecab0121..e135860c208ff4d386a1abd658049e0e0aac73a3 100644 --- a/config/testdata/provider_config.yml +++ b/config/testdata/provider_config.yml @@ -33,6 +33,8 @@ services: # equivalent to interface of dubbo.xml interface : "com.ikurento.user.UserProvider" loadbalance: "random" + version: "1.0" + group: "as" warmup: "100" cluster: "failover" methods: @@ -53,8 +55,13 @@ protocols: protocol_conf: dubbo: session_number: 700 - fail_fast_timeout: "5s" session_timeout: "20s" + # gr_pool_size is recommended to be set to [cpu core number] * 10 + gr_pool_size: 120 + # queue_len is recommended to be set to 64 or 128 + queue_len: 64 + # queue_number is recommended to be set to gr_pool_size / 20 + queue_number: 6 getty_session_param: compress_encoding: false tcp_no_delay: true @@ -62,7 +69,6 @@ protocol_conf: keep_alive_period: "120s" tcp_r_buf_size: 262144 tcp_w_buf_size: 65536 - pkg_rq_size: 1024 pkg_wq_size: 512 tcp_read_timeout: "1s" tcp_write_timeout: "5s" diff --git a/config_center/zookeeper/impl.go b/config_center/zookeeper/impl.go index ef0761efcd0d2cee47425dd5e1099200d3be6a70..f2827b2bb693fc1943116686f8056c0edaeadc99 100644 --- a/config_center/zookeeper/impl.go +++ b/config_center/zookeeper/impl.go @@ -196,7 +196,7 @@ func (r *zookeeperDynamicConfiguration) closeConfigs() { r.cltLock.Lock() defer r.cltLock.Unlock() logger.Infof("begin to close provider zk client") - // 先关闭旧client,以关闭tmp node + // Close the old client first to close the tmp node r.client.Close() r.client = nil } diff --git a/config_center/zookeeper/zookeeper-4unitest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar b/config_center/zookeeper/zookeeper-4unitest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar deleted file mode 100644 index 839531b8b8762a9c19e334a5cbf79314cb16f945..0000000000000000000000000000000000000000 Binary files a/config_center/zookeeper/zookeeper-4unitest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar and /dev/null differ diff --git a/dubbogo.png b/dubbogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2cac434091276df102c3ae405c09621b8d8926ef Binary files /dev/null and b/dubbogo.png differ diff --git a/examples/dubbo/with-configcenter-go-client/app/client.go b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/app/client.go similarity index 95% rename from examples/dubbo/with-configcenter-go-client/app/client.go rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/app/client.go index 867e17dc854a25c3a9b55de522053bc32c28a642..d27af7a31778403d518e6454de7ebab4b9b5cdf7 100644 --- a/examples/dubbo/with-configcenter-go-client/app/client.go +++ b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/app/client.go @@ -27,7 +27,7 @@ import ( ) import ( - "github.com/dubbogo/hessian2" + hessian "github.com/apache/dubbo-go-hessian2" ) import ( @@ -140,7 +140,7 @@ func initSignal() { os.Exit(1) }) - // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出 + // The program exits normally or timeout forcibly exits. fmt.Println("app exit now...") return } diff --git a/examples/dubbo/with-configcenter-go-client/app/user.go b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/app/user.go similarity index 91% rename from examples/dubbo/with-configcenter-go-client/app/user.go rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/app/user.go index d491c3633384ad9ee6acdb2786d383e420f26db3..5bddf1e19f59be1b7fae917cffddfde4d362f44e 100644 --- a/examples/dubbo/with-configcenter-go-client/app/user.go +++ b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/app/user.go @@ -25,7 +25,7 @@ import ( ) import ( - hessian "github.com/dubbogo/hessian2" + hessian "github.com/apache/dubbo-go-hessian2" ) import ( @@ -83,7 +83,7 @@ type User struct { Name string Age int32 Time time.Time - Sex Gender // 注意此处,java enum Object <--> go string + Sex Gender // notice: java enum Object <--> go string } func (u User) String() string { @@ -108,10 +108,6 @@ type UserProvider struct { Echo func(ctx context.Context, req interface{}) (interface{}, error) // Echo represent EchoFilter will be used } -func (u *UserProvider) Service() string { - return "com.ikurento.user.UserProvider" -} - -func (u *UserProvider) Version() string { - return "" +func (u *UserProvider) Reference() string { + return "UserProvider" } diff --git a/examples/dubbo/go-client/app/version.go b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/app/version.go similarity index 100% rename from examples/dubbo/go-client/app/version.go rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/app/version.go diff --git a/examples/dubbo/go-client/assembly/bin/load.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/bin/load.sh similarity index 100% rename from examples/dubbo/go-client/assembly/bin/load.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/bin/load.sh diff --git a/examples/dubbo/go-client/assembly/common/app.properties b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/common/app.properties similarity index 100% rename from examples/dubbo/go-client/assembly/common/app.properties rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/common/app.properties diff --git a/examples/dubbo/go-client/assembly/common/build.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/common/build.sh similarity index 100% rename from examples/dubbo/go-client/assembly/common/build.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/common/build.sh diff --git a/examples/dubbo/go-client/assembly/linux/dev.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/linux/dev.sh similarity index 100% rename from examples/dubbo/go-client/assembly/linux/dev.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/linux/dev.sh diff --git a/examples/dubbo/go-client/assembly/linux/release.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/linux/release.sh similarity index 100% rename from examples/dubbo/go-client/assembly/linux/release.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/linux/release.sh diff --git a/examples/dubbo/go-client/assembly/linux/test.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/linux/test.sh similarity index 100% rename from examples/dubbo/go-client/assembly/linux/test.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/linux/test.sh diff --git a/examples/dubbo/go-client/assembly/mac/dev.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/mac/dev.sh similarity index 100% rename from examples/dubbo/go-client/assembly/mac/dev.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/mac/dev.sh diff --git a/examples/dubbo/go-client/assembly/mac/release.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/mac/release.sh similarity index 100% rename from examples/dubbo/go-client/assembly/mac/release.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/mac/release.sh diff --git a/examples/dubbo/go-client/assembly/mac/test.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/mac/test.sh similarity index 100% rename from examples/dubbo/go-client/assembly/mac/test.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/mac/test.sh diff --git a/examples/dubbo/go-client/assembly/windows/dev.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/windows/dev.sh similarity index 100% rename from examples/dubbo/go-client/assembly/windows/dev.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/windows/dev.sh diff --git a/examples/dubbo/go-client/assembly/windows/release.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/windows/release.sh similarity index 100% rename from examples/dubbo/go-client/assembly/windows/release.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/windows/release.sh diff --git a/examples/dubbo/go-client/assembly/windows/test.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/windows/test.sh similarity index 100% rename from examples/dubbo/go-client/assembly/windows/test.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/assembly/windows/test.sh diff --git a/examples/dubbo/with-configcenter-go-client/profiles/test/client.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/dev/client.yml similarity index 94% rename from examples/dubbo/with-configcenter-go-client/profiles/test/client.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/dev/client.yml index c809041f14d15230a02f154571c02a038ee2ca92..c8e7bd0b053f797f3a5320451f08dcc590832330 100644 --- a/examples/dubbo/with-configcenter-go-client/profiles/test/client.yml +++ b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/dev/client.yml @@ -21,7 +21,6 @@ protocol_conf: connection_number: 2 heartbeat_period: "5s" session_timeout: "20s" - fail_fast_timeout: "5s" pool_size: 64 pool_ttl: 600 getty_session_param: @@ -31,7 +30,6 @@ protocol_conf: keep_alive_period: "120s" tcp_r_buf_size: 262144 tcp_w_buf_size: 65536 - pkg_rq_size: 1024 pkg_wq_size: 512 tcp_read_timeout: "1s" tcp_write_timeout: "5s" diff --git a/examples/dubbo/go-client/profiles/dev/log.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/dev/log.yml similarity index 100% rename from examples/dubbo/go-client/profiles/dev/log.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/dev/log.yml diff --git a/examples/dubbo/with-configcenter-go-client/profiles/dev/client.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/release/client.yml similarity index 94% rename from examples/dubbo/with-configcenter-go-client/profiles/dev/client.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/release/client.yml index c809041f14d15230a02f154571c02a038ee2ca92..c8e7bd0b053f797f3a5320451f08dcc590832330 100644 --- a/examples/dubbo/with-configcenter-go-client/profiles/dev/client.yml +++ b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/release/client.yml @@ -21,7 +21,6 @@ protocol_conf: connection_number: 2 heartbeat_period: "5s" session_timeout: "20s" - fail_fast_timeout: "5s" pool_size: 64 pool_ttl: 600 getty_session_param: @@ -31,7 +30,6 @@ protocol_conf: keep_alive_period: "120s" tcp_r_buf_size: 262144 tcp_w_buf_size: 65536 - pkg_rq_size: 1024 pkg_wq_size: 512 tcp_read_timeout: "1s" tcp_write_timeout: "5s" diff --git a/examples/dubbo/go-client/profiles/release/log.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/release/log.yml similarity index 100% rename from examples/dubbo/go-client/profiles/release/log.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/release/log.yml diff --git a/examples/dubbo/with-configcenter-go-client/profiles/release/client.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/test/client.yml similarity index 94% rename from examples/dubbo/with-configcenter-go-client/profiles/release/client.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/test/client.yml index c809041f14d15230a02f154571c02a038ee2ca92..c8e7bd0b053f797f3a5320451f08dcc590832330 100644 --- a/examples/dubbo/with-configcenter-go-client/profiles/release/client.yml +++ b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/test/client.yml @@ -21,7 +21,6 @@ protocol_conf: connection_number: 2 heartbeat_period: "5s" session_timeout: "20s" - fail_fast_timeout: "5s" pool_size: 64 pool_ttl: 600 getty_session_param: @@ -31,7 +30,6 @@ protocol_conf: keep_alive_period: "120s" tcp_r_buf_size: 262144 tcp_w_buf_size: 65536 - pkg_rq_size: 1024 pkg_wq_size: 512 tcp_read_timeout: "1s" tcp_write_timeout: "5s" diff --git a/examples/dubbo/go-client/profiles/test/log.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/test/log.yml similarity index 100% rename from examples/dubbo/go-client/profiles/test/log.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-client/profiles/test/log.yml diff --git a/examples/dubbo/with-configcenter-go-server/app/server.go b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/app/server.go similarity index 92% rename from examples/dubbo/with-configcenter-go-server/app/server.go rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/app/server.go index d832ae8a29e5aff5dd487294b1b4dc37ba3a8036..cd982992171fdf674e560bfb4ed280c1951cccde 100644 --- a/examples/dubbo/with-configcenter-go-server/app/server.go +++ b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/app/server.go @@ -26,7 +26,7 @@ import ( ) import ( - hessian "github.com/dubbogo/hessian2" + hessian "github.com/apache/dubbo-go-hessian2" ) import ( @@ -78,7 +78,7 @@ func initSignal() { os.Exit(1) }) - // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出 + // The program exits normally or timeout forcibly exits. fmt.Println("provider app exit now...") return } diff --git a/examples/dubbo/with-configcenter-go-server/app/user.go b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/app/user.go similarity index 93% rename from examples/dubbo/with-configcenter-go-server/app/user.go rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/app/user.go index b84e7229cc62ce5b3c8e8b0a3927c55b2aff9df8..0e4d05766887ae41440313b49ba4dc859a09ed35 100644 --- a/examples/dubbo/with-configcenter-go-server/app/user.go +++ b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/app/user.go @@ -25,13 +25,13 @@ import ( ) import ( + hessian "github.com/apache/dubbo-go-hessian2" + "github.com/apache/dubbo-go-hessian2/java_exception" perrors "github.com/pkg/errors" ) import ( "github.com/apache/dubbo-go/config" - hessian "github.com/dubbogo/hessian2" - "github.com/dubbogo/hessian2/java_exception" ) type Gender hessian.JavaEnum @@ -84,7 +84,7 @@ type ( Name string Age int32 Time time.Time - Sex Gender // 注意此处,java enum Object <--> go string + Sex Gender // notice: java enum Object <--> go string } UserProvider struct { @@ -183,12 +183,8 @@ func (u *UserProvider) GetUsers(req []interface{}) ([]interface{}, error) { return []interface{}{user, user1}, err } -func (u *UserProvider) Service() string { - return "com.ikurento.user.UserProvider" -} - -func (u *UserProvider) Version() string { - return "" +func (u *UserProvider) Reference() string { + return "UserProvider" } func println(format string, args ...interface{}) { diff --git a/examples/dubbo/go-server/app/version.go b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/app/version.go similarity index 100% rename from examples/dubbo/go-server/app/version.go rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/app/version.go diff --git a/examples/dubbo/go-server/assembly/bin/load.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/bin/load.sh similarity index 100% rename from examples/dubbo/go-server/assembly/bin/load.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/bin/load.sh diff --git a/examples/dubbo/go-server/assembly/common/app.properties b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/common/app.properties similarity index 100% rename from examples/dubbo/go-server/assembly/common/app.properties rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/common/app.properties diff --git a/examples/dubbo/go-server/assembly/common/build.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/common/build.sh similarity index 100% rename from examples/dubbo/go-server/assembly/common/build.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/common/build.sh diff --git a/examples/dubbo/go-server/assembly/linux/dev.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/linux/dev.sh similarity index 100% rename from examples/dubbo/go-server/assembly/linux/dev.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/linux/dev.sh diff --git a/examples/dubbo/go-server/assembly/linux/release.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/linux/release.sh similarity index 100% rename from examples/dubbo/go-server/assembly/linux/release.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/linux/release.sh diff --git a/examples/dubbo/go-server/assembly/linux/test.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/linux/test.sh similarity index 100% rename from examples/dubbo/go-server/assembly/linux/test.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/linux/test.sh diff --git a/examples/dubbo/go-server/assembly/mac/dev.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/mac/dev.sh similarity index 100% rename from examples/dubbo/go-server/assembly/mac/dev.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/mac/dev.sh diff --git a/examples/dubbo/go-server/assembly/mac/release.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/mac/release.sh similarity index 100% rename from examples/dubbo/go-server/assembly/mac/release.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/mac/release.sh diff --git a/examples/dubbo/go-server/assembly/mac/test.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/mac/test.sh similarity index 100% rename from examples/dubbo/go-server/assembly/mac/test.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/mac/test.sh diff --git a/examples/dubbo/go-server/assembly/windows/dev.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/windows/dev.sh similarity index 100% rename from examples/dubbo/go-server/assembly/windows/dev.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/windows/dev.sh diff --git a/examples/dubbo/go-server/assembly/windows/release.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/windows/release.sh similarity index 100% rename from examples/dubbo/go-server/assembly/windows/release.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/windows/release.sh diff --git a/examples/dubbo/go-server/assembly/windows/test.sh b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/windows/test.sh similarity index 100% rename from examples/dubbo/go-server/assembly/windows/test.sh rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/assembly/windows/test.sh diff --git a/examples/dubbo/go-server/profiles/dev/log.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/dev/log.yml similarity index 100% rename from examples/dubbo/go-server/profiles/dev/log.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/dev/log.yml diff --git a/examples/dubbo/with-configcenter-go-server/profiles/dev/server.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/dev/server.yml similarity index 94% rename from examples/dubbo/with-configcenter-go-server/profiles/dev/server.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/dev/server.yml index 05f758592f5aa69e097f19d14299e15bc9bf5f0f..cdaaca4c3803cf6126f00d67631dd1507d14505c 100644 --- a/examples/dubbo/with-configcenter-go-server/profiles/dev/server.yml +++ b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/dev/server.yml @@ -23,7 +23,6 @@ services: protocol_conf: dubbo: session_number: 700 - fail_fast_timeout: "5s" session_timeout: "20s" getty_session_param: compress_encoding: false @@ -32,7 +31,6 @@ protocol_conf: keep_alive_period: "120s" tcp_r_buf_size: 262144 tcp_w_buf_size: 65536 - pkg_rq_size: 1024 pkg_wq_size: 512 tcp_read_timeout: "1s" tcp_write_timeout: "5s" diff --git a/examples/dubbo/go-server/profiles/release/log.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/release/log.yml similarity index 100% rename from examples/dubbo/go-server/profiles/release/log.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/release/log.yml diff --git a/examples/dubbo/with-configcenter-go-server/profiles/release/server.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/release/server.yml similarity index 94% rename from examples/dubbo/with-configcenter-go-server/profiles/release/server.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/release/server.yml index 05f758592f5aa69e097f19d14299e15bc9bf5f0f..cdaaca4c3803cf6126f00d67631dd1507d14505c 100644 --- a/examples/dubbo/with-configcenter-go-server/profiles/release/server.yml +++ b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/release/server.yml @@ -23,7 +23,6 @@ services: protocol_conf: dubbo: session_number: 700 - fail_fast_timeout: "5s" session_timeout: "20s" getty_session_param: compress_encoding: false @@ -32,7 +31,6 @@ protocol_conf: keep_alive_period: "120s" tcp_r_buf_size: 262144 tcp_w_buf_size: 65536 - pkg_rq_size: 1024 pkg_wq_size: 512 tcp_read_timeout: "1s" tcp_write_timeout: "5s" diff --git a/examples/dubbo/go-server/profiles/test/log.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/test/log.yml similarity index 100% rename from examples/dubbo/go-server/profiles/test/log.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/test/log.yml diff --git a/examples/dubbo/with-configcenter-go-server/profiles/test/server.yml b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/test/server.yml similarity index 94% rename from examples/dubbo/with-configcenter-go-server/profiles/test/server.yml rename to examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/test/server.yml index 05f758592f5aa69e097f19d14299e15bc9bf5f0f..cdaaca4c3803cf6126f00d67631dd1507d14505c 100644 --- a/examples/dubbo/with-configcenter-go-server/profiles/test/server.yml +++ b/examples/configcenter/zookeeper/dubbo/with-configcenter-go-server/profiles/test/server.yml @@ -23,7 +23,6 @@ services: protocol_conf: dubbo: session_number: 700 - fail_fast_timeout: "5s" session_timeout: "20s" getty_session_param: compress_encoding: false @@ -32,7 +31,6 @@ protocol_conf: keep_alive_period: "120s" tcp_r_buf_size: 262144 tcp_w_buf_size: 65536 - pkg_rq_size: 1024 pkg_wq_size: 512 tcp_read_timeout: "1s" tcp_write_timeout: "5s" diff --git a/examples/jsonrpc/with-configcenter-go-client/app/client.go b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/app/client.go similarity index 96% rename from examples/jsonrpc/with-configcenter-go-client/app/client.go rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/app/client.go index 642b45a9343477086300ccb78d56756fbf51a817..5b1634788c455f6b8f0fb964f25a07b525492cf0 100644 --- a/examples/jsonrpc/with-configcenter-go-client/app/client.go +++ b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/app/client.go @@ -125,7 +125,7 @@ func initSignal() { os.Exit(1) }) - // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出 + // The program exits normally or timeout forcibly exits. fmt.Println("app exit now...") return } diff --git a/examples/jsonrpc/with-configcenter-go-client/app/user.go b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/app/user.go similarity index 93% rename from examples/jsonrpc/with-configcenter-go-client/app/user.go rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/app/user.go index ca98b1af0b3c1379c73623162546db9fb4fc95d6..fef665bb3d14709ffd584cbb184c18ffe8d87580 100644 --- a/examples/jsonrpc/with-configcenter-go-client/app/user.go +++ b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/app/user.go @@ -58,10 +58,6 @@ type UserProvider struct { Echo func(ctx context.Context, req interface{}) (interface{}, error) // Echo represent EchoFilter will be used } -func (u *UserProvider) Service() string { - return "com.ikurento.user.UserProvider" -} - -func (u *UserProvider) Version() string { - return "" +func (u *UserProvider) Reference() string { + return "UserProvider" } diff --git a/examples/dubbo/with-configcenter-go-client/app/version.go b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/app/version.go similarity index 100% rename from examples/dubbo/with-configcenter-go-client/app/version.go rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/app/version.go diff --git a/examples/dubbo/with-configcenter-go-client/assembly/bin/load.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/bin/load.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/bin/load.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/bin/load.sh diff --git a/examples/dubbo/with-configcenter-go-client/assembly/common/app.properties b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/common/app.properties similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/common/app.properties rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/common/app.properties diff --git a/examples/jsonrpc/go-client/assembly/common/build.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/common/build.sh similarity index 100% rename from examples/jsonrpc/go-client/assembly/common/build.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/common/build.sh diff --git a/examples/dubbo/with-configcenter-go-client/assembly/linux/dev.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/linux/dev.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/linux/dev.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/linux/dev.sh diff --git a/examples/dubbo/with-configcenter-go-client/assembly/linux/release.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/linux/release.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/linux/release.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/linux/release.sh diff --git a/examples/dubbo/with-configcenter-go-client/assembly/linux/test.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/linux/test.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/linux/test.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/linux/test.sh diff --git a/examples/dubbo/with-configcenter-go-client/assembly/mac/dev.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/mac/dev.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/mac/dev.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/mac/dev.sh diff --git a/examples/dubbo/with-configcenter-go-client/assembly/mac/release.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/mac/release.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/mac/release.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/mac/release.sh diff --git a/examples/dubbo/with-configcenter-go-client/assembly/mac/test.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/mac/test.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/mac/test.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/mac/test.sh diff --git a/examples/dubbo/with-configcenter-go-client/assembly/windows/dev.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/windows/dev.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/windows/dev.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/windows/dev.sh diff --git a/examples/dubbo/with-configcenter-go-client/assembly/windows/release.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/windows/release.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/windows/release.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/windows/release.sh diff --git a/examples/dubbo/with-configcenter-go-client/assembly/windows/test.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/windows/test.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/windows/test.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/assembly/windows/test.sh diff --git a/examples/jsonrpc/with-configcenter-go-client/profiles/dev/client.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/dev/client.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/profiles/dev/client.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/dev/client.yml diff --git a/examples/dubbo/with-configcenter-go-client/profiles/dev/log.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/dev/log.yml similarity index 100% rename from examples/dubbo/with-configcenter-go-client/profiles/dev/log.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/dev/log.yml diff --git a/examples/jsonrpc/with-configcenter-go-client/profiles/release/client.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/release/client.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/profiles/release/client.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/release/client.yml diff --git a/examples/dubbo/with-configcenter-go-client/profiles/release/log.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/release/log.yml similarity index 100% rename from examples/dubbo/with-configcenter-go-client/profiles/release/log.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/release/log.yml diff --git a/examples/jsonrpc/with-configcenter-go-client/profiles/test/client.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/test/client.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/profiles/test/client.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/test/client.yml diff --git a/examples/dubbo/with-configcenter-go-client/profiles/test/log.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/test/log.yml similarity index 100% rename from examples/dubbo/with-configcenter-go-client/profiles/test/log.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-client/profiles/test/log.yml diff --git a/examples/jsonrpc/with-configcenter-go-server/app/server.go b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/app/server.go similarity index 94% rename from examples/jsonrpc/with-configcenter-go-server/app/server.go rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/app/server.go index 851a97c15543961ad29784de449fe1ee56adc9c9..0a0e72915fef0ca4613f78a87fa1057152c1cc9a 100644 --- a/examples/jsonrpc/with-configcenter-go-server/app/server.go +++ b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/app/server.go @@ -67,7 +67,7 @@ func initSignal() { os.Exit(1) }) - // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出 + // The program exits normally or timeout forcibly exits. fmt.Println("provider app exit now...") return } diff --git a/examples/jsonrpc/with-configcenter-go-server/app/user.go b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/app/user.go similarity index 96% rename from examples/jsonrpc/with-configcenter-go-server/app/user.go rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/app/user.go index fbe6f3339c212d2bd42d52b6bbf7c7fcec6fb9c3..9ab9e58cb4d469dda347519674a8eef85b429fce 100644 --- a/examples/jsonrpc/with-configcenter-go-server/app/user.go +++ b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/app/user.go @@ -146,12 +146,8 @@ func (u *UserProvider) GetUsers(req []interface{}) ([]User, error) { return []User{*user, *user1}, err } -func (u *UserProvider) Service() string { - return "com.ikurento.user.UserProvider" -} - -func (u *UserProvider) Version() string { - return "" +func (u *UserProvider) Reference() string { + return "UserProvider" } func println(format string, args ...interface{}) { diff --git a/examples/dubbo/with-configcenter-go-server/app/version.go b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/app/version.go similarity index 100% rename from examples/dubbo/with-configcenter-go-server/app/version.go rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/app/version.go diff --git a/examples/dubbo/with-configcenter-go-server/assembly/bin/load.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/bin/load.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/bin/load.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/bin/load.sh diff --git a/examples/dubbo/with-configcenter-go-server/assembly/common/app.properties b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/common/app.properties similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/common/app.properties rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/common/app.properties diff --git a/examples/dubbo/with-configcenter-go-server/assembly/common/build.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/common/build.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/common/build.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/common/build.sh diff --git a/examples/dubbo/with-configcenter-go-server/assembly/linux/dev.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/linux/dev.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/linux/dev.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/linux/dev.sh diff --git a/examples/dubbo/with-configcenter-go-server/assembly/linux/release.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/linux/release.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/linux/release.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/linux/release.sh diff --git a/examples/dubbo/with-configcenter-go-server/assembly/linux/test.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/linux/test.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/linux/test.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/linux/test.sh diff --git a/examples/dubbo/with-configcenter-go-server/assembly/mac/dev.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/mac/dev.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/mac/dev.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/mac/dev.sh diff --git a/examples/dubbo/with-configcenter-go-server/assembly/mac/release.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/mac/release.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/mac/release.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/mac/release.sh diff --git a/examples/dubbo/with-configcenter-go-server/assembly/mac/test.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/mac/test.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/mac/test.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/mac/test.sh diff --git a/examples/dubbo/with-configcenter-go-server/assembly/windows/dev.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/windows/dev.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/windows/dev.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/windows/dev.sh diff --git a/examples/dubbo/with-configcenter-go-server/assembly/windows/release.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/windows/release.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/windows/release.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/windows/release.sh diff --git a/examples/dubbo/with-configcenter-go-server/assembly/windows/test.sh b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/windows/test.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-server/assembly/windows/test.sh rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/assembly/windows/test.sh diff --git a/examples/dubbo/with-configcenter-go-server/profiles/dev/log.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/dev/log.yml similarity index 100% rename from examples/dubbo/with-configcenter-go-server/profiles/dev/log.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/dev/log.yml diff --git a/examples/jsonrpc/with-configcenter-go-server/profiles/dev/server.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/dev/server.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/profiles/dev/server.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/dev/server.yml diff --git a/examples/dubbo/with-configcenter-go-server/profiles/release/log.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/release/log.yml similarity index 100% rename from examples/dubbo/with-configcenter-go-server/profiles/release/log.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/release/log.yml diff --git a/examples/jsonrpc/with-configcenter-go-server/profiles/release/server.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/release/server.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/profiles/release/server.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/release/server.yml diff --git a/examples/dubbo/with-configcenter-go-server/profiles/test/log.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/test/log.yml similarity index 100% rename from examples/dubbo/with-configcenter-go-server/profiles/test/log.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/test/log.yml diff --git a/examples/jsonrpc/with-configcenter-go-server/profiles/test/server.yml b/examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/test/server.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/profiles/test/server.yml rename to examples/configcenter/zookeeper/jsonrpc/with-configcenter-go-server/profiles/test/server.yml diff --git a/examples/dubbo/go-server/app/user.go b/examples/dubbo/go-server/app/user.go deleted file mode 100644 index 3c261dc029022fe8a3a80a4007e5aa132643eb7c..0000000000000000000000000000000000000000 --- a/examples/dubbo/go-server/app/user.go +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 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 main - -import ( - "context" - "fmt" - "strconv" - "time" -) - -import ( - "github.com/dubbogo/hessian2" - "github.com/dubbogo/hessian2/java_exception" - perrors "github.com/pkg/errors" -) - -import ( - "github.com/apache/dubbo-go/config" -) - -type Gender hessian.JavaEnum - -func init() { - config.SetProviderService(new(UserProvider)) -} - -const ( - MAN hessian.JavaEnum = iota - WOMAN -) - -var genderName = map[hessian.JavaEnum]string{ - MAN: "MAN", - WOMAN: "WOMAN", -} - -var genderValue = map[string]hessian.JavaEnum{ - "MAN": MAN, - "WOMAN": WOMAN, -} - -func (g Gender) JavaClassName() string { - return "com.ikurento.user.Gender" -} - -func (g Gender) String() string { - s, ok := genderName[hessian.JavaEnum(g)] - if ok { - return s - } - - return strconv.Itoa(int(g)) -} - -func (g Gender) EnumValue(s string) hessian.JavaEnum { - v, ok := genderValue[s] - if ok { - return v - } - - return hessian.InvalidJavaEnum -} - -type ( - User struct { - // !!! Cannot define lowercase names of variable - Id string - Name string - Age int32 - Time time.Time - Sex Gender // 注意此处,java enum Object <--> go string - } - - UserProvider struct { - user map[string]User - } -) - -var ( - DefaultUser = User{ - Id: "0", Name: "Alex Stocks", Age: 31, - Sex: Gender(MAN), - } - - userMap = UserProvider{user: make(map[string]User)} -) - -func init() { - userMap.user["A000"] = DefaultUser - userMap.user["A001"] = User{Id: "001", Name: "ZhangSheng", Age: 18, Sex: Gender(MAN)} - userMap.user["A002"] = User{Id: "002", Name: "Lily", Age: 20, Sex: Gender(WOMAN)} - userMap.user["A003"] = User{Id: "113", Name: "Moorse", Age: 30, Sex: Gender(WOMAN)} - for k, v := range userMap.user { - v.Time = time.Now() - userMap.user[k] = v - } -} - -func (u User) String() string { - return fmt.Sprintf( - "User{Id:%s, Name:%s, Age:%d, Time:%s, Sex:%s}", - u.Id, u.Name, u.Age, u.Time, u.Sex, - ) -} - -func (u User) JavaClassName() string { - return "com.ikurento.user.User" -} - -func (u *UserProvider) getUser(userId string) (*User, error) { - if user, ok := userMap.user[userId]; ok { - return &user, nil - } - - return nil, fmt.Errorf("invalid user id:%s", userId) -} - -func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User) error { - var ( - err error - user *User - ) - - println("req:%#v", req) - user, err = u.getUser(req[0].(string)) - if err == nil { - *rsp = *user - println("rsp:%#v", rsp) - } - return err -} - -func (u *UserProvider) GetUser0(id string, name string) (User, error) { - var err error - - println("id:%s, name:%s", id, name) - user, err := u.getUser(id) - if err != nil { - return User{}, err - } - if user.Name != name { - return User{}, perrors.New("name is not " + user.Name) - } - return *user, err -} - -func (u *UserProvider) GetUser2(ctx context.Context, req []interface{}, rsp *User) error { - var err error - - println("req:%#v", req) - rsp.Id = strconv.Itoa(int(req[0].(int32))) - return err -} - -func (u *UserProvider) GetUser3() error { - return nil -} - -func (u *UserProvider) GetErr(ctx context.Context, req []interface{}, rsp *User) error { - return java_exception.NewThrowable("exception") -} - -func (u *UserProvider) GetUsers(req []interface{}) ([]interface{}, error) { - var err error - - println("req:%s", req) - t := req[0].([]interface{}) - user, err := u.getUser(t[0].(string)) - if err != nil { - return nil, err - } - println("user:%v", user) - user1, err := u.getUser(t[1].(string)) - if err != nil { - return nil, err - } - println("user1:%v", user1) - - return []interface{}{user, user1}, err -} - -func (s *UserProvider) MethodMapper() map[string]string { - return map[string]string{ - "GetUser2": "getUser", - } -} - -func (u *UserProvider) Service() string { - return "com.ikurento.user.UserProvider" -} - -func (u *UserProvider) Version() string { - return "" -} - -func println(format string, args ...interface{}) { - fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...) -} diff --git a/examples/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java b/examples/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java deleted file mode 100644 index edf4c0d2b20a08c17241132cd03bf16a51b2fbb8..0000000000000000000000000000000000000000 --- a/examples/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java +++ /dev/null @@ -1,101 +0,0 @@ -// ***************************************************** -// DESC : dubbo consumer -// AUTHOR : writtey by 包增辉(https://github.com/baozh) -// VERSION : 1.0 -// LICENCE : Apache License 2.0 -// EMAIL : alexstocks@foxmail.com -// MOD : 2016-10-19 17:03 -// FILE : Consumer.java -// ****************************************************** - -package com.ikurento.user; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import com.alibaba.dubbo.rpc.service.EchoService; -import java.util.List; - -public class Consumer { - //定义一个私有变量 (Spring中要求) - private UserProvider userProvider; - - //Spring注入(Spring中要求) - public void setUserProvider(UserProvider u) { - this.userProvider = u; - } - - private void benchmarkSayHello() { - for (int i = 0; i < Integer.MAX_VALUE; i ++) { - try { - // String hello = demoService.sayHello("world" + i); - // System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + hello); - } catch (Exception e) { - e.printStackTrace(); - } - - // Thread.sleep(2000); - } - } - - private void testGetUser() throws Exception { - try { - EchoService echoService = (EchoService)userProvider; - Object status = echoService.$echo("OK"); - System.out.println("echo: "+status); - User user1 = userProvider.GetUser("A003"); - System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + - " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString() - + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString()); - User user2 = userProvider.GetUser0("A003","Moorse"); - System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + - " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString() - + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString()); - User user3 = userProvider.getUser(1); - System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + - " UserInfo, Id:" + user3.getId() + ", name:" + user3.getName() + ", sex:" + user3.getSex().toString() - + ", age:" + user3.getAge() + ", time:" + user3.getTime().toString()); - userProvider.GetUser3(); - System.out.println("GetUser3 succ"); - - User user9 = userProvider.GetUser1("A003"); - } catch (Exception e) { - System.out.println("*************exception***********"); - e.printStackTrace(); - } - try { - userProvider.GetErr("A003"); - } catch (Throwable t) { - System.out.println("*************exception***********"); - t.printStackTrace(); - } - } - - private void testGetUsers() throws Exception { - try { - List<String> userIDList = new ArrayList<String>(); - userIDList.add("A001"); - userIDList.add("A002"); - userIDList.add("A003"); - - List<User> userList = userProvider.GetUsers(userIDList); - - for (int i = 0; i < userList.size(); i++) { - User user = userList.get(i); - System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + - " UserInfo, Id:" + user.getId() + ", name:" + user.getName() + ", sex:" + user.getSex().toString() - + ", age:" + user.getAge() + ", time:" + user.getTime().toString()); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - //启动consumer的入口函数(在配置文件中指定) - public void start() throws Exception { - testGetUser(); - testGetUsers(); -// Thread.sleep(120000); -Thread.sleep(2000); - } -} diff --git a/examples/dubbo/go-client/app/client.go b/examples/general/dubbo/go-client/app/client.go similarity index 51% rename from examples/dubbo/go-client/app/client.go rename to examples/general/dubbo/go-client/app/client.go index 7918e2df0fbb2c488569791beefa6d872ca22564..e839b0b2776d8e3b2aba2756d2a622bea2b8e88d 100644 --- a/examples/dubbo/go-client/app/client.go +++ b/examples/general/dubbo/go-client/app/client.go @@ -25,16 +25,14 @@ import ( "syscall" "time" ) - import ( - "github.com/dubbogo/hessian2" + hessian "github.com/apache/dubbo-go-hessian2" ) import ( "github.com/apache/dubbo-go/common/logger" _ "github.com/apache/dubbo-go/common/proxy/proxy_factory" "github.com/apache/dubbo-go/config" - _ "github.com/apache/dubbo-go/protocol/dubbo" _ "github.com/apache/dubbo-go/registry/protocol" _ "github.com/apache/dubbo-go/filter/impl" @@ -59,6 +57,44 @@ func main() { config.Load() + println("\n\ntest") + test() + println("\n\ntest1") + test1() + println("\n\ntest2") + test2() + initSignal() +} + +func initSignal() { + signals := make(chan os.Signal, 1) + // It is not possible to block SIGKILL or syscall.SIGSTOP + signal.Notify(signals, os.Interrupt, os.Kill, syscall.SIGHUP, + syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) + for { + sig := <-signals + logger.Infof("get signal %s", sig.String()) + switch sig { + case syscall.SIGHUP: + // reload() + default: + go time.AfterFunc(time.Duration(survivalTimeout), func() { + logger.Warnf("app exit now by force...") + os.Exit(1) + }) + + // The program exits normally or timeout forcibly exits. + fmt.Println("app exit now...") + return + } + } +} + +func println(format string, args ...interface{}) { + fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...) +} + +func test() { println("\n\n\necho") res, err := userProvider.Echo(context.TODO(), "OK") if err != nil { @@ -109,43 +145,143 @@ func main() { println("\n\n\nstart to test dubbo - getErr") user = &User{} err = userProvider.GetErr(context.TODO(), []interface{}{"A003"}, user) - if err != nil { - println("getErr - error: %v", err) + if err == nil { + panic("err is nil") } + println("getErr - error: %v", err) println("\n\n\nstart to test dubbo illegal method") err = userProvider.GetUser1(context.TODO(), []interface{}{"A003"}, user) + if err == nil { + panic("err is nil") + } + println("error: %v", err) +} + +func test1() { + println("\n\n\necho") + res, err := userProvider1.Echo(context.TODO(), "OK") if err != nil { panic(err) } + println("res: %v\n", res) - initSignal() -} + time.Sleep(3e9) -func initSignal() { - signals := make(chan os.Signal, 1) - // It is not possible to block SIGKILL or syscall.SIGSTOP - signal.Notify(signals, os.Interrupt, os.Kill, syscall.SIGHUP, - syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) - for { - sig := <-signals - logger.Infof("get signal %s", sig.String()) - switch sig { - case syscall.SIGHUP: - // reload() - default: - go time.AfterFunc(time.Duration(survivalTimeout)*time.Second, func() { - logger.Warnf("app exit now by force...") - os.Exit(1) - }) + println("\n\n\nstart to test dubbo") + user := &User{} + err = userProvider1.GetUser(context.TODO(), []interface{}{"A003"}, user) + if err != nil { + panic(err) + } + println("response result: %v", user) - // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出 - fmt.Println("app exit now...") - return - } + println("\n\n\nstart to test dubbo - GetUser0") + ret, err := userProvider1.GetUser0("A003", "Moorse") + if err != nil { + panic(err) + } + println("response result: %v", ret) + + println("\n\n\nstart to test dubbo - GetUsers") + ret1, err := userProvider1.GetUsers([]interface{}{[]interface{}{"A002", "A003"}}) + if err != nil { + panic(err) } + println("response result: %v", ret1) + + println("\n\n\nstart to test dubbo - getUser") + user = &User{} + var i int32 = 1 + err = userProvider1.GetUser2(context.TODO(), []interface{}{i}, user) + if err != nil { + panic(err) + } + println("response result: %v", user) + + println("\n\n\nstart to test dubbo - GetUser3") + err = userProvider1.GetUser3() + if err != nil { + panic(err) + } + println("succ!") + + println("\n\n\nstart to test dubbo - getErr") + user = &User{} + err = userProvider1.GetErr(context.TODO(), []interface{}{"A003"}, user) + if err == nil { + panic("err is nil") + } + println("getErr - error: %v", err) + + println("\n\n\nstart to test dubbo illegal method") + err = userProvider1.GetUser1(context.TODO(), []interface{}{"A003"}, user) + if err == nil { + panic("err is nil") + } + println("error: %v", err) } -func println(format string, args ...interface{}) { - fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...) +func test2() { + println("\n\n\necho") + res, err := userProvider2.Echo(context.TODO(), "OK") + if err != nil { + panic(err) + } + println("res: %v\n", res) + + time.Sleep(3e9) + + println("\n\n\nstart to test dubbo") + user := &User{} + err = userProvider2.GetUser(context.TODO(), []interface{}{"A003"}, user) + if err != nil { + panic(err) + } + println("response result: %v", user) + + println("\n\n\nstart to test dubbo - GetUser0") + ret, err := userProvider2.GetUser0("A003", "Moorse") + if err != nil { + panic(err) + } + println("response result: %v", ret) + + println("\n\n\nstart to test dubbo - GetUsers") + ret1, err := userProvider2.GetUsers([]interface{}{[]interface{}{"A002", "A003"}}) + if err != nil { + panic(err) + } + println("response result: %v", ret1) + + println("\n\n\nstart to test dubbo - getUser") + user = &User{} + var i int32 = 1 + err = userProvider2.GetUser2(context.TODO(), []interface{}{i}, user) + if err != nil { + panic(err) + } + println("response result: %v", user) + + println("\n\n\nstart to test dubbo - GetUser3") + err = userProvider2.GetUser3() + if err != nil { + panic(err) + } + println("succ!") + + println("\n\n\nstart to test dubbo - getErr") + user = &User{} + err = userProvider2.GetErr(context.TODO(), []interface{}{"A003"}, user) + if err == nil { + panic("err is nil") + } + println("getErr - error: %v", err) + + println("\n\n\nstart to test dubbo illegal method") + err = userProvider2.GetUser1(context.TODO(), []interface{}{"A003"}, user) + if err == nil { + panic("err is nil") + } + println("error: %v", err) } diff --git a/examples/dubbo/go-client/app/user.go b/examples/general/dubbo/go-client/app/user.go similarity index 59% rename from examples/dubbo/go-client/app/user.go rename to examples/general/dubbo/go-client/app/user.go index d491c3633384ad9ee6acdb2786d383e420f26db3..104d325d052940439da1c89c565a47520c73dd88 100644 --- a/examples/dubbo/go-client/app/user.go +++ b/examples/general/dubbo/go-client/app/user.go @@ -25,7 +25,7 @@ import ( ) import ( - hessian "github.com/dubbogo/hessian2" + hessian "github.com/apache/dubbo-go-hessian2" ) import ( @@ -34,10 +34,16 @@ import ( type Gender hessian.JavaEnum -var userProvider = new(UserProvider) +var ( + userProvider = new(UserProvider) + userProvider1 = new(UserProvider1) + userProvider2 = new(UserProvider2) +) func init() { config.SetConsumerService(userProvider) + config.SetConsumerService(userProvider1) + config.SetConsumerService(userProvider2) } const ( @@ -83,7 +89,7 @@ type User struct { Name string Age int32 Time time.Time - Sex Gender // 注意此处,java enum Object <--> go string + Sex Gender // notice: java enum Object <--> go string } func (u User) String() string { @@ -108,10 +114,36 @@ type UserProvider struct { Echo func(ctx context.Context, req interface{}) (interface{}, error) // Echo represent EchoFilter will be used } -func (u *UserProvider) Service() string { - return "com.ikurento.user.UserProvider" +func (u *UserProvider) Reference() string { + return "UserProvider" +} + +type UserProvider1 struct { + GetUsers func(req []interface{}) ([]interface{}, error) + GetErr func(ctx context.Context, req []interface{}, rsp *User) error + GetUser func(ctx context.Context, req []interface{}, rsp *User) error + GetUser0 func(id string, name string) (User, error) + GetUser1 func(ctx context.Context, req []interface{}, rsp *User) error + GetUser2 func(ctx context.Context, req []interface{}, rsp *User) error `dubbo:"getUser"` + GetUser3 func() error + Echo func(ctx context.Context, req interface{}) (interface{}, error) // Echo represent EchoFilter will be used +} + +func (u *UserProvider1) Reference() string { + return "UserProvider1" +} + +type UserProvider2 struct { + GetUsers func(req []interface{}) ([]interface{}, error) + GetErr func(ctx context.Context, req []interface{}, rsp *User) error + GetUser func(ctx context.Context, req []interface{}, rsp *User) error + GetUser0 func(id string, name string) (User, error) + GetUser1 func(ctx context.Context, req []interface{}, rsp *User) error + GetUser2 func(ctx context.Context, req []interface{}, rsp *User) error `dubbo:"getUser"` + GetUser3 func() error + Echo func(ctx context.Context, req interface{}) (interface{}, error) // Echo represent EchoFilter will be used } -func (u *UserProvider) Version() string { - return "" +func (u *UserProvider2) Reference() string { + return "UserProvider2" } diff --git a/examples/jsonrpc/go-client/app/version.go b/examples/general/dubbo/go-client/app/version.go similarity index 100% rename from examples/jsonrpc/go-client/app/version.go rename to examples/general/dubbo/go-client/app/version.go diff --git a/examples/jsonrpc/go-client/assembly/bin/load.sh b/examples/general/dubbo/go-client/assembly/bin/load.sh similarity index 100% rename from examples/jsonrpc/go-client/assembly/bin/load.sh rename to examples/general/dubbo/go-client/assembly/bin/load.sh diff --git a/examples/jsonrpc/go-client/assembly/common/app.properties b/examples/general/dubbo/go-client/assembly/common/app.properties similarity index 100% rename from examples/jsonrpc/go-client/assembly/common/app.properties rename to examples/general/dubbo/go-client/assembly/common/app.properties diff --git a/examples/dubbo/with-configcenter-go-client/assembly/common/build.sh b/examples/general/dubbo/go-client/assembly/common/build.sh similarity index 100% rename from examples/dubbo/with-configcenter-go-client/assembly/common/build.sh rename to examples/general/dubbo/go-client/assembly/common/build.sh diff --git a/examples/jsonrpc/go-client/assembly/linux/dev.sh b/examples/general/dubbo/go-client/assembly/linux/dev.sh similarity index 100% rename from examples/jsonrpc/go-client/assembly/linux/dev.sh rename to examples/general/dubbo/go-client/assembly/linux/dev.sh diff --git a/examples/jsonrpc/go-client/assembly/linux/release.sh b/examples/general/dubbo/go-client/assembly/linux/release.sh similarity index 100% rename from examples/jsonrpc/go-client/assembly/linux/release.sh rename to examples/general/dubbo/go-client/assembly/linux/release.sh diff --git a/examples/jsonrpc/go-client/assembly/linux/test.sh b/examples/general/dubbo/go-client/assembly/linux/test.sh similarity index 100% rename from examples/jsonrpc/go-client/assembly/linux/test.sh rename to examples/general/dubbo/go-client/assembly/linux/test.sh diff --git a/examples/jsonrpc/go-client/assembly/mac/dev.sh b/examples/general/dubbo/go-client/assembly/mac/dev.sh similarity index 100% rename from examples/jsonrpc/go-client/assembly/mac/dev.sh rename to examples/general/dubbo/go-client/assembly/mac/dev.sh diff --git a/examples/jsonrpc/go-client/assembly/mac/release.sh b/examples/general/dubbo/go-client/assembly/mac/release.sh similarity index 100% rename from examples/jsonrpc/go-client/assembly/mac/release.sh rename to examples/general/dubbo/go-client/assembly/mac/release.sh diff --git a/examples/jsonrpc/go-client/assembly/mac/test.sh b/examples/general/dubbo/go-client/assembly/mac/test.sh similarity index 100% rename from examples/jsonrpc/go-client/assembly/mac/test.sh rename to examples/general/dubbo/go-client/assembly/mac/test.sh diff --git a/examples/jsonrpc/go-client/assembly/windows/dev.sh b/examples/general/dubbo/go-client/assembly/windows/dev.sh similarity index 100% rename from examples/jsonrpc/go-client/assembly/windows/dev.sh rename to examples/general/dubbo/go-client/assembly/windows/dev.sh diff --git a/examples/jsonrpc/go-client/assembly/windows/release.sh b/examples/general/dubbo/go-client/assembly/windows/release.sh similarity index 100% rename from examples/jsonrpc/go-client/assembly/windows/release.sh rename to examples/general/dubbo/go-client/assembly/windows/release.sh diff --git a/examples/jsonrpc/go-client/assembly/windows/test.sh b/examples/general/dubbo/go-client/assembly/windows/test.sh similarity index 100% rename from examples/jsonrpc/go-client/assembly/windows/test.sh rename to examples/general/dubbo/go-client/assembly/windows/test.sh diff --git a/examples/general/dubbo/go-client/profiles/dev/client.yml b/examples/general/dubbo/go-client/profiles/dev/client.yml new file mode 100644 index 0000000000000000000000000000000000000000..ff696688416dc1e77f87d7831922894979d78da2 --- /dev/null +++ b/examples/general/dubbo/go-client/profiles/dev/client.yml @@ -0,0 +1,83 @@ +# dubbo client yaml configure file + + +check: true +# client +request_timeout : "3s" +# connect timeout +connect_timeout : "3s" + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info client" + version : "0.0.1" + owner : "ZX" + environment : "dev" + +registries : + "hangzhouzk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + +references: + "UserProvider": + # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 + registry: "hangzhouzk" + protocol : "dubbo" + interface : "com.ikurento.user.UserProvider" + cluster: "failover" + methods : + - name: "GetUser" + retries: 3 + "UserProvider1": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 + "UserProvider2": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + group: "as" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 + +protocol_conf: + dubbo: + reconnect_interval: 0 + connection_number: 2 + heartbeat_period: "5s" + session_timeout: "20s" + pool_size: 64 + pool_ttl: 600 + getty_session_param: + compress_encoding: false + tcp_no_delay: true + tcp_keep_alive: true + keep_alive_period: "120s" + tcp_r_buf_size: 262144 + tcp_w_buf_size: 65536 + pkg_wq_size: 512 + tcp_read_timeout: "1s" + tcp_write_timeout: "5s" + wait_timeout: "1s" + max_msg_len: 10240 + session_name: "client" diff --git a/examples/jsonrpc/go-client/profiles/dev/log.yml b/examples/general/dubbo/go-client/profiles/dev/log.yml similarity index 100% rename from examples/jsonrpc/go-client/profiles/dev/log.yml rename to examples/general/dubbo/go-client/profiles/dev/log.yml diff --git a/examples/jsonrpc/go-client/profiles/dev/client.yml b/examples/general/dubbo/go-client/profiles/release/client.yml similarity index 66% rename from examples/jsonrpc/go-client/profiles/dev/client.yml rename to examples/general/dubbo/go-client/profiles/release/client.yml index 8d4346510fac9f7350b3d680b07a3d258b84e521..b4d897fda2b78e30dd912eab9f5a43bbcef9f595 100644 --- a/examples/jsonrpc/go-client/profiles/dev/client.yml +++ b/examples/general/dubbo/go-client/profiles/release/client.yml @@ -1,5 +1,6 @@ # dubbo client yaml configure file + check: true # client request_timeout : "3s" @@ -8,12 +9,12 @@ connect_timeout : "3s" # application config application_config: - organization : "ikurento.com" - name : "BDTService" - module : "dubbogo user-info client" - version : "0.0.1" - owner : "ZX" - environment : "dev" + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info client" + version : "0.0.1" + owner : "ZX" + environment : "release" registries : "hangzhouzk": @@ -33,14 +34,31 @@ references: "UserProvider": # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 registry: "hangzhouzk" - protocol : "jsonrpc" -# version : "2.0" -# group: "as" + protocol : "dubbo" interface : "com.ikurento.user.UserProvider" cluster: "failover" methods : - name: "GetUser" retries: 3 + "UserProvider1": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 + "UserProvider2": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + group: "as" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 protocol_conf: dubbo: @@ -48,7 +66,6 @@ protocol_conf: connection_number: 2 heartbeat_period: "5s" session_timeout: "20s" - fail_fast_timeout: "5s" pool_size: 64 pool_ttl: 600 getty_session_param: @@ -58,7 +75,6 @@ protocol_conf: keep_alive_period: "120s" tcp_r_buf_size: 262144 tcp_w_buf_size: 65536 - pkg_rq_size: 1024 pkg_wq_size: 512 tcp_read_timeout: "1s" tcp_write_timeout: "5s" diff --git a/examples/jsonrpc/go-client/profiles/release/log.yml b/examples/general/dubbo/go-client/profiles/release/log.yml similarity index 100% rename from examples/jsonrpc/go-client/profiles/release/log.yml rename to examples/general/dubbo/go-client/profiles/release/log.yml diff --git a/examples/general/dubbo/go-client/profiles/test/client.yml b/examples/general/dubbo/go-client/profiles/test/client.yml new file mode 100644 index 0000000000000000000000000000000000000000..c8b5c58691a0b35b55adb8f27cd1108433655b45 --- /dev/null +++ b/examples/general/dubbo/go-client/profiles/test/client.yml @@ -0,0 +1,83 @@ +# dubbo client yaml configure file + + +check: true +# client +request_timeout : "3s" +# connect timeout +connect_timeout : "3s" + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info client" + version : "0.0.1" + owner : "ZX" + environment : "test" + +registries : + "hangzhouzk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + +references: + "UserProvider": + # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 + registry: "hangzhouzk" + protocol : "dubbo" + interface : "com.ikurento.user.UserProvider" + cluster: "failover" + methods : + - name: "GetUser" + retries: 3 + "UserProvider1": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 + "UserProvider2": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + group: "as" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 + +protocol_conf: + dubbo: + reconnect_interval: 0 + connection_number: 2 + heartbeat_period: "5s" + session_timeout: "20s" + pool_size: 64 + pool_ttl: 600 + getty_session_param: + compress_encoding: false + tcp_no_delay: true + tcp_keep_alive: true + keep_alive_period: "120s" + tcp_r_buf_size: 262144 + tcp_w_buf_size: 65536 + pkg_wq_size: 512 + tcp_read_timeout: "1s" + tcp_write_timeout: "5s" + wait_timeout: "1s" + max_msg_len: 10240 + session_name: "client" diff --git a/examples/jsonrpc/go-client/profiles/test/log.yml b/examples/general/dubbo/go-client/profiles/test/log.yml similarity index 100% rename from examples/jsonrpc/go-client/profiles/test/log.yml rename to examples/general/dubbo/go-client/profiles/test/log.yml diff --git a/examples/dubbo/go-server/app/app b/examples/general/dubbo/go-server/app/app similarity index 100% rename from examples/dubbo/go-server/app/app rename to examples/general/dubbo/go-server/app/app diff --git a/examples/dubbo/go-server/app/server.go b/examples/general/dubbo/go-server/app/server.go similarity index 89% rename from examples/dubbo/go-server/app/server.go rename to examples/general/dubbo/go-server/app/server.go index 788fc665b872d4f7f1429122cee581a6ab4979e7..ac92b879b15cb88ebc71fc5df90675b01760c899 100644 --- a/examples/dubbo/go-server/app/server.go +++ b/examples/general/dubbo/go-server/app/server.go @@ -26,7 +26,7 @@ import ( ) import ( - hessian "github.com/dubbogo/hessian2" + hessian "github.com/apache/dubbo-go-hessian2" ) import ( @@ -74,12 +74,12 @@ func initSignal() { case syscall.SIGHUP: // reload() default: - go time.AfterFunc(time.Duration(float64(survivalTimeout)*float64(time.Second)), func() { + go time.AfterFunc(time.Duration(survivalTimeout), func() { logger.Warnf("app exit now by force...") os.Exit(1) }) - // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出 + // The program exits normally or timeout forcibly exits. fmt.Println("provider app exit now...") return } diff --git a/examples/general/dubbo/go-server/app/user.go b/examples/general/dubbo/go-server/app/user.go new file mode 100644 index 0000000000000000000000000000000000000000..e07a02e772de589bd9df85ef6e1e69fb2468d347 --- /dev/null +++ b/examples/general/dubbo/go-server/app/user.go @@ -0,0 +1,113 @@ +/* + * 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 main + +import ( + "fmt" + "strconv" + "time" +) + +import ( + hessian "github.com/apache/dubbo-go-hessian2" +) + +type Gender hessian.JavaEnum + +const ( + MAN hessian.JavaEnum = iota + WOMAN +) + +var genderName = map[hessian.JavaEnum]string{ + MAN: "MAN", + WOMAN: "WOMAN", +} + +var genderValue = map[string]hessian.JavaEnum{ + "MAN": MAN, + "WOMAN": WOMAN, +} + +func (g Gender) JavaClassName() string { + return "com.ikurento.user.Gender" +} + +func (g Gender) String() string { + s, ok := genderName[hessian.JavaEnum(g)] + if ok { + return s + } + + return strconv.Itoa(int(g)) +} + +func (g Gender) EnumValue(s string) hessian.JavaEnum { + v, ok := genderValue[s] + if ok { + return v + } + + return hessian.InvalidJavaEnum +} + +type ( + User struct { + // !!! Cannot define lowercase names of variable + Id string + Name string + Age int32 + Time time.Time + Sex Gender // notice: java enum Object <--> go string + } +) + +var ( + DefaultUser = User{ + Id: "0", Name: "Alex Stocks", Age: 31, + Sex: Gender(MAN), + } + + userMap = make(map[string]User) +) + +func init() { + userMap["A000"] = DefaultUser + userMap["A001"] = User{Id: "001", Name: "ZhangSheng", Age: 18, Sex: Gender(MAN)} + userMap["A002"] = User{Id: "002", Name: "Lily", Age: 20, Sex: Gender(WOMAN)} + userMap["A003"] = User{Id: "113", Name: "Moorse", Age: 30, Sex: Gender(WOMAN)} + for k, v := range userMap { + v.Time = time.Now() + userMap[k] = v + } +} + +func (u User) String() string { + return fmt.Sprintf( + "User{Id:%s, Name:%s, Age:%d, Time:%s, Sex:%s}", + u.Id, u.Name, u.Age, u.Time, u.Sex, + ) +} + +func (u User) JavaClassName() string { + return "com.ikurento.user.User" +} + +func println(format string, args ...interface{}) { + fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...) +} diff --git a/examples/general/dubbo/go-server/app/user_provider.go b/examples/general/dubbo/go-server/app/user_provider.go new file mode 100644 index 0000000000000000000000000000000000000000..fdf0a3abb2ac26cc2cbfa5971db3f02b18fe0be0 --- /dev/null +++ b/examples/general/dubbo/go-server/app/user_provider.go @@ -0,0 +1,102 @@ +package main + +import ( + "context" + "fmt" + "strconv" +) + +import ( + "github.com/apache/dubbo-go-hessian2/java_exception" + "github.com/apache/dubbo-go/config" + perrors "github.com/pkg/errors" +) + +func init() { + config.SetProviderService(new(UserProvider)) +} + +type UserProvider struct { +} + +func (u *UserProvider) getUser(userId string) (*User, error) { + if user, ok := userMap[userId]; ok { + return &user, nil + } + + return nil, fmt.Errorf("invalid user id:%s", userId) +} + +func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User) error { + var ( + err error + user *User + ) + + println("req:%#v", req) + user, err = u.getUser(req[0].(string)) + if err == nil { + *rsp = *user + println("rsp:%#v", rsp) + } + return err +} + +func (u *UserProvider) GetUser0(id string, name string) (User, error) { + var err error + + println("id:%s, name:%s", id, name) + user, err := u.getUser(id) + if err != nil { + return User{}, err + } + if user.Name != name { + return User{}, perrors.New("name is not " + user.Name) + } + return *user, err +} + +func (u *UserProvider) GetUser2(ctx context.Context, req []interface{}, rsp *User) error { + var err error + + println("req:%#v", req) + rsp.Id = strconv.Itoa(int(req[0].(int32))) + return err +} + +func (u *UserProvider) GetUser3() error { + return nil +} + +func (u *UserProvider) GetErr(ctx context.Context, req []interface{}, rsp *User) error { + return java_exception.NewThrowable("exception") +} + +func (u *UserProvider) GetUsers(req []interface{}) ([]interface{}, error) { + var err error + + println("req:%s", req) + t := req[0].([]interface{}) + user, err := u.getUser(t[0].(string)) + if err != nil { + return nil, err + } + println("user:%v", user) + user1, err := u.getUser(t[1].(string)) + if err != nil { + return nil, err + } + println("user1:%v", user1) + + return []interface{}{user, user1}, err +} + +func (s *UserProvider) MethodMapper() map[string]string { + return map[string]string{ + "GetUser2": "getUser", + } +} + +func (u *UserProvider) Reference() string { + return "UserProvider" +} diff --git a/examples/general/dubbo/go-server/app/user_provider1.go b/examples/general/dubbo/go-server/app/user_provider1.go new file mode 100644 index 0000000000000000000000000000000000000000..3edc816b592f9e165f149a792a9401a25c8c73c0 --- /dev/null +++ b/examples/general/dubbo/go-server/app/user_provider1.go @@ -0,0 +1,88 @@ +package main + +import ( + "context" + "fmt" + "strconv" +) + +import ( + "github.com/apache/dubbo-go-hessian2/java_exception" + "github.com/apache/dubbo-go/config" + perrors "github.com/pkg/errors" +) + +func init() { + config.SetProviderService(new(UserProvider1)) +} + +type UserProvider1 struct { +} + +func (u *UserProvider1) getUser(userId string) (*User, error) { + if user, ok := userMap[userId]; ok { + return &user, nil + } + + return nil, fmt.Errorf("invalid user id:%s", userId) +} + +func (u *UserProvider1) GetUser(ctx context.Context, req []interface{}, rsp *User) error { + var ( + err error + user *User + ) + + println("req:%#v", req) + user, err = u.getUser(req[0].(string)) + if err == nil { + *rsp = *user + println("rsp:%#v", rsp) + } + return err +} + +func (u *UserProvider1) GetUser0(id string, name string) (User, error) { + var err error + + println("id:%s, name:%s", id, name) + user, err := u.getUser(id) + if err != nil { + return User{}, err + } + if user.Name != name { + return User{}, perrors.New("name is not " + user.Name) + } + return *user, err +} + +func (u *UserProvider1) GetUser2(ctx context.Context, req []interface{}, rsp *User) error { + var err error + + println("req:%#v", req) + rsp.Id = strconv.Itoa(int(req[0].(int32))) + return err +} + +func (u *UserProvider1) GetUser3() error { + return nil +} + +func (u *UserProvider1) GetErr(ctx context.Context, req []interface{}, rsp *User) error { + return java_exception.NewThrowable("exception") +} + +func (u *UserProvider1) GetUsers(req []interface{}) ([]interface{}, error) { + + return []interface{}{}, nil +} + +func (s *UserProvider1) MethodMapper() map[string]string { + return map[string]string{ + "GetUser2": "getUser", + } +} + +func (u *UserProvider1) Reference() string { + return "UserProvider1" +} diff --git a/examples/general/dubbo/go-server/app/user_provider2.go b/examples/general/dubbo/go-server/app/user_provider2.go new file mode 100644 index 0000000000000000000000000000000000000000..d28bcc33963ef73b372508e057679a5910948c25 --- /dev/null +++ b/examples/general/dubbo/go-server/app/user_provider2.go @@ -0,0 +1,97 @@ +package main + +import ( + "context" + "fmt" + "strconv" +) + +import ( + "github.com/apache/dubbo-go-hessian2/java_exception" + "github.com/apache/dubbo-go/config" + perrors "github.com/pkg/errors" +) + +func init() { + config.SetProviderService(new(UserProvider2)) +} + +type UserProvider2 struct { +} + +func (u *UserProvider2) getUser(userId string) (*User, error) { + if user, ok := userMap[userId]; ok { + return &user, nil + } + + return nil, fmt.Errorf("invalid user id:%s", userId) +} + +func (u *UserProvider2) GetUser(ctx context.Context, req []interface{}, rsp *User) error { + var ( + err error + user *User + ) + + println("req:%#v", req) + user, err = u.getUser(req[0].(string)) + if err == nil { + *rsp = *user + println("rsp:%#v", rsp) + } + return err +} + +func (u *UserProvider2) GetUser0(id string, name string) (User, error) { + var err error + + println("id:%s, name:%s", id, name) + user, err := u.getUser(id) + if err != nil { + return User{}, err + } + if user.Name != name { + return User{}, perrors.New("name is not " + user.Name) + } + return *user, err +} + +func (u *UserProvider2) GetUser2(ctx context.Context, req []interface{}, rsp *User) error { + var err error + + println("req:%#v", req) + rsp.Id = strconv.Itoa(int(req[0].(int32))) + return err +} + +func (u *UserProvider2) GetUser3() error { + return nil +} + +func (u *UserProvider2) GetErr(ctx context.Context, req []interface{}, rsp *User) error { + return java_exception.NewThrowable("exception") +} + +func (u *UserProvider2) GetUsers(req []interface{}) ([]interface{}, error) { + var err error + + println("req:%s", req) + t := req[0].([]interface{}) + user, err := u.getUser(t[0].(string)) + if err != nil { + return nil, err + } + println("user:%v", user) + + return []interface{}{user}, err +} + +func (s *UserProvider2) MethodMapper() map[string]string { + return map[string]string{ + "GetUser2": "getUser", + } +} + +func (u *UserProvider2) Reference() string { + return "UserProvider2" +} diff --git a/examples/jsonrpc/go-server/app/version.go b/examples/general/dubbo/go-server/app/version.go similarity index 100% rename from examples/jsonrpc/go-server/app/version.go rename to examples/general/dubbo/go-server/app/version.go diff --git a/examples/jsonrpc/go-server/assembly/bin/load.sh b/examples/general/dubbo/go-server/assembly/bin/load.sh similarity index 100% rename from examples/jsonrpc/go-server/assembly/bin/load.sh rename to examples/general/dubbo/go-server/assembly/bin/load.sh diff --git a/examples/jsonrpc/go-server/assembly/common/app.properties b/examples/general/dubbo/go-server/assembly/common/app.properties similarity index 100% rename from examples/jsonrpc/go-server/assembly/common/app.properties rename to examples/general/dubbo/go-server/assembly/common/app.properties diff --git a/examples/jsonrpc/go-server/assembly/common/build.sh b/examples/general/dubbo/go-server/assembly/common/build.sh similarity index 100% rename from examples/jsonrpc/go-server/assembly/common/build.sh rename to examples/general/dubbo/go-server/assembly/common/build.sh diff --git a/examples/jsonrpc/go-server/assembly/linux/dev.sh b/examples/general/dubbo/go-server/assembly/linux/dev.sh similarity index 100% rename from examples/jsonrpc/go-server/assembly/linux/dev.sh rename to examples/general/dubbo/go-server/assembly/linux/dev.sh diff --git a/examples/jsonrpc/go-server/assembly/linux/release.sh b/examples/general/dubbo/go-server/assembly/linux/release.sh similarity index 100% rename from examples/jsonrpc/go-server/assembly/linux/release.sh rename to examples/general/dubbo/go-server/assembly/linux/release.sh diff --git a/examples/jsonrpc/go-server/assembly/linux/test.sh b/examples/general/dubbo/go-server/assembly/linux/test.sh similarity index 100% rename from examples/jsonrpc/go-server/assembly/linux/test.sh rename to examples/general/dubbo/go-server/assembly/linux/test.sh diff --git a/examples/jsonrpc/go-server/assembly/mac/dev.sh b/examples/general/dubbo/go-server/assembly/mac/dev.sh similarity index 100% rename from examples/jsonrpc/go-server/assembly/mac/dev.sh rename to examples/general/dubbo/go-server/assembly/mac/dev.sh diff --git a/examples/jsonrpc/go-server/assembly/mac/release.sh b/examples/general/dubbo/go-server/assembly/mac/release.sh similarity index 100% rename from examples/jsonrpc/go-server/assembly/mac/release.sh rename to examples/general/dubbo/go-server/assembly/mac/release.sh diff --git a/examples/jsonrpc/go-server/assembly/mac/test.sh b/examples/general/dubbo/go-server/assembly/mac/test.sh similarity index 100% rename from examples/jsonrpc/go-server/assembly/mac/test.sh rename to examples/general/dubbo/go-server/assembly/mac/test.sh diff --git a/examples/jsonrpc/go-server/assembly/windows/dev.sh b/examples/general/dubbo/go-server/assembly/windows/dev.sh similarity index 100% rename from examples/jsonrpc/go-server/assembly/windows/dev.sh rename to examples/general/dubbo/go-server/assembly/windows/dev.sh diff --git a/examples/jsonrpc/go-server/assembly/windows/release.sh b/examples/general/dubbo/go-server/assembly/windows/release.sh similarity index 100% rename from examples/jsonrpc/go-server/assembly/windows/release.sh rename to examples/general/dubbo/go-server/assembly/windows/release.sh diff --git a/examples/jsonrpc/go-server/assembly/windows/test.sh b/examples/general/dubbo/go-server/assembly/windows/test.sh similarity index 100% rename from examples/jsonrpc/go-server/assembly/windows/test.sh rename to examples/general/dubbo/go-server/assembly/windows/test.sh diff --git a/examples/jsonrpc/go-server/profiles/dev/log.yml b/examples/general/dubbo/go-server/profiles/dev/log.yml similarity index 100% rename from examples/jsonrpc/go-server/profiles/dev/log.yml rename to examples/general/dubbo/go-server/profiles/dev/log.yml diff --git a/examples/general/dubbo/go-server/profiles/dev/server.yml b/examples/general/dubbo/go-server/profiles/dev/server.yml new file mode 100644 index 0000000000000000000000000000000000000000..79c2cb2cc22a1b626a631009a0a4c6f29a8f9127 --- /dev/null +++ b/examples/general/dubbo/go-server/profiles/dev/server.yml @@ -0,0 +1,92 @@ +# dubbo server yaml configure file + + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info server" + version : "0.0.1" + owner : "ZX" + environment : "dev" + +registries : + "hangzhouzk": + # 对应java配置中address属性的zookeeper <dubbo:registry address="zookeeper://127.0.0.1:2181"/> + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + + +services: + "UserProvider": + # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 + registry: "hangzhouzk" + protocol : "dubbo" + # 相当于dubbo.xml中的interface + interface : "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + "UserProvider1": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + "UserProvider2": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + group: "as" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + +protocols: + "dubbo1": + name: "dubbo" + # ip : "127.0.0.1" + port: 20000 + + +protocol_conf: + dubbo: + session_number: 700 + session_timeout: "20s" + getty_session_param: + compress_encoding: false + tcp_no_delay: true + tcp_keep_alive: true + keep_alive_period: "120s" + tcp_r_buf_size: 262144 + tcp_w_buf_size: 65536 + pkg_wq_size: 512 + tcp_read_timeout: "1s" + tcp_write_timeout: "5s" + wait_timeout: "1s" + max_msg_len: 1024 + session_name: "server" diff --git a/examples/jsonrpc/go-server/profiles/release/log.yml b/examples/general/dubbo/go-server/profiles/release/log.yml similarity index 100% rename from examples/jsonrpc/go-server/profiles/release/log.yml rename to examples/general/dubbo/go-server/profiles/release/log.yml diff --git a/examples/dubbo/go-server/profiles/dev/server.yml b/examples/general/dubbo/go-server/profiles/release/server.yml similarity index 69% rename from examples/dubbo/go-server/profiles/dev/server.yml rename to examples/general/dubbo/go-server/profiles/release/server.yml index bc4b288542322c8644c7af643dcb8dfafa099b1a..6890ed3bdb5048b02578ca8eba1620464378463c 100644 --- a/examples/dubbo/go-server/profiles/dev/server.yml +++ b/examples/general/dubbo/go-server/profiles/release/server.yml @@ -8,11 +8,10 @@ application_config: module : "dubbogo user-info server" version : "0.0.1" owner : "ZX" - environment : "dev" + environment : "release" registries : "hangzhouzk": - # 对应java配置中address属性的zookeeper <dubbo:registry address="zookeeper://127.0.0.1:2181"/> protocol: "zookeeper" timeout : "3s" address: "127.0.0.1:2181" @@ -27,7 +26,6 @@ registries : services: - "UserProvider": # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 registry: "hangzhouzk" @@ -41,6 +39,31 @@ services: - name: "GetUser" retries: 1 loadbalance: "random" + "UserProvider1": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + "UserProvider2": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + group: "as" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" protocols: "dubbo1": @@ -52,7 +75,6 @@ protocols: protocol_conf: dubbo: session_number: 700 - fail_fast_timeout: "5s" session_timeout: "20s" getty_session_param: compress_encoding: false @@ -61,7 +83,6 @@ protocol_conf: keep_alive_period: "120s" tcp_r_buf_size: 262144 tcp_w_buf_size: 65536 - pkg_rq_size: 1024 pkg_wq_size: 512 tcp_read_timeout: "1s" tcp_write_timeout: "5s" diff --git a/examples/jsonrpc/go-server/profiles/test/log.yml b/examples/general/dubbo/go-server/profiles/test/log.yml similarity index 100% rename from examples/jsonrpc/go-server/profiles/test/log.yml rename to examples/general/dubbo/go-server/profiles/test/log.yml diff --git a/examples/general/dubbo/go-server/profiles/test/server.yml b/examples/general/dubbo/go-server/profiles/test/server.yml new file mode 100644 index 0000000000000000000000000000000000000000..b6dd41da448d7531a3c5f4f24a8f460e5d1775bc --- /dev/null +++ b/examples/general/dubbo/go-server/profiles/test/server.yml @@ -0,0 +1,91 @@ +# dubbo server yaml configure file + + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info server" + version : "0.0.1" + owner : "ZX" + environment : "test" + +registries : + "hangzhouzk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + + +services: + "UserProvider": + # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 + registry: "hangzhouzk" + protocol : "dubbo" + # 相当于dubbo.xml中的interface + interface : "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + "UserProvider1": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + "UserProvider2": + registry: "hangzhouzk" + protocol: "dubbo" + version: "2.0" + group: "as" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + +protocols: + "dubbo1": + name: "dubbo" + # ip : "127.0.0.1" + port: 20000 + + +protocol_conf: + dubbo: + session_number: 700 + session_timeout: "20s" + getty_session_param: + compress_encoding: false + tcp_no_delay: true + tcp_keep_alive: true + keep_alive_period: "120s" + tcp_r_buf_size: 262144 + tcp_w_buf_size: 65536 + pkg_wq_size: 512 + tcp_read_timeout: "1s" + tcp_write_timeout: "5s" + wait_timeout: "1s" + max_msg_len: 1024 + session_name: "server" diff --git a/examples/dubbo/java-client/build.sh b/examples/general/dubbo/java-client/build.sh similarity index 100% rename from examples/dubbo/java-client/build.sh rename to examples/general/dubbo/java-client/build.sh diff --git a/examples/dubbo/java-client/pom.xml b/examples/general/dubbo/java-client/pom.xml similarity index 100% rename from examples/dubbo/java-client/pom.xml rename to examples/general/dubbo/java-client/pom.xml diff --git a/examples/dubbo/java-client/src/main/assembly/assembly.xml b/examples/general/dubbo/java-client/src/main/assembly/assembly.xml similarity index 100% rename from examples/dubbo/java-client/src/main/assembly/assembly.xml rename to examples/general/dubbo/java-client/src/main/assembly/assembly.xml diff --git a/examples/dubbo/java-client/src/main/assembly/conf/dubbo.properties b/examples/general/dubbo/java-client/src/main/assembly/conf/dubbo.properties similarity index 100% rename from examples/dubbo/java-client/src/main/assembly/conf/dubbo.properties rename to examples/general/dubbo/java-client/src/main/assembly/conf/dubbo.properties diff --git a/examples/dubbo/java-client/src/main/assembly/conf/log4j.properties b/examples/general/dubbo/java-client/src/main/assembly/conf/log4j.properties similarity index 100% rename from examples/dubbo/java-client/src/main/assembly/conf/log4j.properties rename to examples/general/dubbo/java-client/src/main/assembly/conf/log4j.properties diff --git a/examples/general/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java b/examples/general/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java new file mode 100644 index 0000000000000000000000000000000000000000..5c9870eecacb51115b266e8e13d81e02323d5a74 --- /dev/null +++ b/examples/general/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java @@ -0,0 +1,208 @@ +// ***************************************************** +// DESC : dubbo consumer +// AUTHOR : writtey by 包增辉(https://github.com/baozh) +// VERSION : 1.0 +// LICENCE : Apache License 2.0 +// EMAIL : alexstocks@foxmail.com +// MOD : 2016-10-19 17:03 +// FILE : Consumer.java +// ****************************************************** + +package com.ikurento.user; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import com.alibaba.dubbo.rpc.service.EchoService; +import java.util.List; + +public class Consumer { + // Define a private variable (Required in Spring) + private UserProvider userProvider; + private UserProvider userProvider1; + private UserProvider userProvider2; + + // Spring DI (Required in Spring) + public void setUserProvider(UserProvider u) { + this.userProvider = u; + } + public void setUserProvider1(UserProvider u) { + this.userProvider1 = u; + } + public void setUserProvider2(UserProvider u) { + this.userProvider2 = u; + } + + // Start the entry function for consumer (Specified in the configuration file) + public void start() throws Exception { + System.out.println("\n\ntest"); + testGetUser(); + testGetUsers(); + System.out.println("\n\ntest1"); + testGetUser1(); + testGetUsers1(); + System.out.println("\n\ntest2"); + testGetUser2(); + testGetUsers2(); + Thread.sleep(2000); + } + + private void testGetUser() throws Exception { + try { + EchoService echoService = (EchoService)userProvider; + Object status = echoService.$echo("OK"); + System.out.println("echo: "+status); + User user1 = userProvider.GetUser("A003"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString() + + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString()); + User user2 = userProvider.GetUser0("A003","Moorse"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString() + + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString()); + User user3 = userProvider.getUser(1); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user3.getId() + ", name:" + user3.getName() + ", sex:" + user3.getSex().toString() + + ", age:" + user3.getAge() + ", time:" + user3.getTime().toString()); + userProvider.GetUser3(); + System.out.println("GetUser3 succ"); + + User user9 = userProvider.GetUser1("A003"); + } catch (Exception e) { + System.out.println("*************exception***********"); + e.printStackTrace(); + } + try { + userProvider.GetErr("A003"); + } catch (Throwable t) { + System.out.println("*************exception***********"); + t.printStackTrace(); + } + } + + private void testGetUsers() throws Exception { + try { + List<String> userIDList = new ArrayList<String>(); + userIDList.add("A001"); + userIDList.add("A002"); + userIDList.add("A003"); + + List<User> userList = userProvider.GetUsers(userIDList); + + for (int i = 0; i < userList.size(); i++) { + User user = userList.get(i); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user.getId() + ", name:" + user.getName() + ", sex:" + user.getSex().toString() + + ", age:" + user.getAge() + ", time:" + user.getTime().toString()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void testGetUser1() throws Exception { + try { + EchoService echoService = (EchoService)userProvider1; + Object status = echoService.$echo("OK"); + System.out.println("echo: "+status); + User user1 = userProvider1.GetUser("A003"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString() + + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString()); + User user2 = userProvider1.GetUser0("A003","Moorse"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString() + + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString()); + User user3 = userProvider1.getUser(1); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user3.getId() + ", name:" + user3.getName() + ", sex:" + user3.getSex().toString() + + ", age:" + user3.getAge() + ", time:" + user3.getTime().toString()); + userProvider1.GetUser3(); + System.out.println("GetUser3 succ"); + + User user9 = userProvider1.GetUser1("A003"); + } catch (Exception e) { + System.out.println("*************exception***********"); + e.printStackTrace(); + } + try { + userProvider1.GetErr("A003"); + } catch (Throwable t) { + System.out.println("*************exception***********"); + t.printStackTrace(); + } + } + + private void testGetUsers1() throws Exception { + try { + List<String> userIDList = new ArrayList<String>(); + userIDList.add("A001"); + userIDList.add("A002"); + userIDList.add("A003"); + + List<User> userList = userProvider1.GetUsers(userIDList); + + for (int i = 0; i < userList.size(); i++) { + User user = userList.get(i); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user.getId() + ", name:" + user.getName() + ", sex:" + user.getSex().toString() + + ", age:" + user.getAge() + ", time:" + user.getTime().toString()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void testGetUser2() throws Exception { + try { + EchoService echoService = (EchoService)userProvider2; + Object status = echoService.$echo("OK"); + System.out.println("echo: "+status); + User user1 = userProvider2.GetUser("A003"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString() + + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString()); + User user2 = userProvider2.GetUser0("A003","Moorse"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString() + + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString()); + User user3 = userProvider2.getUser(1); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user3.getId() + ", name:" + user3.getName() + ", sex:" + user3.getSex().toString() + + ", age:" + user3.getAge() + ", time:" + user3.getTime().toString()); + userProvider2.GetUser3(); + System.out.println("GetUser3 succ"); + + User user9 = userProvider2.GetUser1("A003"); + } catch (Exception e) { + System.out.println("*************exception***********"); + e.printStackTrace(); + } + try { + userProvider2.GetErr("A003"); + } catch (Throwable t) { + System.out.println("*************exception***********"); + t.printStackTrace(); + } + } + + private void testGetUsers2() throws Exception { + try { + List<String> userIDList = new ArrayList<String>(); + userIDList.add("A001"); + userIDList.add("A002"); + userIDList.add("A003"); + + List<User> userList = userProvider2.GetUsers(userIDList); + + for (int i = 0; i < userList.size(); i++) { + User user = userList.get(i); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user.getId() + ", name:" + user.getName() + ", sex:" + user.getSex().toString() + + ", age:" + user.getAge() + ", time:" + user.getTime().toString()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/examples/dubbo/java-client/src/main/java/com/ikurento/user/Gender.java b/examples/general/dubbo/java-client/src/main/java/com/ikurento/user/Gender.java similarity index 100% rename from examples/dubbo/java-client/src/main/java/com/ikurento/user/Gender.java rename to examples/general/dubbo/java-client/src/main/java/com/ikurento/user/Gender.java diff --git a/examples/dubbo/java-client/src/main/java/com/ikurento/user/User.java b/examples/general/dubbo/java-client/src/main/java/com/ikurento/user/User.java similarity index 100% rename from examples/dubbo/java-client/src/main/java/com/ikurento/user/User.java rename to examples/general/dubbo/java-client/src/main/java/com/ikurento/user/User.java diff --git a/examples/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java b/examples/general/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java similarity index 100% rename from examples/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java rename to examples/general/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java diff --git a/examples/dubbo/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml b/examples/general/dubbo/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml similarity index 84% rename from examples/dubbo/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml rename to examples/general/dubbo/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml index 727007257fc5bb1e4d1aa73cfca8aa804a766e93..e7e5445a951614f599a63029f6d42508aaa4fccf 100644 --- a/examples/dubbo/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml +++ b/examples/general/dubbo/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml @@ -33,9 +33,12 @@ <dubbo:protocol id="jsonrpc" name="jsonrpc" /> <!-- 声明需要使用的服务接口 --> - <!--<dubbo:reference id="userProvider" protocol="jsonrpc" interface="com.ikurento.user.UserProvider">--> <dubbo:reference registry="ikurento" check="false" id="userProvider" protocol="dubbo" interface="com.ikurento.user.UserProvider"> <!--<dubbo:parameter key="heartbeat" value="10000"/ --> </dubbo:reference> + <dubbo:reference registry="ikurento" check="false" id="userProvider1" protocol="dubbo" version="2.0" interface="com.ikurento.user.UserProvider"> + </dubbo:reference> + <dubbo:reference registry="ikurento" check="false" id="userProvider2" protocol="dubbo" version="2.0" group="as" interface="com.ikurento.user.UserProvider"> + </dubbo:reference> </beans> diff --git a/examples/jsonrpc/java-client/src/main/resources/META-INF/spring/service.xml b/examples/general/dubbo/java-client/src/main/resources/META-INF/spring/service.xml similarity index 90% rename from examples/jsonrpc/java-client/src/main/resources/META-INF/spring/service.xml rename to examples/general/dubbo/java-client/src/main/resources/META-INF/spring/service.xml index 625a879f97f5a21498be1efc1aa97fce68e76c61..db9fc3cba5a359b8835af53b81e50f8296d2e489 100644 --- a/examples/jsonrpc/java-client/src/main/resources/META-INF/spring/service.xml +++ b/examples/general/dubbo/java-client/src/main/resources/META-INF/spring/service.xml @@ -24,6 +24,8 @@ <bean class="com.ikurento.user.Consumer" init-method="start"> <!-- 声明这个类 要使用的服务名--> <property name="userProvider" ref="userProvider" /> + <property name="userProvider1" ref="userProvider1" /> + <property name="userProvider2" ref="userProvider2" /> </bean> <!-- App config --> diff --git a/examples/dubbo/java-client/src/main/resources/log4j.properties b/examples/general/dubbo/java-client/src/main/resources/log4j.properties similarity index 100% rename from examples/dubbo/java-client/src/main/resources/log4j.properties rename to examples/general/dubbo/java-client/src/main/resources/log4j.properties diff --git a/examples/dubbo/java-server/build.sh b/examples/general/dubbo/java-server/build.sh similarity index 100% rename from examples/dubbo/java-server/build.sh rename to examples/general/dubbo/java-server/build.sh diff --git a/examples/dubbo/java-server/pom.xml b/examples/general/dubbo/java-server/pom.xml similarity index 100% rename from examples/dubbo/java-server/pom.xml rename to examples/general/dubbo/java-server/pom.xml diff --git a/examples/dubbo/java-server/script/debug.sh b/examples/general/dubbo/java-server/script/debug.sh similarity index 100% rename from examples/dubbo/java-server/script/debug.sh rename to examples/general/dubbo/java-server/script/debug.sh diff --git a/examples/dubbo/java-server/src/main/assembly/assembly.xml b/examples/general/dubbo/java-server/src/main/assembly/assembly.xml similarity index 100% rename from examples/dubbo/java-server/src/main/assembly/assembly.xml rename to examples/general/dubbo/java-server/src/main/assembly/assembly.xml diff --git a/examples/dubbo/java-server/src/main/assembly/conf/dubbo.properties b/examples/general/dubbo/java-server/src/main/assembly/conf/dubbo.properties similarity index 100% rename from examples/dubbo/java-server/src/main/assembly/conf/dubbo.properties rename to examples/general/dubbo/java-server/src/main/assembly/conf/dubbo.properties diff --git a/examples/dubbo/java-server/src/main/assembly/conf/log4j.properties b/examples/general/dubbo/java-server/src/main/assembly/conf/log4j.properties similarity index 100% rename from examples/dubbo/java-server/src/main/assembly/conf/log4j.properties rename to examples/general/dubbo/java-server/src/main/assembly/conf/log4j.properties diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/Gender.java b/examples/general/dubbo/java-server/src/main/java/com/ikurento/user/Gender.java similarity index 100% rename from examples/dubbo/java-server/src/main/java/com/ikurento/user/Gender.java rename to examples/general/dubbo/java-server/src/main/java/com/ikurento/user/Gender.java diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/Provider.java b/examples/general/dubbo/java-server/src/main/java/com/ikurento/user/Provider.java similarity index 100% rename from examples/dubbo/java-server/src/main/java/com/ikurento/user/Provider.java rename to examples/general/dubbo/java-server/src/main/java/com/ikurento/user/Provider.java diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/Response.java b/examples/general/dubbo/java-server/src/main/java/com/ikurento/user/Response.java similarity index 100% rename from examples/dubbo/java-server/src/main/java/com/ikurento/user/Response.java rename to examples/general/dubbo/java-server/src/main/java/com/ikurento/user/Response.java diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/User.java b/examples/general/dubbo/java-server/src/main/java/com/ikurento/user/User.java similarity index 100% rename from examples/dubbo/java-server/src/main/java/com/ikurento/user/User.java rename to examples/general/dubbo/java-server/src/main/java/com/ikurento/user/User.java diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java b/examples/general/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java similarity index 100% rename from examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java rename to examples/general/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java diff --git a/examples/general/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java b/examples/general/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..04729fb7a33abe9738ccfdd48a7b2b19028587da --- /dev/null +++ b/examples/general/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java @@ -0,0 +1,121 @@ +package com.ikurento.user; +//ref: https://github.com/JoeCao/dubbo_jsonrpc_example/tree/master/dubbo_server/src/main/java/com/ofpay/demo/api + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +// import org.apache.log4j.Logger; +// import org.apache.log4j.LoggerFactory; + +import java.util.*; + +public class UserProviderAnotherImpl implements UserProvider { + // private static final Logger logger = LoggerFactory.getLogger(getClass()); // Only output to dubbo's log(logs/server.log) + private static final Logger logger = LoggerFactory.getLogger("userLogger"); // Output to user-server.log + + private Map<String, User> userMap = new HashMap<String, User>(); + + public UserProviderAnotherImpl() { + // userMap.put("001", new User("001", "other-zhangsan", 18, new Date(1998-1900, 1, 2, 3, 4, 5), Gender.MAN)); + userMap.put("001", new User("001", "other-zhangsan", 18, new Date(0x12345678), Gender.MAN)); + userMap.put("002", new User("002", "other-lisi", 20, new Date(1996-1900, 1, 2, 3, 4, 5), Gender.MAN)); + userMap.put("003", new User("003", "other-lily", 23, new Date(1993-1900, 1, 2, 3, 4, 5), Gender.WOMAN)); + userMap.put("004", new User("004", "other-lisa", 32, new Date(1985-1900, 1, 2, 3, 4, 5), Gender.WOMAN)); + } + + public boolean isLimit(Gender gender, String name) { + logger.info(String.format("input gender=%sand name=%s", gender, name)); + return Gender.MAN == gender; + } + + public User GetUser(String userId) { + logger.info("input userId = " + userId); + return new User(userId, "Joe", 48); + } + + public User GetUser0(String userId, String name) { + return new User(userId, name, 48); + } + public void GetUser3() { + } + public User GetErr(String userId) throws Exception { + throw new Exception("exception"); + } + public List<User> GetUsers(ArrayList<String> userIdList) { + Iterator it = userIdList.iterator(); + List<User> userList = new ArrayList<User>(); + logger.warn("@userIdList size:" + userIdList.size()); + + while(it.hasNext()) { + String id = (String)(it.next()); + logger.info("GetUsers(@uid:" + id + ")"); + if (userMap.containsKey(id)) { + userList.add(userMap.get(id)); + logger.info("id:" + id + ", user:" + userMap.get(id)); + } + } + + return userList; + } + + public Map<String, User> GetUserMap(List<String> userIdList) { + Iterator it = userIdList.iterator(); + Map<String, User> map = new HashMap<String, User>(); + logger.warn("@userIdList size:" + userIdList.size()); + + while(it.hasNext()) { + String id = (String)(it.next()); + logger.info("GetUsers(@uid:" + id + ")"); + if (userMap.containsKey(id)) { + map.put(id, userMap.get(id)); + logger.info("id:" + id + ", user:" + userMap.get(id)); + } + } + + return map; + } + + public List<User> GetUsers(List<String> userIdList) { + Iterator it = userIdList.iterator(); + List<User> userList = new ArrayList<User>(); + logger.warn("@userIdList size:" + userIdList.size()); + + while(it.hasNext()) { + String id = (String)(it.next()); + logger.info("GetUsers(@uid:" + id + ")"); + if (userMap.containsKey(id)) { + userList.add(userMap.get(id)); + logger.info("id:" + id + ", user:" + userMap.get(id)); + } + } + + return userList; + } + + // @Override + public User getUser(int userCode) { + logger.info("input userCode = " + userCode); + return new User(String.valueOf(userCode), "userCode get", 48); + } + + public User queryUser(User user) { + logger.info("input user = " + user); + return new User(user.getId(), "get:" + user.getName(), user.getAge() + 18); + } + + public Map<String, User> queryAll() { + logger.info("input"); + Map<String, User> map = new HashMap<String, User>(); + map.put("001", new User("001", "Joe", 18)); + map.put("002", new User("002", "Wen", 20)); + + return map; + } + + public int Calc(int a,int b) { + return a + b + 100; + } + + public Response<Integer> Sum(int a,int b) { + return Response.ok(a+b); + } +} diff --git a/examples/general/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java b/examples/general/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..1efbf823740f5e3e4e82931a48bfc02ee9e78029 --- /dev/null +++ b/examples/general/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java @@ -0,0 +1,100 @@ +package com.ikurento.user; + +// ref: https://github.com/JoeCao/dubbo_jsonrpc_example/tree/master/dubbo_server/src/main/java/com/ofpay/demo/api + +import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.Iterator; + +// import org.apache.log4j.Logger; +// import org.apache.log4j.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UserProviderImpl implements UserProvider { + // private static final Logger logger = LoggerFactory.getLogger(getClass()); // Only output to dubbo's log(logs/server.log) + private static final Logger LOG = LoggerFactory.getLogger("UserLogger"); // Output to user-server.log + Map<String, User> userMap = new HashMap<String, User>(); + + public UserProviderImpl() { + userMap.put("A001", new User("A001", "demo-zhangsan", 18)); + userMap.put("A002", new User("A002", "demo-lisi", 20)); + userMap.put("A003", new User("A003", "demo-lily", 23)); + userMap.put("A004", new User("A004", "demo-lisa", 32)); + } + + public boolean isLimit(Gender gender, String name) { + return Gender.WOMAN == gender; + } + + public User GetUser(String userId) { + return new User(userId, "zhangsan", 18); + } + public User GetErr(String userId) throws Exception { + throw new Exception("exception"); + } + public User GetUser0(String userId, String name) { + return new User(userId, name, 18); + } + + public List<User> GetUsers(List<String> userIdList) { + Iterator it = userIdList.iterator(); + List<User> userList = new ArrayList<User>(); + LOG.warn("@userIdList size:" + userIdList.size()); + + while(it.hasNext()) { + String id = (String)(it.next()); + LOG.info("GetUsers(@uid:" + id + ")"); + if (userMap.containsKey(id)) { + userList.add(userMap.get(id)); + LOG.info("id:" + id + ", user:" + userMap.get(id)); + } + } + + return userList; + } + + public void GetUser3() { + } + + public Map<String, User> GetUserMap(List<String> userIdList) { + Iterator it = userIdList.iterator(); + Map<String, User> map = new HashMap<String, User>(); + LOG.warn("@userIdList size:" + userIdList.size()); + + while(it.hasNext()) { + String id = (String)(it.next()); + LOG.info("GetUsers(@uid:" + id + ")"); + if (userMap.containsKey(id)) { + map.put(id, userMap.get(id)); + LOG.info("id:" + id + ", user:" + userMap.get(id)); + } + } + + return map; + } + + public User queryUser(User user) { + return new User(user.getId(), "hello:" +user.getName(), user.getAge() + 18); + } + + public Map<String, User> queryAll() { + return userMap; + } + + + public User getUser(int userCode) { + return new User(String.valueOf(userCode), "userCode get", 48); + } + + + public int Calc(int a,int b) { + return a + b; + } + + public Response<Integer> Sum(int a,int b) { + return Response.ok(a+b); + } +} diff --git a/examples/dubbo/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml b/examples/general/dubbo/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml similarity index 100% rename from examples/dubbo/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml rename to examples/general/dubbo/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml diff --git a/examples/dubbo/java-server/src/main/resources/log4j.properties b/examples/general/dubbo/java-server/src/main/resources/log4j.properties similarity index 100% rename from examples/dubbo/java-server/src/main/resources/log4j.properties rename to examples/general/dubbo/java-server/src/main/resources/log4j.properties diff --git a/examples/jsonrpc/go-client/app/client.go b/examples/general/jsonrpc/go-client/app/client.go similarity index 53% rename from examples/jsonrpc/go-client/app/client.go rename to examples/general/jsonrpc/go-client/app/client.go index 7a47e14bda652dbb4689bfe520bc163a2b0635dc..0d86275a8bfb46fdd0e3dfae91ea459d17012344 100644 --- a/examples/jsonrpc/go-client/app/client.go +++ b/examples/general/jsonrpc/go-client/app/client.go @@ -51,6 +51,45 @@ func main() { config.Load() + println("\n\ntest") + test() + println("\n\ntest1") + test1() + println("\n\ntest2") + test2() + + initSignal() +} + +func initSignal() { + signals := make(chan os.Signal, 1) + // It is not possible to block SIGKILL or syscall.SIGSTOP + signal.Notify(signals, os.Interrupt, os.Kill, syscall.SIGHUP, + syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) + for { + sig := <-signals + logger.Infof("get signal %s", sig.String()) + switch sig { + case syscall.SIGHUP: + // reload() + default: + go time.AfterFunc(time.Duration(survivalTimeout), func() { + logger.Warnf("app exit now by force...") + os.Exit(1) + }) + + // The program exits normally or timeout forcibly exits. + fmt.Println("app exit now...") + return + } + } +} + +func println(format string, args ...interface{}) { + fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...) +} + +func test() { println("\n\n\necho") res, err := userProvider.Echo(context.TODO(), "OK") if err != nil { @@ -100,37 +139,120 @@ func main() { println("\n\n\nstart to test jsonrpc illegal method") err = userProvider.GetUser1(context.TODO(), []interface{}{"A003"}, user) + if err == nil { + panic("err is nil") + } + println("error: %v", err) +} + +func test1() { + println("\n\n\necho") + res, err := userProvider1.Echo(context.TODO(), "OK") + if err != nil { + println("echo - error: %v", err) + } else { + println("res: %v", res) + } + + time.Sleep(3e9) + + println("\n\n\nstart to test jsonrpc") + user := &JsonRPCUser{} + err = userProvider1.GetUser(context.TODO(), []interface{}{"A003"}, user) if err != nil { panic(err) } + println("response result: %v", user) - initSignal() -} + println("\n\n\nstart to test jsonrpc - GetUser0") + ret, err := userProvider1.GetUser0("A003", "Moorse") + if err != nil { + panic(err) + } + println("response result: %v", ret) -func initSignal() { - signals := make(chan os.Signal, 1) - // It is not possible to block SIGKILL or syscall.SIGSTOP - signal.Notify(signals, os.Interrupt, os.Kill, syscall.SIGHUP, - syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) - for { - sig := <-signals - logger.Infof("get signal %s", sig.String()) - switch sig { - case syscall.SIGHUP: - // reload() - default: - go time.AfterFunc(time.Duration(survivalTimeout)*time.Second, func() { - logger.Warnf("app exit now by force...") - os.Exit(1) - }) + println("\n\n\nstart to test jsonrpc - GetUsers") + ret1, err := userProvider1.GetUsers([]interface{}{[]interface{}{"A002", "A003"}}) + if err != nil { + panic(err) + } + println("response result: %v", ret1) - // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出 - fmt.Println("app exit now...") - return - } + println("\n\n\nstart to test jsonrpc - getUser") + user = &JsonRPCUser{} + err = userProvider1.GetUser2(context.TODO(), []interface{}{1}, user) + if err != nil { + panic(err) } + println("response result: %v", user) + + println("\n\n\nstart to test jsonrpc - GetUser3") + err = userProvider1.GetUser3() + if err != nil { + panic(err) + } + println("succ!") + + println("\n\n\nstart to test jsonrpc illegal method") + err = userProvider1.GetUser1(context.TODO(), []interface{}{"A003"}, user) + if err == nil { + panic("err is nil") + } + println("error: %v", err) } -func println(format string, args ...interface{}) { - fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...) +func test2() { + println("\n\n\necho") + res, err := userProvider2.Echo(context.TODO(), "OK") + if err != nil { + println("echo - error: %v", err) + } else { + println("res: %v", res) + } + + time.Sleep(3e9) + + println("\n\n\nstart to test jsonrpc") + user := &JsonRPCUser{} + err = userProvider2.GetUser(context.TODO(), []interface{}{"A003"}, user) + if err != nil { + panic(err) + } + println("response result: %v", user) + + println("\n\n\nstart to test jsonrpc - GetUser0") + ret, err := userProvider2.GetUser0("A003", "Moorse") + if err != nil { + panic(err) + } + println("response result: %v", ret) + + println("\n\n\nstart to test jsonrpc - GetUsers") + ret1, err := userProvider2.GetUsers([]interface{}{[]interface{}{"A002", "A003"}}) + if err != nil { + panic(err) + } + println("response result: %v", ret1) + + println("\n\n\nstart to test jsonrpc - getUser") + user = &JsonRPCUser{} + err = userProvider2.GetUser2(context.TODO(), []interface{}{1}, user) + if err != nil { + panic(err) + } + println("response result: %v", user) + + println("\n\n\nstart to test jsonrpc - GetUser3") + err = userProvider2.GetUser3() + if err != nil { + panic(err) + } + println("succ!") + + println("\n\n\nstart to test jsonrpc illegal method") + err = userProvider2.GetUser1(context.TODO(), []interface{}{"A003"}, user) + if err == nil { + panic("err is nil") + } + println("error: %v", err) } diff --git a/examples/jsonrpc/go-client/app/user.go b/examples/general/jsonrpc/go-client/app/user.go similarity index 55% rename from examples/jsonrpc/go-client/app/user.go rename to examples/general/jsonrpc/go-client/app/user.go index ca98b1af0b3c1379c73623162546db9fb4fc95d6..c6fdbe13a8533c1bfb5ac4d442ef0c3ec968c298 100644 --- a/examples/jsonrpc/go-client/app/user.go +++ b/examples/general/jsonrpc/go-client/app/user.go @@ -27,10 +27,16 @@ import ( "github.com/apache/dubbo-go/config" ) -var userProvider = new(UserProvider) +var ( + userProvider = new(UserProvider) + userProvider1 = new(UserProvider1) + userProvider2 = new(UserProvider2) +) func init() { config.SetConsumerService(userProvider) + config.SetConsumerService(userProvider1) + config.SetConsumerService(userProvider2) } type JsonRPCUser struct { @@ -58,10 +64,34 @@ type UserProvider struct { Echo func(ctx context.Context, req interface{}) (interface{}, error) // Echo represent EchoFilter will be used } -func (u *UserProvider) Service() string { - return "com.ikurento.user.UserProvider" +func (u *UserProvider) Reference() string { + return "UserProvider" +} + +type UserProvider1 struct { + GetUsers func(req []interface{}) ([]JsonRPCUser, error) + GetUser func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error + GetUser0 func(id string, name string) (JsonRPCUser, error) + GetUser1 func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error + GetUser2 func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error `dubbo:"getUser"` + GetUser3 func() error + Echo func(ctx context.Context, req interface{}) (interface{}, error) // Echo represent EchoFilter will be used +} + +func (u *UserProvider1) Reference() string { + return "UserProvider1" +} + +type UserProvider2 struct { + GetUsers func(req []interface{}) ([]JsonRPCUser, error) + GetUser func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error + GetUser0 func(id string, name string) (JsonRPCUser, error) + GetUser1 func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error + GetUser2 func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error `dubbo:"getUser"` + GetUser3 func() error + Echo func(ctx context.Context, req interface{}) (interface{}, error) // Echo represent EchoFilter will be used } -func (u *UserProvider) Version() string { - return "" +func (u *UserProvider2) Reference() string { + return "UserProvider2" } diff --git a/examples/jsonrpc/with-configcenter-go-client/app/version.go b/examples/general/jsonrpc/go-client/app/version.go similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/app/version.go rename to examples/general/jsonrpc/go-client/app/version.go diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/bin/load.sh b/examples/general/jsonrpc/go-client/assembly/bin/load.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/bin/load.sh rename to examples/general/jsonrpc/go-client/assembly/bin/load.sh diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/common/app.properties b/examples/general/jsonrpc/go-client/assembly/common/app.properties similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/common/app.properties rename to examples/general/jsonrpc/go-client/assembly/common/app.properties diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/common/build.sh b/examples/general/jsonrpc/go-client/assembly/common/build.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/common/build.sh rename to examples/general/jsonrpc/go-client/assembly/common/build.sh diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/linux/dev.sh b/examples/general/jsonrpc/go-client/assembly/linux/dev.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/linux/dev.sh rename to examples/general/jsonrpc/go-client/assembly/linux/dev.sh diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/linux/release.sh b/examples/general/jsonrpc/go-client/assembly/linux/release.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/linux/release.sh rename to examples/general/jsonrpc/go-client/assembly/linux/release.sh diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/linux/test.sh b/examples/general/jsonrpc/go-client/assembly/linux/test.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/linux/test.sh rename to examples/general/jsonrpc/go-client/assembly/linux/test.sh diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/mac/dev.sh b/examples/general/jsonrpc/go-client/assembly/mac/dev.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/mac/dev.sh rename to examples/general/jsonrpc/go-client/assembly/mac/dev.sh diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/mac/release.sh b/examples/general/jsonrpc/go-client/assembly/mac/release.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/mac/release.sh rename to examples/general/jsonrpc/go-client/assembly/mac/release.sh diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/mac/test.sh b/examples/general/jsonrpc/go-client/assembly/mac/test.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/mac/test.sh rename to examples/general/jsonrpc/go-client/assembly/mac/test.sh diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/windows/dev.sh b/examples/general/jsonrpc/go-client/assembly/windows/dev.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/windows/dev.sh rename to examples/general/jsonrpc/go-client/assembly/windows/dev.sh diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/windows/release.sh b/examples/general/jsonrpc/go-client/assembly/windows/release.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/windows/release.sh rename to examples/general/jsonrpc/go-client/assembly/windows/release.sh diff --git a/examples/jsonrpc/with-configcenter-go-client/assembly/windows/test.sh b/examples/general/jsonrpc/go-client/assembly/windows/test.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/assembly/windows/test.sh rename to examples/general/jsonrpc/go-client/assembly/windows/test.sh diff --git a/examples/general/jsonrpc/go-client/profiles/dev/client.yml b/examples/general/jsonrpc/go-client/profiles/dev/client.yml new file mode 100644 index 0000000000000000000000000000000000000000..788e06eecd6014eefaf12913b6394e5e0a95efdf --- /dev/null +++ b/examples/general/jsonrpc/go-client/profiles/dev/client.yml @@ -0,0 +1,60 @@ +# dubbo client yaml configure file + +check: true +# client +request_timeout : "3s" +# connect timeout +connect_timeout : "3s" + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info client" + version : "0.0.1" + owner : "ZX" + environment : "dev" + +registries : + "hangzhouzk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + +references: + "UserProvider": + # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 + registry: "hangzhouzk" + protocol : "jsonrpc" + interface : "com.ikurento.user.UserProvider" + cluster: "failover" + methods : + - name: "GetUser" + retries: 3 + "UserProvider1": + registry: "hangzhouzk" + protocol: "jsonrpc" + version : "2.0" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 + "UserProvider2": + registry: "hangzhouzk" + protocol: "jsonrpc" + version : "2.0" + group: "as" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 diff --git a/examples/jsonrpc/with-configcenter-go-client/profiles/dev/log.yml b/examples/general/jsonrpc/go-client/profiles/dev/log.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/profiles/dev/log.yml rename to examples/general/jsonrpc/go-client/profiles/dev/log.yml diff --git a/examples/jsonrpc/go-client/profiles/release/client.yml b/examples/general/jsonrpc/go-client/profiles/release/client.yml similarity index 59% rename from examples/jsonrpc/go-client/profiles/release/client.yml rename to examples/general/jsonrpc/go-client/profiles/release/client.yml index 3b82dd07bd0b41ace267721d151238c71beaa5a4..0084e5b04d48fea480f22df8e031eb91e1d6e835 100644 --- a/examples/jsonrpc/go-client/profiles/release/client.yml +++ b/examples/general/jsonrpc/go-client/profiles/release/client.yml @@ -34,34 +34,27 @@ references: # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 registry: "hangzhouzk" protocol : "jsonrpc" -# version : "2.0" -# group: "as" interface : "com.ikurento.user.UserProvider" cluster: "failover" methods : - name: "GetUser" retries: 3 - -protocol_conf: - dubbo: - reconnect_interval: 0 - connection_number: 2 - heartbeat_period: "5s" - session_timeout: "20s" - fail_fast_timeout: "5s" - pool_size: 64 - pool_ttl: 600 - getty_session_param: - compress_encoding: false - tcp_no_delay: true - tcp_keep_alive: true - keep_alive_period: "120s" - tcp_r_buf_size: 262144 - tcp_w_buf_size: 65536 - pkg_rq_size: 1024 - pkg_wq_size: 512 - tcp_read_timeout: "1s" - tcp_write_timeout: "5s" - wait_timeout: "1s" - max_msg_len: 10240 - session_name: "client" + "UserProvider1": + registry: "hangzhouzk" + protocol: "jsonrpc" + version : "2.0" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 + "UserProvider2": + registry: "hangzhouzk" + protocol: "jsonrpc" + version : "2.0" + group: "as" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 diff --git a/examples/jsonrpc/with-configcenter-go-client/profiles/release/log.yml b/examples/general/jsonrpc/go-client/profiles/release/log.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/profiles/release/log.yml rename to examples/general/jsonrpc/go-client/profiles/release/log.yml diff --git a/examples/general/jsonrpc/go-client/profiles/test/client.yml b/examples/general/jsonrpc/go-client/profiles/test/client.yml new file mode 100644 index 0000000000000000000000000000000000000000..3efdedad4ab8acffb9d8724273deb8c12117837d --- /dev/null +++ b/examples/general/jsonrpc/go-client/profiles/test/client.yml @@ -0,0 +1,60 @@ +# dubbo client yaml configure file + +check: true +# client +request_timeout : "3s" +# connect timeout +connect_timeout : "3s" + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info client" + version : "0.0.1" + owner : "ZX" + environment : "test" + +registries : + "hangzhouzk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + +references: + "UserProvider": + # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 + registry: "hangzhouzk" + protocol : "jsonrpc" + interface : "com.ikurento.user.UserProvider" + cluster: "failover" + methods : + - name: "GetUser" + retries: 3 + "UserProvider1": + registry: "hangzhouzk" + protocol: "jsonrpc" + version : "2.0" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 + "UserProvider2": + registry: "hangzhouzk" + protocol: "jsonrpc" + version : "2.0" + group: "as" + interface: "com.ikurento.user.UserProvider" + cluster: "failover" + methods: + - name: "GetUser" + retries: 3 diff --git a/examples/jsonrpc/with-configcenter-go-client/profiles/test/log.yml b/examples/general/jsonrpc/go-client/profiles/test/log.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-client/profiles/test/log.yml rename to examples/general/jsonrpc/go-client/profiles/test/log.yml diff --git a/examples/jsonrpc/go-server/app/server.go b/examples/general/jsonrpc/go-server/app/server.go similarity index 89% rename from examples/jsonrpc/go-server/app/server.go rename to examples/general/jsonrpc/go-server/app/server.go index 8a226e23ad74960612ef1cfe2f82740a6e7516d8..e36b6efe9d115d8352f09f1f5011ea00d92f0d13 100644 --- a/examples/jsonrpc/go-server/app/server.go +++ b/examples/general/jsonrpc/go-server/app/server.go @@ -64,12 +64,12 @@ func initSignal() { case syscall.SIGHUP: // reload() default: - go time.AfterFunc(time.Duration(float64(survivalTimeout)*float64(time.Second)), func() { + go time.AfterFunc(time.Duration(survivalTimeout), func() { logger.Warnf("app exit now by force...") os.Exit(1) }) - // 要么fastFailTimeout时间内执行完毕下面的逻辑然后程序退出,要么执行上面的超时函数程序强行退出 + // The program exits normally or timeout forcibly exits. fmt.Println("provider app exit now...") return } diff --git a/examples/general/jsonrpc/go-server/app/user.go b/examples/general/jsonrpc/go-server/app/user.go new file mode 100644 index 0000000000000000000000000000000000000000..837661003e75f1d8c2d5442c756f45cb32f5d590 --- /dev/null +++ b/examples/general/jsonrpc/go-server/app/user.go @@ -0,0 +1,78 @@ +/* + * 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 main + +import ( + "fmt" + "time" +) + +type Gender int + +const ( + MAN = iota + WOMAN +) + +var genderStrings = [...]string{ + "MAN", + "WOMAN", +} + +func (g Gender) String() string { + return genderStrings[g] +} + +type ( + User struct { + Id string `json:"id"` + Name string `json:"name"` + Age int `json:"age"` + sex Gender + Birth int `json:"time"` + Sex string `json:"sex"` + } +) + +var ( + DefaultUser = User{ + Id: "0", Name: "Alex Stocks", Age: 31, + // Birth: int(time.Date(1985, time.November, 10, 23, 0, 0, 0, time.UTC).Unix()), + Birth: int(time.Date(1985, 11, 24, 15, 15, 0, 0, time.Local).Unix()), + sex: Gender(MAN), + } + + userMap = make(map[string]User) +) + +func init() { + DefaultUser.Sex = DefaultUser.sex.String() + userMap["A000"] = DefaultUser + userMap["A001"] = User{Id: "001", Name: "ZhangSheng", Age: 18, sex: MAN} + userMap["A002"] = User{Id: "002", Name: "Lily", Age: 20, sex: WOMAN} + userMap["A003"] = User{Id: "113", Name: "Moorse", Age: 30, sex: MAN} + for k, v := range userMap { + v.Birth = int(time.Now().AddDate(-1*v.Age, 0, 0).Unix()) + v.Sex = userMap[k].sex.String() + userMap[k] = v + } +} + +func println(format string, args ...interface{}) { + fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...) +} diff --git a/examples/general/jsonrpc/go-server/app/user_provider.go b/examples/general/jsonrpc/go-server/app/user_provider.go new file mode 100644 index 0000000000000000000000000000000000000000..4af4bb040484eb8613c50545e93312aa232f7de2 --- /dev/null +++ b/examples/general/jsonrpc/go-server/app/user_provider.go @@ -0,0 +1,98 @@ +package main + +import ( + "context" + "fmt" + "strconv" +) + +import ( + "github.com/apache/dubbo-go/config" + perrors "github.com/pkg/errors" +) + +func init() { + config.SetProviderService(new(UserProvider)) +} + +type UserProvider struct { +} + +func (u *UserProvider) getUser(userId string) (*User, error) { + if user, ok := userMap[userId]; ok { + return &user, nil + } + + return nil, fmt.Errorf("invalid user id:%s", userId) +} + +func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User) error { + var ( + err error + user *User + ) + + println("req:%#v", req) + user, err = u.getUser(req[0].(string)) + if err == nil { + *rsp = *user + println("rsp:%#v", rsp) + } + return err +} + +func (u *UserProvider) GetUser0(id string, name string) (User, error) { + var err error + + println("id:%s, name:%s", id, name) + user, err := u.getUser(id) + if err != nil { + return User{}, err + } + if user.Name != name { + return User{}, perrors.New("name is not " + user.Name) + } + return *user, err +} + +func (u *UserProvider) GetUser2(ctx context.Context, req []interface{}, rsp *User) error { + var err error + + println("req:%#v", req) + rsp.Id = strconv.FormatFloat(req[0].(float64), 'f', 0, 64) + rsp.Sex = Gender(MAN).String() + return err +} + +func (u *UserProvider) GetUser3() error { + return nil +} + +func (u *UserProvider) GetUsers(req []interface{}) ([]User, error) { + var err error + + println("req:%s", req) + t := req[0].([]interface{}) + user, err := u.getUser(t[0].(string)) + if err != nil { + return nil, err + } + println("user:%v", user) + user1, err := u.getUser(t[1].(string)) + if err != nil { + return nil, err + } + println("user1:%v", user1) + + return []User{*user, *user1}, err +} + +func (s *UserProvider) MethodMapper() map[string]string { + return map[string]string{ + "GetUser2": "getUser", + } +} + +func (u *UserProvider) Reference() string { + return "UserProvider" +} diff --git a/examples/general/jsonrpc/go-server/app/user_provider1.go b/examples/general/jsonrpc/go-server/app/user_provider1.go new file mode 100644 index 0000000000000000000000000000000000000000..1557c6b8d22c3e6969e8b48b87008576eb71a984 --- /dev/null +++ b/examples/general/jsonrpc/go-server/app/user_provider1.go @@ -0,0 +1,83 @@ +package main + +import ( + "context" + "fmt" + "strconv" +) + +import ( + "github.com/apache/dubbo-go/config" + perrors "github.com/pkg/errors" +) + +func init() { + config.SetProviderService(new(UserProvider1)) +} + +type UserProvider1 struct { +} + +func (u *UserProvider1) getUser(userId string) (*User, error) { + if user, ok := userMap[userId]; ok { + return &user, nil + } + + return nil, fmt.Errorf("invalid user id:%s", userId) +} + +func (u *UserProvider1) GetUser(ctx context.Context, req []interface{}, rsp *User) error { + var ( + err error + user *User + ) + + println("req:%#v", req) + user, err = u.getUser(req[0].(string)) + if err == nil { + *rsp = *user + println("rsp:%#v", rsp) + } + return err +} + +func (u *UserProvider1) GetUser0(id string, name string) (User, error) { + var err error + + println("id:%s, name:%s", id, name) + user, err := u.getUser(id) + if err != nil { + return User{}, err + } + if user.Name != name { + return User{}, perrors.New("name is not " + user.Name) + } + return *user, err +} + +func (u *UserProvider1) GetUser2(ctx context.Context, req []interface{}, rsp *User) error { + var err error + + println("req:%#v", req) + rsp.Id = strconv.FormatFloat(req[0].(float64), 'f', 0, 64) + rsp.Sex = Gender(MAN).String() + return err +} + +func (u *UserProvider1) GetUser3() error { + return nil +} + +func (u *UserProvider1) GetUsers(req []interface{}) ([]User, error) { + return []User{}, nil +} + +func (s *UserProvider1) MethodMapper() map[string]string { + return map[string]string{ + "GetUser2": "getUser", + } +} + +func (u *UserProvider1) Reference() string { + return "UserProvider1" +} diff --git a/examples/general/jsonrpc/go-server/app/user_provider2.go b/examples/general/jsonrpc/go-server/app/user_provider2.go new file mode 100644 index 0000000000000000000000000000000000000000..7d2fb80a99763235610628865b4704a3999c489b --- /dev/null +++ b/examples/general/jsonrpc/go-server/app/user_provider2.go @@ -0,0 +1,93 @@ +package main + +import ( + "context" + "fmt" + "strconv" +) + +import ( + "github.com/apache/dubbo-go/config" + perrors "github.com/pkg/errors" +) + +func init() { + config.SetProviderService(new(UserProvider2)) +} + +type UserProvider2 struct { +} + +func (u *UserProvider2) getUser(userId string) (*User, error) { + if user, ok := userMap[userId]; ok { + return &user, nil + } + + return nil, fmt.Errorf("invalid user id:%s", userId) +} + +func (u *UserProvider2) GetUser(ctx context.Context, req []interface{}, rsp *User) error { + var ( + err error + user *User + ) + + println("req:%#v", req) + user, err = u.getUser(req[0].(string)) + if err == nil { + *rsp = *user + println("rsp:%#v", rsp) + } + return err +} + +func (u *UserProvider2) GetUser0(id string, name string) (User, error) { + var err error + + println("id:%s, name:%s", id, name) + user, err := u.getUser(id) + if err != nil { + return User{}, err + } + if user.Name != name { + return User{}, perrors.New("name is not " + user.Name) + } + return *user, err +} + +func (u *UserProvider2) GetUser2(ctx context.Context, req []interface{}, rsp *User) error { + var err error + + println("req:%#v", req) + rsp.Id = strconv.FormatFloat(req[0].(float64), 'f', 0, 64) + rsp.Sex = Gender(MAN).String() + return err +} + +func (u *UserProvider2) GetUser3() error { + return nil +} + +func (u *UserProvider2) GetUsers(req []interface{}) ([]User, error) { + var err error + + println("req:%s", req) + t := req[0].([]interface{}) + user, err := u.getUser(t[0].(string)) + if err != nil { + return nil, err + } + println("user:%v", user) + + return []User{*user}, err +} + +func (s *UserProvider2) MethodMapper() map[string]string { + return map[string]string{ + "GetUser2": "getUser", + } +} + +func (u *UserProvider2) Reference() string { + return "UserProvider2" +} diff --git a/examples/jsonrpc/with-configcenter-go-server/app/version.go b/examples/general/jsonrpc/go-server/app/version.go similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/app/version.go rename to examples/general/jsonrpc/go-server/app/version.go diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/bin/load.sh b/examples/general/jsonrpc/go-server/assembly/bin/load.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/bin/load.sh rename to examples/general/jsonrpc/go-server/assembly/bin/load.sh diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/common/app.properties b/examples/general/jsonrpc/go-server/assembly/common/app.properties similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/common/app.properties rename to examples/general/jsonrpc/go-server/assembly/common/app.properties diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/common/build.sh b/examples/general/jsonrpc/go-server/assembly/common/build.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/common/build.sh rename to examples/general/jsonrpc/go-server/assembly/common/build.sh diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/linux/dev.sh b/examples/general/jsonrpc/go-server/assembly/linux/dev.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/linux/dev.sh rename to examples/general/jsonrpc/go-server/assembly/linux/dev.sh diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/linux/release.sh b/examples/general/jsonrpc/go-server/assembly/linux/release.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/linux/release.sh rename to examples/general/jsonrpc/go-server/assembly/linux/release.sh diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/linux/test.sh b/examples/general/jsonrpc/go-server/assembly/linux/test.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/linux/test.sh rename to examples/general/jsonrpc/go-server/assembly/linux/test.sh diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/mac/dev.sh b/examples/general/jsonrpc/go-server/assembly/mac/dev.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/mac/dev.sh rename to examples/general/jsonrpc/go-server/assembly/mac/dev.sh diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/mac/release.sh b/examples/general/jsonrpc/go-server/assembly/mac/release.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/mac/release.sh rename to examples/general/jsonrpc/go-server/assembly/mac/release.sh diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/mac/test.sh b/examples/general/jsonrpc/go-server/assembly/mac/test.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/mac/test.sh rename to examples/general/jsonrpc/go-server/assembly/mac/test.sh diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/windows/dev.sh b/examples/general/jsonrpc/go-server/assembly/windows/dev.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/windows/dev.sh rename to examples/general/jsonrpc/go-server/assembly/windows/dev.sh diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/windows/release.sh b/examples/general/jsonrpc/go-server/assembly/windows/release.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/windows/release.sh rename to examples/general/jsonrpc/go-server/assembly/windows/release.sh diff --git a/examples/jsonrpc/with-configcenter-go-server/assembly/windows/test.sh b/examples/general/jsonrpc/go-server/assembly/windows/test.sh similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/assembly/windows/test.sh rename to examples/general/jsonrpc/go-server/assembly/windows/test.sh diff --git a/examples/jsonrpc/with-configcenter-go-server/profiles/dev/log.yml b/examples/general/jsonrpc/go-server/profiles/dev/log.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/profiles/dev/log.yml rename to examples/general/jsonrpc/go-server/profiles/dev/log.yml diff --git a/examples/general/jsonrpc/go-server/profiles/dev/server.yml b/examples/general/jsonrpc/go-server/profiles/dev/server.yml new file mode 100644 index 0000000000000000000000000000000000000000..4d74d2ef6fed9b0206729717d7b7081a3eadec96 --- /dev/null +++ b/examples/general/jsonrpc/go-server/profiles/dev/server.yml @@ -0,0 +1,75 @@ +# dubbo server yaml configure file + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info server" + version : "0.0.1" + owner : "ZX" + environment : "dev" + +registries : + "hangzhouzk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + + +services: + "UserProvider": + # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 + registry: "hangzhouzk" + protocol : "jsonrpc" + # 相当于dubbo.xml中的interface + interface : "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + "UserProvider1": + registry: "hangzhouzk" + protocol: "jsonrpc" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + version: "2.0" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + "UserProvider2": + registry: "hangzhouzk" + protocol: "jsonrpc" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + version: "2.0" + group: "as" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + +protocols: + #- name: "dubbo" + # ip : "127.0.0.1" + # port : 20000 + "jsonrpc1": + name: "jsonrpc" + ip: "127.0.0.1" + port: 20001 + diff --git a/examples/jsonrpc/with-configcenter-go-server/profiles/release/log.yml b/examples/general/jsonrpc/go-server/profiles/release/log.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/profiles/release/log.yml rename to examples/general/jsonrpc/go-server/profiles/release/log.yml diff --git a/examples/general/jsonrpc/go-server/profiles/release/server.yml b/examples/general/jsonrpc/go-server/profiles/release/server.yml new file mode 100644 index 0000000000000000000000000000000000000000..3f7d2fdfff208801a6b89e7a90350e57133f31c3 --- /dev/null +++ b/examples/general/jsonrpc/go-server/profiles/release/server.yml @@ -0,0 +1,75 @@ +# dubbo server yaml configure file + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info server" + version : "0.0.1" + owner : "ZX" + environment : "release" + +registries : + "hangzhouzk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + + +services: + "UserProvider": + # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 + registry: "hangzhouzk" + protocol : "jsonrpc" + # 相当于dubbo.xml中的interface + interface : "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + "UserProvider1": + registry: "hangzhouzk" + protocol: "jsonrpc" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + version: "2.0" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + "UserProvider2": + registry: "hangzhouzk" + protocol: "jsonrpc" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + version: "2.0" + group: "as" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + +protocols: + #- name: "dubbo" + # ip : "127.0.0.1" + # port : 20000 + "jsonrpc1": + name: "jsonrpc" + ip: "127.0.0.1" + port: 20001 + diff --git a/examples/jsonrpc/with-configcenter-go-server/profiles/test/log.yml b/examples/general/jsonrpc/go-server/profiles/test/log.yml similarity index 100% rename from examples/jsonrpc/with-configcenter-go-server/profiles/test/log.yml rename to examples/general/jsonrpc/go-server/profiles/test/log.yml diff --git a/examples/general/jsonrpc/go-server/profiles/test/server.yml b/examples/general/jsonrpc/go-server/profiles/test/server.yml new file mode 100644 index 0000000000000000000000000000000000000000..dd0637e7970281236b92e37888c554d83d87de96 --- /dev/null +++ b/examples/general/jsonrpc/go-server/profiles/test/server.yml @@ -0,0 +1,75 @@ +# dubbo server yaml configure file + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info server" + version : "0.0.1" + owner : "ZX" + environment : "test" + +registries : + "hangzhouzk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + + +services: + "UserProvider": + # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 + registry: "hangzhouzk" + protocol : "jsonrpc" + # 相当于dubbo.xml中的interface + interface : "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + "UserProvider1": + registry: "hangzhouzk" + protocol: "jsonrpc" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + version: "2.0" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + "UserProvider2": + registry: "hangzhouzk" + protocol: "jsonrpc" + interface: "com.ikurento.user.UserProvider" + loadbalance: "random" + version: "2.0" + group: "as" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + +protocols: + #- name: "dubbo" + # ip : "127.0.0.1" + # port : 20000 + "jsonrpc1": + name: "jsonrpc" + ip: "127.0.0.1" + port: 20001 + diff --git a/examples/jsonrpc/java-client/build.sh b/examples/general/jsonrpc/java-client/build.sh similarity index 100% rename from examples/jsonrpc/java-client/build.sh rename to examples/general/jsonrpc/java-client/build.sh diff --git a/examples/jsonrpc/java-client/pom.xml b/examples/general/jsonrpc/java-client/pom.xml similarity index 100% rename from examples/jsonrpc/java-client/pom.xml rename to examples/general/jsonrpc/java-client/pom.xml diff --git a/examples/jsonrpc/java-client/src/main/assembly/assembly.xml b/examples/general/jsonrpc/java-client/src/main/assembly/assembly.xml similarity index 100% rename from examples/jsonrpc/java-client/src/main/assembly/assembly.xml rename to examples/general/jsonrpc/java-client/src/main/assembly/assembly.xml diff --git a/examples/jsonrpc/java-client/src/main/assembly/conf/dubbo.properties b/examples/general/jsonrpc/java-client/src/main/assembly/conf/dubbo.properties similarity index 100% rename from examples/jsonrpc/java-client/src/main/assembly/conf/dubbo.properties rename to examples/general/jsonrpc/java-client/src/main/assembly/conf/dubbo.properties diff --git a/examples/jsonrpc/java-client/src/main/assembly/conf/log4j.properties b/examples/general/jsonrpc/java-client/src/main/assembly/conf/log4j.properties similarity index 100% rename from examples/jsonrpc/java-client/src/main/assembly/conf/log4j.properties rename to examples/general/jsonrpc/java-client/src/main/assembly/conf/log4j.properties diff --git a/examples/general/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java b/examples/general/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java new file mode 100644 index 0000000000000000000000000000000000000000..1a38dbfba906a951fcf8bd481650608bd5d35c9f --- /dev/null +++ b/examples/general/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java @@ -0,0 +1,196 @@ +// ***************************************************** +// DESC : dubbo consumer +// AUTHOR : writtey by 包增辉(https://github.com/baozh) +// VERSION : 1.0 +// LICENCE : Apache License 2.0 +// EMAIL : alexstocks@foxmail.com +// MOD : 2016-10-19 17:03 +// FILE : Consumer.java +// ****************************************************** + +package com.ikurento.user; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import com.alibaba.dubbo.rpc.service.EchoService; +import java.util.List; + +public class Consumer { + // Define a private variable (Required in Spring) + private UserProvider userProvider; + private UserProvider userProvider1; + private UserProvider userProvider2; + + // Spring DI (Required in Spring) + public void setUserProvider(UserProvider u) { + this.userProvider = u; + } + public void setUserProvider1(UserProvider u) { + this.userProvider1 = u; + } + public void setUserProvider2(UserProvider u) { + this.userProvider2 = u; + } + + // Start the entry function for consumer (Specified in the configuration file) + public void start() throws Exception { + System.out.println("\n\ntest"); + testGetUser(); + testGetUsers(); + System.out.println("\n\ntest1"); + testGetUser1(); + testGetUsers1(); + System.out.println("\n\ntest2"); + testGetUser2(); + testGetUsers2(); + Thread.sleep(2000); + } + + private void testGetUser() throws Exception { + try { + EchoService echoService = (EchoService)userProvider; + Object status = echoService.$echo("OK"); + System.out.println("echo: "+status); + } catch (Exception e) { + e.printStackTrace(); + } + try { + User user1 = userProvider.GetUser("A003"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString() + + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString()); + User user2 = userProvider.GetUser0("A003","Moorse"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString() + + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString()); + User user3 = userProvider.getUser(1); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user3.getId() + ", name:" + user3.getName() + ", sex:" + user3.getSex().toString() + + ", age:" + user3.getAge() + ", time:" + user3.getTime().toString()); + + userProvider.GetUser3(); + System.out.println("GetUser3 succ"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void testGetUsers() throws Exception { + try { + List<String> userIDList = new ArrayList<String>(); + userIDList.add("A001"); + userIDList.add("A002"); + userIDList.add("A003"); + + List<User> userList = userProvider.GetUsers(userIDList); + + for (int i = 0; i < userList.size(); i++) { + User user = userList.get(i); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user.getId() + ", name:" + user.getName() + ", sex:" + user.getSex().toString() + + ", age:" + user.getAge() + ", time:" + user.getTime().toString()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void testGetUser1() throws Exception { + try { + EchoService echoService = (EchoService)userProvider1; + Object status = echoService.$echo("OK"); + System.out.println("echo: "+status); + } catch (Exception e) { + e.printStackTrace(); + } + try { + User user1 = userProvider1.GetUser("A003"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString() + + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString()); + User user2 = userProvider1.GetUser0("A003","Moorse"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString() + + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString()); + User user3 = userProvider1.getUser(1); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user3.getId() + ", name:" + user3.getName() + ", sex:" + user3.getSex().toString() + + ", age:" + user3.getAge() + ", time:" + user3.getTime().toString()); + + userProvider1.GetUser3(); + System.out.println("GetUser3 succ"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void testGetUsers1() throws Exception { + try { + List<String> userIDList = new ArrayList<String>(); + userIDList.add("A001"); + userIDList.add("A002"); + userIDList.add("A003"); + + List<User> userList = userProvider1.GetUsers(userIDList); + + for (int i = 0; i < userList.size(); i++) { + User user = userList.get(i); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user.getId() + ", name:" + user.getName() + ", sex:" + user.getSex().toString() + + ", age:" + user.getAge() + ", time:" + user.getTime().toString()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void testGetUser2() throws Exception { + try { + EchoService echoService = (EchoService)userProvider2; + Object status = echoService.$echo("OK"); + System.out.println("echo: "+status); + } catch (Exception e) { + e.printStackTrace(); + } + try { + User user1 = userProvider2.GetUser("A003"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString() + + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString()); + User user2 = userProvider2.GetUser0("A003","Moorse"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString() + + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString()); + User user3 = userProvider2.getUser(1); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user3.getId() + ", name:" + user3.getName() + ", sex:" + user3.getSex().toString() + + ", age:" + user3.getAge() + ", time:" + user3.getTime().toString()); + + userProvider2.GetUser3(); + System.out.println("GetUser3 succ"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void testGetUsers2() throws Exception { + try { + List<String> userIDList = new ArrayList<String>(); + userIDList.add("A001"); + userIDList.add("A002"); + userIDList.add("A003"); + + List<User> userList = userProvider2.GetUsers(userIDList); + + for (int i = 0; i < userList.size(); i++) { + User user = userList.get(i); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user.getId() + ", name:" + user.getName() + ", sex:" + user.getSex().toString() + + ", age:" + user.getAge() + ", time:" + user.getTime().toString()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Gender.java b/examples/general/jsonrpc/java-client/src/main/java/com/ikurento/user/Gender.java similarity index 100% rename from examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Gender.java rename to examples/general/jsonrpc/java-client/src/main/java/com/ikurento/user/Gender.java diff --git a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/User.java b/examples/general/jsonrpc/java-client/src/main/java/com/ikurento/user/User.java similarity index 100% rename from examples/jsonrpc/java-client/src/main/java/com/ikurento/user/User.java rename to examples/general/jsonrpc/java-client/src/main/java/com/ikurento/user/User.java diff --git a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java b/examples/general/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java similarity index 100% rename from examples/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java rename to examples/general/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java diff --git a/examples/jsonrpc/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml b/examples/general/jsonrpc/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml similarity index 87% rename from examples/jsonrpc/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml rename to examples/general/jsonrpc/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml index c01f4ab064a83aa62adc7de676cdaede7108bd23..da21e8a359c003983ebea3269d4f2dfd255e3b29 100644 --- a/examples/jsonrpc/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml +++ b/examples/general/jsonrpc/java-client/src/main/resources/META-INF/spring/dubbo.consumer.xml @@ -37,5 +37,9 @@ <!-- dubbo:reference id="userProvider" protocol="dubbo" interface="com.ikurento.user.UserProvider"> <dubbo:parameter key="heartbeat" value="10000"/ --> </dubbo:reference> + <dubbo:reference id="userProvider1" protocol="jsonrpc" version="2.0" interface="com.ikurento.user.UserProvider"> + </dubbo:reference> + <dubbo:reference id="userProvider2" protocol="jsonrpc" version="2.0" group="as" interface="com.ikurento.user.UserProvider"> + </dubbo:reference> </beans> diff --git a/examples/dubbo/java-client/src/main/resources/META-INF/spring/service.xml b/examples/general/jsonrpc/java-client/src/main/resources/META-INF/spring/service.xml similarity index 90% rename from examples/dubbo/java-client/src/main/resources/META-INF/spring/service.xml rename to examples/general/jsonrpc/java-client/src/main/resources/META-INF/spring/service.xml index 625a879f97f5a21498be1efc1aa97fce68e76c61..db9fc3cba5a359b8835af53b81e50f8296d2e489 100644 --- a/examples/dubbo/java-client/src/main/resources/META-INF/spring/service.xml +++ b/examples/general/jsonrpc/java-client/src/main/resources/META-INF/spring/service.xml @@ -24,6 +24,8 @@ <bean class="com.ikurento.user.Consumer" init-method="start"> <!-- 声明这个类 要使用的服务名--> <property name="userProvider" ref="userProvider" /> + <property name="userProvider1" ref="userProvider1" /> + <property name="userProvider2" ref="userProvider2" /> </bean> <!-- App config --> diff --git a/examples/jsonrpc/java-client/src/main/resources/log4j.properties b/examples/general/jsonrpc/java-client/src/main/resources/log4j.properties similarity index 100% rename from examples/jsonrpc/java-client/src/main/resources/log4j.properties rename to examples/general/jsonrpc/java-client/src/main/resources/log4j.properties diff --git a/examples/jsonrpc/java-server/build.sh b/examples/general/jsonrpc/java-server/build.sh similarity index 100% rename from examples/jsonrpc/java-server/build.sh rename to examples/general/jsonrpc/java-server/build.sh diff --git a/examples/jsonrpc/java-server/pom.xml b/examples/general/jsonrpc/java-server/pom.xml similarity index 100% rename from examples/jsonrpc/java-server/pom.xml rename to examples/general/jsonrpc/java-server/pom.xml diff --git a/examples/jsonrpc/java-server/script/debug.sh b/examples/general/jsonrpc/java-server/script/debug.sh similarity index 100% rename from examples/jsonrpc/java-server/script/debug.sh rename to examples/general/jsonrpc/java-server/script/debug.sh diff --git a/examples/jsonrpc/java-server/src/main/assembly/assembly.xml b/examples/general/jsonrpc/java-server/src/main/assembly/assembly.xml similarity index 100% rename from examples/jsonrpc/java-server/src/main/assembly/assembly.xml rename to examples/general/jsonrpc/java-server/src/main/assembly/assembly.xml diff --git a/examples/jsonrpc/java-server/src/main/assembly/conf/dubbo.properties b/examples/general/jsonrpc/java-server/src/main/assembly/conf/dubbo.properties similarity index 100% rename from examples/jsonrpc/java-server/src/main/assembly/conf/dubbo.properties rename to examples/general/jsonrpc/java-server/src/main/assembly/conf/dubbo.properties diff --git a/examples/jsonrpc/java-server/src/main/assembly/conf/log4j.properties b/examples/general/jsonrpc/java-server/src/main/assembly/conf/log4j.properties similarity index 100% rename from examples/jsonrpc/java-server/src/main/assembly/conf/log4j.properties rename to examples/general/jsonrpc/java-server/src/main/assembly/conf/log4j.properties diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/Gender.java b/examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/Gender.java similarity index 100% rename from examples/jsonrpc/java-server/src/main/java/com/ikurento/user/Gender.java rename to examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/Gender.java diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/Provider.java b/examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/Provider.java similarity index 100% rename from examples/jsonrpc/java-server/src/main/java/com/ikurento/user/Provider.java rename to examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/Provider.java diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/Response.java b/examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/Response.java similarity index 100% rename from examples/jsonrpc/java-server/src/main/java/com/ikurento/user/Response.java rename to examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/Response.java diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/User.java b/examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/User.java similarity index 100% rename from examples/jsonrpc/java-server/src/main/java/com/ikurento/user/User.java rename to examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/User.java diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java b/examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java similarity index 100% rename from examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java rename to examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java b/examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java similarity index 94% rename from examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java rename to examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java index 753a6f89a5f60e0f4884711d4c3b79e52ed2f094..9e22b78b3de2412c8aefbfdbb37d2886d016a0f4 100644 --- a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java +++ b/examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java @@ -9,8 +9,8 @@ import org.slf4j.LoggerFactory; import java.util.*; public class UserProviderAnotherImpl implements UserProvider { - // private static final Logger logger = LoggerFactory.getLogger(getClass()); // 只输出到dubbo的log(logs/server.log) - private static final Logger logger = LoggerFactory.getLogger("userLogger"); // 输出到user-server.log + // private static final Logger logger = LoggerFactory.getLogger(getClass()); // Only output to dubbo's log(logs/server.log) + private static final Logger logger = LoggerFactory.getLogger("userLogger"); // Output to user-server.log private Map<String, User> userMap = new HashMap<String, User>(); diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java b/examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java similarity index 93% rename from examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java rename to examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java index 960c678cf76cf4bafb3de9d5ce2a587b61aa1bac..1ff8afa62220463932872df2172b35e4e16a4591 100644 --- a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java +++ b/examples/general/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java @@ -14,8 +14,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class UserProviderImpl implements UserProvider { - // private static final Logger logger = LoggerFactory.getLogger(getClass()); // 只输出到dubbo的log(logs/server.log) - private static final Logger LOG = LoggerFactory.getLogger("UserLogger"); // 输出到user-server.log + // private static final Logger logger = LoggerFactory.getLogger(getClass()); // Only output to dubbo's log(logs/server.log) + private static final Logger LOG = LoggerFactory.getLogger("UserLogger"); // Output to user-server.log Map<String, User> userMap = new HashMap<String, User>(); public UserProviderImpl() { diff --git a/examples/jsonrpc/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml b/examples/general/jsonrpc/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml similarity index 100% rename from examples/jsonrpc/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml rename to examples/general/jsonrpc/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml diff --git a/examples/jsonrpc/java-server/src/main/resources/log4j.properties b/examples/general/jsonrpc/java-server/src/main/resources/log4j.properties similarity index 100% rename from examples/jsonrpc/java-server/src/main/resources/log4j.properties rename to examples/general/jsonrpc/java-server/src/main/resources/log4j.properties diff --git a/examples/generic/go-client/app/client.go b/examples/generic/go-client/app/client.go new file mode 100644 index 0000000000000000000000000000000000000000..8d5a1bc5fa6cb186fcf456d385f8dad16b750ea3 --- /dev/null +++ b/examples/generic/go-client/app/client.go @@ -0,0 +1,100 @@ +/* + * 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 main + +import ( + "fmt" + "time" +) + +import ( + _ "github.com/apache/dubbo-go/common/proxy/proxy_factory" + "github.com/apache/dubbo-go/config" + "github.com/apache/dubbo-go/protocol/dubbo" + _ "github.com/apache/dubbo-go/registry/protocol" + + _ "github.com/apache/dubbo-go/filter/impl" + + _ "github.com/apache/dubbo-go/cluster/cluster_impl" + _ "github.com/apache/dubbo-go/cluster/loadbalance" + _ "github.com/apache/dubbo-go/registry/zookeeper" +) + +var ( + survivalTimeout int = 10e9 +) + +// they are necessary: +// export CONF_CONSUMER_FILE_PATH="xxx" +// export APP_LOG_CONF_FILE="xxx" +func main() { + println("\n\ntest") + test() + println("\n\ntest2") + test2() + +} +func test() { + var appName = "UserProviderGer" + var referenceConfig = config.ReferenceConfig{ + InterfaceName: "com.ikurento.user.UserProvider", + Cluster: "failover", + Registry: "hangzhouzk", + Protocol: dubbo.DUBBO, + Generic: true, + } + referenceConfig.GenericLoad(appName) //appName is the unique identification of RPCService + + time.Sleep(3 * time.Second) + println("\n\n\nstart to generic invoke") + resp, err := referenceConfig.GetRPCService().(*config.GenericService).Invoke([]interface{}{"GetUser", []string{"java.lang.String"}, []interface{}{"A003"}}) + if err != nil { + panic(err) + } + fmt.Printf("res: %+v\n", resp) + println("succ!") + +} +func test2() { + var appName = "UserProviderGer" + var referenceConfig = config.ReferenceConfig{ + InterfaceName: "com.ikurento.user.UserProvider", + Cluster: "failover", + Registry: "hangzhouzk", + Protocol: dubbo.DUBBO, + Generic: true, + } + referenceConfig.GenericLoad(appName) //appName is the unique identification of RPCService + + time.Sleep(3 * time.Second) + println("\n\n\nstart to generic invoke") + user := User{ + Id: "3213", + Name: "panty", + Age: 25, + Time: time.Now(), + Sex: Gender(MAN), + } + resp, err := referenceConfig.GetRPCService().(*config.GenericService).Invoke([]interface{}{"queryUser", []string{"com.ikurento.user.User"}, []interface{}{user}}) + if err != nil { + panic(err) + } + fmt.Printf("res: %+v\n", resp) + println("succ!") + +} diff --git a/examples/generic/go-client/app/user.go b/examples/generic/go-client/app/user.go new file mode 100644 index 0000000000000000000000000000000000000000..9b226e24456e850f1b31fc0501e04d573cec35fd --- /dev/null +++ b/examples/generic/go-client/app/user.go @@ -0,0 +1,57 @@ +package main + +import ( + "strconv" + "time" +) +import ( + hessian "github.com/apache/dubbo-go-hessian2" +) + +type Gender hessian.JavaEnum + +const ( + MAN hessian.JavaEnum = iota + WOMAN +) + +var genderName = map[hessian.JavaEnum]string{ + MAN: "MAN", + WOMAN: "WOMAN", +} + +var genderValue = map[string]hessian.JavaEnum{ + "MAN": MAN, + "WOMAN": WOMAN, +} + +func (g Gender) JavaClassName() string { + return "com.ikurento.user.Gender" +} + +func (g Gender) String() string { + s, ok := genderName[hessian.JavaEnum(g)] + if ok { + return s + } + + return strconv.Itoa(int(g)) +} + +func (g Gender) EnumValue(s string) hessian.JavaEnum { + v, ok := genderValue[s] + if ok { + return v + } + + return hessian.InvalidJavaEnum +} + +type User struct { + // !!! Cannot define lowercase names of variable + Id string + Name string + Age int32 + Time time.Time + Sex Gender // 注意此处,java enum Object <--> go string +} diff --git a/examples/generic/go-client/assembly/bin/load.sh b/examples/generic/go-client/assembly/bin/load.sh new file mode 100644 index 0000000000000000000000000000000000000000..07d5d15eac7b7974845e36c3807e7ec55875de65 --- /dev/null +++ b/examples/generic/go-client/assembly/bin/load.sh @@ -0,0 +1,196 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : dubbogo app devops script +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-05-13 02:01 +# FILE : load.sh +# ****************************************************** + +APP_NAME="APPLICATION_NAME" +APP_ARGS="" +SLEEP_INTERVAL=5 +MAX_LIFETIME=4000 + +PROJECT_HOME="" +OS_NAME=`uname` +if [[ ${OS_NAME} != "Windows" ]]; then + PROJECT_HOME=`pwd` + PROJECT_HOME=${PROJECT_HOME}"/" +else + APP_NAME="APPLICATION_NAME.exe" +fi + +export CONF_CONSUMER_FILE_PATH=${PROJECT_HOME}"TARGET_CONF_FILE" +export APP_LOG_CONF_FILE=${PROJECT_HOME}"TARGET_LOG_CONF_FILE" +# export GOTRACEBACK=system +# export GODEBUG=gctrace=1 + +usage() { + echo "Usage: $0 start [conf suffix]" + echo " $0 stop" + echo " $0 term" + echo " $0 restart" + echo " $0 list" + echo " $0 monitor" + echo " $0 crontab" + exit +} + +start() { + arg=$1 + if [ "$arg" = "" ];then + echo "No registry type! Default client.yml!" + else + export CONF_CONSUMER_FILE_PATH=${CONF_CONSUMER_FILE_PATH//\.yml/\_$arg\.yml} + fi + if [ ! -f "${CONF_CONSUMER_FILE_PATH}" ];then + echo $CONF_CONSUMER_FILE_PATH" is not existing!" + return + fi + APP_LOG_PATH=${PROJECT_HOME}"logs/" + mkdir -p ${APP_LOG_PATH} + APP_BIN=${PROJECT_HOME}sbin/${APP_NAME} + chmod u+x ${APP_BIN} + # CMD="nohup ${APP_BIN} ${APP_ARGS} >>${APP_NAME}.nohup.out 2>&1 &" + CMD="${APP_BIN}" + eval ${CMD} + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + CUR=`date +%FT%T` + if [ "${PID}" != "" ]; then + for p in ${PID} + do + echo "start ${APP_NAME} ( pid =" ${p} ") at " ${CUR} + done + fi +} + +stop() { + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + if [ "${PID}" != "" ]; + then + for ps in ${PID} + do + echo "kill -SIGINT ${APP_NAME} ( pid =" ${ps} ")" + kill -2 ${ps} + done + fi +} + + +term() { + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + if [ "${PID}" != "" ]; + then + for ps in ${PID} + do + echo "kill -9 ${APP_NAME} ( pid =" ${ps} ")" + kill -9 ${ps} + done + fi +} + +list() { + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{printf("%s,%s,%s,%s\n", $1, $2, $9, $10)}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{printf("%s,%s,%s,%s,%s\n", $1, $4, $6, $7, $8)}'` + fi + + if [ "${PID}" != "" ]; then + echo "list ${APP_NAME}" + + if [[ ${OS_NAME} == "Linux" || ${OS_NAME} == "Darwin" ]]; then + echo "index: user, pid, start, duration" + else + echo "index: PID, WINPID, UID, STIME, COMMAND" + fi + idx=0 + for ps in ${PID} + do + echo "${idx}: ${ps}" + ((idx ++)) + done + fi +} + +monitor() { + idx=0 + while true; do + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + if [[ "${PID}" == "" ]]; then + start + idx=0 + fi + + ((LIFE=idx*${SLEEP_INTERVAL})) + echo "${APP_NAME} ( pid = " ${PID} ") has been working in normal state for " $LIFE " seconds." + ((idx ++)) + sleep ${SLEEP_INTERVAL} + done +} + +crontab() { + idx=0 + while true; do + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + if [[ "${PID}" == "" ]]; then + start + idx=0 + fi + + ((LIFE=idx*${SLEEP_INTERVAL})) + echo "${APP_NAME} ( pid = " ${PID} ") has been working in normal state for " $LIFE " seconds." + ((idx ++)) + sleep ${SLEEP_INTERVAL} + if [[ ${LIFE} -gt ${MAX_LIFETIME} ]]; then + kill -9 ${PID} + fi + done +} + +opt=$1 +case C"$opt" in + Cstart) + start $2 + ;; + Cstop) + stop + ;; + Cterm) + term + ;; + Crestart) + term + start $2 + ;; + Clist) + list + ;; + Cmonitor) + monitor + ;; + Ccrontab) + crontab + ;; + C*) + usage + ;; +esac + diff --git a/examples/generic/go-client/assembly/common/app.properties b/examples/generic/go-client/assembly/common/app.properties new file mode 100644 index 0000000000000000000000000000000000000000..6bbd6db850ceeaf5ff873fee01a3578237cbd557 --- /dev/null +++ b/examples/generic/go-client/assembly/common/app.properties @@ -0,0 +1,17 @@ +# dubbogo application configure script +# ****************************************************** +# DESC : dubbogo environment variable +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:29 +# FILE : app.properties +# ****************************************************** + +export TARGET_EXEC_NAME="user_info_client" +# BUILD_PACKAGE="dubbogo-examples/user-info/client/app" +export BUILD_PACKAGE="app" + +export TARGET_CONF_FILE="conf/client.yml" +export TARGET_LOG_CONF_FILE="conf/log.yml" diff --git a/examples/generic/go-client/assembly/common/build.sh b/examples/generic/go-client/assembly/common/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..e72418297ad2f0ac6985476b5a8d5e03b9e7584e --- /dev/null +++ b/examples/generic/go-client/assembly/common/build.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:28 +# FILE : build.sh +# ****************************************************** + +rm -rf target/ + +PROJECT_HOME=`pwd` +TARGET_FOLDER=${PROJECT_HOME}/target/${GOOS} + +TARGET_SBIN_NAME=${TARGET_EXEC_NAME} +version=`cat app/version.go | grep Version | grep -v "Apache" | awk -F '=' '{print $2}' | awk -F '"' '{print $2}'` +if [[ ${GOOS} == "windows" ]]; then + TARGET_SBIN_NAME=${TARGET_SBIN_NAME}.exe +fi +TARGET_NAME=${TARGET_FOLDER}/${TARGET_SBIN_NAME} +if [[ $PROFILE == "dev" || $PROFILE == "test" ]]; then + # GFLAGS=-gcflags "-N -l" -race -x -v # -x会把go build的详细过程输出 + # GFLAGS=-gcflags "-N -l" -race -v + # GFLAGS="-gcflags \"-N -l\" -v" + cd ${BUILD_PACKAGE} && GOOS=$GOOS GOARCH=$GOARCH go build -gcflags "-N -l" -x -v -i -o ${TARGET_NAME} && cd - +else + # -s去掉符号表(然后panic时候的stack trace就没有任何文件名/行号信息了,这个等价于普通C/C++程序被strip的效果), + # -w去掉DWARF调试信息,得到的程序就不能用gdb调试了。-s和-w也可以分开使用,一般来说如果不打算用gdb调试, + # -w基本没啥损失。-s的损失就有点大了。 + cd ${BUILD_PACKAGE} && GOOS=$GOOS GOARCH=$GOARCH go build -ldflags "-w" -x -v -i -o ${TARGET_NAME} && cd - +fi + +TAR_NAME=${TARGET_EXEC_NAME}-${version}-`date "+%Y%m%d-%H%M"`-${PROFILE} + +mkdir -p ${TARGET_FOLDER}/${TAR_NAME} + +SBIN_DIR=${TARGET_FOLDER}/${TAR_NAME}/sbin +BIN_DIR=${TARGET_FOLDER}/${TAR_NAME} +CONF_DIR=${TARGET_FOLDER}/${TAR_NAME}/conf + +mkdir -p ${SBIN_DIR} +mkdir -p ${CONF_DIR} + +mv ${TARGET_NAME} ${SBIN_DIR} +cp -r assembly/bin ${BIN_DIR} +cd ${BIN_DIR}/bin/ && mv load.sh load_${TARGET_EXEC_NAME}.sh && cd - + +platform=$(uname) +# modify APPLICATION_NAME +if [ ${platform} == "Darwin" ]; then + sed -i "" "s~APPLICATION_NAME~${TARGET_EXEC_NAME}~g" ${BIN_DIR}/bin/* +else + sed -i "s~APPLICATION_NAME~${TARGET_EXEC_NAME}~g" ${BIN_DIR}/bin/* +fi + +# modify TARGET_CONF_FILE +if [ ${platform} == "Darwin" ]; then + sed -i "" "s~TARGET_CONF_FILE~${TARGET_CONF_FILE}~g" ${BIN_DIR}/bin/* +else + sed -i "s~TARGET_CONF_FILE~${TARGET_CONF_FILE}~g" ${BIN_DIR}/bin/* +fi + +# modify TARGET_LOG_CONF_FILE +if [ ${platform} == "Darwin" ]; then + sed -i "" "s~TARGET_LOG_CONF_FILE~${TARGET_LOG_CONF_FILE}~g" ${BIN_DIR}/bin/* +else + sed -i "s~TARGET_LOG_CONF_FILE~${TARGET_LOG_CONF_FILE}~g" ${BIN_DIR}/bin/* +fi + +cp -r profiles/${PROFILE}/* ${CONF_DIR} + +cd ${TARGET_FOLDER} + +tar czf ${TAR_NAME}.tar.gz ${TAR_NAME}/* + diff --git a/examples/generic/go-client/assembly/linux/dev.sh b/examples/generic/go-client/assembly/linux/dev.sh new file mode 100644 index 0000000000000000000000000000000000000000..3373f01b948b708cd7bc1958c9d56a9042c60a68 --- /dev/null +++ b/examples/generic/go-client/assembly/linux/dev.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for dev env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2017-10-18 13:24 +# FILE : dev.sh +# ****************************************************** + + +set -e + +export GOOS=linux +export GOARCH=amd64 + +export PROFILE="dev" + +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/generic/go-client/assembly/linux/release.sh b/examples/generic/go-client/assembly/linux/release.sh new file mode 100644 index 0000000000000000000000000000000000000000..34867b8b3488778cd76a1dc7802393dcab6b0df0 --- /dev/null +++ b/examples/generic/go-client/assembly/linux/release.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for release env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=linux +export GOARCH=amd64 + +export PROFILE="release" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/generic/go-client/assembly/linux/test.sh b/examples/generic/go-client/assembly/linux/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..1bbbefd1e14e08c16deaf859e2841f4d1fe88e9c --- /dev/null +++ b/examples/generic/go-client/assembly/linux/test.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for test env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=linux +export GOARCH=amd64 + +export PROFILE="test" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/generic/go-client/assembly/mac/dev.sh b/examples/generic/go-client/assembly/mac/dev.sh new file mode 100644 index 0000000000000000000000000000000000000000..b68ac83b6524a6713cd90c4fc5968fe64b1a9545 --- /dev/null +++ b/examples/generic/go-client/assembly/mac/dev.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for dev env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2017-10-18 13:24 +# FILE : dev.sh +# ****************************************************** + + +set -e + +export GOOS=darwin +export GOARCH=amd64 + +export PROFILE="dev" + +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/generic/go-client/assembly/mac/release.sh b/examples/generic/go-client/assembly/mac/release.sh new file mode 100644 index 0000000000000000000000000000000000000000..688288b3b1b989e8af70a3674b34ea8e0668f3b4 --- /dev/null +++ b/examples/generic/go-client/assembly/mac/release.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for release env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=darwin +export GOARCH=amd64 + +export PROFILE="release" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/generic/go-client/assembly/mac/test.sh b/examples/generic/go-client/assembly/mac/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..56d6c11ecd6a1dc5984c74b88c10be9239e57428 --- /dev/null +++ b/examples/generic/go-client/assembly/mac/test.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for test env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=darwin +export GOARCH=amd64 + +export PROFILE="test" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/generic/go-client/assembly/windows/dev.sh b/examples/generic/go-client/assembly/windows/dev.sh new file mode 100644 index 0000000000000000000000000000000000000000..91cf6f23bcbecb26db798469a30529261aabbbb6 --- /dev/null +++ b/examples/generic/go-client/assembly/windows/dev.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for dev env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2017-10-18 13:24 +# FILE : dev.sh +# ****************************************************** + + +set -e + +export GOOS=linux +export GOARCH=amd64 + +export PROFILE="dev" +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/generic/go-client/assembly/windows/release.sh b/examples/generic/go-client/assembly/windows/release.sh new file mode 100644 index 0000000000000000000000000000000000000000..f317720bd53d9c9e5f8f484b6eb682c9c736af0c --- /dev/null +++ b/examples/generic/go-client/assembly/windows/release.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for release env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=windows +export GOARCH=amd64 + +export PROFILE="release" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/generic/go-client/assembly/windows/test.sh b/examples/generic/go-client/assembly/windows/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..7dd2bec5260e647b57a46aaa37acc098babff068 --- /dev/null +++ b/examples/generic/go-client/assembly/windows/test.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for test env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=windows +export GOARCH=amd64 + +export PROFILE="test" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/generic/go-client/profiles/dev/client.yml b/examples/generic/go-client/profiles/dev/client.yml new file mode 100644 index 0000000000000000000000000000000000000000..f4e3180aa88cbbdffd519d70b3cc83b2e2b6674a --- /dev/null +++ b/examples/generic/go-client/profiles/dev/client.yml @@ -0,0 +1,55 @@ +# dubbo client yaml configure file + + +check: true +# client +request_timeout : "3s" +# connect timeout +connect_timeout : "3s" + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo genric client" + version : "0.0.1" + owner : "ZX" + environment : "dev" + +registries : + "hangzhouzk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + +references: + +protocol_conf: + dubbo: + reconnect_interval: 0 + connection_number: 2 + heartbeat_period: "5s" + session_timeout: "20s" + pool_size: 64 + pool_ttl: 600 + getty_session_param: + compress_encoding: false + tcp_no_delay: true + tcp_keep_alive: true + keep_alive_period: "120s" + tcp_r_buf_size: 262144 + tcp_w_buf_size: 65536 + pkg_wq_size: 512 + tcp_read_timeout: "1s" + tcp_write_timeout: "5s" + wait_timeout: "1s" + max_msg_len: 10240 + session_name: "client" diff --git a/examples/generic/go-client/profiles/dev/log.yml b/examples/generic/go-client/profiles/dev/log.yml new file mode 100644 index 0000000000000000000000000000000000000000..59fa4279ad85272c4c49d532beaf23b74d00f58a --- /dev/null +++ b/examples/generic/go-client/profiles/dev/log.yml @@ -0,0 +1,28 @@ + +level: "debug" +development: true +disableCaller: false +disableStacktrace: false +sampling: +encoding: "console" + +# encoder +encoderConfig: + messageKey: "message" + levelKey: "level" + timeKey: "time" + nameKey: "logger" + callerKey: "caller" + stacktraceKey: "stacktrace" + lineEnding: "" + levelEncoder: "capitalColor" + timeEncoder: "iso8601" + durationEncoder: "seconds" + callerEncoder: "short" + nameEncoder: "" + +outputPaths: + - "stderr" +errorOutputPaths: + - "stderr" +initialFields: diff --git a/examples/generic/go-client/profiles/release/client.yml b/examples/generic/go-client/profiles/release/client.yml new file mode 100644 index 0000000000000000000000000000000000000000..5a21bca6c93336a8888b55a6a7e81f9240c709a5 --- /dev/null +++ b/examples/generic/go-client/profiles/release/client.yml @@ -0,0 +1,55 @@ +# dubbo client yaml configure file + + +check: true +# client +request_timeout : "3s" +# connect timeout +connect_timeout : "3s" + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo generic client" + version : "0.0.1" + owner : "ZX" + environment : "release" + +registries : + "hangzhouzk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + +references: + +protocol_conf: + dubbo: + reconnect_interval: 0 + connection_number: 2 + heartbeat_period: "5s" + session_timeout: "20s" + pool_size: 64 + pool_ttl: 600 + getty_session_param: + compress_encoding: false + tcp_no_delay: true + tcp_keep_alive: true + keep_alive_period: "120s" + tcp_r_buf_size: 262144 + tcp_w_buf_size: 65536 + pkg_wq_size: 512 + tcp_read_timeout: "1s" + tcp_write_timeout: "5s" + wait_timeout: "1s" + max_msg_len: 10240 + session_name: "client" diff --git a/examples/generic/go-client/profiles/release/log.yml b/examples/generic/go-client/profiles/release/log.yml new file mode 100644 index 0000000000000000000000000000000000000000..e0514be020eedf594d99d112183cdd5ce199e46d --- /dev/null +++ b/examples/generic/go-client/profiles/release/log.yml @@ -0,0 +1,28 @@ + +level: "warn" +development: true +disableCaller: true +disableStacktrace: true +sampling: +encoding: "console" + +# encoder +encoderConfig: + messageKey: "message" + levelKey: "level" + timeKey: "time" + nameKey: "logger" + callerKey: "caller" + stacktraceKey: "stacktrace" + lineEnding: "" + levelEncoder: "capitalColor" + timeEncoder: "iso8601" + durationEncoder: "seconds" + callerEncoder: "short" + nameEncoder: "" + +outputPaths: + - "stderr" +errorOutputPaths: + - "stderr" +initialFields: diff --git a/examples/generic/go-client/profiles/test/client.yml b/examples/generic/go-client/profiles/test/client.yml new file mode 100644 index 0000000000000000000000000000000000000000..7442c64c71abf47db9c15d85c6bcd2ced8057e46 --- /dev/null +++ b/examples/generic/go-client/profiles/test/client.yml @@ -0,0 +1,55 @@ +# dubbo client yaml configure file + + +check: true +# client +request_timeout : "3s" +# connect timeout +connect_timeout : "3s" + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info client" + version : "0.0.1" + owner : "ZX" + environment : "test" + +registries : + "hangzhouzk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + username: "" + password: "" + "shanghaizk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2182" + username: "" + password: "" + +references: + +protocol_conf: + dubbo: + reconnect_interval: 0 + connection_number: 2 + heartbeat_period: "5s" + session_timeout: "20s" + pool_size: 64 + pool_ttl: 600 + getty_session_param: + compress_encoding: false + tcp_no_delay: true + tcp_keep_alive: true + keep_alive_period: "120s" + tcp_r_buf_size: 262144 + tcp_w_buf_size: 65536 + pkg_wq_size: 512 + tcp_read_timeout: "1s" + tcp_write_timeout: "5s" + wait_timeout: "1s" + max_msg_len: 10240 + session_name: "client" diff --git a/examples/generic/go-client/profiles/test/log.yml b/examples/generic/go-client/profiles/test/log.yml new file mode 100644 index 0000000000000000000000000000000000000000..baee0b7248484e425f88f35ab128212c931ff85e --- /dev/null +++ b/examples/generic/go-client/profiles/test/log.yml @@ -0,0 +1,28 @@ + +level: "info" +development: false +disableCaller: false +disableStacktrace: true +sampling: +encoding: "console" + +# encoder +encoderConfig: + messageKey: "message" + levelKey: "level" + timeKey: "time" + nameKey: "logger" + callerKey: "caller" + stacktraceKey: "stacktrace" + lineEnding: "" + levelEncoder: "capitalColor" + timeEncoder: "iso8601" + durationEncoder: "seconds" + callerEncoder: "short" + nameEncoder: "" + +outputPaths: + - "stderr" +errorOutputPaths: + - "stderr" +initialFields: diff --git a/examples/generic/java-server/build.sh b/examples/generic/java-server/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..0c197da639c1c1d9375e18c24dd73366c49deefe --- /dev/null +++ b/examples/generic/java-server/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# ****************************************************** +# EMAIL : alexstocks@foxmail.com +# FILE : build.sh +# ****************************************************** + +# mvn dependency:sources +mvn clean package -Dmaven.test.skip +# mvn -X clean compile package -DskipTests=true diff --git a/examples/generic/java-server/pom.xml b/examples/generic/java-server/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..975157865e59f24693d755dd20b0aac4b179a793 --- /dev/null +++ b/examples/generic/java-server/pom.xml @@ -0,0 +1,181 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.ikurento</groupId> + <artifactId>user-info-server</artifactId> + <packaging>jar</packaging> + <version>0.2.0</version> + <description>The demo provider module of dubbo project</description> + <properties> + <skip_maven_deploy>false</skip_maven_deploy> + + <dubbo-version>2.6.5</dubbo-version> + <dubbo-jsonrpc-version>1.0.1</dubbo-jsonrpc-version> + </properties> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>com.alibaba</groupId> + <artifactId>dubbo-dependencies-bom</artifactId> + <version>${dubbo-version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.25</version> + </dependency> + + <dependency> + <groupId>com.alibaba</groupId> + <artifactId>dubbo</artifactId> + <version>${dubbo-version}</version> + <exclusions> + </exclusions> + </dependency> + + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-all</artifactId> + </dependency> + <dependency> + <groupId>org.apache.curator</groupId> + <artifactId>curator-framework</artifactId> + <version>2.12.0</version> + </dependency> + + <dependency> + <groupId>com.qianmi</groupId> + <artifactId>dubbo-rpc-jsonrpc</artifactId> + <version>${dubbo-jsonrpc-version}</version> + <exclusions> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.mortbay.jetty</groupId> + <artifactId>jetty</artifactId> + <version>6.1.26</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>2.9.9</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>2.9.9</version> + </dependency> + + <dependency> + <groupId>com.github.sgroschupf</groupId> + <artifactId>zkclient</artifactId> + <version>0.1</version> + <exclusions> + <exclusion> + <artifactId>org.apache.zookeeper</artifactId> + <groupId>zookeeper</groupId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.apache.zookeeper</groupId> + <artifactId>zookeeper</artifactId> + <version>3.4.14</version> + </dependency> + + </dependencies> + + <repositories> + <repository> + <id>nexus-aliyu</id> + <url>http://maven.aliyun.com/nexus/content/groups/public</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>nexus-aliyu</id> + <url>http://maven.aliyun.com/nexus/content/groups/public</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + + + <build> + + <plugins> + <plugin> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>unpack</id> + <phase>package</phase> + <goals> + <goal>unpack</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>com.alibaba</groupId> + <artifactId>dubbo</artifactId> + <version>${dubbo-version}</version> + <outputDirectory>${project.build.directory}/dubbo</outputDirectory> + <includes>META-INF/assembly/**</includes> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>make-assembly</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + <configuration> + <descriptors> + <descriptor>src/main/assembly/assembly.xml</descriptor> + </descriptors> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + +</project> + + diff --git a/examples/generic/java-server/script/debug.sh b/examples/generic/java-server/script/debug.sh new file mode 100644 index 0000000000000000000000000000000000000000..27c5d800d846018127e762944151aa8e9ad4495d --- /dev/null +++ b/examples/generic/java-server/script/debug.sh @@ -0,0 +1,16 @@ +#!/us1r/bin/env bash +# ****************************************************** +# DESC : +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2017-10-09 21:52 +# FILE : to debug user info dubbo server +# ****************************************************** + +# jdb -classpath /Users/alex/tmp/us/conf:/Users/alex/tmp/us/lib/*:/Users/alex/test/java/dubbo/2.5.4/dubbo-remoting/dubbo-remoting-api/src/main/java/ com.alibaba.dubbo.container.Main +jdb -classpath /Users/alex/tmp/us/conf:/Users/alex/tmp/us/lib/* -sourcepath /Users/alex/test/java/dubbo/2.5.4/dubbo-remoting/dubbo-remoting-api/src/main/java/:/Users/alex/tmp/java-server/src/main/java com.alibaba.dubbo.container.Main +# jdb stop at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec:76 +# run + diff --git a/examples/generic/java-server/src/main/assembly/assembly.xml b/examples/generic/java-server/src/main/assembly/assembly.xml new file mode 100644 index 0000000000000000000000000000000000000000..2f01fea20f5391112cccb88c87bfe4ae1b59750a --- /dev/null +++ b/examples/generic/java-server/src/main/assembly/assembly.xml @@ -0,0 +1,45 @@ +<!-- + - Copyright 1999-2011 Alibaba Group. + - + - Licensed 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. +--> +<assembly> + <id>assembly</id> + <formats> + <format>tar.gz</format> + </formats> + <includeBaseDirectory>true</includeBaseDirectory> + <fileSets> + <fileSet> + <directory>${project.build.directory}/dubbo/META-INF/assembly/bin</directory> + <outputDirectory>bin</outputDirectory> + <fileMode>0755</fileMode> + <directoryMode>0755</directoryMode> + </fileSet> + <fileSet> + <directory>src/main/assembly/conf</directory> + <includes> + <include>dubbo.properties</include> + <include>log4j.*</include> + </includes> + <outputDirectory>conf</outputDirectory> + <fileMode>0644</fileMode> + <directoryMode>0755</directoryMode> + </fileSet> + </fileSets> + <dependencySets> + <dependencySet> + <outputDirectory>lib</outputDirectory> + </dependencySet> + </dependencySets> +</assembly> \ No newline at end of file diff --git a/examples/generic/java-server/src/main/assembly/conf/dubbo.properties b/examples/generic/java-server/src/main/assembly/conf/dubbo.properties new file mode 100644 index 0000000000000000000000000000000000000000..2826f31303717256725b02a79e1698043709d2f3 --- /dev/null +++ b/examples/generic/java-server/src/main/assembly/conf/dubbo.properties @@ -0,0 +1,14 @@ +### dubbo注册中心配置 ## +dubbo.container = log4j,spring +dubbo.application.name = user-info-server +dubbo.application.environment = product +dubbo.application.owner = AlexStocks +dubbo.registry.address = 127.0.0.1:2181 +dubbo.registry.protocol = zookeeper +dubbo.consumer.timeout = 10000 +dubbo.provider.timeout = 10000 +dubbo.protocol.name = dubbo +dubbo.protocol.port = 10000 + +dubbo.log4j.file = logs/dubbo.log +dubbo.log4j.level = INFO diff --git a/examples/generic/java-server/src/main/assembly/conf/log4j.properties b/examples/generic/java-server/src/main/assembly/conf/log4j.properties new file mode 100644 index 0000000000000000000000000000000000000000..13c80493329261ea677de77624b363bf99c82652 --- /dev/null +++ b/examples/generic/java-server/src/main/assembly/conf/log4j.properties @@ -0,0 +1,20 @@ +## Logger configure file for myproject +log.dir=logs/ +datestamp=yyyy-MM-dd/HH:mm:ss.SSS + +log4j.rootLogger=DEBUG, file, console + +log4j.appender.file=org.apache.log4j.DailyRollingFileAppender +log4j.appender.file.threshold=DEBUG +log4j.appender.file.File=${log.dir}/log4j.log +log4j.appender.file.DatePattern=-yyyyMMddHH +log4j.appender.file.ImmediateFlush=true +log4j.appender.file.Append=true +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{${datestamp}} %5p: %l - %m%n + +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.Threshold=DEBUG +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{${datestamp}} %5p: %l - %m%n + diff --git a/examples/generic/java-server/src/main/java/com/ikurento/user/Gender.java b/examples/generic/java-server/src/main/java/com/ikurento/user/Gender.java new file mode 100644 index 0000000000000000000000000000000000000000..72c30ae8d4bae8fc71b4cb598205141b2d1d2020 --- /dev/null +++ b/examples/generic/java-server/src/main/java/com/ikurento/user/Gender.java @@ -0,0 +1,6 @@ +package com.ikurento.user; + +public enum Gender { + MAN, + WOMAN +} diff --git a/examples/generic/java-server/src/main/java/com/ikurento/user/Provider.java b/examples/generic/java-server/src/main/java/com/ikurento/user/Provider.java new file mode 100644 index 0000000000000000000000000000000000000000..0031f5569fd5f16ded0da6e5426f78805fad4a42 --- /dev/null +++ b/examples/generic/java-server/src/main/java/com/ikurento/user/Provider.java @@ -0,0 +1,33 @@ +/* + * 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 com.ikurento.user; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class Provider { + + /** + * To get ipv6 address to work, add + * System.setProperty("java.net.preferIPv6Addresses", "true"); + * before running your application. + */ + public static void main(String[] args) throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo.provider.xml"}); + context.start(); + System.in.read(); // press any key to exit + } +} diff --git a/examples/generic/java-server/src/main/java/com/ikurento/user/Response.java b/examples/generic/java-server/src/main/java/com/ikurento/user/Response.java new file mode 100644 index 0000000000000000000000000000000000000000..3447e5c2537625f424b54291c53783a51922ae7b --- /dev/null +++ b/examples/generic/java-server/src/main/java/com/ikurento/user/Response.java @@ -0,0 +1,76 @@ +package com.ikurento.user; + +import java.io.*; +//import java.util.Objects; + +public final class Response<T> implements Serializable { + private static final long serialVersionUID = 3727205004706510648L; + public static final Integer OK = 200; + public static final Integer ERR = 500; + private Integer Status; + private String Err; + private T Data; + + public Response() { + } + + public static <T> Response<T> ok() { + Response r = new Response(); + r.Status = OK; + return r; + } + + public static <T> Response<T> ok(Object Data) { + Response r = new Response(); + r.Status = OK; + r.Data = Data; + return r; + } + + public static <T> Response<T> notOk(String Err) { + Response r = new Response(); + r.Status = ERR; + r.Err = Err; + return r; + } + + public static <T> Response<T> notOk(Integer Status, String Err) { + Response r = new Response(); + r.Status = Status; + r.Err = Err; + return r; + } + +// public Boolean isSuccess() { +// return Objects.equals(this.Status, OK); +// } + + public Integer getStatus() { + return this.Status; + } + + public void setStatus(Integer Status) { + this.Status = Status; + } + + public String getErr() { + return this.Err; + } + + public void setErr(String Err) { + this.Err = Err; + } + + public T getData() { + return this.Data; + } + + public void setData(T Data) { + this.Status = OK; + this.Data = Data; + } + + public String toString() { + return "Response{Status=" + this.Status + ", Err='" + this.Err + '\'' + ", Data=" + this.Data + '}'; + } +} \ No newline at end of file diff --git a/examples/generic/java-server/src/main/java/com/ikurento/user/User.java b/examples/generic/java-server/src/main/java/com/ikurento/user/User.java new file mode 100644 index 0000000000000000000000000000000000000000..eafc0fe1c0e0c7b72a0fce73b6a333668797145e --- /dev/null +++ b/examples/generic/java-server/src/main/java/com/ikurento/user/User.java @@ -0,0 +1,79 @@ +package com.ikurento.user; +// ref: https://github.com/JoeCao/dubbo_jsonrpc_example/tree/master/dubbo_server/src/main/java/com/ofpay/demo/api + +import java.util.Date; +import java.io.Serializable; + +public class User implements Serializable { + + private String id; + + private String name; + + private int age; + + private Date time = new Date(); + + private Gender sex = Gender.MAN; + + public User() { + } + + public User(String id, String name, int age) { + this.id = id; + this.name = name; + this.age = age; + } + + public User(String id, String name, int age, Date time, Gender sex) { + this.id = id; + this.name = name; + this.age = age; + this.time = time; + this.sex = sex; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } + + public Gender getSex() { + return sex; + } + + public void setSex(Gender sex) { + this.sex = sex; + } + + public String toString() { + return "User{id:" + id + ", name:" + name + ", age:" + age + ", time:" + time + ", gender:" + sex + "}"; + } +} diff --git a/examples/generic/java-server/src/main/java/com/ikurento/user/UserProvider.java b/examples/generic/java-server/src/main/java/com/ikurento/user/UserProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..24567d23be662312a4750f07b605c685a8dfa5fe --- /dev/null +++ b/examples/generic/java-server/src/main/java/com/ikurento/user/UserProvider.java @@ -0,0 +1,32 @@ +package com.ikurento.user; +// https://github.com/JoeCao/dubbo_jsonrpc_example/tree/master/dubbo_server/src/main/java/com/ofpay/demo/api + +import java.util.List; +import java.util.Map; + +public interface UserProvider { + + boolean isLimit(Gender gender, String name); + + User GetUser(String userId); // the first alpha is Upper case to compatible with golang. + + List<User> GetUsers(List<String> userIdList); + + void GetUser3(); + + User GetUser0(String userId, String name); + + User GetErr(String userId) throws Exception; + + Map<String, User> GetUserMap(List<String> userIdList); + + User getUser(int usercode); + + User queryUser(User user); + + Map<String, User> queryAll(); + + int Calc(int a,int b); + + Response<Integer> Sum(int a, int b); +} diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java b/examples/generic/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java similarity index 100% rename from examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java rename to examples/generic/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java b/examples/generic/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java similarity index 100% rename from examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java rename to examples/generic/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java diff --git a/examples/generic/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml b/examples/generic/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml new file mode 100644 index 0000000000000000000000000000000000000000..f8dd13a833e6095485d0504e21cec272a3c9a288 --- /dev/null +++ b/examples/generic/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - Copyright 1999-2011 Alibaba Group. + - + - Licensed 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd + http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> + + <!-- 应用名 --> + <dubbo:application name="user-info-server"/> + <!-- 连接到哪个本地注册中心 --> + <dubbo:registry id="ikurento" address="zookeeper://127.0.0.1:2181" /> + <dubbo:registry id="ikurento2" address="zookeeper://127.0.0.1:2182" /> + <!-- 用dubbo协议在20880端口暴露服务 --> + <!-- dubbo:protocol host="127.0.0.1" / --> + <dubbo:protocol id="dubbo" name="dubbo" host="127.0.0.1" port="20010" /> + <dubbo:protocol id="jsonrpc" name="jsonrpc" host="127.0.0.1" port="10010" /> + <!-- 声明需要暴露的服务接口 --> + <dubbo:service id="aaa" registry="ikurento" timeout="3000" interface="com.ikurento.user.UserProvider" ref="demoService"/> + <dubbo:service id="bbb" registry="ikurento" timeout="3000" interface="com.ikurento.user.UserProvider" ref="otherService" version="2.0"/> + <dubbo:service id="ccc" registry="ikurento" timeout="3000" interface="com.ikurento.user.UserProvider" ref="otherService" group="as" version="2.0"/> + + <bean id="demoService" class="com.ikurento.user.UserProviderImpl" /> + <bean id="otherService" class="com.ikurento.user.UserProviderAnotherImpl"/> + +</beans> diff --git a/examples/generic/java-server/src/main/resources/log4j.properties b/examples/generic/java-server/src/main/resources/log4j.properties new file mode 100644 index 0000000000000000000000000000000000000000..13c80493329261ea677de77624b363bf99c82652 --- /dev/null +++ b/examples/generic/java-server/src/main/resources/log4j.properties @@ -0,0 +1,20 @@ +## Logger configure file for myproject +log.dir=logs/ +datestamp=yyyy-MM-dd/HH:mm:ss.SSS + +log4j.rootLogger=DEBUG, file, console + +log4j.appender.file=org.apache.log4j.DailyRollingFileAppender +log4j.appender.file.threshold=DEBUG +log4j.appender.file.File=${log.dir}/log4j.log +log4j.appender.file.DatePattern=-yyyyMMddHH +log4j.appender.file.ImmediateFlush=true +log4j.appender.file.Append=true +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{${datestamp}} %5p: %l - %m%n + +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.Threshold=DEBUG +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{${datestamp}} %5p: %l - %m%n + diff --git a/examples/helloworld/dubbo/go-client/app/client.go b/examples/helloworld/dubbo/go-client/app/client.go new file mode 100644 index 0000000000000000000000000000000000000000..b416edb5a9b77c2782af01de854bc0c40b4b00bb --- /dev/null +++ b/examples/helloworld/dubbo/go-client/app/client.go @@ -0,0 +1,54 @@ +/* + * 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 main + +import ( + "context" + "fmt" + "time" +) + +import ( + _ "github.com/apache/dubbo-go/common/proxy/proxy_factory" + "github.com/apache/dubbo-go/config" + _ "github.com/apache/dubbo-go/protocol/dubbo" + _ "github.com/apache/dubbo-go/registry/protocol" + + _ "github.com/apache/dubbo-go/filter/impl" + + _ "github.com/apache/dubbo-go/cluster/cluster_impl" + _ "github.com/apache/dubbo-go/cluster/loadbalance" + _ "github.com/apache/dubbo-go/registry/zookeeper" +) + +// they are necessary: +// export CONF_CONSUMER_FILE_PATH="xxx" +// export APP_LOG_CONF_FILE="xxx" +func main() { + + config.Load() + time.Sleep(3e9) + + println("\n\n\nstart to test dubbo") + user := &User{} + err := userProvider.GetUser(context.TODO(), []interface{}{"A001"}, user) + if err != nil { + panic(err) + } + fmt.Printf("response result: %v\n", user) +} diff --git a/examples/helloworld/dubbo/go-client/app/user.go b/examples/helloworld/dubbo/go-client/app/user.go new file mode 100644 index 0000000000000000000000000000000000000000..9820dbc08b0f52af9a6d4f9fa364344f0649fbc8 --- /dev/null +++ b/examples/helloworld/dubbo/go-client/app/user.go @@ -0,0 +1,57 @@ +/* + * 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 main + +import ( + "context" + "time" +) + +import ( + hessian "github.com/apache/dubbo-go-hessian2" +) + +import ( + "github.com/apache/dubbo-go/config" +) + +var userProvider = new(UserProvider) + +func init() { + config.SetConsumerService(userProvider) + hessian.RegisterPOJO(&User{}) +} + +type User struct { + Id string + Name string + Age int32 + Time time.Time +} + +type UserProvider struct { + GetUser func(ctx context.Context, req []interface{}, rsp *User) error +} + +func (u *UserProvider) Reference() string { + return "UserProvider" +} + +func (User) JavaClassName() string { + return "com.ikurento.user.User" +} diff --git a/examples/helloworld/dubbo/go-client/assembly/bin/load.sh b/examples/helloworld/dubbo/go-client/assembly/bin/load.sh new file mode 100644 index 0000000000000000000000000000000000000000..07d5d15eac7b7974845e36c3807e7ec55875de65 --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/bin/load.sh @@ -0,0 +1,196 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : dubbogo app devops script +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-05-13 02:01 +# FILE : load.sh +# ****************************************************** + +APP_NAME="APPLICATION_NAME" +APP_ARGS="" +SLEEP_INTERVAL=5 +MAX_LIFETIME=4000 + +PROJECT_HOME="" +OS_NAME=`uname` +if [[ ${OS_NAME} != "Windows" ]]; then + PROJECT_HOME=`pwd` + PROJECT_HOME=${PROJECT_HOME}"/" +else + APP_NAME="APPLICATION_NAME.exe" +fi + +export CONF_CONSUMER_FILE_PATH=${PROJECT_HOME}"TARGET_CONF_FILE" +export APP_LOG_CONF_FILE=${PROJECT_HOME}"TARGET_LOG_CONF_FILE" +# export GOTRACEBACK=system +# export GODEBUG=gctrace=1 + +usage() { + echo "Usage: $0 start [conf suffix]" + echo " $0 stop" + echo " $0 term" + echo " $0 restart" + echo " $0 list" + echo " $0 monitor" + echo " $0 crontab" + exit +} + +start() { + arg=$1 + if [ "$arg" = "" ];then + echo "No registry type! Default client.yml!" + else + export CONF_CONSUMER_FILE_PATH=${CONF_CONSUMER_FILE_PATH//\.yml/\_$arg\.yml} + fi + if [ ! -f "${CONF_CONSUMER_FILE_PATH}" ];then + echo $CONF_CONSUMER_FILE_PATH" is not existing!" + return + fi + APP_LOG_PATH=${PROJECT_HOME}"logs/" + mkdir -p ${APP_LOG_PATH} + APP_BIN=${PROJECT_HOME}sbin/${APP_NAME} + chmod u+x ${APP_BIN} + # CMD="nohup ${APP_BIN} ${APP_ARGS} >>${APP_NAME}.nohup.out 2>&1 &" + CMD="${APP_BIN}" + eval ${CMD} + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + CUR=`date +%FT%T` + if [ "${PID}" != "" ]; then + for p in ${PID} + do + echo "start ${APP_NAME} ( pid =" ${p} ") at " ${CUR} + done + fi +} + +stop() { + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + if [ "${PID}" != "" ]; + then + for ps in ${PID} + do + echo "kill -SIGINT ${APP_NAME} ( pid =" ${ps} ")" + kill -2 ${ps} + done + fi +} + + +term() { + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + if [ "${PID}" != "" ]; + then + for ps in ${PID} + do + echo "kill -9 ${APP_NAME} ( pid =" ${ps} ")" + kill -9 ${ps} + done + fi +} + +list() { + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{printf("%s,%s,%s,%s\n", $1, $2, $9, $10)}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{printf("%s,%s,%s,%s,%s\n", $1, $4, $6, $7, $8)}'` + fi + + if [ "${PID}" != "" ]; then + echo "list ${APP_NAME}" + + if [[ ${OS_NAME} == "Linux" || ${OS_NAME} == "Darwin" ]]; then + echo "index: user, pid, start, duration" + else + echo "index: PID, WINPID, UID, STIME, COMMAND" + fi + idx=0 + for ps in ${PID} + do + echo "${idx}: ${ps}" + ((idx ++)) + done + fi +} + +monitor() { + idx=0 + while true; do + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + if [[ "${PID}" == "" ]]; then + start + idx=0 + fi + + ((LIFE=idx*${SLEEP_INTERVAL})) + echo "${APP_NAME} ( pid = " ${PID} ") has been working in normal state for " $LIFE " seconds." + ((idx ++)) + sleep ${SLEEP_INTERVAL} + done +} + +crontab() { + idx=0 + while true; do + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + if [[ "${PID}" == "" ]]; then + start + idx=0 + fi + + ((LIFE=idx*${SLEEP_INTERVAL})) + echo "${APP_NAME} ( pid = " ${PID} ") has been working in normal state for " $LIFE " seconds." + ((idx ++)) + sleep ${SLEEP_INTERVAL} + if [[ ${LIFE} -gt ${MAX_LIFETIME} ]]; then + kill -9 ${PID} + fi + done +} + +opt=$1 +case C"$opt" in + Cstart) + start $2 + ;; + Cstop) + stop + ;; + Cterm) + term + ;; + Crestart) + term + start $2 + ;; + Clist) + list + ;; + Cmonitor) + monitor + ;; + Ccrontab) + crontab + ;; + C*) + usage + ;; +esac + diff --git a/examples/helloworld/dubbo/go-client/assembly/common/app.properties b/examples/helloworld/dubbo/go-client/assembly/common/app.properties new file mode 100644 index 0000000000000000000000000000000000000000..6bbd6db850ceeaf5ff873fee01a3578237cbd557 --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/common/app.properties @@ -0,0 +1,17 @@ +# dubbogo application configure script +# ****************************************************** +# DESC : dubbogo environment variable +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:29 +# FILE : app.properties +# ****************************************************** + +export TARGET_EXEC_NAME="user_info_client" +# BUILD_PACKAGE="dubbogo-examples/user-info/client/app" +export BUILD_PACKAGE="app" + +export TARGET_CONF_FILE="conf/client.yml" +export TARGET_LOG_CONF_FILE="conf/log.yml" diff --git a/examples/helloworld/dubbo/go-client/assembly/common/build.sh b/examples/helloworld/dubbo/go-client/assembly/common/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..e72418297ad2f0ac6985476b5a8d5e03b9e7584e --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/common/build.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:28 +# FILE : build.sh +# ****************************************************** + +rm -rf target/ + +PROJECT_HOME=`pwd` +TARGET_FOLDER=${PROJECT_HOME}/target/${GOOS} + +TARGET_SBIN_NAME=${TARGET_EXEC_NAME} +version=`cat app/version.go | grep Version | grep -v "Apache" | awk -F '=' '{print $2}' | awk -F '"' '{print $2}'` +if [[ ${GOOS} == "windows" ]]; then + TARGET_SBIN_NAME=${TARGET_SBIN_NAME}.exe +fi +TARGET_NAME=${TARGET_FOLDER}/${TARGET_SBIN_NAME} +if [[ $PROFILE == "dev" || $PROFILE == "test" ]]; then + # GFLAGS=-gcflags "-N -l" -race -x -v # -x会把go build的详细过程输出 + # GFLAGS=-gcflags "-N -l" -race -v + # GFLAGS="-gcflags \"-N -l\" -v" + cd ${BUILD_PACKAGE} && GOOS=$GOOS GOARCH=$GOARCH go build -gcflags "-N -l" -x -v -i -o ${TARGET_NAME} && cd - +else + # -s去掉符号表(然后panic时候的stack trace就没有任何文件名/行号信息了,这个等价于普通C/C++程序被strip的效果), + # -w去掉DWARF调试信息,得到的程序就不能用gdb调试了。-s和-w也可以分开使用,一般来说如果不打算用gdb调试, + # -w基本没啥损失。-s的损失就有点大了。 + cd ${BUILD_PACKAGE} && GOOS=$GOOS GOARCH=$GOARCH go build -ldflags "-w" -x -v -i -o ${TARGET_NAME} && cd - +fi + +TAR_NAME=${TARGET_EXEC_NAME}-${version}-`date "+%Y%m%d-%H%M"`-${PROFILE} + +mkdir -p ${TARGET_FOLDER}/${TAR_NAME} + +SBIN_DIR=${TARGET_FOLDER}/${TAR_NAME}/sbin +BIN_DIR=${TARGET_FOLDER}/${TAR_NAME} +CONF_DIR=${TARGET_FOLDER}/${TAR_NAME}/conf + +mkdir -p ${SBIN_DIR} +mkdir -p ${CONF_DIR} + +mv ${TARGET_NAME} ${SBIN_DIR} +cp -r assembly/bin ${BIN_DIR} +cd ${BIN_DIR}/bin/ && mv load.sh load_${TARGET_EXEC_NAME}.sh && cd - + +platform=$(uname) +# modify APPLICATION_NAME +if [ ${platform} == "Darwin" ]; then + sed -i "" "s~APPLICATION_NAME~${TARGET_EXEC_NAME}~g" ${BIN_DIR}/bin/* +else + sed -i "s~APPLICATION_NAME~${TARGET_EXEC_NAME}~g" ${BIN_DIR}/bin/* +fi + +# modify TARGET_CONF_FILE +if [ ${platform} == "Darwin" ]; then + sed -i "" "s~TARGET_CONF_FILE~${TARGET_CONF_FILE}~g" ${BIN_DIR}/bin/* +else + sed -i "s~TARGET_CONF_FILE~${TARGET_CONF_FILE}~g" ${BIN_DIR}/bin/* +fi + +# modify TARGET_LOG_CONF_FILE +if [ ${platform} == "Darwin" ]; then + sed -i "" "s~TARGET_LOG_CONF_FILE~${TARGET_LOG_CONF_FILE}~g" ${BIN_DIR}/bin/* +else + sed -i "s~TARGET_LOG_CONF_FILE~${TARGET_LOG_CONF_FILE}~g" ${BIN_DIR}/bin/* +fi + +cp -r profiles/${PROFILE}/* ${CONF_DIR} + +cd ${TARGET_FOLDER} + +tar czf ${TAR_NAME}.tar.gz ${TAR_NAME}/* + diff --git a/examples/helloworld/dubbo/go-client/assembly/linux/dev.sh b/examples/helloworld/dubbo/go-client/assembly/linux/dev.sh new file mode 100644 index 0000000000000000000000000000000000000000..3373f01b948b708cd7bc1958c9d56a9042c60a68 --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/linux/dev.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for dev env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2017-10-18 13:24 +# FILE : dev.sh +# ****************************************************** + + +set -e + +export GOOS=linux +export GOARCH=amd64 + +export PROFILE="dev" + +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-client/assembly/linux/release.sh b/examples/helloworld/dubbo/go-client/assembly/linux/release.sh new file mode 100644 index 0000000000000000000000000000000000000000..34867b8b3488778cd76a1dc7802393dcab6b0df0 --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/linux/release.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for release env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=linux +export GOARCH=amd64 + +export PROFILE="release" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-client/assembly/linux/test.sh b/examples/helloworld/dubbo/go-client/assembly/linux/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..1bbbefd1e14e08c16deaf859e2841f4d1fe88e9c --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/linux/test.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for test env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=linux +export GOARCH=amd64 + +export PROFILE="test" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-client/assembly/mac/dev.sh b/examples/helloworld/dubbo/go-client/assembly/mac/dev.sh new file mode 100644 index 0000000000000000000000000000000000000000..b68ac83b6524a6713cd90c4fc5968fe64b1a9545 --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/mac/dev.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for dev env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2017-10-18 13:24 +# FILE : dev.sh +# ****************************************************** + + +set -e + +export GOOS=darwin +export GOARCH=amd64 + +export PROFILE="dev" + +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-client/assembly/mac/release.sh b/examples/helloworld/dubbo/go-client/assembly/mac/release.sh new file mode 100644 index 0000000000000000000000000000000000000000..688288b3b1b989e8af70a3674b34ea8e0668f3b4 --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/mac/release.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for release env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=darwin +export GOARCH=amd64 + +export PROFILE="release" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-client/assembly/mac/test.sh b/examples/helloworld/dubbo/go-client/assembly/mac/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..56d6c11ecd6a1dc5984c74b88c10be9239e57428 --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/mac/test.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for test env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=darwin +export GOARCH=amd64 + +export PROFILE="test" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-client/assembly/windows/dev.sh b/examples/helloworld/dubbo/go-client/assembly/windows/dev.sh new file mode 100644 index 0000000000000000000000000000000000000000..91cf6f23bcbecb26db798469a30529261aabbbb6 --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/windows/dev.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for dev env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2017-10-18 13:24 +# FILE : dev.sh +# ****************************************************** + + +set -e + +export GOOS=linux +export GOARCH=amd64 + +export PROFILE="dev" +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-client/assembly/windows/release.sh b/examples/helloworld/dubbo/go-client/assembly/windows/release.sh new file mode 100644 index 0000000000000000000000000000000000000000..f317720bd53d9c9e5f8f484b6eb682c9c736af0c --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/windows/release.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for release env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=windows +export GOARCH=amd64 + +export PROFILE="release" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-client/assembly/windows/test.sh b/examples/helloworld/dubbo/go-client/assembly/windows/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..7dd2bec5260e647b57a46aaa37acc098babff068 --- /dev/null +++ b/examples/helloworld/dubbo/go-client/assembly/windows/test.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for test env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=windows +export GOARCH=amd64 + +export PROFILE="test" +export PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then + . ${PROJECT_HOME}/assembly/common/app.properties +fi + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then + sh ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/dubbo/go-client/profiles/dev/client.yml b/examples/helloworld/dubbo/go-client/profiles/dev/client.yml similarity index 77% rename from examples/dubbo/go-client/profiles/dev/client.yml rename to examples/helloworld/dubbo/go-client/profiles/dev/client.yml index 1595f23c34d3a374c47678ecc7350696e1d8b2c9..fed05b09734c41ef7b53ad2d88a953f997d50735 100644 --- a/examples/dubbo/go-client/profiles/dev/client.yml +++ b/examples/helloworld/dubbo/go-client/profiles/dev/client.yml @@ -17,30 +17,25 @@ application_config: environment : "dev" registries : - "hangzhouzk": - # 对应java配置中address属性的zookeeper <dubbo:registry address="zookeeper://127.0.0.1:2181"/> + "demoZk": protocol: "zookeeper" timeout : "3s" address: "127.0.0.1:2181" username: "" password: "" - "shanghaizk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2182" - username: "" - password: "" + references: "UserProvider": # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 - registry: "hangzhouzk" + registry: "demoZk" protocol : "dubbo" interface : "com.ikurento.user.UserProvider" cluster: "failover" methods : - - name: "GetUser" - retries: 3 + - name: "GetUser" + retries: 3 + protocol_conf: dubbo: @@ -48,7 +43,6 @@ protocol_conf: connection_number: 2 heartbeat_period: "5s" session_timeout: "20s" - fail_fast_timeout: "5s" pool_size: 64 pool_ttl: 600 getty_session_param: diff --git a/examples/helloworld/dubbo/go-client/profiles/dev/log.yml b/examples/helloworld/dubbo/go-client/profiles/dev/log.yml new file mode 100644 index 0000000000000000000000000000000000000000..59fa4279ad85272c4c49d532beaf23b74d00f58a --- /dev/null +++ b/examples/helloworld/dubbo/go-client/profiles/dev/log.yml @@ -0,0 +1,28 @@ + +level: "debug" +development: true +disableCaller: false +disableStacktrace: false +sampling: +encoding: "console" + +# encoder +encoderConfig: + messageKey: "message" + levelKey: "level" + timeKey: "time" + nameKey: "logger" + callerKey: "caller" + stacktraceKey: "stacktrace" + lineEnding: "" + levelEncoder: "capitalColor" + timeEncoder: "iso8601" + durationEncoder: "seconds" + callerEncoder: "short" + nameEncoder: "" + +outputPaths: + - "stderr" +errorOutputPaths: + - "stderr" +initialFields: diff --git a/examples/dubbo/go-client/profiles/release/client.yml b/examples/helloworld/dubbo/go-client/profiles/release/client.yml similarity index 87% rename from examples/dubbo/go-client/profiles/release/client.yml rename to examples/helloworld/dubbo/go-client/profiles/release/client.yml index 7a193ea64d783220f016c6b6220d602a5c586129..02bf722754632f12d0e8e7cab3979ce360ffd7c7 100644 --- a/examples/dubbo/go-client/profiles/release/client.yml +++ b/examples/helloworld/dubbo/go-client/profiles/release/client.yml @@ -23,20 +23,13 @@ registries : address: "127.0.0.1:2181" username: "" password: "" - "shanghaizk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2182" - username: "" - password: "" + references: "UserProvider": # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 registry: "hangzhouzk" protocol : "dubbo" -# version: "2.0" -# group: "as" interface : "com.ikurento.user.UserProvider" cluster: "failover" methods : @@ -49,7 +42,6 @@ protocol_conf: connection_number: 2 heartbeat_period: "5s" session_timeout: "20s" - fail_fast_timeout: "5s" pool_size: 64 pool_ttl: 600 getty_session_param: diff --git a/examples/helloworld/dubbo/go-client/profiles/release/log.yml b/examples/helloworld/dubbo/go-client/profiles/release/log.yml new file mode 100644 index 0000000000000000000000000000000000000000..e0514be020eedf594d99d112183cdd5ce199e46d --- /dev/null +++ b/examples/helloworld/dubbo/go-client/profiles/release/log.yml @@ -0,0 +1,28 @@ + +level: "warn" +development: true +disableCaller: true +disableStacktrace: true +sampling: +encoding: "console" + +# encoder +encoderConfig: + messageKey: "message" + levelKey: "level" + timeKey: "time" + nameKey: "logger" + callerKey: "caller" + stacktraceKey: "stacktrace" + lineEnding: "" + levelEncoder: "capitalColor" + timeEncoder: "iso8601" + durationEncoder: "seconds" + callerEncoder: "short" + nameEncoder: "" + +outputPaths: + - "stderr" +errorOutputPaths: + - "stderr" +initialFields: diff --git a/examples/dubbo/go-client/profiles/test/client.yml b/examples/helloworld/dubbo/go-client/profiles/test/client.yml similarity index 84% rename from examples/dubbo/go-client/profiles/test/client.yml rename to examples/helloworld/dubbo/go-client/profiles/test/client.yml index 24ede19d7d2365fb9c7d92d31bc312cfc7935388..417a388c6cfb38a6a1563e9c4ab8856e4b2f30f8 100644 --- a/examples/dubbo/go-client/profiles/test/client.yml +++ b/examples/helloworld/dubbo/go-client/profiles/test/client.yml @@ -23,25 +23,17 @@ registries : address: "127.0.0.1:2181" username: "" password: "" - "shanghaizk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2182" - username: "" - password: "" references: "UserProvider": # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 registry: "hangzhouzk" protocol : "dubbo" -# version: "2.0" -# group: "as" interface : "com.ikurento.user.UserProvider" cluster: "failover" methods : - - name: "GetUser" - retries: 3 + - name: "GetUser" + retries: 3 protocol_conf: dubbo: @@ -49,7 +41,6 @@ protocol_conf: connection_number: 2 heartbeat_period: "5s" session_timeout: "20s" - fail_fast_timeout: "5s" pool_size: 64 pool_ttl: 600 getty_session_param: diff --git a/examples/helloworld/dubbo/go-client/profiles/test/log.yml b/examples/helloworld/dubbo/go-client/profiles/test/log.yml new file mode 100644 index 0000000000000000000000000000000000000000..baee0b7248484e425f88f35ab128212c931ff85e --- /dev/null +++ b/examples/helloworld/dubbo/go-client/profiles/test/log.yml @@ -0,0 +1,28 @@ + +level: "info" +development: false +disableCaller: false +disableStacktrace: true +sampling: +encoding: "console" + +# encoder +encoderConfig: + messageKey: "message" + levelKey: "level" + timeKey: "time" + nameKey: "logger" + callerKey: "caller" + stacktraceKey: "stacktrace" + lineEnding: "" + levelEncoder: "capitalColor" + timeEncoder: "iso8601" + durationEncoder: "seconds" + callerEncoder: "short" + nameEncoder: "" + +outputPaths: + - "stderr" +errorOutputPaths: + - "stderr" +initialFields: diff --git a/examples/helloworld/dubbo/go-server/app/server.go b/examples/helloworld/dubbo/go-server/app/server.go new file mode 100644 index 0000000000000000000000000000000000000000..f02a6ba05e8723410c985823caafe88192f5af7e --- /dev/null +++ b/examples/helloworld/dubbo/go-server/app/server.go @@ -0,0 +1,77 @@ +/* + * 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 main + +import ( + "fmt" + "os" + "os/signal" + "syscall" + "time" +) + +import ( + "github.com/apache/dubbo-go/common/logger" + "github.com/apache/dubbo-go/config" + _ "github.com/apache/dubbo-go/protocol/dubbo" + _ "github.com/apache/dubbo-go/registry/protocol" + + _ "github.com/apache/dubbo-go/common/proxy/proxy_factory" + _ "github.com/apache/dubbo-go/filter/impl" + + _ "github.com/apache/dubbo-go/cluster/cluster_impl" + _ "github.com/apache/dubbo-go/cluster/loadbalance" + _ "github.com/apache/dubbo-go/registry/zookeeper" +) + +var ( + survivalTimeout = int(3e9) +) + +// they are necessary: +// export CONF_PROVIDER_FILE_PATH="xxx" +// export APP_LOG_CONF_FILE="xxx" +func main() { + + config.Load() + + initSignal() +} + +func initSignal() { + signals := make(chan os.Signal, 1) + // It is not possible to block SIGKILL or syscall.SIGSTOP + signal.Notify(signals, os.Interrupt, os.Kill, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT) + for { + sig := <-signals + logger.Infof("get signal %s", sig.String()) + switch sig { + case syscall.SIGHUP: + // reload() + default: + go time.AfterFunc(time.Duration(survivalTimeout), func() { + logger.Warnf("app exit now by force...") + os.Exit(1) + }) + + // The program exits normally or timeout forcibly exits. + fmt.Println("provider app exit now...") + return + } + } +} diff --git a/examples/helloworld/dubbo/go-server/app/user.go b/examples/helloworld/dubbo/go-server/app/user.go new file mode 100644 index 0000000000000000000000000000000000000000..ee7aa1c7ed33654ae38bdf2d8fd77257a70e3e85 --- /dev/null +++ b/examples/helloworld/dubbo/go-server/app/user.go @@ -0,0 +1,59 @@ +/* + * 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 main + +import ( + "context" + "time" +) + +import ( + "github.com/apache/dubbo-go-hessian2" +) + +import ( + "github.com/apache/dubbo-go/config" +) + +func init() { + config.SetProviderService(new(UserProvider)) + // ------for hessian2------ + hessian.RegisterPOJO(&User{}) +} + +type User struct { + Id string + Name string + Age int32 + Time time.Time +} + +type UserProvider struct { +} + +func (u *UserProvider) GetUser(ctx context.Context, req []interface{}) (*User, error) { + return &User{"A001", "Alex Stocks", 18, time.Now()}, nil +} + +func (u *UserProvider) Reference() string { + return "UserProvider" +} + +func (u User) JavaClassName() string { + return "com.ikurento.user.User" +} diff --git a/examples/helloworld/dubbo/go-server/assembly/bin/load.sh b/examples/helloworld/dubbo/go-server/assembly/bin/load.sh new file mode 100644 index 0000000000000000000000000000000000000000..47fc5e38ded155a43c30b8cbf4d2a5ae04b58d0c --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/bin/load.sh @@ -0,0 +1,144 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : dubbogo app devops script +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-05-13 02:01 +# FILE : load.sh +# ****************************************************** + +APP_NAME="APPLICATION_NAME" +APP_ARGS="" + + +PROJECT_HOME="" +OS_NAME=`uname` +if [[ ${OS_NAME} != "Windows" ]]; then + PROJECT_HOME=`pwd` + PROJECT_HOME=${PROJECT_HOME}"/" +fi + +export CONF_PROVIDER_FILE_PATH=${PROJECT_HOME}"TARGET_CONF_FILE" +export APP_LOG_CONF_FILE=${PROJECT_HOME}"TARGET_LOG_CONF_FILE" + +usage() { + echo "Usage: $0 start [conf suffix]" + echo " $0 stop" + echo " $0 term" + echo " $0 restart" + echo " $0 list" + echo " $0 monitor" + echo " $0 crontab" + exit +} + +start() { + arg=$1 + if [ "$arg" = "" ];then + echo "No registry type! Default server.yml!" + else + export CONF_PROVIDER_FILE_PATH=${CONF_PROVIDER_FILE_PATH//\.yml/\_$arg\.yml} + fi + if [ ! -f "${CONF_PROVIDER_FILE_PATH}" ];then + echo $CONF_PROVIDER_FILE_PATH" is not existing!" + return + fi + APP_LOG_PATH="${PROJECT_HOME}logs/" + mkdir -p ${APP_LOG_PATH} + APP_BIN=${PROJECT_HOME}sbin/${APP_NAME} + chmod u+x ${APP_BIN} + # CMD="nohup ${APP_BIN} ${APP_ARGS} >>${APP_NAME}.nohup.out 2>&1 &" + CMD="${APP_BIN}" + eval ${CMD} + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + CUR=`date +%FT%T` + if [ "${PID}" != "" ]; then + for p in ${PID} + do + echo "start ${APP_NAME} ( pid =" ${p} ") at " ${CUR} + done + fi +} + +stop() { + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + if [ "${PID}" != "" ]; + then + for ps in ${PID} + do + echo "kill -SIGINT ${APP_NAME} ( pid =" ${ps} ")" + kill -2 ${ps} + done + fi +} + + +term() { + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $2}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{print $1}'` + fi + if [ "${PID}" != "" ]; + then + for ps in ${PID} + do + echo "kill -9 ${APP_NAME} ( pid =" ${ps} ")" + kill -9 ${ps} + done + fi +} + +list() { + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{printf("%s,%s,%s,%s\n", $1, $2, $9, $10)}'` + if [[ ${OS_NAME} != "Linux" && ${OS_NAME} != "Darwin" ]]; then + PID=`ps aux | grep -w ${APP_NAME} | grep -v grep | awk '{printf("%s,%s,%s,%s,%s\n", $1, $4, $6, $7, $8)}'` + fi + + if [ "${PID}" != "" ]; then + echo "list ${APP_NAME}" + + if [[ ${OS_NAME} == "Linux" || ${OS_NAME} == "Darwin" ]]; then + echo "index: user, pid, start, duration" + else + echo "index: PID, WINPID, UID, STIME, COMMAND" + fi + idx=0 + for ps in ${PID} + do + echo "${idx}: ${ps}" + ((idx ++)) + done + fi +} + +opt=$1 +case C"$opt" in + Cstart) + start $2 + ;; + Cstop) + stop + ;; + Cterm) + term + ;; + Crestart) + term + start $2 + ;; + Clist) + list + ;; + C*) + usage + ;; +esac + diff --git a/examples/helloworld/dubbo/go-server/assembly/common/app.properties b/examples/helloworld/dubbo/go-server/assembly/common/app.properties new file mode 100644 index 0000000000000000000000000000000000000000..dffb755b0811dd140d3f04e232f5f80ff60181df --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/common/app.properties @@ -0,0 +1,17 @@ +# dubbogo application configure script +# ****************************************************** +# DESC : application environment variable +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:29 +# FILE : app.properties +# ****************************************************** + +TARGET_EXEC_NAME="user_info_server" +# BUILD_PACKAGE="dubbogo-examples/user-info/server/app" +BUILD_PACKAGE="app" + +TARGET_CONF_FILE="conf/server.yml" +TARGET_LOG_CONF_FILE="conf/log.yml" diff --git a/examples/helloworld/dubbo/go-server/assembly/common/build.sh b/examples/helloworld/dubbo/go-server/assembly/common/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..15ac904f7c265d942d7018439719af7e7391aa41 --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/common/build.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:28 +# FILE : build.sh +# ****************************************************** + +rm -rf target/ + +PROJECT_HOME=`pwd` +TARGET_FOLDER=${PROJECT_HOME}/target/${GOOS} + +TARGET_SBIN_NAME=${TARGET_EXEC_NAME} +version=`cat app/version.go | grep Version | grep -v "Apache" | awk -F '=' '{print $2}' | awk -F '"' '{print $2}'` +if [[ ${GOOS} == "windows" ]]; then + TARGET_SBIN_NAME=${TARGET_SBIN_NAME}.exe +fi +TARGET_NAME=${TARGET_FOLDER}/${TARGET_SBIN_NAME} +if [[ $PROFILE = "test" ]]; then + # GFLAGS=-gcflags "-N -l" -race -x -v # -x会把go build的详细过程输出 + # GFLAGS=-gcflags "-N -l" -race -v + # GFLAGS="-gcflags \"-N -l\" -v" + cd ${BUILD_PACKAGE} && go build -gcflags "-N -l" -x -v -i -o ${TARGET_NAME} && cd - +else + # -s去掉符号表(然后panic时候的stack trace就没有任何文件名/行号信息了,这个等价于普通C/C++程序被strip的效果), + # -w去掉DWARF调试信息,得到的程序就不能用gdb调试了。-s和-w也可以分开使用,一般来说如果不打算用gdb调试, + # -w基本没啥损失。-s的损失就有点大了。 + cd ${BUILD_PACKAGE} && go build -ldflags "-w" -x -v -i -o ${TARGET_NAME} && cd - +fi + +TAR_NAME=${TARGET_EXEC_NAME}-${version}-`date "+%Y%m%d-%H%M"`-${PROFILE} + +mkdir -p ${TARGET_FOLDER}/${TAR_NAME} + +SBIN_DIR=${TARGET_FOLDER}/${TAR_NAME}/sbin +BIN_DIR=${TARGET_FOLDER}/${TAR_NAME} +CONF_DIR=${TARGET_FOLDER}/${TAR_NAME}/conf + +mkdir -p ${SBIN_DIR} +mkdir -p ${CONF_DIR} + +mv ${TARGET_NAME} ${SBIN_DIR} +cp -r assembly/bin ${BIN_DIR} +# modify APPLICATION_NAME +# OS=`uname` +# if [[ $OS=="Darwin" ]]; then +if [ "$(uname)" == "Darwin" ]; then + sed -i "" "s~APPLICATION_NAME~${TARGET_EXEC_NAME}~g" ${BIN_DIR}/bin/* +else + sed -i "s~APPLICATION_NAME~${TARGET_EXEC_NAME}~g" ${BIN_DIR}/bin/* +fi +# modify TARGET_CONF_FILE +if [ "$(uname)" == "Darwin" ]; then + sed -i "" "s~TARGET_CONF_FILE~${TARGET_CONF_FILE}~g" ${BIN_DIR}/bin/* +else + sed -i "s~TARGET_CONF_FILE~${TARGET_CONF_FILE}~g" ${BIN_DIR}/bin/* +fi +# modify TARGET_LOG_CONF_FILE +if [ "$(uname)" == "Darwin" ]; then + sed -i "" "s~TARGET_LOG_CONF_FILE~${TARGET_LOG_CONF_FILE}~g" ${BIN_DIR}/bin/* +else + sed -i "s~TARGET_LOG_CONF_FILE~${TARGET_LOG_CONF_FILE}~g" ${BIN_DIR}/bin/* +fi + +cp -r profiles/${PROFILE}/* ${CONF_DIR} + +cd ${TARGET_FOLDER} + +tar czf ${TAR_NAME}.tar.gz ${TAR_NAME}/* + diff --git a/examples/helloworld/dubbo/go-server/assembly/linux/dev.sh b/examples/helloworld/dubbo/go-server/assembly/linux/dev.sh new file mode 100644 index 0000000000000000000000000000000000000000..55886f09fb4873be84cfa46aae592f5f000120a4 --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/linux/dev.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for dev env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2018-06-24 17:32 +# FILE : dev.sh +# ****************************************************** + + +set -e + +export GOOS=linux +export GOARCH=amd64 + +PROFILE=dev + +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then +. ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then +. ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-server/assembly/linux/release.sh b/examples/helloworld/dubbo/go-server/assembly/linux/release.sh new file mode 100644 index 0000000000000000000000000000000000000000..9772ad9614583917d62beba2db9fcaefea63e1ed --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/linux/release.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for release env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:25 +# FILE : release.sh +# ****************************************************** + + +set -e + +export GOOS=linux +export GOARCH=amd64 + +PROFILE=release + +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then +. ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then +. ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-server/assembly/linux/test.sh b/examples/helloworld/dubbo/go-server/assembly/linux/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..2fc4a98862bee5ef11a23e1b74058627a899181d --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/linux/test.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for test env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=linux +export GOARCH=amd64 + +PROFILE=test + +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then +. ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then +. ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-server/assembly/mac/dev.sh b/examples/helloworld/dubbo/go-server/assembly/mac/dev.sh new file mode 100644 index 0000000000000000000000000000000000000000..5dfa78490b895ce556c809ead32b6f517a5f1450 --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/mac/dev.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for dev env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2018-06-24 17:32 +# FILE : dev.sh +# ****************************************************** + + +set -e + +export GOOS=darwin +export GOARCH=amd64 + +PROFILE=dev + +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then +. ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then +. ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-server/assembly/mac/release.sh b/examples/helloworld/dubbo/go-server/assembly/mac/release.sh new file mode 100644 index 0000000000000000000000000000000000000000..1ec21c7b511ccce9eddfac22a2374b57a7a697bf --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/mac/release.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for release env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:25 +# FILE : release.sh +# ****************************************************** + + +set -e + +export GOOS=darwin +export GOARCH=amd64 + +PROFILE=release + +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then +. ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then +. ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-server/assembly/mac/test.sh b/examples/helloworld/dubbo/go-server/assembly/mac/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..d34914c7dbed0e442b4accf51a3ecdf7c2984db8 --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/mac/test.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for release env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:25 +# FILE : release.sh +# ****************************************************** + +set -e + +export GOOS=darwin +export GOARCH=amd64 + +PROFILE=test + +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then +. ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then +. ${PROJECT_HOME}/assembly/common/build.sh +fi + diff --git a/examples/helloworld/dubbo/go-server/assembly/windows/dev.sh b/examples/helloworld/dubbo/go-server/assembly/windows/dev.sh new file mode 100644 index 0000000000000000000000000000000000000000..97fbb6f698e500ad08d971b13cc1ffd00cd97803 --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/windows/dev.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for dev env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2018-06-24 17:34 +# FILE : dev.sh +# ****************************************************** + + +set -e + +export GOOS=windows +export GOARCH=amd64 + +PROFILE=dev + +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then +. ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then +. ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-server/assembly/windows/release.sh b/examples/helloworld/dubbo/go-server/assembly/windows/release.sh new file mode 100644 index 0000000000000000000000000000000000000000..782cb10c7828eb277b5905f10f8dd6ad1c2d6bed --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/windows/release.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for release env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:25 +# FILE : release.sh +# ****************************************************** + + +set -e + +export GOOS=windows +export GOARCH=amd64 + +PROFILE=release + +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then +. ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then +. ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-server/assembly/windows/test.sh b/examples/helloworld/dubbo/go-server/assembly/windows/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..2037ddecf2545f1543d5d28be728fb0899722098 --- /dev/null +++ b/examples/helloworld/dubbo/go-server/assembly/windows/test.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# ****************************************************** +# DESC : build script for test env +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2016-07-12 16:34 +# FILE : test.sh +# ****************************************************** + + +set -e + +export GOOS=windows +export GOARCH=amd64 + +PROFILE=test + +PROJECT_HOME=`pwd` + +if [ -f "${PROJECT_HOME}/assembly/common/app.properties" ]; then +. ${PROJECT_HOME}/assembly/common/app.properties +fi + + +if [ -f "${PROJECT_HOME}/assembly/common/build.sh" ]; then +. ${PROJECT_HOME}/assembly/common/build.sh +fi diff --git a/examples/helloworld/dubbo/go-server/profiles/dev/log.yml b/examples/helloworld/dubbo/go-server/profiles/dev/log.yml new file mode 100644 index 0000000000000000000000000000000000000000..59fa4279ad85272c4c49d532beaf23b74d00f58a --- /dev/null +++ b/examples/helloworld/dubbo/go-server/profiles/dev/log.yml @@ -0,0 +1,28 @@ + +level: "debug" +development: true +disableCaller: false +disableStacktrace: false +sampling: +encoding: "console" + +# encoder +encoderConfig: + messageKey: "message" + levelKey: "level" + timeKey: "time" + nameKey: "logger" + callerKey: "caller" + stacktraceKey: "stacktrace" + lineEnding: "" + levelEncoder: "capitalColor" + timeEncoder: "iso8601" + durationEncoder: "seconds" + callerEncoder: "short" + nameEncoder: "" + +outputPaths: + - "stderr" +errorOutputPaths: + - "stderr" +initialFields: diff --git a/examples/helloworld/dubbo/go-server/profiles/dev/server.yml b/examples/helloworld/dubbo/go-server/profiles/dev/server.yml new file mode 100644 index 0000000000000000000000000000000000000000..be7eedeaa3fd186f4cd2ea264b31429165e55bf1 --- /dev/null +++ b/examples/helloworld/dubbo/go-server/profiles/dev/server.yml @@ -0,0 +1,57 @@ +# dubbo server yaml configure file + + +# application config +application_config: + organization : "ikurento.com" + name : "BDTService" + module : "dubbogo user-info server" + version : "0.0.1" + owner : "ZX" + environment : "dev" + +registries : + "demoZk": + protocol: "zookeeper" + timeout : "3s" + address: "127.0.0.1:2181" + +services: + "UserProvider": + # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 + registry: "demoZk" + protocol : "dubbo" + # 相当于dubbo.xml中的interface + interface : "com.ikurento.user.UserProvider" + loadbalance: "random" + warmup: "100" + cluster: "failover" + methods: + - name: "GetUser" + retries: 1 + loadbalance: "random" + +protocols: + "dubbo": + name: "dubbo" + port: 20000 + + +protocol_conf: + dubbo: + session_number: 700 + session_timeout: "20s" + getty_session_param: + compress_encoding: false + tcp_no_delay: true + tcp_keep_alive: true + keep_alive_period: "120s" + tcp_r_buf_size: 262144 + tcp_w_buf_size: 65536 + pkg_rq_size: 1024 + pkg_wq_size: 512 + tcp_read_timeout: "1s" + tcp_write_timeout: "5s" + wait_timeout: "1s" + max_msg_len: 1024 + session_name: "server" diff --git a/examples/helloworld/dubbo/go-server/profiles/release/log.yml b/examples/helloworld/dubbo/go-server/profiles/release/log.yml new file mode 100644 index 0000000000000000000000000000000000000000..e0514be020eedf594d99d112183cdd5ce199e46d --- /dev/null +++ b/examples/helloworld/dubbo/go-server/profiles/release/log.yml @@ -0,0 +1,28 @@ + +level: "warn" +development: true +disableCaller: true +disableStacktrace: true +sampling: +encoding: "console" + +# encoder +encoderConfig: + messageKey: "message" + levelKey: "level" + timeKey: "time" + nameKey: "logger" + callerKey: "caller" + stacktraceKey: "stacktrace" + lineEnding: "" + levelEncoder: "capitalColor" + timeEncoder: "iso8601" + durationEncoder: "seconds" + callerEncoder: "short" + nameEncoder: "" + +outputPaths: + - "stderr" +errorOutputPaths: + - "stderr" +initialFields: diff --git a/examples/dubbo/go-server/profiles/release/server.yml b/examples/helloworld/dubbo/go-server/profiles/release/server.yml similarity index 89% rename from examples/dubbo/go-server/profiles/release/server.yml rename to examples/helloworld/dubbo/go-server/profiles/release/server.yml index 3db12902f1d349e1703f2f977c682c61b0d35938..4786e83669046babbfc4758829155d8f4ce3a438 100644 --- a/examples/dubbo/go-server/profiles/release/server.yml +++ b/examples/helloworld/dubbo/go-server/profiles/release/server.yml @@ -17,12 +17,6 @@ registries : address: "127.0.0.1:2181" username: "" password: "" - "shanghaizk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2182" - username: "" - password: "" services: @@ -40,6 +34,7 @@ services: retries: 1 loadbalance: "random" + protocols: "dubbo1": name: "dubbo" @@ -50,7 +45,6 @@ protocols: protocol_conf: dubbo: session_number: 700 - fail_fast_timeout: "5s" session_timeout: "20s" getty_session_param: compress_encoding: false diff --git a/examples/helloworld/dubbo/go-server/profiles/test/log.yml b/examples/helloworld/dubbo/go-server/profiles/test/log.yml new file mode 100644 index 0000000000000000000000000000000000000000..baee0b7248484e425f88f35ab128212c931ff85e --- /dev/null +++ b/examples/helloworld/dubbo/go-server/profiles/test/log.yml @@ -0,0 +1,28 @@ + +level: "info" +development: false +disableCaller: false +disableStacktrace: true +sampling: +encoding: "console" + +# encoder +encoderConfig: + messageKey: "message" + levelKey: "level" + timeKey: "time" + nameKey: "logger" + callerKey: "caller" + stacktraceKey: "stacktrace" + lineEnding: "" + levelEncoder: "capitalColor" + timeEncoder: "iso8601" + durationEncoder: "seconds" + callerEncoder: "short" + nameEncoder: "" + +outputPaths: + - "stderr" +errorOutputPaths: + - "stderr" +initialFields: diff --git a/examples/dubbo/go-server/profiles/test/server.yml b/examples/helloworld/dubbo/go-server/profiles/test/server.yml similarity index 80% rename from examples/dubbo/go-server/profiles/test/server.yml rename to examples/helloworld/dubbo/go-server/profiles/test/server.yml index 12f10e004c6b1b5ea1afcf37fe79306bd4d10d82..ba6eb2b8005a4dc2d655f44ec38b93a01072d4f1 100644 --- a/examples/dubbo/go-server/profiles/test/server.yml +++ b/examples/helloworld/dubbo/go-server/profiles/test/server.yml @@ -17,12 +17,7 @@ registries : address: "127.0.0.1:2181" username: "" password: "" - "shanghaizk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2182" - username: "" - password: "" + services: @@ -36,21 +31,20 @@ services: warmup: "100" cluster: "failover" methods: - - name: "GetUser" - retries: 1 - loadbalance: "random" + - name: "GetUser" + retries: 1 + loadbalance: "random" protocols: "dubbo1": - name: "dubbo" - # ip : "127.0.0.1" - port: 20000 + name: "dubbo" + # ip : "127.0.0.1" + port: 20000 protocol_conf: dubbo: session_number: 700 - fail_fast_timeout: "5s" session_timeout: "20s" getty_session_param: compress_encoding: false diff --git a/examples/helloworld/dubbo/java-server/build.sh b/examples/helloworld/dubbo/java-server/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..0c197da639c1c1d9375e18c24dd73366c49deefe --- /dev/null +++ b/examples/helloworld/dubbo/java-server/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# ****************************************************** +# EMAIL : alexstocks@foxmail.com +# FILE : build.sh +# ****************************************************** + +# mvn dependency:sources +mvn clean package -Dmaven.test.skip +# mvn -X clean compile package -DskipTests=true diff --git a/examples/helloworld/dubbo/java-server/pom.xml b/examples/helloworld/dubbo/java-server/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..975157865e59f24693d755dd20b0aac4b179a793 --- /dev/null +++ b/examples/helloworld/dubbo/java-server/pom.xml @@ -0,0 +1,181 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.ikurento</groupId> + <artifactId>user-info-server</artifactId> + <packaging>jar</packaging> + <version>0.2.0</version> + <description>The demo provider module of dubbo project</description> + <properties> + <skip_maven_deploy>false</skip_maven_deploy> + + <dubbo-version>2.6.5</dubbo-version> + <dubbo-jsonrpc-version>1.0.1</dubbo-jsonrpc-version> + </properties> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>com.alibaba</groupId> + <artifactId>dubbo-dependencies-bom</artifactId> + <version>${dubbo-version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>1.7.25</version> + </dependency> + + <dependency> + <groupId>com.alibaba</groupId> + <artifactId>dubbo</artifactId> + <version>${dubbo-version}</version> + <exclusions> + </exclusions> + </dependency> + + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty-all</artifactId> + </dependency> + <dependency> + <groupId>org.apache.curator</groupId> + <artifactId>curator-framework</artifactId> + <version>2.12.0</version> + </dependency> + + <dependency> + <groupId>com.qianmi</groupId> + <artifactId>dubbo-rpc-jsonrpc</artifactId> + <version>${dubbo-jsonrpc-version}</version> + <exclusions> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.mortbay.jetty</groupId> + <artifactId>jetty</artifactId> + <version>6.1.26</version> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>2.9.9</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>2.9.9</version> + </dependency> + + <dependency> + <groupId>com.github.sgroschupf</groupId> + <artifactId>zkclient</artifactId> + <version>0.1</version> + <exclusions> + <exclusion> + <artifactId>org.apache.zookeeper</artifactId> + <groupId>zookeeper</groupId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.apache.zookeeper</groupId> + <artifactId>zookeeper</artifactId> + <version>3.4.14</version> + </dependency> + + </dependencies> + + <repositories> + <repository> + <id>nexus-aliyu</id> + <url>http://maven.aliyun.com/nexus/content/groups/public</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>nexus-aliyu</id> + <url>http://maven.aliyun.com/nexus/content/groups/public</url> + <releases> + <enabled>true</enabled> + </releases> + <snapshots> + <enabled>false</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + + + <build> + + <plugins> + <plugin> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>unpack</id> + <phase>package</phase> + <goals> + <goal>unpack</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>com.alibaba</groupId> + <artifactId>dubbo</artifactId> + <version>${dubbo-version}</version> + <outputDirectory>${project.build.directory}/dubbo</outputDirectory> + <includes>META-INF/assembly/**</includes> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <id>make-assembly</id> + <phase>package</phase> + <goals> + <goal>single</goal> + </goals> + <configuration> + <descriptors> + <descriptor>src/main/assembly/assembly.xml</descriptor> + </descriptors> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + + +</project> + + diff --git a/examples/helloworld/dubbo/java-server/script/debug.sh b/examples/helloworld/dubbo/java-server/script/debug.sh new file mode 100644 index 0000000000000000000000000000000000000000..27c5d800d846018127e762944151aa8e9ad4495d --- /dev/null +++ b/examples/helloworld/dubbo/java-server/script/debug.sh @@ -0,0 +1,16 @@ +#!/us1r/bin/env bash +# ****************************************************** +# DESC : +# AUTHOR : Alex Stocks +# VERSION : 1.0 +# LICENCE : Apache License 2.0 +# EMAIL : alexstocks@foxmail.com +# MOD : 2017-10-09 21:52 +# FILE : to debug user info dubbo server +# ****************************************************** + +# jdb -classpath /Users/alex/tmp/us/conf:/Users/alex/tmp/us/lib/*:/Users/alex/test/java/dubbo/2.5.4/dubbo-remoting/dubbo-remoting-api/src/main/java/ com.alibaba.dubbo.container.Main +jdb -classpath /Users/alex/tmp/us/conf:/Users/alex/tmp/us/lib/* -sourcepath /Users/alex/test/java/dubbo/2.5.4/dubbo-remoting/dubbo-remoting-api/src/main/java/:/Users/alex/tmp/java-server/src/main/java com.alibaba.dubbo.container.Main +# jdb stop at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec:76 +# run + diff --git a/examples/helloworld/dubbo/java-server/src/main/assembly/assembly.xml b/examples/helloworld/dubbo/java-server/src/main/assembly/assembly.xml new file mode 100644 index 0000000000000000000000000000000000000000..2f01fea20f5391112cccb88c87bfe4ae1b59750a --- /dev/null +++ b/examples/helloworld/dubbo/java-server/src/main/assembly/assembly.xml @@ -0,0 +1,45 @@ +<!-- + - Copyright 1999-2011 Alibaba Group. + - + - Licensed 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. +--> +<assembly> + <id>assembly</id> + <formats> + <format>tar.gz</format> + </formats> + <includeBaseDirectory>true</includeBaseDirectory> + <fileSets> + <fileSet> + <directory>${project.build.directory}/dubbo/META-INF/assembly/bin</directory> + <outputDirectory>bin</outputDirectory> + <fileMode>0755</fileMode> + <directoryMode>0755</directoryMode> + </fileSet> + <fileSet> + <directory>src/main/assembly/conf</directory> + <includes> + <include>dubbo.properties</include> + <include>log4j.*</include> + </includes> + <outputDirectory>conf</outputDirectory> + <fileMode>0644</fileMode> + <directoryMode>0755</directoryMode> + </fileSet> + </fileSets> + <dependencySets> + <dependencySet> + <outputDirectory>lib</outputDirectory> + </dependencySet> + </dependencySets> +</assembly> \ No newline at end of file diff --git a/examples/helloworld/dubbo/java-server/src/main/assembly/conf/dubbo.properties b/examples/helloworld/dubbo/java-server/src/main/assembly/conf/dubbo.properties new file mode 100644 index 0000000000000000000000000000000000000000..2826f31303717256725b02a79e1698043709d2f3 --- /dev/null +++ b/examples/helloworld/dubbo/java-server/src/main/assembly/conf/dubbo.properties @@ -0,0 +1,14 @@ +### dubbo注册中心配置 ## +dubbo.container = log4j,spring +dubbo.application.name = user-info-server +dubbo.application.environment = product +dubbo.application.owner = AlexStocks +dubbo.registry.address = 127.0.0.1:2181 +dubbo.registry.protocol = zookeeper +dubbo.consumer.timeout = 10000 +dubbo.provider.timeout = 10000 +dubbo.protocol.name = dubbo +dubbo.protocol.port = 10000 + +dubbo.log4j.file = logs/dubbo.log +dubbo.log4j.level = INFO diff --git a/examples/helloworld/dubbo/java-server/src/main/assembly/conf/log4j.properties b/examples/helloworld/dubbo/java-server/src/main/assembly/conf/log4j.properties new file mode 100644 index 0000000000000000000000000000000000000000..13c80493329261ea677de77624b363bf99c82652 --- /dev/null +++ b/examples/helloworld/dubbo/java-server/src/main/assembly/conf/log4j.properties @@ -0,0 +1,20 @@ +## Logger configure file for myproject +log.dir=logs/ +datestamp=yyyy-MM-dd/HH:mm:ss.SSS + +log4j.rootLogger=DEBUG, file, console + +log4j.appender.file=org.apache.log4j.DailyRollingFileAppender +log4j.appender.file.threshold=DEBUG +log4j.appender.file.File=${log.dir}/log4j.log +log4j.appender.file.DatePattern=-yyyyMMddHH +log4j.appender.file.ImmediateFlush=true +log4j.appender.file.Append=true +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{${datestamp}} %5p: %l - %m%n + +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.Threshold=DEBUG +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{${datestamp}} %5p: %l - %m%n + diff --git a/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/Provider.java b/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/Provider.java new file mode 100644 index 0000000000000000000000000000000000000000..0031f5569fd5f16ded0da6e5426f78805fad4a42 --- /dev/null +++ b/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/Provider.java @@ -0,0 +1,33 @@ +/* + * 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 com.ikurento.user; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class Provider { + + /** + * To get ipv6 address to work, add + * System.setProperty("java.net.preferIPv6Addresses", "true"); + * before running your application. + */ + public static void main(String[] args) throws Exception { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo.provider.xml"}); + context.start(); + System.in.read(); // press any key to exit + } +} diff --git a/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/User.java b/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/User.java new file mode 100644 index 0000000000000000000000000000000000000000..06f3f18f0a8ae940000fae3155e448c3181a0054 --- /dev/null +++ b/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/User.java @@ -0,0 +1,70 @@ +package com.ikurento.user; +// ref: https://github.com/JoeCao/dubbo_jsonrpc_example/tree/master/dubbo_server/src/main/java/com/ofpay/demo/api + +import java.util.Date; +import java.io.Serializable; + +public class User implements Serializable { + + private String id; + + private String name; + + private int age; + + private Date time = new Date(); + + public User() { + } + + public User(String id, String name, int age) { + this.id = id; + this.name = name; + this.age = age; + } + + public User(String id, String name, int age, Date time) { + this.id = id; + this.name = name; + this.age = age; + this.time = time; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } + + + + public String toString() { + return "User{id:" + id + ", name:" + name + ", age:" + age + ", time:" + time +"}"; + } +} diff --git a/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java b/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..f3301cd642ca58a57ac5e2041ec5f958d383b7fb --- /dev/null +++ b/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java @@ -0,0 +1,9 @@ +package com.ikurento.user; +// https://github.com/JoeCao/dubbo_jsonrpc_example/tree/master/dubbo_server/src/main/java/com/ofpay/demo/api + + +public interface UserProvider { + + User GetUser(String userId); // the first alpha is Upper case to compatible with golang. + +} diff --git a/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java b/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..4a394b80a4b767f25e2ff13b2d4cfe7a500f759a --- /dev/null +++ b/examples/helloworld/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java @@ -0,0 +1,15 @@ +package com.ikurento.user; + +// ref: https://github.com/JoeCao/dubbo_jsonrpc_example/tree/master/dubbo_server/src/main/java/com/ofpay/demo/api + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class UserProviderImpl implements UserProvider { + private static final Logger LOG = LoggerFactory.getLogger("UserLogger"); //Output to user-server.log + + public User GetUser(String userId) { + return new User(userId, "zhangsan", 18); + } + +} diff --git a/examples/helloworld/dubbo/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml b/examples/helloworld/dubbo/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml new file mode 100644 index 0000000000000000000000000000000000000000..fe23e1f3e91d841c30534c82d8d69e6628f6b528 --- /dev/null +++ b/examples/helloworld/dubbo/java-server/src/main/resources/META-INF/spring/dubbo.provider.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - Copyright 1999-2011 Alibaba Group. + - + - Licensed 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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd + http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> + + <!-- 应用名 --> + <dubbo:application name="user-info-server"/> + <!-- 连接到哪个本地注册中心 --> + <dubbo:registry id="ikurento" address="zookeeper://127.0.0.1:2181" /> + <!-- 用dubbo协议在20880端口暴露服务 --> + <!-- dubbo:protocol host="127.0.0.1" / --> + <dubbo:protocol id="dubbo" name="dubbo" host="127.0.0.1" port="20010" /> + <!-- 声明需要暴露的服务接口 --> + <dubbo:service id="aaa" registry="ikurento" timeout="3000" interface="com.ikurento.user.UserProvider" ref="demoService"/> + + <bean id="demoService" class="com.ikurento.user.UserProviderImpl" /> + +</beans> diff --git a/examples/helloworld/dubbo/java-server/src/main/resources/log4j.properties b/examples/helloworld/dubbo/java-server/src/main/resources/log4j.properties new file mode 100644 index 0000000000000000000000000000000000000000..13c80493329261ea677de77624b363bf99c82652 --- /dev/null +++ b/examples/helloworld/dubbo/java-server/src/main/resources/log4j.properties @@ -0,0 +1,20 @@ +## Logger configure file for myproject +log.dir=logs/ +datestamp=yyyy-MM-dd/HH:mm:ss.SSS + +log4j.rootLogger=DEBUG, file, console + +log4j.appender.file=org.apache.log4j.DailyRollingFileAppender +log4j.appender.file.threshold=DEBUG +log4j.appender.file.File=${log.dir}/log4j.log +log4j.appender.file.DatePattern=-yyyyMMddHH +log4j.appender.file.ImmediateFlush=true +log4j.appender.file.Append=true +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{${datestamp}} %5p: %l - %m%n + +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.Threshold=DEBUG +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%d{${datestamp}} %5p: %l - %m%n + diff --git a/examples/jsonrpc/go-client/profiles/test/client.yml b/examples/jsonrpc/go-client/profiles/test/client.yml deleted file mode 100644 index 1b0529c455a9492d68d040632451bd13198552a4..0000000000000000000000000000000000000000 --- a/examples/jsonrpc/go-client/profiles/test/client.yml +++ /dev/null @@ -1,67 +0,0 @@ -# dubbo client yaml configure file - -check: true -# client -request_timeout : "3s" -# connect timeout -connect_timeout : "3s" - -# application config -application_config: - organization : "ikurento.com" - name : "BDTService" - module : "dubbogo user-info client" - version : "0.0.1" - owner : "ZX" - environment : "test" - -registries : - "hangzhouzk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2181" - username: "" - password: "" - "shanghaizk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2182" - username: "" - password: "" - -references: - "UserProvider": - # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 - registry: "hangzhouzk" - protocol : "jsonrpc" -# version : "2.0" -# group: "as" - interface : "com.ikurento.user.UserProvider" - cluster: "failover" - methods : - - name: "GetUser" - retries: 3 - -protocol_conf: - dubbo: - reconnect_interval: 0 - connection_number: 2 - heartbeat_period: "5s" - session_timeout: "20s" - fail_fast_timeout: "5s" - pool_size: 64 - pool_ttl: 600 - getty_session_param: - compress_encoding: false - tcp_no_delay: true - tcp_keep_alive: true - keep_alive_period: "120s" - tcp_r_buf_size: 262144 - tcp_w_buf_size: 65536 - pkg_rq_size: 1024 - pkg_wq_size: 512 - tcp_read_timeout: "1s" - tcp_write_timeout: "5s" - wait_timeout: "1s" - max_msg_len: 10240 - session_name: "client" diff --git a/examples/jsonrpc/go-server/app/user.go b/examples/jsonrpc/go-server/app/user.go deleted file mode 100644 index e86d915417cc54b05faa25ebaa06dae2c5fb6dd1..0000000000000000000000000000000000000000 --- a/examples/jsonrpc/go-server/app/user.go +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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 main - -import ( - "context" - "fmt" - "strconv" - "time" -) - -import ( - perrors "github.com/pkg/errors" -) - -import ( - "github.com/apache/dubbo-go/config" -) - -type Gender int - -func init() { - config.SetProviderService(new(UserProvider)) -} - -const ( - MAN = iota - WOMAN -) - -var genderStrings = [...]string{ - "MAN", - "WOMAN", -} - -func (g Gender) String() string { - return genderStrings[g] -} - -type ( - User struct { - Id string `json:"id"` - Name string `json:"name"` - Age int `json:"age"` - sex Gender - Birth int `json:"time"` - Sex string `json:"sex"` - } - - UserProvider struct { - user map[string]User - } -) - -var ( - DefaultUser = User{ - Id: "0", Name: "Alex Stocks", Age: 31, - // Birth: int(time.Date(1985, time.November, 10, 23, 0, 0, 0, time.UTC).Unix()), - Birth: int(time.Date(1985, 11, 24, 15, 15, 0, 0, time.Local).Unix()), - sex: Gender(MAN), - } - - userMap = UserProvider{user: make(map[string]User)} -) - -func init() { - DefaultUser.Sex = DefaultUser.sex.String() - userMap.user["A000"] = DefaultUser - userMap.user["A001"] = User{Id: "001", Name: "ZhangSheng", Age: 18, sex: MAN} - userMap.user["A002"] = User{Id: "002", Name: "Lily", Age: 20, sex: WOMAN} - userMap.user["A003"] = User{Id: "113", Name: "Moorse", Age: 30, sex: MAN} - for k, v := range userMap.user { - v.Birth = int(time.Now().AddDate(-1*v.Age, 0, 0).Unix()) - v.Sex = userMap.user[k].sex.String() - userMap.user[k] = v - } -} - -func (u *UserProvider) getUser(userId string) (*User, error) { - if user, ok := userMap.user[userId]; ok { - return &user, nil - } - - return nil, fmt.Errorf("invalid user id:%s", userId) -} - -func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User) error { - var ( - err error - user *User - ) - - println("req:%#v", req) - user, err = u.getUser(req[0].(string)) - if err == nil { - *rsp = *user - println("rsp:%#v", rsp) - } - return err -} - -func (u *UserProvider) GetUser0(id string, name string) (User, error) { - var err error - - println("id:%s, name:%s", id, name) - user, err := u.getUser(id) - if err != nil { - return User{}, err - } - if user.Name != name { - return User{}, perrors.New("name is not " + user.Name) - } - return *user, err -} - -func (u *UserProvider) GetUser2(ctx context.Context, req []interface{}, rsp *User) error { - var err error - - println("req:%#v", req) - rsp.Id = strconv.FormatFloat(req[0].(float64), 'f', 0, 64) - rsp.Sex = Gender(MAN).String() - return err -} - -func (u *UserProvider) GetUser3() error { - return nil -} - -func (u *UserProvider) GetUsers(req []interface{}) ([]User, error) { - var err error - - println("req:%s", req) - t := req[0].([]interface{}) - user, err := u.getUser(t[0].(string)) - if err != nil { - return nil, err - } - println("user:%v", user) - user1, err := u.getUser(t[1].(string)) - if err != nil { - return nil, err - } - println("user1:%v", user1) - - return []User{*user, *user1}, err -} - -func (s *UserProvider) MethodMapper() map[string]string { - return map[string]string{ - "GetUser2": "getUser", - } -} - -func (u *UserProvider) Service() string { - return "com.ikurento.user.UserProvider" -} - -func (u *UserProvider) Version() string { - return "" -} - -func println(format string, args ...interface{}) { - fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...) -} diff --git a/examples/jsonrpc/go-server/profiles/dev/server.yml b/examples/jsonrpc/go-server/profiles/dev/server.yml deleted file mode 100644 index b5384a28a37535bf7493d6ae07166f6da3b4c440..0000000000000000000000000000000000000000 --- a/examples/jsonrpc/go-server/profiles/dev/server.yml +++ /dev/null @@ -1,50 +0,0 @@ -# dubbo server yaml configure file - -# application config -application_config: - organization : "ikurento.com" - name : "BDTService" - module : "dubbogo user-info server" - version : "0.0.1" - owner : "ZX" - environment : "dev" - -registries : - "hangzhouzk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2181" - username: "" - password: "" - "shanghaizk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2182" - username: "" - password: "" - - -services: - "UserProvider": - # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 - registry: "hangzhouzk" - protocol : "jsonrpc" - # 相当于dubbo.xml中的interface - interface : "com.ikurento.user.UserProvider" - loadbalance: "random" - warmup: "100" - cluster: "failover" - methods: - - name: "GetUser" - retries: 1 - loadbalance: "random" - -protocols: - #- name: "dubbo" - # ip : "127.0.0.1" - # port : 20000 - "jsonrpc1": - name: "jsonrpc" - ip: "127.0.0.1" - port: 20001 - diff --git a/examples/jsonrpc/go-server/profiles/release/server.yml b/examples/jsonrpc/go-server/profiles/release/server.yml deleted file mode 100644 index 213d31d53eb2523e2e132810c7435b3696581a31..0000000000000000000000000000000000000000 --- a/examples/jsonrpc/go-server/profiles/release/server.yml +++ /dev/null @@ -1,50 +0,0 @@ -# dubbo server yaml configure file - -# application config -application_config: - organization : "ikurento.com" - name : "BDTService" - module : "dubbogo user-info server" - version : "0.0.1" - owner : "ZX" - environment : "release" - -registries : - "hangzhouzk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2181" - username: "" - password: "" - "shanghaizk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2182" - username: "" - password: "" - - -services: - "UserProvider": - # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 - registry: "hangzhouzk" - protocol : "jsonrpc" - # 相当于dubbo.xml中的interface - interface : "com.ikurento.user.UserProvider" - loadbalance: "random" - warmup: "100" - cluster: "failover" - methods: - - name: "GetUser" - retries: 1 - loadbalance: "random" - -protocols: - #- name: "dubbo" - # ip : "127.0.0.1" - # port : 20000 - "jsonrpc1": - name: "jsonrpc" - ip: "127.0.0.1" - port: 20001 - diff --git a/examples/jsonrpc/go-server/profiles/test/server.yml b/examples/jsonrpc/go-server/profiles/test/server.yml deleted file mode 100644 index 9b6dcb0b5c4513cf12ec5a505be64be156593c94..0000000000000000000000000000000000000000 --- a/examples/jsonrpc/go-server/profiles/test/server.yml +++ /dev/null @@ -1,50 +0,0 @@ -# dubbo server yaml configure file - -# application config -application_config: - organization : "ikurento.com" - name : "BDTService" - module : "dubbogo user-info server" - version : "0.0.1" - owner : "ZX" - environment : "test" - -registries : - "hangzhouzk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2181" - username: "" - password: "" - "shanghaizk": - protocol: "zookeeper" - timeout : "3s" - address: "127.0.0.1:2182" - username: "" - password: "" - - -services: - "UserProvider": - # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册 - registry: "hangzhouzk" - protocol : "jsonrpc" - # 相当于dubbo.xml中的interface - interface : "com.ikurento.user.UserProvider" - loadbalance: "random" - warmup: "100" - cluster: "failover" - methods: - - name: "GetUser" - retries: 1 - loadbalance: "random" - -protocols: - #- name: "dubbo" - # ip : "127.0.0.1" - # port : 20000 - "jsonrpc1": - name: "jsonrpc" - ip: "127.0.0.1" - port: 20001 - diff --git a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java b/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java deleted file mode 100644 index ddf899aa10979d65f9c88bc0b79ccbb065812417..0000000000000000000000000000000000000000 --- a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java +++ /dev/null @@ -1,97 +0,0 @@ -// ***************************************************** -// DESC : dubbo consumer -// AUTHOR : writtey by 包增辉(https://github.com/baozh) -// VERSION : 1.0 -// LICENCE : Apache License 2.0 -// EMAIL : alexstocks@foxmail.com -// MOD : 2016-10-19 17:03 -// FILE : Consumer.java -// ****************************************************** - -package com.ikurento.user; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import com.alibaba.dubbo.rpc.service.EchoService; -import java.util.List; - -public class Consumer { - //定义一个私有变量 (Spring中要求) - private UserProvider userProvider; - - //Spring注入(Spring中要求) - public void setUserProvider(UserProvider u) { - this.userProvider = u; - } - - private void benchmarkSayHello() { - for (int i = 0; i < Integer.MAX_VALUE; i ++) { - try { - // String hello = demoService.sayHello("world" + i); - // System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + hello); - } catch (Exception e) { - e.printStackTrace(); - } - - // Thread.sleep(2000); - } - } - - private void testGetUser() throws Exception { - try { - EchoService echoService = (EchoService)userProvider; - Object status = echoService.$echo("OK"); - System.out.println("echo: "+status); - } catch (Exception e) { - e.printStackTrace(); - } - try { - User user1 = userProvider.GetUser("A003"); - System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + - " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString() - + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString()); - User user2 = userProvider.GetUser0("A003","Moorse"); - System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + - " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString() - + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString()); - User user3 = userProvider.getUser(1); - System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + - " UserInfo, Id:" + user3.getId() + ", name:" + user3.getName() + ", sex:" + user3.getSex().toString() - + ", age:" + user3.getAge() + ", time:" + user3.getTime().toString()); - - userProvider.GetUser3(); - System.out.println("GetUser3 succ"); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void testGetUsers() throws Exception { - try { - List<String> userIDList = new ArrayList<String>(); - userIDList.add("A001"); - userIDList.add("A002"); - userIDList.add("A003"); - - List<User> userList = userProvider.GetUsers(userIDList); - - for (int i = 0; i < userList.size(); i++) { - User user = userList.get(i); - System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + - " UserInfo, Id:" + user.getId() + ", name:" + user.getName() + ", sex:" + user.getSex().toString() - + ", age:" + user.getAge() + ", time:" + user.getTime().toString()); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - //启动consumer的入口函数(在配置文件中指定) - public void start() throws Exception { - testGetUser(); - testGetUsers(); -// Thread.sleep(120000); -Thread.sleep(2000); - } -} diff --git a/filter/impl/active_filter.go b/filter/impl/active_filter.go index 435bfe7488c520b14d770aea01b3c3baf4950056..d7dad74cf3f5ccadf39372335bc1efb22f497523 100644 --- a/filter/impl/active_filter.go +++ b/filter/impl/active_filter.go @@ -1,14 +1,19 @@ -// Licensed 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. +/* + * 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. + */ // @author yiji@apache.org package impl diff --git a/filter/impl/echo_filter_test.go b/filter/impl/echo_filter_test.go index e2752c85b24b5dbc8175cbd125ed771b412d1818..e2e592974701ad18c5b01e884485c022ee2320b8 100644 --- a/filter/impl/echo_filter_test.go +++ b/filter/impl/echo_filter_test.go @@ -34,11 +34,11 @@ import ( func TestEchoFilter_Invoke(t *testing.T) { filter := GetFilter() result := filter.Invoke(protocol.NewBaseInvoker(common.URL{}), - invocation.NewRPCInvocationForProvider("$echo", []interface{}{"OK"}, nil)) + invocation.NewRPCInvocation("$echo", []interface{}{"OK"}, nil)) assert.Equal(t, "OK", result.Result()) result = filter.Invoke(protocol.NewBaseInvoker(common.URL{}), - invocation.NewRPCInvocationForProvider("MethodName", []interface{}{"OK"}, nil)) + invocation.NewRPCInvocation("MethodName", []interface{}{"OK"}, nil)) assert.Nil(t, result.Error()) assert.Nil(t, result.Result()) } diff --git a/filter/impl/generic_filter.go b/filter/impl/generic_filter.go new file mode 100644 index 0000000000000000000000000000000000000000..35aadb11a444bda56109e238b17267f71ec2606b --- /dev/null +++ b/filter/impl/generic_filter.go @@ -0,0 +1,133 @@ +/* + * 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 impl + +import ( + "reflect" + "strings" +) +import ( + hessian "github.com/apache/dubbo-go-hessian2" +) +import ( + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/filter" + "github.com/apache/dubbo-go/protocol" + invocation2 "github.com/apache/dubbo-go/protocol/invocation" +) + +const ( + GENERIC = "generic" +) + +func init() { + extension.SetFilter(GENERIC, GetGenericFilter) +} + +// when do a generic invoke, struct need to be map + +type GenericFilter struct{} + +func (ef *GenericFilter) Invoke(invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { + if invocation.MethodName() == constant.GENERIC && len(invocation.Arguments()) == 3 { + oldArguments := invocation.Arguments() + var newParams []hessian.Object + if oldParams, ok := oldArguments[2].([]interface{}); ok { + for i := range oldParams { + newParams = append(newParams, hessian.Object(struct2MapAll(oldParams[i]))) + } + } else { + return invoker.Invoke(invocation) + } + newArguments := []interface{}{ + oldArguments[0], + oldArguments[1], + newParams, + } + newInvocation := invocation2.NewRPCInvocation(invocation.MethodName(), newArguments, invocation.Attachments()) + newInvocation.SetReply(invocation.Reply()) + return invoker.Invoke(newInvocation) + } + return invoker.Invoke(invocation) +} + +func (ef *GenericFilter) OnResponse(result protocol.Result, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result { + return result +} + +func GetGenericFilter() filter.Filter { + return &GenericFilter{} +} +func struct2MapAll(obj interface{}) interface{} { + if obj == nil { + return obj + } + t := reflect.TypeOf(obj) + v := reflect.ValueOf(obj) + if t.Kind() == reflect.Struct { + result := make(map[string]interface{}, t.NumField()) + for i := 0; i < t.NumField(); i++ { + if v.Field(i).Kind() == reflect.Struct || v.Field(i).Kind() == reflect.Slice || v.Field(i).Kind() == reflect.Map { + if v.Field(i).CanInterface() { + setInMap(result, t.Field(i), struct2MapAll(v.Field(i).Interface())) + } + } else { + if v.Field(i).CanInterface() { + setInMap(result, t.Field(i), v.Field(i).Interface()) + } + } + } + return result + } else if t.Kind() == reflect.Slice { + value := reflect.ValueOf(obj) + var newTemps = make([]interface{}, 0, value.Len()) + for i := 0; i < value.Len(); i++ { + newTemp := struct2MapAll(value.Index(i).Interface()) + newTemps = append(newTemps, newTemp) + } + return newTemps + } else if t.Kind() == reflect.Map { + var newTempMap = make(map[string]interface{}, v.Len()) + iter := v.MapRange() + for iter.Next() { + mapK := iter.Key().String() + if !iter.Value().CanInterface() { + continue + } + mapV := iter.Value().Interface() + newTempMap[mapK] = struct2MapAll(mapV) + } + return newTempMap + } else { + return obj + } +} +func setInMap(m map[string]interface{}, structField reflect.StructField, value interface{}) (result map[string]interface{}) { + result = m + if tagName := structField.Tag.Get("m"); tagName == "" { + result[headerAtoa(structField.Name)] = value + } else { + result[tagName] = value + } + return +} +func headerAtoa(a string) (b string) { + b = strings.ToLower(a[:1]) + a[1:] + return +} diff --git a/filter/impl/generic_filter_test.go b/filter/impl/generic_filter_test.go new file mode 100644 index 0000000000000000000000000000000000000000..9797c40df1f57017241675013620a53320e475ad --- /dev/null +++ b/filter/impl/generic_filter_test.go @@ -0,0 +1,121 @@ +/* + * 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 impl + +import ( + "reflect" + "testing" +) +import ( + "github.com/stretchr/testify/assert" +) + +func Test_struct2MapAll(t *testing.T) { + var testData struct { + AaAa string `m:"aaAa"` + BaBa string + CaCa struct { + AaAa string + BaBa string `m:"baBa"` + XxYy struct { + xxXx string `m:"xxXx"` + Xx string `m:"xx"` + } `m:"xxYy"` + } `m:"caCa"` + } + testData.AaAa = "1" + testData.BaBa = "1" + testData.CaCa.BaBa = "2" + testData.CaCa.AaAa = "2" + testData.CaCa.XxYy.xxXx = "3" + testData.CaCa.XxYy.Xx = "3" + m := struct2MapAll(testData).(map[string]interface{}) + assert.Equal(t, "1", m["aaAa"].(string)) + assert.Equal(t, "1", m["baBa"].(string)) + assert.Equal(t, "2", m["caCa"].(map[string]interface{})["aaAa"].(string)) + assert.Equal(t, "3", m["caCa"].(map[string]interface{})["xxYy"].(map[string]interface{})["xx"].(string)) + + assert.Equal(t, reflect.Map, reflect.TypeOf(m["caCa"]).Kind()) + assert.Equal(t, reflect.Map, reflect.TypeOf(m["caCa"].(map[string]interface{})["xxYy"]).Kind()) +} + +type testStruct struct { + AaAa string + BaBa string `m:"baBa"` + XxYy struct { + xxXx string `m:"xxXx"` + Xx string `m:"xx"` + } `m:"xxYy"` +} + +func Test_struct2MapAll_Slice(t *testing.T) { + var testData struct { + AaAa string `m:"aaAa"` + BaBa string + CaCa []testStruct `m:"caCa"` + } + testData.AaAa = "1" + testData.BaBa = "1" + var tmp testStruct + tmp.BaBa = "2" + tmp.AaAa = "2" + tmp.XxYy.xxXx = "3" + tmp.XxYy.Xx = "3" + testData.CaCa = append(testData.CaCa, tmp) + m := struct2MapAll(testData).(map[string]interface{}) + + assert.Equal(t, "1", m["aaAa"].(string)) + assert.Equal(t, "1", m["baBa"].(string)) + assert.Equal(t, "2", m["caCa"].([]interface{})[0].(map[string]interface{})["aaAa"].(string)) + assert.Equal(t, "3", m["caCa"].([]interface{})[0].(map[string]interface{})["xxYy"].(map[string]interface{})["xx"].(string)) + + assert.Equal(t, reflect.Slice, reflect.TypeOf(m["caCa"]).Kind()) + assert.Equal(t, reflect.Map, reflect.TypeOf(m["caCa"].([]interface{})[0].(map[string]interface{})["xxYy"]).Kind()) +} +func Test_struct2MapAll_Map(t *testing.T) { + var testData struct { + AaAa string + Baba map[string]interface{} + CaCa map[string]string + DdDd map[string]interface{} + } + testData.AaAa = "aaaa" + testData.Baba = make(map[string]interface{}) + testData.CaCa = make(map[string]string) + testData.DdDd = nil + + testData.Baba["kk"] = 1 + var structData struct { + Str string + } + structData.Str = "str" + testData.Baba["struct"] = structData + testData.Baba["nil"] = nil + testData.CaCa["k1"] = "v1" + testData.CaCa["kv2"] = "v2" + m := struct2MapAll(testData) + + assert.Equal(t, reflect.Map, reflect.TypeOf(m).Kind()) + assert.Equal(t, reflect.String, reflect.TypeOf(m.(map[string]interface{})["aaAa"]).Kind()) + assert.Equal(t, reflect.Map, reflect.TypeOf(m.(map[string]interface{})["baba"]).Kind()) + assert.Equal(t, reflect.Map, reflect.TypeOf(m.(map[string]interface{})["baba"].(map[string]interface{})["struct"]).Kind()) + assert.Equal(t, "str", m.(map[string]interface{})["baba"].(map[string]interface{})["struct"].(map[string]interface{})["str"]) + assert.Equal(t, nil, m.(map[string]interface{})["baba"].(map[string]interface{})["nil"]) + assert.Equal(t, reflect.Map, reflect.TypeOf(m.(map[string]interface{})["caCa"]).Kind()) + assert.Equal(t, reflect.Map, reflect.TypeOf(m.(map[string]interface{})["ddDd"]).Kind()) +} diff --git a/go.mod b/go.mod index e1ab3c34bfb26e8fa8a81ee0e95d03a969a84be8..52785aa5f5cfbc8158a49c90a369d179a332f5f0 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,49 @@ module github.com/apache/dubbo-go require ( - github.com/dubbogo/getty v1.0.7 + github.com/Workiva/go-datastructures v1.0.50 + github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190802083043-4cd0c391755e // indirect + github.com/apache/dubbo-go-hessian2 v1.2.5-0.20190731020727-1697039810c8 + github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 // indirect + github.com/coreos/bbolt v1.3.3 // indirect + github.com/coreos/etcd v3.3.13+incompatible + github.com/coreos/go-semver v0.3.0 // indirect + github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect + github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect + github.com/dubbogo/getty v1.2.2 github.com/dubbogo/gost v1.1.1 - github.com/dubbogo/hessian2 v1.2.0 + github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect + github.com/go-errors/errors v1.0.1 // indirect + github.com/gogo/protobuf v1.2.1 // indirect + github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect + github.com/golang/mock v1.3.1 + github.com/google/btree v1.0.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 // indirect + github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.9.5 // indirect + github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 + github.com/jonboulle/clockwork v0.1.0 // indirect + github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 // indirect + github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f // indirect + github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 // indirect github.com/magiconair/properties v1.8.1 + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/nacos-group/nacos-sdk-go v0.0.0-20190723125407-0242d42e3dbb github.com/pkg/errors v0.8.1 + github.com/prometheus/client_golang v1.1.0 // indirect github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec + github.com/soheilhy/cmux v0.1.4 // indirect github.com/stretchr/testify v1.3.0 - github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f + github.com/tebeka/strftime v0.1.3 // indirect + github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect + github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 // indirect + github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect + go.etcd.io/bbolt v1.3.3 // indirect + go.etcd.io/etcd v3.3.13+incompatible go.uber.org/atomic v1.4.0 go.uber.org/zap v1.10.0 + google.golang.org/grpc v1.22.1 gopkg.in/yaml.v2 v2.2.2 ) diff --git a/go.sum b/go.sum index 745c68f1ecc255fd4c016e653581e7434e05bdfa..e70701ff96cccb0026edaa36135f3ed785863159 100644 --- a/go.sum +++ b/go.sum @@ -1,45 +1,232 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Workiva/go-datastructures v1.0.50 h1:slDmfW6KCHcC7U+LP3DDBbm4fqTwZGn1beOFPfGaLvo= +github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190802083043-4cd0c391755e h1:MSuLXx/mveDbpDNhVrcWTMeV4lbYWKcyO4rH+jAxmX0= +github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190802083043-4cd0c391755e/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= +github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= +github.com/apache/dubbo-go-hessian2 v1.2.5-0.20190731020727-1697039810c8 h1:7zJlM+8bpCAUhv03TZnXkT4MLlLWng1s7An8CLuN73E= +github.com/apache/dubbo-go-hessian2 v1.2.5-0.20190731020727-1697039810c8/go.mod h1:LWnndnrFXZmJLAzoyNAPNHSIJ1KOHVkTSsHgC3YYWlo= +github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI= +github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY= +github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dubbogo/getty v1.0.7 h1:5Hg+JwXyCKm9Yr4yJkm98ahhnoa8c2h6br5QJxwQ+YU= -github.com/dubbogo/getty v1.0.7/go.mod h1:cRMSuoCmwc5lULFFnYZTxyCfZhObmRTNbS7XRnPNHSo= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dubbogo/getty v1.2.2 h1:qDC9WXjxcs5NPvWZz2ruVKBKr2r1Jjm6i0Sq//CQwbE= +github.com/dubbogo/getty v1.2.2/go.mod h1:K4b3MkGLf7T+lMgQNFgpg0dI1Wvv1PTisFs1Psf86kU= github.com/dubbogo/gost v1.1.1 h1:JCM7vx5edPIjDA5ovJTuzEEXuw2t7xLyrlgi2mi5jHI= github.com/dubbogo/gost v1.1.1/go.mod h1:R7wZm1DrmrKGr50mBZVcg6C9ekG8aL5hP+sgWcIDwQg= -github.com/dubbogo/hessian2 v1.2.0 h1:5wFYuMzzRhneUAPbVBVKubIknrEjUM/B76vievYD0Vw= -github.com/dubbogo/hessian2 v1.2.0/go.mod h1:7EohF3mE7xmZcj43nP172sapRHOEifcV/jwyHhG4SaY= +github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 h1:Ghm4eQYC0nEPnSJdVkTrXpu9KtoVCSo1hg7mtI7G9KU= +github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:BWIsLfhgKhV5g/oF34aRjniBHLTZe5DNekSjbAjIS6c= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4= +github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8 h1:mGIXW/lubQ4B+3bXTLxcTMTjUNDqoF6T/HUW9LbFx9s= github.com/jinzhu/copier v0.0.0-20190625015134-976e0346caa8/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570 h1:0iQektZGS248WXmGIYOwRXSQhD4qn3icjMpuxwO7qlo= +github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570/go.mod h1:BLt8L9ld7wVsvEWQbuLrUZnCMnUmLZ+CGDzKtclrTlE= +github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f h1:sgUSP4zdTUZYZgAGGtN5Lxk92rK+JUFOwf+FT99EEI4= +github.com/lestrrat/go-file-rotatelogs v0.0.0-20180223000712-d3151e2a480f/go.mod h1:UGmTpUd3rjbtfIpwAPrcfmGf/Z1HS95TATB+m57TPB8= +github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042 h1:Bvq8AziQ5jFF4BHGAEDSqwPW1NJS3XshxbRCxtjFAZc= +github.com/lestrrat/go-strftime v0.0.0-20180220042222-ba3bf9c1d042/go.mod h1:TPpsiPUEh0zFL1Snz4crhMlBe60PYxRHr5oFF3rRYg0= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nacos-group/nacos-sdk-go v0.0.0-20190723125407-0242d42e3dbb h1:lbmvw8r9W55w+aQgWn35W1nuleRIECMoqUrmwAOAvoI= +github.com/nacos-group/nacos-sdk-go v0.0.0-20190723125407-0242d42e3dbb/go.mod h1:CEkSvEpoveoYjA81m4HNeYQ0sge0LFGKSEqO3JKHllo= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec h1:6ncX5ko6B9LntYM0YBRXkiSaZMmLYeZ/NWcmeB43mMY= github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f h1:QatZ4lsJBY3x1+Imst9g95+vUl7m52dqM9Pi4aSMW8w= -github.com/ulule/deepcopier v0.0.0-20171107155558-ca99b135e50f/go.mod h1:BNLmYJ8oMJPIPpNx5968jCyUhwEU1XT3YsuOqtbo5qo= +github.com/tebeka/strftime v0.1.3 h1:5HQXOqWKYRFfNyBMNVc9z5+QzuBtIXy03psIhtdJYto= +github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 h1:kF/7m/ZU+0D4Jj5eZ41Zm3IH/J8OElK1Qtd7tVKAwLk= +github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v3.3.13+incompatible h1:jCejD5EMnlGxFvcGRyEV4VGlENZc7oPQX6o0t7n3xbw= +go.etcd.io/etcd v3.3.13+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53 h1:kcXqo9vE6fsZY5X5Rd7R1l7fTgnWaDCVmln65REefiE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdOCQUEXhbk/P4A9WmJq0= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.22.1 h1:/7cs52RnTJmD43s3uxzlq2U7nqVTd/37viQwMrMNlOM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk= +gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/protocol/RpcStatus.go b/protocol/RpcStatus.go index b9f3e6ecb18583034e310471164773bebe689cd9..78796b6beaf24dac33d7e0210703a9027f9fe568 100644 --- a/protocol/RpcStatus.go +++ b/protocol/RpcStatus.go @@ -1,14 +1,19 @@ -// Licensed 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. +/* + * 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. + */ // @author yiji@apache.org package protocol diff --git a/protocol/dubbo/client.go b/protocol/dubbo/client.go index 8ba46e7b0b321095652fb7c6d0c1c7403e1fea1e..6ac5e7215429338aa7cabb646b3afd3f1a136b68 100644 --- a/protocol/dubbo/client.go +++ b/protocol/dubbo/client.go @@ -24,8 +24,9 @@ import ( ) import ( + "github.com/apache/dubbo-go-hessian2" "github.com/dubbogo/getty" - "github.com/dubbogo/hessian2" + "github.com/dubbogo/gost/sync" perrors "github.com/pkg/errors" "go.uber.org/atomic" "gopkg.in/yaml.v2" @@ -45,7 +46,8 @@ var ( errClientClosed = perrors.New("client closed") errClientReadTimeout = perrors.New("client read timeout") - clientConf *ClientConfig + clientConf *ClientConfig + clientGrpool *gxsync.TaskPool ) func init() { @@ -78,6 +80,7 @@ func init() { } clientConf = conf + setClientGrpool() } func SetClientConf(c ClientConfig) { @@ -87,59 +90,29 @@ func SetClientConf(c ClientConfig) { logger.Warnf("[ClientConfig CheckValidity] error: %v", err) return } + setClientGrpool() } func GetClientConf() ClientConfig { return *clientConf } -type CallOptions struct { +func setClientGrpool() { + if clientConf.GrPoolSize > 1 { + clientGrpool = gxsync.NewTaskPool(gxsync.WithTaskPoolTaskPoolSize(clientConf.GrPoolSize), gxsync.WithTaskPoolTaskQueueLength(clientConf.QueueLen), + gxsync.WithTaskPoolTaskQueueNumber(clientConf.QueueNumber)) + } +} + +type Options struct { + // connect timeout + ConnectTimeout time.Duration // request timeout RequestTimeout time.Duration - // response timeout - ResponseTimeout time.Duration - // serial ID - SerialID SerialID - Meta map[interface{}]interface{} } -type CallOption func(*CallOptions) - -//func WithCallRequestTimeout(d time.Duration) CallOption { -// return func(o *CallOptions) { -// o.RequestTimeout = d -// } -//} -// -//func WithCallResponseTimeout(d time.Duration) CallOption { -// return func(o *CallOptions) { -// o.ResponseTimeout = d -// } -//} -// -//func WithCallSerialID(s SerialID) CallOption { -// return func(o *CallOptions) { -// o.SerialID = s -// } -//} -// -//func WithCallMeta_All(callMeta map[interface{}]interface{}) CallOption { -// return func(o *CallOptions) { -// o.Meta = callMeta -// } -//} - -//func WithCallMeta(k, v interface{}) CallOption { -// return func(o *CallOptions) { -// if o.Meta == nil { -// o.Meta = make(map[interface{}]interface{}) -// } -// o.Meta[k] = v -// } -//} - type CallResponse struct { - Opts CallOptions + Opts Options Cause error Start time.Time // invoke(call) start time == write start time ReadStart time.Time // read start time, write duration = ReadStart - Start @@ -149,6 +122,7 @@ type CallResponse struct { type AsyncCallback func(response CallResponse) type Client struct { + opts Options conf ClientConfig pool *gettyRPCClientPool sequence atomic.Uint64 @@ -156,9 +130,18 @@ type Client struct { pendingResponses *sync.Map } -func NewClient() *Client { +func NewClient(opt Options) *Client { + + switch { + case opt.ConnectTimeout == 0: + opt.ConnectTimeout = 3e9 + fallthrough + case opt.RequestTimeout == 0: + opt.RequestTimeout = 3e9 + } c := &Client{ + opts: opt, pendingResponses: new(sync.Map), conf: *clientConf, } @@ -168,64 +151,38 @@ func NewClient() *Client { } // call one way -func (c *Client) CallOneway(addr string, svcUrl common.URL, method string, args interface{}, opts ...CallOption) error { - var copts CallOptions - - for _, o := range opts { - o(&copts) - } +func (c *Client) CallOneway(addr string, svcUrl common.URL, method string, args interface{}) error { - return perrors.WithStack(c.call(CT_OneWay, addr, svcUrl, method, args, nil, nil, copts)) + return perrors.WithStack(c.call(CT_OneWay, addr, svcUrl, method, args, nil, nil)) } // if @reply is nil, the transport layer will get the response without notify the invoker. -func (c *Client) Call(addr string, svcUrl common.URL, method string, args, reply interface{}, opts ...CallOption) error { - var copts CallOptions - - for _, o := range opts { - o(&copts) - } +func (c *Client) Call(addr string, svcUrl common.URL, method string, args, reply interface{}) error { ct := CT_TwoWay if reply == nil { ct = CT_OneWay } - return perrors.WithStack(c.call(ct, addr, svcUrl, method, args, reply, nil, copts)) + return perrors.WithStack(c.call(ct, addr, svcUrl, method, args, reply, nil)) } func (c *Client) AsyncCall(addr string, svcUrl common.URL, method string, args interface{}, - callback AsyncCallback, reply interface{}, opts ...CallOption) error { + callback AsyncCallback, reply interface{}) error { - var copts CallOptions - for _, o := range opts { - o(&copts) - } - - return perrors.WithStack(c.call(CT_TwoWay, addr, svcUrl, method, args, reply, callback, copts)) + return perrors.WithStack(c.call(CT_TwoWay, addr, svcUrl, method, args, reply, callback)) } func (c *Client) call(ct CallType, addr string, svcUrl common.URL, method string, - args, reply interface{}, callback AsyncCallback, opts CallOptions) error { - - if opts.RequestTimeout == 0 { - opts.RequestTimeout = c.conf.GettySessionParam.tcpWriteTimeout - } - if opts.ResponseTimeout == 0 { - opts.ResponseTimeout = c.conf.GettySessionParam.tcpReadTimeout - } + args, reply interface{}, callback AsyncCallback) error { p := &DubboPackage{} p.Service.Path = strings.TrimPrefix(svcUrl.Path, "/") p.Service.Interface = svcUrl.GetParam(constant.INTERFACE_KEY, "") p.Service.Version = svcUrl.GetParam(constant.VERSION_KEY, "") p.Service.Method = method - p.Service.Timeout = opts.RequestTimeout - if opts.SerialID == 0 { - p.Header.SerialID = byte(S_Dubbo) - } else { - p.Header.SerialID = byte(opts.SerialID) - } + p.Service.Timeout = c.opts.RequestTimeout + p.Header.SerialID = byte(S_Dubbo) p.Body = args var rsp *PendingResponse @@ -234,7 +191,6 @@ func (c *Client) call(ct CallType, addr string, svcUrl common.URL, method string rsp = NewPendingResponse() rsp.reply = reply rsp.callback = callback - rsp.opts = opts } else { p.Header.Type = hessian.PackageRequest } @@ -245,13 +201,15 @@ func (c *Client) call(ct CallType, addr string, svcUrl common.URL, method string conn *gettyRPCClient ) conn, session, err = c.selectSession(addr) - if err != nil || session == nil { - logger.Warnf("%s, %v", errSessionNotExist.Error(), err) + if err != nil { + return perrors.WithStack(err) + } + if session == nil { return errSessionNotExist } defer c.pool.release(conn, err) - if err = c.transfer(session, p, rsp, opts); err != nil { + if err = c.transfer(session, p, rsp); err != nil { return perrors.WithStack(err) } @@ -260,7 +218,7 @@ func (c *Client) call(ct CallType, addr string, svcUrl common.URL, method string } select { - case <-time.After(opts.ResponseTimeout): + case <-getty.GetTimeWheel().After(c.opts.RequestTimeout): err = errClientReadTimeout c.removePendingResponse(SequenceType(rsp.seq)) case <-rsp.done: @@ -286,11 +244,11 @@ func (c *Client) selectSession(addr string) (*gettyRPCClient, getty.Session, err } func (c *Client) heartbeat(session getty.Session) error { - return c.transfer(session, nil, NewPendingResponse(), CallOptions{}) + return c.transfer(session, nil, NewPendingResponse()) } func (c *Client) transfer(session getty.Session, pkg *DubboPackage, - rsp *PendingResponse, opts CallOptions) error { + rsp *PendingResponse) error { var ( sequence uint64 @@ -313,7 +271,7 @@ func (c *Client) transfer(session getty.Session, pkg *DubboPackage, c.addPendingResponse(rsp) } - err = session.WritePkg(pkg, opts.RequestTimeout) + err = session.WritePkg(pkg, c.opts.RequestTimeout) if err != nil { c.removePendingResponse(SequenceType(rsp.seq)) } else if rsp != nil { // cond2 diff --git a/protocol/dubbo/client_test.go b/protocol/dubbo/client_test.go index a39b0aef743d18c24f41b41655abfada996503e8..cd961d382933443e37a08c21b4e4de5edb971860 100644 --- a/protocol/dubbo/client_test.go +++ b/protocol/dubbo/client_test.go @@ -26,7 +26,7 @@ import ( ) import ( - "github.com/dubbogo/hessian2" + hessian "github.com/apache/dubbo-go-hessian2" perrors "github.com/pkg/errors" "github.com/stretchr/testify/assert" ) @@ -42,6 +42,10 @@ func TestClient_CallOneway(t *testing.T) { c := &Client{ pendingResponses: new(sync.Map), conf: *clientConf, + opts: Options{ + ConnectTimeout: 3e9, + RequestTimeout: 6e9, + }, } c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) @@ -59,17 +63,21 @@ func TestClient_Call(t *testing.T) { c := &Client{ pendingResponses: new(sync.Map), conf: *clientConf, + opts: Options{ + ConnectTimeout: 3e9, + RequestTimeout: 10e9, + }, } c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) - // user := &User{} - //err := c.Call("127.0.0.1:20000", url, "GetBigPkg", []interface{}{nil}, user) - //assert.NoError(t, err) - //assert.NotEqual(t, "", user.Id) - //assert.NotEqual(t, "", user.Name) - user := &User{} - err := c.Call("127.0.0.1:20000", url, "GetUser", []interface{}{"1", "username"}, user) + err := c.Call("127.0.0.1:20000", url, "GetBigPkg", []interface{}{nil}, user) + assert.NoError(t, err) + assert.NotEqual(t, "", user.Id) + assert.NotEqual(t, "", user.Name) + + user = &User{} + err = c.Call("127.0.0.1:20000", url, "GetUser", []interface{}{"1", "username"}, user) assert.NoError(t, err) assert.Equal(t, User{Id: "1", Name: "username"}, *user) @@ -120,6 +128,10 @@ func TestClient_AsyncCall(t *testing.T) { c := &Client{ pendingResponses: new(sync.Map), conf: *clientConf, + opts: Options{ + ConnectTimeout: 3e9, + RequestTimeout: 6e9, + }, } c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) @@ -152,7 +164,6 @@ func InitTest(t *testing.T) (protocol.Protocol, common.URL) { ConnectionNum: 2, HeartbeatPeriod: "5s", SessionTimeout: "20s", - FailFastTimeout: "5s", PoolTTL: 600, PoolSize: 64, GettySessionParam: GettySessionParam{ @@ -162,7 +173,6 @@ func InitTest(t *testing.T) (protocol.Protocol, common.URL) { KeepAlivePeriod: "120s", TcpRBufSize: 262144, TcpWBufSize: 65536, - PkgRQSize: 1024, PkgWQSize: 512, TcpReadTimeout: "4s", TcpWriteTimeout: "5s", @@ -173,9 +183,8 @@ func InitTest(t *testing.T) (protocol.Protocol, common.URL) { }) assert.NoError(t, clientConf.CheckValidity()) SetServerConfig(ServerConfig{ - SessionNumber: 700, - SessionTimeout: "20s", - FailFastTimeout: "5s", + SessionNumber: 700, + SessionTimeout: "20s", GettySessionParam: GettySessionParam{ CompressEncoding: false, TcpNoDelay: true, @@ -183,7 +192,6 @@ func InitTest(t *testing.T) (protocol.Protocol, common.URL) { KeepAlivePeriod: "120s", TcpRBufSize: 262144, TcpWBufSize: 65536, - PkgRQSize: 1024, PkgWQSize: 512, TcpReadTimeout: "1s", TcpWriteTimeout: "5s", @@ -195,11 +203,11 @@ func InitTest(t *testing.T) (protocol.Protocol, common.URL) { // Export proto := GetProtocol() - url, err := common.NewURL(context.Background(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&"+ + url, err := common.NewURL(context.Background(), "dubbo://127.0.0.1:20000/UserProvider?anyhost=true&"+ "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"+ "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"+ "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"+ - "side=provider&timeout=3000×tamp=1556509797245") + "side=provider&timeout=3000×tamp=1556509797245&bean.name=UserProvider") assert.NoError(t, err) proto.Export(protocol.NewBaseInvoker(url)) @@ -274,12 +282,8 @@ func (u *UserProvider) GetUser6(id int64) (*User, error) { return &User{Id: "1"}, nil } -func (u *UserProvider) Service() string { - return "com.ikurento.user.UserProvider" -} - -func (u *UserProvider) Version() string { - return "" +func (u *UserProvider) Reference() string { + return "UserProvider" } func (u User) JavaClassName() string { diff --git a/protocol/dubbo/codec.go b/protocol/dubbo/codec.go index cb57fc896f5e1c0be99a1e5978841ae17503064b..98c29a4e5bc576f7e37f74c0c0abbbab4687717b 100644 --- a/protocol/dubbo/codec.go +++ b/protocol/dubbo/codec.go @@ -25,7 +25,7 @@ import ( ) import ( - "github.com/dubbogo/hessian2" + "github.com/apache/dubbo-go-hessian2" perrors "github.com/pkg/errors" ) @@ -112,7 +112,6 @@ type PendingResponse struct { readStart time.Time callback AsyncCallback reply interface{} - opts CallOptions done chan struct{} } @@ -125,7 +124,6 @@ func NewPendingResponse() *PendingResponse { func (r PendingResponse) GetCallResponse() CallResponse { return CallResponse{ - Opts: r.opts, Cause: r.err, Start: r.start, ReadStart: r.readStart, diff --git a/protocol/dubbo/codec_test.go b/protocol/dubbo/codec_test.go index 4f5229d67242e582a128caa40c205482e813f08e..52bb1fc130bb2dad866799f01c43d11ffd10a220 100644 --- a/protocol/dubbo/codec_test.go +++ b/protocol/dubbo/codec_test.go @@ -20,10 +20,11 @@ package dubbo import ( "testing" "time" +) +import ( + hessian "github.com/apache/dubbo-go-hessian2" "github.com/stretchr/testify/assert" - - hessian "github.com/dubbogo/hessian2" ) func TestDubboPackage_MarshalAndUnmarshal(t *testing.T) { @@ -49,6 +50,7 @@ func TestDubboPackage_MarshalAndUnmarshal(t *testing.T) { // request pkg.Header.Type = hessian.PackageRequest pkg.Service.Interface = "Service" + pkg.Service.Path = "path" pkg.Service.Version = "2.6" pkg.Service.Method = "Method" pkg.Service.Timeout = time.Second @@ -63,10 +65,10 @@ func TestDubboPackage_MarshalAndUnmarshal(t *testing.T) { assert.Equal(t, byte(S_Dubbo), pkgres.Header.SerialID) assert.Equal(t, int64(10086), pkgres.Header.ID) assert.Equal(t, "2.5.4", pkgres.Body.([]interface{})[0]) - assert.Equal(t, "", pkgres.Body.([]interface{})[1]) + assert.Equal(t, "path", pkgres.Body.([]interface{})[1]) assert.Equal(t, "2.6", pkgres.Body.([]interface{})[2]) assert.Equal(t, "Method", pkgres.Body.([]interface{})[3]) assert.Equal(t, "Ljava/lang/String;", pkgres.Body.([]interface{})[4]) assert.Equal(t, []interface{}{"a"}, pkgres.Body.([]interface{})[5]) - assert.Equal(t, map[interface{}]interface{}{"interface": "Service", "path": "", "group": "", "timeout": "1000"}, pkgres.Body.([]interface{})[6]) + assert.Equal(t, map[interface{}]interface{}{"group": "", "interface": "Service", "path": "path", "timeout": "1000"}, pkgres.Body.([]interface{})[6]) } diff --git a/protocol/dubbo/config.go b/protocol/dubbo/config.go index 0af1a4a41116fca06d6793fddaf7f69ade2f30c0..1ac3c9ad97ec34319c7728555e56cdfb3d038ba7 100644 --- a/protocol/dubbo/config.go +++ b/protocol/dubbo/config.go @@ -34,7 +34,6 @@ type ( keepAlivePeriod time.Duration TcpRBufSize int `default:"262144" yaml:"tcp_r_buf_size" json:"tcp_r_buf_size,omitempty"` TcpWBufSize int `default:"65536" yaml:"tcp_w_buf_size" json:"tcp_w_buf_size,omitempty"` - PkgRQSize int `default:"1024" yaml:"pkg_rq_size" json:"pkg_rq_size,omitempty"` PkgWQSize int `default:"1024" yaml:"pkg_wq_size" json:"pkg_wq_size,omitempty"` TcpReadTimeout string `default:"1s" yaml:"tcp_read_timeout" json:"tcp_read_timeout,omitempty"` tcpReadTimeout time.Duration @@ -48,20 +47,15 @@ type ( // Config holds supported types by the multiconfig package ServerConfig struct { - // local address - //AppName string `default:"rpc-server" yaml:"app_name" json:"app_name,omitempty"` - //Host string `default:"127.0.0.1" yaml:"host" json:"host,omitempty"` - //Ports []string `yaml:"ports" json:"ports,omitempty"` // `default:["10000"]` - //ProfilePort int `default:"10086" yaml:"profile_port" json:"profile_port,omitempty"` - // session SessionTimeout string `default:"60s" yaml:"session_timeout" json:"session_timeout,omitempty"` sessionTimeout time.Duration SessionNumber int `default:"1000" yaml:"session_number" json:"session_number,omitempty"` - // app - FailFastTimeout string `default:"5s" yaml:"fail_fast_timeout" json:"fail_fast_timeout,omitempty"` - failFastTimeout time.Duration + // grpool + GrPoolSize int `default:"0" yaml:"gr_pool_size" json:"gr_pool_size,omitempty"` + QueueLen int `default:"0" yaml:"queue_len" json:"queue_len,omitempty"` + QueueNumber int `default:"0" yaml:"queue_number" json:"queue_number,omitempty"` // session tcp parameters GettySessionParam GettySessionParam `required:"true" yaml:"getty_session_param" json:"getty_session_param,omitempty"` @@ -69,11 +63,6 @@ type ( // Config holds supported types by the multiconfig package ClientConfig struct { - // local address - //AppName string `default:"rpc-client" yaml:"app_name" json:"app_name,omitempty"` - //Host string `default:"127.0.0.1" yaml:"host" json:"host,omitempty"` - //ProfilePort int `default:"10086" yaml:"profile_port" json:"profile_port,omitempty"` - ReconnectInterval int `default:"0" yaml:"reconnect_interval" json:"reconnect_interval,omitempty"` // session pool @@ -87,14 +76,15 @@ type ( SessionTimeout string `default:"60s" yaml:"session_timeout" json:"session_timeout,omitempty"` sessionTimeout time.Duration - // app - FailFastTimeout string `default:"5s" yaml:"fail_fast_timeout" json:"fail_fast_timeout,omitempty"` - failFastTimeout time.Duration - // Connection Pool PoolSize int `default:"2" yaml:"pool_size" json:"pool_size,omitempty"` PoolTTL int `default:"180" yaml:"pool_ttl" json:"pool_ttl,omitempty"` + // grpool + GrPoolSize int `default:"0" yaml:"gr_pool_size" json:"gr_pool_size,omitempty"` + QueueLen int `default:"0" yaml:"queue_len" json:"queue_len,omitempty"` + QueueNumber int `default:"0" yaml:"queue_number" json:"queue_number,omitempty"` + // session tcp parameters GettySessionParam GettySessionParam `required:"true" yaml:"getty_session_param" json:"getty_session_param,omitempty"` } @@ -125,6 +115,8 @@ func (c *GettySessionParam) CheckValidity() error { func (c *ClientConfig) CheckValidity() error { var err error + c.ReconnectInterval = c.ReconnectInterval * 1e6 + if c.heartbeatPeriod, err = time.ParseDuration(c.HeartbeatPeriod); err != nil { return perrors.WithMessagef(err, "time.ParseDuration(HeartbeatPeroid{%#v})", c.HeartbeatPeriod) } @@ -133,10 +125,6 @@ func (c *ClientConfig) CheckValidity() error { return perrors.WithMessagef(err, "time.ParseDuration(SessionTimeout{%#v})", c.SessionTimeout) } - if c.failFastTimeout, err = time.ParseDuration(c.FailFastTimeout); err != nil { - return perrors.WithMessagef(err, "time.ParseDuration(FailFastTimeout{%#v})", c.FailFastTimeout) - } - return perrors.WithStack(c.GettySessionParam.CheckValidity()) } @@ -147,9 +135,5 @@ func (c *ServerConfig) CheckValidity() error { return perrors.WithMessagef(err, "time.ParseDuration(SessionTimeout{%#v})", c.SessionTimeout) } - if c.failFastTimeout, err = time.ParseDuration(c.FailFastTimeout); err != nil { - return perrors.WithMessagef(err, "time.ParseDuration(FailFastTimeout{%#v})", c.FailFastTimeout) - } - return perrors.WithStack(c.GettySessionParam.CheckValidity()) } diff --git a/protocol/dubbo/dubbo_exporter.go b/protocol/dubbo/dubbo_exporter.go index bdec8a349f358f265fe064ed2083433f27d40a3b..cb06b6b69c9d0873342af5ea49fae054f029608c 100644 --- a/protocol/dubbo/dubbo_exporter.go +++ b/protocol/dubbo/dubbo_exporter.go @@ -39,9 +39,9 @@ func NewDubboExporter(key string, invoker protocol.Invoker, exporterMap *sync.Ma } func (de *DubboExporter) Unexport() { - service := de.GetInvoker().GetUrl().GetParam(constant.INTERFACE_KEY, "") + serviceId := de.GetInvoker().GetUrl().GetParam(constant.BEAN_NAME_KEY, "") de.BaseExporter.Unexport() - err := common.ServiceMap.UnRegister(DUBBO, service) + err := common.ServiceMap.UnRegister(DUBBO, serviceId) if err != nil { logger.Errorf("[DubboExporter.Unexport] error: %v", err) } diff --git a/protocol/dubbo/dubbo_invoker_test.go b/protocol/dubbo/dubbo_invoker_test.go index 182d6d8e0b11cfcb231789cebf9c4cefdecfa258..09a4c128b600e605de616a65027da9b2ce6fcb20 100644 --- a/protocol/dubbo/dubbo_invoker_test.go +++ b/protocol/dubbo/dubbo_invoker_test.go @@ -38,13 +38,18 @@ func TestDubboInvoker_Invoke(t *testing.T) { c := &Client{ pendingResponses: new(sync.Map), conf: *clientConf, + opts: Options{ + ConnectTimeout: 3e9, + RequestTimeout: 6e9, + }, } c.pool = newGettyRPCClientConnPool(c, clientConf.PoolSize, time.Duration(int(time.Second)*clientConf.PoolTTL)) invoker := NewDubboInvoker(url, c) user := &User{} - inv := invocation.NewRPCInvocationForConsumer("GetUser", nil, []interface{}{"1", "username"}, user, nil, url, nil) + inv := invocation.NewRPCInvocationWithOptions(invocation.WithMethodName("GetUser"), invocation.WithArguments([]interface{}{"1", "username"}), + invocation.WithReply(user)) // Call res := invoker.Invoke(inv) diff --git a/protocol/dubbo/dubbo_protocol.go b/protocol/dubbo/dubbo_protocol.go index a2df3d91b2fa6b1ef8907ecba8832368d0613b8e..4438a0b3d0e32127536b818806d190a2d2a5a2ba 100644 --- a/protocol/dubbo/dubbo_protocol.go +++ b/protocol/dubbo/dubbo_protocol.go @@ -21,6 +21,7 @@ import ( "github.com/apache/dubbo-go/common" "github.com/apache/dubbo-go/common/extension" "github.com/apache/dubbo-go/common/logger" + "github.com/apache/dubbo-go/config" "github.com/apache/dubbo-go/protocol" "sync" ) @@ -63,7 +64,10 @@ func (dp *DubboProtocol) Export(invoker protocol.Invoker) protocol.Exporter { } func (dp *DubboProtocol) Refer(url common.URL) protocol.Invoker { - invoker := NewDubboInvoker(url, NewClient()) + invoker := NewDubboInvoker(url, NewClient(Options{ + ConnectTimeout: config.GetConsumerConfig().ConnectTimeout, + RequestTimeout: config.GetConsumerConfig().RequestTimeout, + })) dp.SetInvokers(invoker) logger.Infof("Refer service: %s", url.String()) return invoker diff --git a/protocol/dubbo/listener.go b/protocol/dubbo/listener.go index 55ee929301e4e62e6b868c5b85b9952fc354b723..aa208284825665dae4c23f871117a7f34c548d16 100644 --- a/protocol/dubbo/listener.go +++ b/protocol/dubbo/listener.go @@ -27,8 +27,8 @@ import ( ) import ( + "github.com/apache/dubbo-go-hessian2" "github.com/dubbogo/getty" - "github.com/dubbogo/hessian2" perrors "github.com/pkg/errors" ) @@ -91,6 +91,7 @@ func (h *RpcClientHandler) OnMessage(session getty.Session, pkg interface{}) { if p.Err != nil { logger.Errorf("rpc heartbeat response{error: %#v}", p.Err) } + h.conn.pool.rpcClient.removePendingResponse(SequenceType(p.Header.ID)) return } logger.Debugf("get rpc response{header: %#v, body: %#v}", p.Header, p.Body) @@ -208,12 +209,8 @@ func (h *RpcServerHandler) OnMessage(session getty.Session, pkg interface{}) { twoway = false } - group := p.Body.(map[string]interface{})["attachments"].(map[interface{}]interface{})[constant.GROUP_KEY] - if group == nil { - group = "" - } u := common.NewURLWithOptions(common.WithPath(p.Service.Path), common.WithParams(url.Values{}), - common.WithParamsValue(constant.GROUP_KEY, group.(string)), + common.WithParamsValue(constant.GROUP_KEY, p.Service.Group), common.WithParamsValue(constant.INTERFACE_KEY, p.Service.Interface), common.WithParamsValue(constant.VERSION_KEY, p.Service.Version)) exporter, _ := dubboProtocol.ExporterMap().Load(u.ServiceKey()) @@ -227,9 +224,9 @@ func (h *RpcServerHandler) OnMessage(session getty.Session, pkg interface{}) { } invoker := exporter.(protocol.Exporter).GetInvoker() if invoker != nil { - result := invoker.Invoke(invocation.NewRPCInvocationForProvider(p.Service.Method, p.Body.(map[string]interface{})["args"].([]interface{}), map[string]string{ + result := invoker.Invoke(invocation.NewRPCInvocation(p.Service.Method, p.Body.(map[string]interface{})["args"].([]interface{}), map[string]string{ constant.PATH_KEY: p.Service.Path, - constant.GROUP_KEY: group.(string), + constant.GROUP_KEY: p.Service.Group, constant.INTERFACE_KEY: p.Service.Interface, constant.VERSION_KEY: p.Service.Version, })) diff --git a/protocol/dubbo/pool.go b/protocol/dubbo/pool.go index de205fa75f5fe8e8ef75c7c0f12cc2f78b3c397b..546a5b335aee3e71a6e00e49888710edb20c694a 100644 --- a/protocol/dubbo/pool.go +++ b/protocol/dubbo/pool.go @@ -62,16 +62,18 @@ func newGettyRPCClientConn(pool *gettyRPCClientPool, protocol, addr string) (*ge getty.WithReconnectInterval(pool.rpcClient.conf.ReconnectInterval), ), } - c.gettyClient.RunEventLoop(c.newSession) + go c.gettyClient.RunEventLoop(c.newSession) idx := 1 + times := int(pool.rpcClient.opts.ConnectTimeout / 1e6) for { idx++ if c.isAvailable() { break } - if idx > 5000 { - return nil, perrors.New(fmt.Sprintf("failed to create client connection to %s in 5 seconds", addr)) + if idx > times { + c.gettyClient.Close() + return nil, perrors.New(fmt.Sprintf("failed to create client connection to %s in %f seconds", addr, float32(times)/1000)) } time.Sleep(1e6) } @@ -109,7 +111,6 @@ func (c *gettyRPCClient) newSession(session getty.Session) error { session.SetMaxMsgLen(conf.GettySessionParam.MaxMsgLen) session.SetPkgHandler(NewRpcClientPackageHandler(c.pool.rpcClient)) session.SetEventListener(NewRpcClientHandler(c)) - session.SetRQLen(conf.GettySessionParam.PkgRQSize) session.SetWQLen(conf.GettySessionParam.PkgWQSize) session.SetReadTimeout(conf.GettySessionParam.tcpReadTimeout) session.SetWriteTimeout(conf.GettySessionParam.tcpWriteTimeout) @@ -117,6 +118,8 @@ func (c *gettyRPCClient) newSession(session getty.Session) error { session.SetWaitTime(conf.GettySessionParam.waitTimeout) logger.Debugf("client new session:%s\n", session.Stat()) + session.SetTaskPool(clientGrpool) + return nil } @@ -166,7 +169,9 @@ func (c *gettyRPCClient) removeSession(session getty.Session) { } logger.Infof("after remove session{%s}, left session number:%d", session.Stat(), len(c.sessions)) if len(c.sessions) == 0 { + c.pool.Lock() c.close() // -> pool.remove(c) + c.pool.Unlock() } } @@ -193,8 +198,8 @@ func (c *gettyRPCClient) getClientRpcSession(session getty.Session) (rpcSession, err error rpcSession rpcSession ) - c.lock.Lock() - defer c.lock.Unlock() + c.lock.RLock() + defer c.lock.RUnlock() if c.sessions == nil { return rpcSession, errClientClosed } @@ -241,11 +246,11 @@ func (c *gettyRPCClient) close() error { type gettyRPCClientPool struct { rpcClient *Client - size int // []*gettyRPCClient数组的size - ttl int64 // 每个gettyRPCClient的有效期时间. pool对象会在getConn时执行ttl检查 + size int // size of []*gettyRPCClient + ttl int64 // ttl of every gettyRPCClient, it is checked when getConn sync.Mutex - conns []*gettyRPCClient // 从[]*gettyRPCClient 可见key是连接地址,而value是对应这个地址的连接数组 + conns []*gettyRPCClient } func newGettyRPCClientConnPool(rpcClient *Client, size int, ttl time.Duration) *gettyRPCClientPool { @@ -270,7 +275,6 @@ func (p *gettyRPCClientPool) close() { func (p *gettyRPCClientPool) getGettyRpcClient(protocol, addr string) (*gettyRPCClient, error) { p.Lock() - defer p.Unlock() if p.conns == nil { return nil, errClientPoolClosed } @@ -287,10 +291,11 @@ func (p *gettyRPCClientPool) getGettyRpcClient(protocol, addr string) (*gettyRPC } conn.created = now //update created time + p.Unlock() return conn, nil } - // create new conn + p.Unlock() return newGettyRPCClientConn(p, protocol, addr) } diff --git a/protocol/dubbo/readwriter.go b/protocol/dubbo/readwriter.go index 042b8789104d1e671807405a81045dc30adcf789..8c6c8a5a53af4df9a89eae5db5752eb07f3aa446 100644 --- a/protocol/dubbo/readwriter.go +++ b/protocol/dubbo/readwriter.go @@ -23,10 +23,11 @@ import ( ) import ( + hessian "github.com/apache/dubbo-go-hessian2" "github.com/dubbogo/getty" - hessian "github.com/dubbogo/hessian2" perrors "github.com/pkg/errors" ) + import ( "github.com/apache/dubbo-go/common" "github.com/apache/dubbo-go/common/constant" @@ -140,11 +141,17 @@ func (p *RpcServerPackageHandler) Read(ss getty.Session, data []byte) (interface attachments = req[6].(map[interface{}]interface{}) } pkg.Service.Interface = attachments[constant.INTERFACE_KEY].(string) + if pkg.Service.Path == "" && attachments[constant.PATH_KEY] != nil { + pkg.Service.Path = attachments[constant.PATH_KEY].(string) + } + if attachments[constant.GROUP_KEY] != nil { + pkg.Service.Group = attachments[constant.GROUP_KEY].(string) + } pkg.Body = map[string]interface{}{ "dubboVersion": dubboVersion, "argsTypes": argsTypes, "args": args, - "service": common.ServiceMap.GetService(DUBBO, pkg.Service.Interface), + "service": common.ServiceMap.GetService(DUBBO, pkg.Service.Path), // path as a key "attachments": attachments, } } diff --git a/protocol/dubbo/server.go b/protocol/dubbo/server.go index 25c8f1bf4d7deaf87c3216cbfcd70d499ed2fb24..8daeee05e2ccc115aad590c2ed80a269360482d5 100644 --- a/protocol/dubbo/server.go +++ b/protocol/dubbo/server.go @@ -24,6 +24,7 @@ import ( import ( "github.com/dubbogo/getty" + "github.com/dubbogo/gost/sync" "gopkg.in/yaml.v2" ) @@ -33,7 +34,10 @@ import ( "github.com/apache/dubbo-go/config" ) -var srvConf *ServerConfig +var ( + srvConf *ServerConfig + srvGrpool *gxsync.TaskPool +) func init() { @@ -64,6 +68,7 @@ func init() { } srvConf = conf + SetServerGrpool() } func SetServerConfig(s ServerConfig) { @@ -73,12 +78,20 @@ func SetServerConfig(s ServerConfig) { logger.Warnf("[ServerConfig CheckValidity] error: %v", err) return } + SetServerGrpool() } func GetServerConfig() ServerConfig { return *srvConf } +func SetServerGrpool() { + if srvConf.GrPoolSize > 1 { + srvGrpool = gxsync.NewTaskPool(gxsync.WithTaskPoolTaskPoolSize(srvConf.GrPoolSize), gxsync.WithTaskPoolTaskQueueLength(srvConf.QueueLen), + gxsync.WithTaskPoolTaskQueueNumber(srvConf.QueueNumber)) + } +} + type Server struct { conf ServerConfig tcpServer getty.Server @@ -123,7 +136,6 @@ func (s *Server) newSession(session getty.Session) error { session.SetMaxMsgLen(conf.GettySessionParam.MaxMsgLen) session.SetPkgHandler(rpcServerPkgHandler) session.SetEventListener(s.rpcHandler) - session.SetRQLen(conf.GettySessionParam.PkgRQSize) session.SetWQLen(conf.GettySessionParam.PkgWQSize) session.SetReadTimeout(conf.GettySessionParam.tcpReadTimeout) session.SetWriteTimeout(conf.GettySessionParam.tcpWriteTimeout) @@ -131,6 +143,8 @@ func (s *Server) newSession(session getty.Session) error { session.SetWaitTime(conf.GettySessionParam.waitTimeout) logger.Debugf("app accepts new session:%s\n", session.Stat()) + session.SetTaskPool(srvGrpool) + return nil } diff --git a/protocol/invocation/rpcinvocation.go b/protocol/invocation/rpcinvocation.go index d515cc4c8ad4bcdcc88eccd4b1e8ddb545a17315..2124a22f1611b24d7f4370de64b117c58c4f7e7b 100644 --- a/protocol/invocation/rpcinvocation.go +++ b/protocol/invocation/rpcinvocation.go @@ -22,8 +22,6 @@ import ( ) import ( - "github.com/apache/dubbo-go/common" - "github.com/apache/dubbo-go/common/constant" "github.com/apache/dubbo-go/protocol" ) @@ -41,27 +39,7 @@ type RPCInvocation struct { invoker protocol.Invoker } -func NewRPCInvocationForConsumer(methodName string, parameterTypes []reflect.Type, arguments []interface{}, - reply interface{}, callBack interface{}, url common.URL, invoker protocol.Invoker) *RPCInvocation { - - attachments := map[string]string{} - attachments[constant.PATH_KEY] = url.Path - attachments[constant.GROUP_KEY] = url.GetParam(constant.GROUP_KEY, "") - attachments[constant.INTERFACE_KEY] = url.GetParam(constant.INTERFACE_KEY, "") - attachments[constant.VERSION_KEY] = url.GetParam(constant.VERSION_KEY, "") - - return &RPCInvocation{ - methodName: methodName, - parameterTypes: parameterTypes, - arguments: arguments, - reply: reply, - callBack: callBack, - attachments: attachments, - invoker: invoker, - } -} - -func NewRPCInvocationForProvider(methodName string, arguments []interface{}, attachments map[string]string) *RPCInvocation { +func NewRPCInvocation(methodName string, arguments []interface{}, attachments map[string]string) *RPCInvocation { return &RPCInvocation{ methodName: methodName, arguments: arguments, @@ -69,26 +47,6 @@ func NewRPCInvocationForProvider(methodName string, arguments []interface{}, att } } -type option func(invo *RPCInvocation) - -func WithMethodName(methodName string) option { - return func(invo *RPCInvocation) { - invo.methodName = methodName - } -} - -func WithParameterTypes(parameterTypes []reflect.Type) option { - return func(invo *RPCInvocation) { - invo.parameterTypes = parameterTypes - } -} - -func WithArguments(arguments []interface{}) option { - return func(invo *RPCInvocation) { - invo.arguments = arguments - } -} - func NewRPCInvocationWithOptions(opts ...option) *RPCInvocation { invo := &RPCInvocation{} for _, opt := range opts { @@ -147,14 +105,58 @@ func (r *RPCInvocation) SetInvoker() protocol.Invoker { return r.invoker } +func (r *RPCInvocation) CallBack() interface{} { + return r.callBack +} + func (r *RPCInvocation) SetCallBack(c interface{}) { r.callBack = c } -func (r *RPCInvocation) CallBack() interface{} { - return r.callBack +/////////////////////////// +// option +/////////////////////////// + +type option func(invo *RPCInvocation) + +func WithMethodName(methodName string) option { + return func(invo *RPCInvocation) { + invo.methodName = methodName + } +} + +func WithParameterTypes(parameterTypes []reflect.Type) option { + return func(invo *RPCInvocation) { + invo.parameterTypes = parameterTypes + } +} + +func WithArguments(arguments []interface{}) option { + return func(invo *RPCInvocation) { + invo.arguments = arguments + } +} + +func WithReply(reply interface{}) option { + return func(invo *RPCInvocation) { + invo.reply = reply + } +} + +func WithCallBack(callBack interface{}) option { + return func(invo *RPCInvocation) { + invo.callBack = callBack + } +} + +func WithAttachments(attachments map[string]string) option { + return func(invo *RPCInvocation) { + invo.attachments = attachments + } } -func (r *RPCInvocation) SetMethod(method string) { - r.methodName = method +func WithInvoker(invoker protocol.Invoker) option { + return func(invo *RPCInvocation) { + invo.invoker = invoker + } } diff --git a/protocol/invoker.go b/protocol/invoker.go index fe6aab848caceed50fc3db3e657ce87c45eac2ed..f5d41a09ad2778c12c7e5e68167a4d0acc9e3f4c 100644 --- a/protocol/invoker.go +++ b/protocol/invoker.go @@ -22,6 +22,7 @@ import ( "github.com/apache/dubbo-go/common/logger" ) +//go:generate mockgen -source invoker.go -destination mock/mock_invoker.go -self_package github.com/apache/dubbo-go/protocol/mock --package mock Invoker // Extension - Invoker type Invoker interface { common.Node diff --git a/protocol/jsonrpc/http_test.go b/protocol/jsonrpc/http_test.go index f05f47b8c1b571846335852503bb2c3a5a8c5a8d..1f446803fd6c5f174f51e3fe9496c49ae4991691 100644 --- a/protocol/jsonrpc/http_test.go +++ b/protocol/jsonrpc/http_test.go @@ -54,11 +54,11 @@ func TestHTTPClient_Call(t *testing.T) { // Export proto := GetProtocol() - url, err := common.NewURL(context.Background(), "jsonrpc://127.0.0.1:20001/com.ikurento.user.UserProvider?anyhost=true&"+ + url, err := common.NewURL(context.Background(), "jsonrpc://127.0.0.1:20001/UserProvider?anyhost=true&"+ "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"+ "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"+ "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"+ - "side=provider&timeout=3000×tamp=1556509797245") + "side=provider&timeout=3000×tamp=1556509797245&bean.name=UserProvider") assert.NoError(t, err) proto.Export(protocol.NewBaseInvoker(url)) time.Sleep(time.Second * 2) @@ -185,10 +185,6 @@ func (u *UserProvider) GetUser4(id float64) (*User, error) { return &User{Id: "1"}, nil } -func (u *UserProvider) Service() string { - return "com.ikurento.user.UserProvider" -} - -func (u *UserProvider) Version() string { - return "" +func (u *UserProvider) Reference() string { + return "UserProvider" } diff --git a/protocol/jsonrpc/jsonrpc_exporter.go b/protocol/jsonrpc/jsonrpc_exporter.go index 21a2465cddde7709bf5a23f6247ecb74016bf129..6720330494a3b833d4a67d8b2408377ce62b1ddf 100644 --- a/protocol/jsonrpc/jsonrpc_exporter.go +++ b/protocol/jsonrpc/jsonrpc_exporter.go @@ -39,9 +39,9 @@ func NewJsonrpcExporter(key string, invoker protocol.Invoker, exporterMap *sync. } func (je *JsonrpcExporter) Unexport() { - service := je.GetInvoker().GetUrl().GetParam(constant.INTERFACE_KEY, "") + serviceId := je.GetInvoker().GetUrl().GetParam(constant.BEAN_NAME_KEY, "") je.BaseExporter.Unexport() - err := common.ServiceMap.UnRegister(JSONRPC, service) + err := common.ServiceMap.UnRegister(JSONRPC, serviceId) if err != nil { logger.Errorf("[JsonrpcExporter.Unexport] error: %v", err) } diff --git a/protocol/jsonrpc/jsonrpc_invoker_test.go b/protocol/jsonrpc/jsonrpc_invoker_test.go index 0dd427eb69127317d646c599506dc476f2859a3f..bc88759bf522a35a30e8585429f1db614c3a15ce 100644 --- a/protocol/jsonrpc/jsonrpc_invoker_test.go +++ b/protocol/jsonrpc/jsonrpc_invoker_test.go @@ -41,11 +41,11 @@ func TestJsonrpcInvoker_Invoke(t *testing.T) { // Export proto := GetProtocol() - url, err := common.NewURL(context.Background(), "jsonrpc://127.0.0.1:20001/com.ikurento.user.UserProvider?anyhost=true&"+ + url, err := common.NewURL(context.Background(), "jsonrpc://127.0.0.1:20001/UserProvider?anyhost=true&"+ "application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"+ "environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"+ "module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"+ - "side=provider&timeout=3000×tamp=1556509797245") + "side=provider&timeout=3000×tamp=1556509797245&bean.name=UserProvider") assert.NoError(t, err) proto.Export(protocol.NewBaseInvoker(url)) time.Sleep(time.Second * 2) @@ -57,7 +57,9 @@ func TestJsonrpcInvoker_Invoke(t *testing.T) { jsonInvoker := NewJsonrpcInvoker(url, client) user := &User{} - res := jsonInvoker.Invoke(invocation.NewRPCInvocationForConsumer("GetUser", nil, []interface{}{"1", "username"}, user, nil, url, nil)) + res := jsonInvoker.Invoke(invocation.NewRPCInvocationWithOptions(invocation.WithMethodName("GetUser"), invocation.WithArguments([]interface{}{"1", "username"}), + invocation.WithReply(user))) + assert.NoError(t, res.Error()) assert.Equal(t, User{Id: "1", Name: "username"}, *res.Result().(*User)) diff --git a/protocol/jsonrpc/server.go b/protocol/jsonrpc/server.go index 22dc7cfc49c978a7c042652158210ef6fda48892..6b3a39c68b4fdb417e8d2efaec4a43806acb2219 100644 --- a/protocol/jsonrpc/server.go +++ b/protocol/jsonrpc/server.go @@ -325,7 +325,7 @@ func serveRequest(ctx context.Context, exporter, _ := jsonrpcProtocol.ExporterMap().Load(path) invoker := exporter.(*JsonrpcExporter).GetInvoker() if invoker != nil { - result := invoker.Invoke(invocation.NewRPCInvocationForProvider(methodName, args, map[string]string{ + result := invoker.Invoke(invocation.NewRPCInvocation(methodName, args, map[string]string{ constant.PATH_KEY: path, constant.VERSION_KEY: codec.req.Version, })) @@ -348,15 +348,14 @@ func serveRequest(ctx context.Context, } } } - serviceName := invoker.GetUrl().Service() // get method - svc := common.ServiceMap.GetService(JSONRPC, serviceName) + svc := common.ServiceMap.GetService(JSONRPC, path) if svc == nil { - return perrors.New("cannot find svc " + serviceName) + return perrors.New("cannot find svc " + path) } method := svc.Method()[methodName] if method == nil { - return perrors.New("cannot find method " + methodName + " of svc " + serviceName) + return perrors.New("cannot find method " + methodName + " of svc " + path) } in := []reflect.Value{svc.Rcvr()} diff --git a/protocol/mock/mock_invoker.go b/protocol/mock/mock_invoker.go new file mode 100644 index 0000000000000000000000000000000000000000..557dafa277e95c39d0b960436ac10ba8842c9186 --- /dev/null +++ b/protocol/mock/mock_invoker.go @@ -0,0 +1,87 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: invoker.go + +// Package mock is a generated GoMock package. +package mock + +import ( + "reflect" +) + +import ( + "github.com/golang/mock/gomock" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/protocol" +) + +// MockInvoker is a mock of Invoker interface +type MockInvoker struct { + ctrl *gomock.Controller + recorder *MockInvokerMockRecorder +} + +// MockInvokerMockRecorder is the mock recorder for MockInvoker +type MockInvokerMockRecorder struct { + mock *MockInvoker +} + +// NewMockInvoker creates a new mock instance +func NewMockInvoker(ctrl *gomock.Controller) *MockInvoker { + mock := &MockInvoker{ctrl: ctrl} + mock.recorder = &MockInvokerMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockInvoker) EXPECT() *MockInvokerMockRecorder { + return m.recorder +} + +// GetUrl mocks base method +func (m *MockInvoker) GetUrl() common.URL { + ret := m.ctrl.Call(m, "GetUrl") + ret0, _ := ret[0].(common.URL) + return ret0 +} + +// GetUrl indicates an expected call of GetUrl +func (mr *MockInvokerMockRecorder) GetUrl() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUrl", reflect.TypeOf((*MockInvoker)(nil).GetUrl)) +} + +// IsAvailable mocks base method +func (m *MockInvoker) IsAvailable() bool { + ret := m.ctrl.Call(m, "IsAvailable") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsAvailable indicates an expected call of IsAvailable +func (mr *MockInvokerMockRecorder) IsAvailable() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsAvailable", reflect.TypeOf((*MockInvoker)(nil).IsAvailable)) +} + +// Destroy mocks base method +func (m *MockInvoker) Destroy() { + m.ctrl.Call(m, "Destroy") +} + +// Destroy indicates an expected call of Destroy +func (mr *MockInvokerMockRecorder) Destroy() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Destroy", reflect.TypeOf((*MockInvoker)(nil).Destroy)) +} + +// Invoke mocks base method +func (m *MockInvoker) Invoke(arg0 protocol.Invocation) protocol.Result { + ret := m.ctrl.Call(m, "Invoke", arg0) + ret0, _ := ret[0].(protocol.Result) + return ret0 +} + +// Invoke indicates an expected call of Invoke +func (mr *MockInvokerMockRecorder) Invoke(arg0 interface{}) *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Invoke", reflect.TypeOf((*MockInvoker)(nil).Invoke), arg0) +} diff --git a/registry/etcdv3/listener.go b/registry/etcdv3/listener.go new file mode 100644 index 0000000000000000000000000000000000000000..a8f2facc1aa43db4daea77c03f332df16f302431 --- /dev/null +++ b/registry/etcdv3/listener.go @@ -0,0 +1,88 @@ +package etcdv3 + +import ( + "context" + "strings" +) + +import ( + perrors "github.com/pkg/errors" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/logger" + "github.com/apache/dubbo-go/registry" + "github.com/apache/dubbo-go/remoting" +) + +type dataListener struct { + interestedURL []*common.URL + listener remoting.ConfigurationListener +} + +func NewRegistryDataListener(listener remoting.ConfigurationListener) *dataListener { + return &dataListener{listener: listener, interestedURL: []*common.URL{}} +} + +func (l *dataListener) AddInterestedURL(url *common.URL) { + l.interestedURL = append(l.interestedURL, url) +} + +func (l *dataListener) DataChange(eventType remoting.Event) bool { + + url := eventType.Path[strings.Index(eventType.Path, "/providers/")+len("/providers/"):] + serviceURL, err := common.NewURL(context.Background(), url) + if err != nil { + logger.Warnf("Listen NewURL(r{%s}) = error{%v}", eventType.Path, err) + return false + } + + for _, v := range l.interestedURL { + if serviceURL.URLEqual(*v) { + l.listener.Process(&remoting.ConfigChangeEvent{Key: eventType.Path, Value: serviceURL, ConfigType: eventType.Action}) + return true + } + } + + return false +} + +type configurationListener struct { + registry *etcdV3Registry + events chan *remoting.ConfigChangeEvent +} + +func NewConfigurationListener(reg *etcdV3Registry) *configurationListener { + // add a new waiter + reg.wg.Add(1) + return &configurationListener{registry: reg, events: make(chan *remoting.ConfigChangeEvent, 32)} +} +func (l *configurationListener) Process(configType *remoting.ConfigChangeEvent) { + l.events <- configType +} + +func (l *configurationListener) Next() (*registry.ServiceEvent, error) { + for { + select { + case <-l.registry.done: + logger.Warnf("listener's etcd client connection is broken, so etcd event listener exit now.") + return nil, perrors.New("listener stopped") + + case e := <-l.events: + logger.Infof("got etcd event %#v", e) + if e.ConfigType == remoting.EventTypeDel { + select { + case <-l.registry.done: + logger.Warnf("update @result{%s}. But its connection to registry is invalid", e.Value) + default: + } + continue + } + return ®istry.ServiceEvent{Action: e.ConfigType, Service: e.Value.(common.URL)}, nil + } + } +} +func (l *configurationListener) Close() { + l.registry.wg.Done() +} diff --git a/registry/etcdv3/listener_test.go b/registry/etcdv3/listener_test.go new file mode 100644 index 0000000000000000000000000000000000000000..0ac8fc475e454e737e0ea03301709457561e961c --- /dev/null +++ b/registry/etcdv3/listener_test.go @@ -0,0 +1,71 @@ +package etcdv3 + +import ( + "context" + "testing" + "time" +) + +import ( + "github.com/dubbogo/getty" + "github.com/stretchr/testify/suite" + "go.etcd.io/etcd/embed" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/remoting" +) + +type RegistryTestSuite struct { + suite.Suite + etcd *embed.Etcd +} + +// start etcd server +func (suite *RegistryTestSuite) SetupSuite() { + + t := suite.T() + + cfg := embed.NewConfig() + cfg.Dir = "/tmp/default.etcd" + e, err := embed.StartEtcd(cfg) + if err != nil { + t.Fatal(err) + } + select { + case <-e.Server.ReadyNotify(): + t.Log("Server is ready!") + case <-getty.GetTimeWheel().After(60 * time.Second): + e.Server.Stop() // trigger a shutdown + t.Logf("Server took too long to start!") + } + + suite.etcd = e + return +} + +// stop etcd server +func (suite *RegistryTestSuite) TearDownSuite() { + suite.etcd.Close() +} + +func (suite *RegistryTestSuite) TestDataChange() { + + t := suite.T() + + listener := NewRegistryDataListener(&MockDataListener{}) + url, _ := common.NewURL(context.Background(), "jsonrpc%3A%2F%2F127.0.0.1%3A20001%2Fcom.ikurento.user.UserProvider%3Fanyhost%3Dtrue%26app.version%3D0.0.1%26application%3DBDTService%26category%3Dproviders%26cluster%3Dfailover%26dubbo%3Ddubbo-provider-golang-2.6.0%26environment%3Ddev%26group%3D%26interface%3Dcom.ikurento.user.UserProvider%26ip%3D10.32.20.124%26loadbalance%3Drandom%26methods.GetUser.loadbalance%3Drandom%26methods.GetUser.retries%3D1%26methods.GetUser.weight%3D0%26module%3Ddubbogo%2Buser-info%2Bserver%26name%3DBDTService%26organization%3Dikurento.com%26owner%3DZX%26pid%3D74500%26retries%3D0%26service.filter%3Decho%26side%3Dprovider%26timestamp%3D1560155407%26version%3D%26warmup%3D100") + listener.AddInterestedURL(&url) + if !listener.DataChange(remoting.Event{Path: "/dubbo/com.ikurento.user.UserProvider/providers/jsonrpc%3A%2F%2F127.0.0.1%3A20001%2Fcom.ikurento.user.UserProvider%3Fanyhost%3Dtrue%26app.version%3D0.0.1%26application%3DBDTService%26category%3Dproviders%26cluster%3Dfailover%26dubbo%3Ddubbo-provider-golang-2.6.0%26environment%3Ddev%26group%3D%26interface%3Dcom.ikurento.user.UserProvider%26ip%3D10.32.20.124%26loadbalance%3Drandom%26methods.GetUser.loadbalance%3Drandom%26methods.GetUser.retries%3D1%26methods.GetUser.weight%3D0%26module%3Ddubbogo%2Buser-info%2Bserver%26name%3DBDTService%26organization%3Dikurento.com%26owner%3DZX%26pid%3D74500%26retries%3D0%26service.filter%3Decho%26side%3Dprovider%26timestamp%3D1560155407%26version%3D%26warmup%3D100"}) { + t.Fatal("data change not ok") + } +} + +func TestRegistrySuite(t *testing.T) { + suite.Run(t, &RegistryTestSuite{}) +} + +type MockDataListener struct{} + +func (*MockDataListener) Process(configType *remoting.ConfigChangeEvent) {} diff --git a/registry/etcdv3/registry.go b/registry/etcdv3/registry.go new file mode 100644 index 0000000000000000000000000000000000000000..5802142989e5d8297f027ddecff3d7780070729f --- /dev/null +++ b/registry/etcdv3/registry.go @@ -0,0 +1,325 @@ +package etcdv3 + +import ( + "fmt" + "net/url" + "os" + "path" + "strconv" + "strings" + "sync" + "time" +) + +import ( + perrors "github.com/pkg/errors" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/common/logger" + "github.com/apache/dubbo-go/common/utils" + "github.com/apache/dubbo-go/registry" + "github.com/apache/dubbo-go/remoting/etcdv3" +) + +var ( + processID = "" + localIP = "" +) + +const Name = "etcdv3" + +func init() { + processID = fmt.Sprintf("%d", os.Getpid()) + localIP, _ = utils.GetLocalIP() + extension.SetRegistry(Name, newETCDV3Registry) +} + +type etcdV3Registry struct { + *common.URL + birth int64 // time of file birth, seconds since Epoch; 0 if unknown + + cltLock sync.Mutex + client *etcdv3.Client + services map[string]common.URL // service name + protocol -> service config + + listenerLock sync.Mutex + listener *etcdv3.EventListener + dataListener *dataListener + configListener *configurationListener + + wg sync.WaitGroup // wg+done for etcd client restart + done chan struct{} +} + +func (r *etcdV3Registry) Client() *etcdv3.Client { + return r.client +} +func (r *etcdV3Registry) SetClient(client *etcdv3.Client) { + r.client = client +} +func (r *etcdV3Registry) ClientLock() *sync.Mutex { + return &r.cltLock +} +func (r *etcdV3Registry) WaitGroup() *sync.WaitGroup { + return &r.wg +} +func (r *etcdV3Registry) GetDone() chan struct{} { + return r.done +} +func (r *etcdV3Registry) RestartCallBack() bool { + + services := []common.URL{} + for _, confIf := range r.services { + services = append(services, confIf) + } + + flag := true + for _, confIf := range services { + err := r.Register(confIf) + if err != nil { + logger.Errorf("(etcdV3ProviderRegistry)register(conf{%#v}) = error{%#v}", + confIf, perrors.WithStack(err)) + flag = false + break + } + logger.Infof("success to re-register service :%v", confIf.Key()) + } + return flag +} + +func newETCDV3Registry(url *common.URL) (registry.Registry, error) { + + timeout, err := time.ParseDuration(url.GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT)) + if err != nil { + logger.Errorf("timeout config %v is invalid ,err is %v", + url.GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT), err.Error()) + return nil, perrors.WithMessagef(err, "new etcd registry(address:%+v)", url.Location) + } + + logger.Infof("etcd address is: %v, timeout is: %s", url.Location, timeout.String()) + + r := &etcdV3Registry{ + URL: url, + birth: time.Now().UnixNano(), + done: make(chan struct{}), + services: make(map[string]common.URL), + } + + if err := etcdv3.ValidateClient( + r, + etcdv3.WithName(etcdv3.RegistryETCDV3Client), + etcdv3.WithTimeout(timeout), + etcdv3.WithEndpoints(url.Location), + ); err != nil { + return nil, err + } + + r.wg.Add(1) + go etcdv3.HandleClientRestart(r) + + r.listener = etcdv3.NewEventListener(r.client) + r.configListener = NewConfigurationListener(r) + r.dataListener = NewRegistryDataListener(r.configListener) + + return r, nil +} + +func (r *etcdV3Registry) GetUrl() common.URL { + return *r.URL +} + +func (r *etcdV3Registry) IsAvailable() bool { + + select { + case <-r.done: + return false + default: + return true + } +} + +func (r *etcdV3Registry) Destroy() { + + if r.configListener != nil { + r.configListener.Close() + } + r.stop() +} + +func (r *etcdV3Registry) stop() { + + close(r.done) + + // close current client + r.client.Close() + + r.cltLock.Lock() + r.client = nil + r.services = nil + r.cltLock.Unlock() +} + +func (r *etcdV3Registry) Register(svc common.URL) error { + + role, err := strconv.Atoi(r.URL.GetParam(constant.ROLE_KEY, "")) + if err != nil { + return perrors.WithMessage(err, "get registry role") + } + + r.cltLock.Lock() + if _, ok := r.services[svc.Key()]; ok { + r.cltLock.Unlock() + return perrors.New(fmt.Sprintf("Path{%s} has been registered", svc.Path)) + } + r.cltLock.Unlock() + + switch role { + case common.PROVIDER: + logger.Debugf("(provider register )Register(conf{%#v})", svc) + if err := r.registerProvider(svc); err != nil { + return perrors.WithMessage(err, "register provider") + } + case common.CONSUMER: + logger.Debugf("(consumer register )Register(conf{%#v})", svc) + if err := r.registerConsumer(svc); err != nil { + return perrors.WithMessage(err, "register consumer") + } + default: + return perrors.New(fmt.Sprintf("unknown role %d", role)) + } + + r.cltLock.Lock() + r.services[svc.Key()] = svc + r.cltLock.Unlock() + return nil +} + +func (r *etcdV3Registry) createDirIfNotExist(k string) error { + + var tmpPath string + for _, str := range strings.Split(k, "/")[1:] { + tmpPath = path.Join(tmpPath, "/", str) + if err := r.client.Create(tmpPath, ""); err != nil { + return perrors.WithMessagef(err, "create path %s in etcd", tmpPath) + } + } + + return nil +} + +func (r *etcdV3Registry) registerConsumer(svc common.URL) error { + + consumersNode := fmt.Sprintf("/dubbo/%s/%s", svc.Service(), common.DubboNodes[common.CONSUMER]) + if err := r.createDirIfNotExist(consumersNode); err != nil { + logger.Errorf("etcd client create path %s: %v", consumersNode, err) + return perrors.WithMessage(err, "etcd create consumer nodes") + } + providersNode := fmt.Sprintf("/dubbo/%s/%s", svc.Service(), common.DubboNodes[common.PROVIDER]) + if err := r.createDirIfNotExist(providersNode); err != nil { + return perrors.WithMessage(err, "create provider node") + } + + params := url.Values{} + + params.Add("protocol", svc.Protocol) + + params.Add("category", (common.RoleType(common.CONSUMER)).String()) + params.Add("dubbo", "dubbogo-consumer-"+constant.Version) + + encodedURL := url.QueryEscape(fmt.Sprintf("consumer://%s%s?%s", localIP, svc.Path, params.Encode())) + dubboPath := fmt.Sprintf("/dubbo/%s/%s", svc.Service(), (common.RoleType(common.CONSUMER)).String()) + if err := r.client.Create(path.Join(dubboPath, encodedURL), ""); err != nil { + return perrors.WithMessagef(err, "create k/v in etcd (path:%s, url:%s)", dubboPath, encodedURL) + } + + return nil +} + +func (r *etcdV3Registry) registerProvider(svc common.URL) error { + + if len(svc.Path) == 0 || len(svc.Methods) == 0 { + return perrors.New(fmt.Sprintf("service path %s or service method %s", svc.Path, svc.Methods)) + } + + var ( + urlPath string + encodedURL string + dubboPath string + ) + + providersNode := fmt.Sprintf("/dubbo/%s/%s", svc.Service(), common.DubboNodes[common.PROVIDER]) + if err := r.createDirIfNotExist(providersNode); err != nil { + return perrors.WithMessage(err, "create provider node") + } + + params := url.Values{} + for k, v := range svc.Params { + params[k] = v + } + + params.Add("pid", processID) + params.Add("ip", localIP) + params.Add("anyhost", "true") + params.Add("category", (common.RoleType(common.PROVIDER)).String()) + params.Add("dubbo", "dubbo-provider-golang-"+constant.Version) + params.Add("side", (common.RoleType(common.PROVIDER)).Role()) + + if len(svc.Methods) == 0 { + params.Add("methods", strings.Join(svc.Methods, ",")) + } + + logger.Debugf("provider url params:%#v", params) + var host string + if len(svc.Ip) == 0 { + host = localIP + ":" + svc.Port + } else { + host = svc.Ip + ":" + svc.Port + } + + urlPath = svc.Path + + encodedURL = url.QueryEscape(fmt.Sprintf("%s://%s%s?%s", svc.Protocol, host, urlPath, params.Encode())) + dubboPath = fmt.Sprintf("/dubbo/%s/%s", svc.Service(), (common.RoleType(common.PROVIDER)).String()) + + if err := r.client.Create(path.Join(dubboPath, encodedURL), ""); err != nil { + return perrors.WithMessagef(err, "create k/v in etcd (path:%s, url:%s)", dubboPath, encodedURL) + } + + return nil +} + +func (r *etcdV3Registry) Subscribe(svc common.URL) (registry.Listener, error) { + + var ( + configListener *configurationListener + ) + + r.listenerLock.Lock() + configListener = r.configListener + r.listenerLock.Unlock() + if r.listener == nil { + r.cltLock.Lock() + client := r.client + r.cltLock.Unlock() + if client == nil { + return nil, perrors.New("etcd client broken") + } + + // new client & listener + listener := etcdv3.NewEventListener(r.client) + + r.listenerLock.Lock() + r.listener = listener + r.listenerLock.Unlock() + } + + //register the svc to dataListener + r.dataListener.AddInterestedURL(&svc) + go r.listener.ListenServiceEvent(fmt.Sprintf("/dubbo/%s/providers", svc.Service()), r.dataListener) + + return configListener, nil +} diff --git a/registry/etcdv3/registry_test.go b/registry/etcdv3/registry_test.go new file mode 100644 index 0000000000000000000000000000000000000000..26204c74ad4305278e33d9c8b50199cfa578bf8a --- /dev/null +++ b/registry/etcdv3/registry_test.go @@ -0,0 +1,112 @@ +package etcdv3 + +import ( + "context" + "strconv" + "testing" + "time" +) + +import ( + "github.com/stretchr/testify/assert" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" +) + +func initRegistry(t *testing.T) *etcdV3Registry { + + regurl, err := common.NewURL(context.Background(), "registry://127.0.0.1:2379", common.WithParamsValue(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER))) + if err != nil { + t.Fatal(err) + } + + reg, err := newETCDV3Registry(®url) + if err != nil { + t.Fatal(err) + } + + out := reg.(*etcdV3Registry) + out.client.CleanKV() + return out +} + +func (suite *RegistryTestSuite) TestRegister() { + + t := suite.T() + + url, _ := common.NewURL(context.Background(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider", common.WithParamsValue(constant.CLUSTER_KEY, "mock"), common.WithMethods([]string{"GetUser", "AddUser"})) + + reg := initRegistry(t) + err := reg.Register(url) + children, _, err := reg.client.GetChildrenKVList("/dubbo/com.ikurento.user.UserProvider/providers") + if err != nil { + t.Fatal(err) + } + assert.Regexp(t, ".*dubbo%3A%2F%2F127.0.0.1%3A20000%2Fcom.ikurento.user.UserProvider%3Fanyhost%3Dtrue%26category%3Dproviders%26cluster%3Dmock%26dubbo%3Ddubbo-provider-golang-2.6.0%26.*provider", children) + assert.NoError(t, err) +} + +func (suite *RegistryTestSuite) TestSubscribe() { + + t := suite.T() + regurl, _ := common.NewURL(context.Background(), "registry://127.0.0.1:1111", common.WithParamsValue(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER))) + url, _ := common.NewURL(context.Background(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider", common.WithParamsValue(constant.CLUSTER_KEY, "mock"), common.WithMethods([]string{"GetUser", "AddUser"})) + + reg := initRegistry(t) + //provider register + err := reg.Register(url) + if err != nil { + t.Fatal(err) + } + + //consumer register + regurl.Params.Set(constant.ROLE_KEY, strconv.Itoa(common.CONSUMER)) + reg2 := initRegistry(t) + + reg2.Register(url) + listener, err := reg2.Subscribe(url) + if err != nil { + t.Fatal(err) + } + + serviceEvent, err := listener.Next() + if err != nil { + t.Fatal(err) + } + assert.Regexp(t, ".*ServiceEvent{Action{add}.*", serviceEvent.String()) +} + +func (suite *RegistryTestSuite) TestConsumerDestory() { + + t := suite.T() + url, _ := common.NewURL(context.Background(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider", common.WithParamsValue(constant.CLUSTER_KEY, "mock"), common.WithMethods([]string{"GetUser", "AddUser"})) + + reg := initRegistry(t) + _, err := reg.Subscribe(url) + if err != nil { + t.Fatal(err) + } + + //listener.Close() + time.Sleep(1e9) + reg.Destroy() + + assert.Equal(t, false, reg.IsAvailable()) + +} + +func (suite *RegistryTestSuite) TestProviderDestory() { + + t := suite.T() + reg := initRegistry(t) + url, _ := common.NewURL(context.Background(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider", common.WithParamsValue(constant.CLUSTER_KEY, "mock"), common.WithMethods([]string{"GetUser", "AddUser"})) + reg.Register(url) + + //listener.Close() + time.Sleep(1e9) + reg.Destroy() + assert.Equal(t, false, reg.IsAvailable()) +} diff --git a/registry/nacos/listener.go b/registry/nacos/listener.go new file mode 100644 index 0000000000000000000000000000000000000000..c42abd0bb16573da33c20c150896f85b3a7edfd0 --- /dev/null +++ b/registry/nacos/listener.go @@ -0,0 +1,199 @@ +package nacos + +import ( + "bytes" + "net/url" + "reflect" + "strconv" + "sync" +) + +import ( + "github.com/nacos-group/nacos-sdk-go/clients/naming_client" + "github.com/nacos-group/nacos-sdk-go/model" + "github.com/nacos-group/nacos-sdk-go/vo" + perrors "github.com/pkg/errors" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/logger" + "github.com/apache/dubbo-go/registry" + "github.com/apache/dubbo-go/remoting" +) + +type nacosListener struct { + namingClient naming_client.INamingClient + listenUrl common.URL + events chan *remoting.ConfigChangeEvent + instanceMap map[string]model.Instance + cacheLock sync.Mutex + done chan struct{} + subscribeParam *vo.SubscribeParam +} + +func NewNacosListener(url common.URL, namingClient naming_client.INamingClient) (*nacosListener, error) { + listener := &nacosListener{ + namingClient: namingClient, + listenUrl: url, events: make(chan *remoting.ConfigChangeEvent, 32), + instanceMap: map[string]model.Instance{}, + done: make(chan struct{}), + } + err := listener.startListen() + return listener, err +} + +func generateInstance(ss model.SubscribeService) model.Instance { + return model.Instance{ + InstanceId: ss.InstanceId, + Ip: ss.Ip, + Port: ss.Port, + ServiceName: ss.ServiceName, + Valid: ss.Valid, + Enable: ss.Enable, + Weight: ss.Weight, + Metadata: ss.Metadata, + ClusterName: ss.ClusterName, + } +} + +func generateUrl(instance model.Instance) *common.URL { + if instance.Metadata == nil { + logger.Errorf("nacos instance metadata is empty,instance:%+v", instance) + return nil + } + path := instance.Metadata["path"] + myInterface := instance.Metadata["interface"] + if len(path) == 0 && len(myInterface) == 0 { + logger.Errorf("nacos instance metadata does not have both path key and interface key,instance:%+v", instance) + return nil + } + if len(path) == 0 && len(myInterface) != 0 { + path = "/" + myInterface + } + protocol := instance.Metadata["protocol"] + if len(protocol) == 0 { + logger.Errorf("nacos instance metadata does not have protocol key,instance:%+v", instance) + return nil + } + urlMap := url.Values{} + for k, v := range instance.Metadata { + urlMap.Set(k, v) + } + return common.NewURLWithOptions( + common.WithIp(instance.Ip), + common.WithPort(strconv.Itoa(int(instance.Port))), + common.WithProtocol(protocol), + common.WithParams(urlMap), + common.WithPath(path), + ) +} + +func (nl *nacosListener) Callback(services []model.SubscribeService, err error) { + if err != nil { + logger.Errorf("nacos subscribe callback error:%s , subscribe:%+v ", err.Error(), nl.subscribeParam) + return + } + nl.cacheLock.Lock() + defer nl.cacheLock.Unlock() + addInstances := make([]model.Instance, 0, len(services)) + delInstances := make([]model.Instance, 0, len(services)) + updateInstances := make([]model.Instance, 0, len(services)) + + newInstanceMap := make(map[string]model.Instance, len(services)) + + for i := range services { + if !services[i].Enable || !services[i].Valid { + // instance is not available,so ignore it + continue + } + host := services[i].Ip + ":" + strconv.Itoa(int(services[i].Port)) + instance := generateInstance(services[i]) + newInstanceMap[host] = instance + if old, ok := nl.instanceMap[host]; !ok { + //instance is not exsit in cache,add it to cache + addInstances = append(addInstances, instance) + } else { + //instance is not different from cache,update it to cache + if !reflect.DeepEqual(old, instance) { + updateInstances = append(updateInstances, instance) + } + } + } + + for host, inst := range nl.instanceMap { + if _, ok := newInstanceMap[host]; !ok { + //cache instance is not exsit in new instance list, remove it from cache + delInstances = append(delInstances, inst) + } + } + + nl.instanceMap = newInstanceMap + + for i := range addInstances { + newUrl := generateUrl(addInstances[i]) + if newUrl != nil { + nl.process(&remoting.ConfigChangeEvent{Value: *newUrl, ConfigType: remoting.EventTypeAdd}) + } + } + for i := range delInstances { + newUrl := generateUrl(delInstances[i]) + if newUrl != nil { + nl.process(&remoting.ConfigChangeEvent{Value: *newUrl, ConfigType: remoting.EventTypeDel}) + } + } + + for i := range updateInstances { + newUrl := generateUrl(updateInstances[i]) + if newUrl != nil { + nl.process(&remoting.ConfigChangeEvent{Value: *newUrl, ConfigType: remoting.EvnetTypeUpdate}) + } + } +} + +func getSubscribeName(url common.URL) string { + var buffer bytes.Buffer + + buffer.Write([]byte(common.DubboNodes[common.PROVIDER])) + appendParam(&buffer, url, constant.INTERFACE_KEY) + appendParam(&buffer, url, constant.VERSION_KEY) + appendParam(&buffer, url, constant.GROUP_KEY) + return buffer.String() +} + +func (nl *nacosListener) startListen() error { + if nl.namingClient == nil { + return perrors.New("nacos naming client stopped") + } + serviceName := getSubscribeName(nl.listenUrl) + nl.subscribeParam = &vo.SubscribeParam{ServiceName: serviceName, SubscribeCallback: nl.Callback} + return nl.namingClient.Subscribe(nl.subscribeParam) +} + +func (nl *nacosListener) stopListen() error { + return nl.namingClient.Unsubscribe(nl.subscribeParam) +} + +func (nl *nacosListener) process(configType *remoting.ConfigChangeEvent) { + nl.events <- configType +} + +func (nl *nacosListener) Next() (*registry.ServiceEvent, error) { + for { + select { + case <-nl.done: + logger.Warnf("nacos listener is close!listenUrl:%+v", nl.listenUrl) + return nil, perrors.New("listener stopped") + + case e := <-nl.events: + logger.Debugf("got nacos event %s", e) + return ®istry.ServiceEvent{Action: e.ConfigType, Service: e.Value.(common.URL)}, nil + } + } +} + +func (nl *nacosListener) Close() { + nl.stopListen() + close(nl.done) +} diff --git a/registry/nacos/registry.go b/registry/nacos/registry.go new file mode 100644 index 0000000000000000000000000000000000000000..f10e230bc44dba8f8007ea659db3747a237c9de1 --- /dev/null +++ b/registry/nacos/registry.go @@ -0,0 +1,176 @@ +package nacos + +import ( + "bytes" + "net" + "strconv" + "strings" + "time" +) +import ( + "github.com/nacos-group/nacos-sdk-go/clients" + "github.com/nacos-group/nacos-sdk-go/clients/naming_client" + nacosConstant "github.com/nacos-group/nacos-sdk-go/common/constant" + "github.com/nacos-group/nacos-sdk-go/vo" + perrors "github.com/pkg/errors" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/extension" + "github.com/apache/dubbo-go/common/utils" + "github.com/apache/dubbo-go/registry" +) + +var ( + localIP = "" +) + +func init() { + localIP, _ = utils.GetLocalIP() + extension.SetRegistry(constant.NACOS_KEY, newNacosRegistry) +} + +type nacosRegistry struct { + *common.URL + namingClient naming_client.INamingClient +} + +func getNacosConfig(url *common.URL) (map[string]interface{}, error) { + if url == nil { + return nil, perrors.New("url is empty!") + } + if len(url.Location) == 0 { + return nil, perrors.New("url.location is empty!") + } + configMap := make(map[string]interface{}, 2) + + addresses := strings.Split(url.Location, ",") + serverConfigs := make([]nacosConstant.ServerConfig, 0, len(addresses)) + for _, addr := range addresses { + ip, portStr, err := net.SplitHostPort(addr) + if err != nil { + return nil, perrors.WithMessagef(err, "split [%s] ", addr) + } + port, _ := strconv.Atoi(portStr) + serverConfigs = append(serverConfigs, nacosConstant.ServerConfig{ + IpAddr: ip, + Port: uint64(port), + }) + } + configMap["serverConfigs"] = serverConfigs + + var clientConfig nacosConstant.ClientConfig + timeout, err := time.ParseDuration(url.GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT)) + if err != nil { + return nil, err + } + clientConfig.TimeoutMs = uint64(timeout.Seconds() * 1000) + clientConfig.ListenInterval = 2 * clientConfig.TimeoutMs + clientConfig.CacheDir = url.GetParam(constant.NACOS_CACHE_DIR_KEY, "") + clientConfig.LogDir = url.GetParam(constant.NACOS_LOG_DIR_KEY, "") + clientConfig.Endpoint = url.GetParam(constant.NACOS_ENDPOINT, "") + clientConfig.NotLoadCacheAtStart = true + configMap["clientConfig"] = clientConfig + + return configMap, nil +} + +func newNacosRegistry(url *common.URL) (registry.Registry, error) { + nacosConfig, err := getNacosConfig(url) + if err != nil { + return nil, err + } + client, err := clients.CreateNamingClient(nacosConfig) + if err != nil { + return nil, err + } + registry := nacosRegistry{ + URL: url, + namingClient: client, + } + return ®istry, nil +} + +func getCategory(url common.URL) string { + role, _ := strconv.Atoi(url.GetParam(constant.ROLE_KEY, strconv.Itoa(constant.NACOS_DEFAULT_ROLETYPE))) + category := common.DubboNodes[role] + return category +} + +func getServiceName(url common.URL) string { + var buffer bytes.Buffer + + buffer.Write([]byte(getCategory(url))) + appendParam(&buffer, url, constant.INTERFACE_KEY) + appendParam(&buffer, url, constant.VERSION_KEY) + appendParam(&buffer, url, constant.GROUP_KEY) + return buffer.String() +} + +func appendParam(target *bytes.Buffer, url common.URL, key string) { + value := url.GetParam(key, "") + if strings.TrimSpace(value) != "" { + target.Write([]byte(constant.NACOS_SERVICE_NAME_SEPARATOR)) + target.Write([]byte(value)) + } +} + +func createRegisterParam(url common.URL, serviceName string) vo.RegisterInstanceParam { + category := getCategory(url) + params := make(map[string]string, len(url.Params)+3) + for k, _ := range url.Params { + params[k] = url.Params.Get(k) + } + params[constant.NACOS_CATEGORY_KEY] = category + params[constant.NACOS_PROTOCOL_KEY] = url.Protocol + params[constant.NACOS_PATH_KEY] = url.Path + if len(url.Ip) == 0 { + url.Ip = localIP + } + if len(url.Port) == 0 || url.Port == "0" { + url.Port = "80" + } + port, _ := strconv.Atoi(url.Port) + instance := vo.RegisterInstanceParam{ + Ip: url.Ip, + Port: uint64(port), + Metadata: params, + Weight: 1, + Enable: true, + Healthy: true, + Ephemeral: true, + ServiceName: serviceName, + } + return instance +} + +func (nr *nacosRegistry) Register(url common.URL) error { + serviceName := getServiceName(url) + param := createRegisterParam(url, serviceName) + isRegistry, err := nr.namingClient.RegisterInstance(param) + if err != nil { + return err + } + if !isRegistry { + return perrors.New("registry [" + serviceName + "] to nacos failed") + } + return nil +} + +func (nr *nacosRegistry) Subscribe(conf common.URL) (registry.Listener, error) { + return NewNacosListener(conf, nr.namingClient) +} + +func (nr *nacosRegistry) GetUrl() common.URL { + return *nr.URL +} + +func (nr *nacosRegistry) IsAvailable() bool { + return true +} + +func (nr *nacosRegistry) Destroy() { + return +} diff --git a/registry/nacos/registry_test.go b/registry/nacos/registry_test.go new file mode 100644 index 0000000000000000000000000000000000000000..97dea0d2b016c8f84ee7cf6f4856ba545b720a48 --- /dev/null +++ b/registry/nacos/registry_test.go @@ -0,0 +1,174 @@ +package nacos + +import ( + "context" + "encoding/json" + "net/url" + "strconv" + "testing" +) + +import ( + "github.com/nacos-group/nacos-sdk-go/vo" + "github.com/stretchr/testify/assert" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" +) + +func Test_Register(t *testing.T) { + regurl, _ := common.NewURL(context.TODO(), "registry://console.nacos.io:80", common.WithParamsValue(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER))) + urlMap := url.Values{} + urlMap.Set(constant.GROUP_KEY, "guangzhou-idc") + urlMap.Set(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER)) + urlMap.Set(constant.INTERFACE_KEY, "com.ikurento.user.UserProvider") + urlMap.Set(constant.VERSION_KEY, "1.0.0") + urlMap.Set(constant.CLUSTER_KEY, "mock") + url, _ := common.NewURL(context.TODO(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider", common.WithParams(urlMap), common.WithMethods([]string{"GetUser", "AddUser"})) + + reg, err := newNacosRegistry(®url) + assert.Nil(t, err) + if err != nil { + t.Errorf("new nacos registry error:%s \n", err.Error()) + return + } + err = reg.Register(url) + assert.Nil(t, err) + if err != nil { + t.Errorf("register error:%s \n", err.Error()) + return + } + nacosReg := reg.(*nacosRegistry) + service, _ := nacosReg.namingClient.GetService(vo.GetServiceParam{ServiceName: "providers:com.ikurento.user.UserProvider:1.0.0:guangzhou-idc"}) + data, _ := json.Marshal(service) + t.Logf(string(data)) + assert.Equal(t, 1, len(service.Hosts)) +} + +func TestNacosRegistry_Subscribe(t *testing.T) { + regurl, _ := common.NewURL(context.TODO(), "registry://console.nacos.io:80", common.WithParamsValue(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER))) + urlMap := url.Values{} + urlMap.Set(constant.GROUP_KEY, "guangzhou-idc") + urlMap.Set(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER)) + urlMap.Set(constant.INTERFACE_KEY, "com.ikurento.user.UserProvider") + urlMap.Set(constant.VERSION_KEY, "1.0.0") + urlMap.Set(constant.CLUSTER_KEY, "mock") + urlMap.Set(constant.NACOS_PATH_KEY, "") + url, _ := common.NewURL(context.TODO(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider", common.WithParams(urlMap), common.WithMethods([]string{"GetUser", "AddUser"})) + + reg, _ := newNacosRegistry(®url) + err := reg.Register(url) + assert.Nil(t, err) + if err != nil { + t.Errorf("new nacos registry error:%s \n", err.Error()) + return + } + + regurl.Params.Set(constant.ROLE_KEY, strconv.Itoa(common.CONSUMER)) + reg2, _ := newNacosRegistry(®url) + listener, err := reg2.Subscribe(url) + assert.Nil(t, err) + if err != nil { + t.Errorf("subscribe error:%s \n", err.Error()) + return + } + serviceEvent, _ := listener.Next() + assert.NoError(t, err) + if err != nil { + t.Errorf("listener error:%s \n", err.Error()) + return + } + t.Logf("serviceEvent:%+v \n", serviceEvent) + assert.Regexp(t, ".*ServiceEvent{Action{add}.*", serviceEvent.String()) + +} + +func TestNacosRegistry_Subscribe_del(t *testing.T) { + regurl, _ := common.NewURL(context.TODO(), "registry://console.nacos.io:80", common.WithParamsValue(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER))) + urlMap := url.Values{} + urlMap.Set(constant.GROUP_KEY, "guangzhou-idc") + urlMap.Set(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER)) + urlMap.Set(constant.INTERFACE_KEY, "com.ikurento.user.UserProvider") + urlMap.Set(constant.VERSION_KEY, "1.0.0") + urlMap.Set(constant.CLUSTER_KEY, "mock") + urlMap.Set(constant.NACOS_PATH_KEY, "") + url1, _ := common.NewURL(context.TODO(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider", common.WithParams(urlMap), common.WithMethods([]string{"GetUser", "AddUser"})) + url2, _ := common.NewURL(context.TODO(), "dubbo://127.0.0.2:20000/com.ikurento.user.UserProvider", common.WithParams(urlMap), common.WithMethods([]string{"GetUser", "AddUser"})) + + reg, _ := newNacosRegistry(®url) + err := reg.Register(url1) + assert.Nil(t, err) + if err != nil { + t.Errorf("register1 error:%s \n", err.Error()) + return + } + err = reg.Register(url2) + assert.Nil(t, err) + if err != nil { + t.Errorf("register2 error:%s \n", err.Error()) + return + } + + regurl.Params.Set(constant.ROLE_KEY, strconv.Itoa(common.CONSUMER)) + reg2, _ := newNacosRegistry(®url) + listener, err := reg2.Subscribe(url1) + assert.Nil(t, err) + if err != nil { + t.Errorf("subscribe error:%s \n", err.Error()) + return + } + + serviceEvent1, _ := listener.Next() + assert.NoError(t, err) + if err != nil { + t.Errorf("listener1 error:%s \n", err.Error()) + return + } + t.Logf("serviceEvent1:%+v \n", serviceEvent1) + assert.Regexp(t, ".*ServiceEvent{Action{add}.*", serviceEvent1.String()) + + serviceEvent2, _ := listener.Next() + assert.NoError(t, err) + if err != nil { + t.Errorf("listener2 error:%s \n", err.Error()) + return + } + t.Logf("serviceEvent2:%+v \n", serviceEvent2) + assert.Regexp(t, ".*ServiceEvent{Action{add}.*", serviceEvent2.String()) + + nacosReg := reg.(*nacosRegistry) + //deregister instance to mock instance offline + nacosReg.namingClient.DeregisterInstance(vo.DeregisterInstanceParam{Ip: "127.0.0.2", Port: 20000, ServiceName: "providers:com.ikurento.user.UserProvider:1.0.0:guangzhou-idc"}) + + serviceEvent3, _ := listener.Next() + assert.NoError(t, err) + if err != nil { + return + } + t.Logf("serviceEvent3:%+v \n", serviceEvent3) + assert.Regexp(t, ".*ServiceEvent{Action{delete}.*", serviceEvent3.String()) +} + +func TestNacosListener_Close(t *testing.T) { + regurl, _ := common.NewURL(context.TODO(), "registry://console.nacos.io:80", common.WithParamsValue(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER))) + urlMap := url.Values{} + urlMap.Set(constant.GROUP_KEY, "guangzhou-idc") + urlMap.Set(constant.ROLE_KEY, strconv.Itoa(common.PROVIDER)) + urlMap.Set(constant.INTERFACE_KEY, "com.ikurento.user.UserProvider2") + urlMap.Set(constant.VERSION_KEY, "1.0.0") + urlMap.Set(constant.CLUSTER_KEY, "mock") + urlMap.Set(constant.NACOS_PATH_KEY, "") + url1, _ := common.NewURL(context.TODO(), "dubbo://127.0.0.1:20000/com.ikurento.user.UserProvider2", common.WithParams(urlMap), common.WithMethods([]string{"GetUser", "AddUser"})) + reg, _ := newNacosRegistry(®url) + listener, err := reg.Subscribe(url1) + assert.Nil(t, err) + if err != nil { + t.Errorf("subscribe error:%s \n", err.Error()) + return + } + listener.Close() + _, err = listener.Next() + assert.NotNil(t, err) +} diff --git a/registry/zookeeper/listener.go b/registry/zookeeper/listener.go index 67f20370602a0a9c5c3d87ef93b1bafed3449d36..7d58cee1220b9aedba353d929ca1e936cf9366f2 100644 --- a/registry/zookeeper/listener.go +++ b/registry/zookeeper/listener.go @@ -45,11 +45,16 @@ func (l *RegistryDataListener) AddInterestedURL(url *common.URL) { } func (l *RegistryDataListener) DataChange(eventType remoting.Event) bool { - //截取最后一位 - url := eventType.Path[strings.Index(eventType.Path, "/providers/")+len("/providers/"):] + // Intercept the last bit + index := strings.Index(eventType.Path, "/providers/") + if index == -1 { + logger.Warn("Listen with no url, event.path={%v}", eventType.Path) + return false + } + url := eventType.Path[index+len("/providers/"):] serviceURL, err := common.NewURL(context.TODO(), url) if err != nil { - logger.Errorf("Listen NewURL(r{%s}) = error{%v}", url, err) + logger.Errorf("Listen NewURL(r{%s}) = error{%v} eventType.Path={%v}", url, err, eventType.Path) return false } for _, v := range l.interestedURL { diff --git a/registry/zookeeper/registry.go b/registry/zookeeper/registry.go index 0f4f57917bb53c61aa6ad8c700d11e2d9582b151..e86b7cfccad5fc03dfce56d2501af021a3cfe624 100644 --- a/registry/zookeeper/registry.go +++ b/registry/zookeeper/registry.go @@ -41,7 +41,6 @@ import ( "github.com/apache/dubbo-go/common/utils" "github.com/apache/dubbo-go/registry" "github.com/apache/dubbo-go/remoting/zookeeper" - "github.com/apache/dubbo-go/version" ) const ( @@ -231,10 +230,11 @@ func (r *zkRegistry) Register(conf common.URL) error { case common.PROVIDER: - // 检验服务是否已经注册过 + // Check if the service has been registered r.cltLock.Lock() - // 注意此处与consumerZookeeperRegistry的差异,consumer用的是conf.Path, - // 因为consumer要提供watch功能给selector使用, provider允许注册同一个service的多个group or version + // Note the difference between consumer and consumerZookeeperRegistry (consumer use conf.Path). + // Because the consumer wants to provide monitoring functions for the selector, + // the provider allows multiple groups or versions of the same service to be registered. _, ok = r.services[conf.Key()] r.cltLock.Unlock() if ok { @@ -299,11 +299,12 @@ func (r *zkRegistry) register(c common.URL) error { } params.Add("anyhost", "true") - // dubbo java consumer来启动找provider url时,因为category不匹配,会找不到provider,导致consumer启动不了,所以使用consumers&providers + // Dubbo java consumer to start looking for the provider url,because the category does not match, + // the provider will not find, causing the consumer can not start, so we use consumers. // DubboRole = [...]string{"consumer", "", "", "provider"} // params.Add("category", (RoleType(PROVIDER)).Role()) params.Add("category", (common.RoleType(common.PROVIDER)).String()) - params.Add("dubbo", "dubbo-provider-golang-"+version.Version) + params.Add("dubbo", "dubbo-provider-golang-"+constant.Version) params.Add("side", (common.RoleType(common.PROVIDER)).Role()) @@ -321,7 +322,7 @@ func (r *zkRegistry) register(c common.URL) error { rawURL = fmt.Sprintf("%s://%s%s?%s", c.Protocol, host, c.Path, params.Encode()) encodedURL = url.QueryEscape(rawURL) - // 把自己注册service providers + // Print your own registration service providers. dubboPath = fmt.Sprintf("/dubbo/%s/%s", c.Service(), (common.RoleType(common.PROVIDER)).String()) logger.Debugf("provider path:%s, url:%s", dubboPath, rawURL) @@ -346,7 +347,7 @@ func (r *zkRegistry) register(c common.URL) error { params.Add("protocol", c.Protocol) params.Add("category", (common.RoleType(common.CONSUMER)).String()) - params.Add("dubbo", "dubbogo-consumer-"+version.Version) + params.Add("dubbo", "dubbogo-consumer-"+constant.Version) rawURL = fmt.Sprintf("consumer://%s%s?%s", localIP, c.Path, params.Encode()) encodedURL = url.QueryEscape(rawURL) @@ -381,7 +382,11 @@ func (r *zkRegistry) registerTempZookeeperNode(root string, node string) error { } zkPath, err = r.client.RegisterTemp(root, node) if err != nil { - logger.Errorf("RegisterTempNode(root{%s}, node{%s}) = error{%v}", root, node, perrors.WithStack(err)) + if err == zk.ErrNodeExists { + logger.Warnf("RegisterTempNode(root{%s}, node{%s}) = error{%v}", root, node, perrors.WithStack(err)) + } else { + logger.Errorf("RegisterTempNode(root{%s}, node{%s}) = error{%v}", root, node, perrors.WithStack(err)) + } return perrors.WithMessagef(err, "RegisterTempNode(root{%s}, node{%s})", root, node) } logger.Debugf("create a zookeeper node:%s", zkPath) @@ -452,7 +457,7 @@ func (r *zkRegistry) getListener(conf *common.URL) (*RegistryConfigurationListen r.listenerLock.Unlock() } - //注册到dataconfig的interested + //Interested register to dataconfig. r.dataListener.AddInterestedURL(conf) go r.listener.ListenServiceEvent(fmt.Sprintf("/dubbo/%s/"+conf.GetParam(constant.CATEGORY_KEY, constant.DEFAULT_CATEGORY), conf.Service()), r.dataListener) @@ -464,7 +469,7 @@ func (r *zkRegistry) closeRegisters() { r.cltLock.Lock() defer r.cltLock.Unlock() logger.Infof("begin to close provider zk client") - // 先关闭旧client,以关闭tmp node + // Close the old client first to close the tmp node. r.client.Close() r.client = nil r.services = nil diff --git a/registry/zookeeper/zookeeper-4unitest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar b/registry/zookeeper/zookeeper-4unitest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar deleted file mode 100644 index 839531b8b8762a9c19e334a5cbf79314cb16f945..0000000000000000000000000000000000000000 Binary files a/registry/zookeeper/zookeeper-4unitest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar and /dev/null differ diff --git a/remoting/etcdv3/client.go b/remoting/etcdv3/client.go new file mode 100644 index 0000000000000000000000000000000000000000..57d1211fe30e00dcb1ad16733f36b7969ebaf505 --- /dev/null +++ b/remoting/etcdv3/client.go @@ -0,0 +1,480 @@ +package etcdv3 + +import ( + "context" + "path" + "sync" + "time" +) + +import ( + "github.com/coreos/etcd/clientv3" + "github.com/coreos/etcd/clientv3/concurrency" + perrors "github.com/pkg/errors" + "google.golang.org/grpc" +) + +import ( + "github.com/apache/dubbo-go/common/logger" +) + +const ( + ConnDelay = 3 + MaxFailTimes = 15 + RegistryETCDV3Client = "etcd registry" +) + +var ( + ErrNilETCDV3Client = perrors.New("etcd raw client is nil") // full describe the ERR + ErrKVPairNotFound = perrors.New("k/v pair not found") +) + +type Options struct { + name string + endpoints []string + client *Client + timeout time.Duration + heartbeat int // heartbeat second +} + +type Option func(*Options) + +func WithEndpoints(endpoints ...string) Option { + return func(opt *Options) { + opt.endpoints = endpoints + } +} +func WithName(name string) Option { + return func(opt *Options) { + opt.name = name + } +} +func WithTimeout(timeout time.Duration) Option { + return func(opt *Options) { + opt.timeout = timeout + } +} + +func WithHeartbeat(heartbeat int) Option { + return func(opt *Options) { + opt.heartbeat = heartbeat + } +} + +func ValidateClient(container clientFacade, opts ...Option) error { + + options := &Options{ + heartbeat: 1, // default heartbeat + } + for _, opt := range opts { + opt(options) + } + + lock := container.ClientLock() + lock.Lock() + defer lock.Unlock() + + // new Client + if container.Client() == nil { + newClient, err := newClient(options.name, options.endpoints, options.timeout, options.heartbeat) + if err != nil { + logger.Warnf("new etcd client (name{%s}, etcd addresses{%v}, timeout{%d}) = error{%v}", + options.name, options.endpoints, options.timeout, err) + return perrors.WithMessagef(err, "new client (address:%+v)", options.endpoints) + } + container.SetClient(newClient) + } + + // Client lose connection with etcd server + if container.Client().rawClient == nil { + + newClient, err := newClient(options.name, options.endpoints, options.timeout, options.heartbeat) + if err != nil { + logger.Warnf("new etcd client (name{%s}, etcd addresses{%v}, timeout{%d}) = error{%v}", + options.name, options.endpoints, options.timeout, err) + return perrors.WithMessagef(err, "new client (address:%+v)", options.endpoints) + } + container.SetClient(newClient) + } + + return nil +} + +type Client struct { + lock sync.RWMutex + + // these properties are only set once when they are started. + name string + endpoints []string + timeout time.Duration + heartbeat int + + ctx context.Context // if etcd server connection lose, the ctx.Done will be sent msg + cancel context.CancelFunc // cancel the ctx, all watcher will stopped + rawClient *clientv3.Client + + exit chan struct{} + Wait sync.WaitGroup +} + +func newClient(name string, endpoints []string, timeout time.Duration, heartbeat int) (*Client, error) { + + ctx, cancel := context.WithCancel(context.Background()) + rawClient, err := clientv3.New(clientv3.Config{ + Context: ctx, + Endpoints: endpoints, + DialTimeout: timeout, + DialOptions: []grpc.DialOption{grpc.WithBlock()}, + }) + if err != nil { + return nil, perrors.WithMessage(err, "new raw client block connect to server") + } + + c := &Client{ + + name: name, + timeout: timeout, + endpoints: endpoints, + heartbeat: heartbeat, + + ctx: ctx, + cancel: cancel, + rawClient: rawClient, + + exit: make(chan struct{}), + } + + if err := c.maintenanceStatus(); err != nil { + return nil, perrors.WithMessage(err, "client maintenance status") + } + return c, nil +} + +// NOTICE: need to get the lock before calling this method +func (c *Client) clean() { + + // close raw client + c.rawClient.Close() + + // cancel ctx for raw client + c.cancel() + + // clean raw client + c.rawClient = nil +} + +func (c *Client) stop() bool { + + select { + case <-c.exit: + return true + default: + close(c.exit) + } + return false +} + +func (c *Client) Close() { + + if c == nil { + return + } + + // stop the client + c.stop() + + // wait client maintenance status stop + c.Wait.Wait() + + c.lock.Lock() + if c.rawClient != nil { + c.clean() + } + c.lock.Unlock() + logger.Warnf("etcd client{name:%s, endpoints:%s} exit now.", c.name, c.endpoints) +} + +func (c *Client) maintenanceStatus() error { + + s, err := concurrency.NewSession(c.rawClient, concurrency.WithTTL(c.heartbeat)) + if err != nil { + return perrors.WithMessage(err, "new session with server") + } + + // must add wg before go maintenance status goroutine + c.Wait.Add(1) + go c.maintenanceStatusLoop(s) + return nil +} + +func (c *Client) maintenanceStatusLoop(s *concurrency.Session) { + + defer func() { + c.Wait.Done() + logger.Infof("etcd client {endpoints:%v, name:%s} maintenance goroutine game over.", c.endpoints, c.name) + }() + + for { + select { + case <-c.Done(): + // Client be stopped, will clean the client hold resources + return + case <-s.Done(): + logger.Warn("etcd server stopped") + c.lock.Lock() + // when etcd server stopped, cancel ctx, stop all watchers + c.clean() + // when connection lose, stop client, trigger reconnect to etcd + c.stop() + c.lock.Unlock() + return + } + } +} + +// if k not exist will put k/v in etcd +// if k is already exist in etcd, return nil +func (c *Client) put(k string, v string, opts ...clientv3.OpOption) error { + + c.lock.RLock() + defer c.lock.RUnlock() + + if c.rawClient == nil { + return ErrNilETCDV3Client + } + + _, err := c.rawClient.Txn(c.ctx). + If(clientv3.Compare(clientv3.Version(k), "<", 1)). + Then(clientv3.OpPut(k, v, opts...)). + Commit() + if err != nil { + return err + + } + return nil +} + +func (c *Client) delete(k string) error { + + c.lock.RLock() + defer c.lock.RUnlock() + + if c.rawClient == nil { + return ErrNilETCDV3Client + } + + _, err := c.rawClient.Delete(c.ctx, k) + if err != nil { + return err + + } + return nil +} + +func (c *Client) get(k string) (string, error) { + + c.lock.RLock() + defer c.lock.RUnlock() + + if c.rawClient == nil { + return "", ErrNilETCDV3Client + } + + resp, err := c.rawClient.Get(c.ctx, k) + if err != nil { + return "", err + } + + if len(resp.Kvs) == 0 { + return "", ErrKVPairNotFound + } + + return string(resp.Kvs[0].Value), nil +} + +func (c *Client) CleanKV() error { + + c.lock.RLock() + defer c.lock.RUnlock() + + if c.rawClient == nil { + return ErrNilETCDV3Client + } + + _, err := c.rawClient.Delete(c.ctx, "", clientv3.WithPrefix()) + if err != nil { + return err + } + + return nil +} + +func (c *Client) getChildren(k string) ([]string, []string, error) { + + c.lock.RLock() + defer c.lock.RUnlock() + + if c.rawClient == nil { + return nil, nil, ErrNilETCDV3Client + } + + resp, err := c.rawClient.Get(c.ctx, k, clientv3.WithPrefix()) + if err != nil { + return nil, nil, err + } + + if len(resp.Kvs) == 0 { + return nil, nil, ErrKVPairNotFound + } + + var ( + kList []string + vList []string + ) + + for _, kv := range resp.Kvs { + kList = append(kList, string(kv.Key)) + vList = append(vList, string(kv.Value)) + } + + return kList, vList, nil +} + +func (c *Client) watchWithPrefix(prefix string) (clientv3.WatchChan, error) { + + c.lock.RLock() + defer c.lock.RUnlock() + + if c.rawClient == nil { + return nil, ErrNilETCDV3Client + } + + return c.rawClient.Watch(c.ctx, prefix, clientv3.WithPrefix()), nil +} + +func (c *Client) watch(k string) (clientv3.WatchChan, error) { + + c.lock.RLock() + defer c.lock.RUnlock() + + if c.rawClient == nil { + return nil, ErrNilETCDV3Client + } + + return c.rawClient.Watch(c.ctx, k), nil +} + +func (c *Client) keepAliveKV(k string, v string) error { + + c.lock.RLock() + defer c.lock.RUnlock() + + if c.rawClient == nil { + return ErrNilETCDV3Client + } + + lease, err := c.rawClient.Grant(c.ctx, int64(time.Second.Seconds())) + if err != nil { + return perrors.WithMessage(err, "grant lease") + } + + keepAlive, err := c.rawClient.KeepAlive(c.ctx, lease.ID) + if err != nil || keepAlive == nil { + c.rawClient.Revoke(c.ctx, lease.ID) + return perrors.WithMessage(err, "keep alive lease") + } + + _, err = c.rawClient.Put(c.ctx, k, v, clientv3.WithLease(lease.ID)) + if err != nil { + return perrors.WithMessage(err, "put k/v with lease") + } + return nil +} + +func (c *Client) Done() <-chan struct{} { + return c.exit +} + +func (c *Client) Valid() bool { + select { + case <-c.exit: + return false + default: + } + + c.lock.RLock() + if c.rawClient == nil { + c.lock.RUnlock() + return false + } + c.lock.RUnlock() + return true +} + +func (c *Client) Create(k string, v string) error { + + err := c.put(k, v) + if err != nil { + return perrors.WithMessagef(err, "put k/v (key: %s value %s)", k, v) + } + return nil +} + +func (c *Client) Delete(k string) error { + + err := c.delete(k) + if err != nil { + return perrors.WithMessagef(err, "delete k/v (key %s)", k) + } + + return nil +} + +func (c *Client) RegisterTemp(basePath string, node string) (string, error) { + + completeKey := path.Join(basePath, node) + + err := c.keepAliveKV(completeKey, "") + if err != nil { + return "", perrors.WithMessagef(err, "keepalive kv (key %s)", completeKey) + } + + return completeKey, nil +} + +func (c *Client) GetChildrenKVList(k string) ([]string, []string, error) { + + kList, vList, err := c.getChildren(k) + if err != nil { + return nil, nil, perrors.WithMessagef(err, "get key children (key %s)", k) + } + return kList, vList, nil +} + +func (c *Client) Get(k string) (string, error) { + + v, err := c.get(k) + if err != nil { + return "", perrors.WithMessagef(err, "get key value (key %s)", k) + } + + return v, nil +} + +func (c *Client) Watch(k string) (clientv3.WatchChan, error) { + + wc, err := c.watch(k) + if err != nil { + return nil, perrors.WithMessagef(err, "watch prefix (key %s)", k) + } + return wc, nil +} + +func (c *Client) WatchWithPrefix(prefix string) (clientv3.WatchChan, error) { + + wc, err := c.watchWithPrefix(prefix) + if err != nil { + return nil, perrors.WithMessagef(err, "watch prefix (key %s)", prefix) + } + return wc, nil +} diff --git a/remoting/etcdv3/client_test.go b/remoting/etcdv3/client_test.go new file mode 100644 index 0000000000000000000000000000000000000000..187789e0abfac6a0e195bebd68ce4b91e0f9bdec --- /dev/null +++ b/remoting/etcdv3/client_test.go @@ -0,0 +1,366 @@ +package etcdv3 + +import ( + "fmt" + "net/url" + "path" + "reflect" + "strings" + "sync" + "testing" + "time" +) + +import ( + "github.com/coreos/etcd/mvcc/mvccpb" + perrors "github.com/pkg/errors" + "github.com/stretchr/testify/suite" + "go.etcd.io/etcd/embed" + "google.golang.org/grpc/connectivity" +) + +// tests dataset +var tests = []struct { + input struct { + k string + v string + } +}{ + {input: struct { + k string + v string + }{k: "name", v: "scott.wang"}}, + {input: struct { + k string + v string + }{k: "namePrefix", v: "prefix.scott.wang"}}, + {input: struct { + k string + v string + }{k: "namePrefix1", v: "prefix1.scott.wang"}}, + {input: struct { + k string + v string + }{k: "age", v: "27"}}, +} + +// test dataset prefix +const prefix = "name" + +type ClientTestSuite struct { + suite.Suite + + etcdConfig struct { + name string + endpoints []string + timeout time.Duration + heartbeat int + } + + etcd *embed.Etcd + + client *Client +} + +// start etcd server +func (suite *ClientTestSuite) SetupSuite() { + + t := suite.T() + + DefaultListenPeerURLs := "http://localhost:2382" + DefaultListenClientURLs := "http://localhost:2381" + lpurl, _ := url.Parse(DefaultListenPeerURLs) + lcurl, _ := url.Parse(DefaultListenClientURLs) + cfg := embed.NewConfig() + cfg.LPUrls = []url.URL{*lpurl} + cfg.LCUrls = []url.URL{*lcurl} + cfg.Dir = "/tmp/default.etcd" + e, err := embed.StartEtcd(cfg) + if err != nil { + t.Fatal(err) + } + select { + case <-e.Server.ReadyNotify(): + t.Log("Server is ready!") + case <-time.After(60 * time.Second): + e.Server.Stop() // trigger a shutdown + t.Logf("Server took too long to start!") + } + + suite.etcd = e + return +} + +// stop etcd server +func (suite *ClientTestSuite) TearDownSuite() { + suite.etcd.Close() +} + +func (suite *ClientTestSuite) setUpClient() *Client { + c, err := newClient(suite.etcdConfig.name, + suite.etcdConfig.endpoints, + suite.etcdConfig.timeout, + suite.etcdConfig.heartbeat) + if err != nil { + suite.T().Fatal(err) + } + return c +} + +// set up a client for suite +func (suite *ClientTestSuite) SetupTest() { + c := suite.setUpClient() + c.CleanKV() + suite.client = c + return +} + +func (suite *ClientTestSuite) TestClientClose() { + + fmt.Println("called client close") + + c := suite.client + t := suite.T() + + defer c.Close() + if c.rawClient.ActiveConnection().GetState() != connectivity.Ready { + t.Fatal(suite.client.rawClient.ActiveConnection().GetState()) + } +} + +func (suite *ClientTestSuite) TestClientValid() { + + fmt.Println("called client valid") + + c := suite.client + t := suite.T() + + if c.Valid() != true { + t.Fatal("client is not valid") + } + c.Close() + if suite.client.Valid() != false { + t.Fatal("client is valid") + } +} + +func (suite *ClientTestSuite) TestClientDone() { + + c := suite.client + + go func() { + time.Sleep(2 * time.Second) + c.Close() + }() + + c.Wait.Wait() +} + +func (suite *ClientTestSuite) TestClientCreateKV() { + + tests := tests + + c := suite.client + t := suite.T() + + defer suite.client.Close() + + for _, tc := range tests { + + k := tc.input.k + v := tc.input.v + expect := tc.input.v + + if err := c.Create(k, v); err != nil { + t.Fatal(err) + } + + value, err := c.Get(k) + if err != nil { + t.Fatal(err) + } + + if value != expect { + t.Fatalf("expect %v but get %v", expect, value) + } + + } +} + +func (suite *ClientTestSuite) TestClientDeleteKV() { + + tests := tests + c := suite.client + t := suite.T() + + defer c.Close() + + for _, tc := range tests { + + k := tc.input.k + v := tc.input.v + expect := ErrKVPairNotFound + + if err := c.Create(k, v); err != nil { + t.Fatal(err) + } + + if err := c.Delete(k); err != nil { + t.Fatal(err) + } + + _, err := c.Get(k) + if perrors.Cause(err) == expect { + continue + } + + if err != nil { + t.Fatal(err) + } + } + +} + +func (suite *ClientTestSuite) TestClientGetChildrenKVList() { + + tests := tests + + c := suite.client + t := suite.T() + + var expectKList []string + var expectVList []string + + for _, tc := range tests { + + k := tc.input.k + v := tc.input.v + + if strings.Contains(k, prefix) { + expectKList = append(expectKList, k) + expectVList = append(expectVList, v) + } + + if err := c.Create(k, v); err != nil { + t.Fatal(err) + } + } + + kList, vList, err := c.GetChildrenKVList(prefix) + if err != nil { + t.Fatal(err) + } + + if reflect.DeepEqual(expectKList, kList) && reflect.DeepEqual(expectVList, vList) { + return + } + + t.Fatalf("expect keylist %v but got %v expect valueList %v but got %v ", expectKList, kList, expectVList, vList) + +} + +func (suite *ClientTestSuite) TestClientWatch() { + + tests := tests + + c := suite.client + t := suite.T() + + wg := sync.WaitGroup{} + wg.Add(1) + + go func() { + + defer wg.Done() + + wc, err := c.watch(prefix) + if err != nil { + t.Fatal(err) + } + + for e := range wc { + + for _, event := range e.Events { + t.Logf("type IsCreate %v k %s v %s", event.IsCreate(), event.Kv.Key, event.Kv.Value) + } + } + + }() + + for _, tc := range tests { + + k := tc.input.k + v := tc.input.v + + if err := c.Create(k, v); err != nil { + t.Fatal(err) + } + + if err := c.delete(k); err != nil { + t.Fatal(err) + } + } + + c.Close() + + wg.Wait() + +} + +func (suite *ClientTestSuite) TestClientRegisterTemp() { + + c := suite.client + observeC := suite.setUpClient() + t := suite.T() + + wg := sync.WaitGroup{} + wg.Add(1) + + go func() { + completePath := path.Join("scott", "wang") + wc, err := observeC.watch(completePath) + if err != nil { + t.Fatal(err) + } + + for e := range wc { + + for _, event := range e.Events { + + if event.Type == mvccpb.DELETE { + t.Logf("complete key (%s) is delete", completePath) + wg.Done() + observeC.Close() + return + } + t.Logf("type IsCreate %v k %s v %s", event.IsCreate(), event.Kv.Key, event.Kv.Value) + } + } + }() + + _, err := c.RegisterTemp("scott", "wang") + if err != nil { + t.Fatal(err) + } + + time.Sleep(2 * time.Second) + c.Close() + + wg.Wait() +} + +func TestClientSuite(t *testing.T) { + suite.Run(t, &ClientTestSuite{ + etcdConfig: struct { + name string + endpoints []string + timeout time.Duration + heartbeat int + }{ + name: "test", + endpoints: []string{"localhost:2381"}, + timeout: time.Second, + heartbeat: 1, + }, + }) +} diff --git a/remoting/etcdv3/facade.go b/remoting/etcdv3/facade.go new file mode 100644 index 0000000000000000000000000000000000000000..e75b39d6bcd7f67f7606c6b212f59e7a42178fd8 --- /dev/null +++ b/remoting/etcdv3/facade.go @@ -0,0 +1,82 @@ +package etcdv3 + +import ( + "sync" + "time" +) + +import ( + "github.com/dubbogo/getty" + perrors "github.com/pkg/errors" +) + +import ( + "github.com/apache/dubbo-go/common" + "github.com/apache/dubbo-go/common/constant" + "github.com/apache/dubbo-go/common/logger" +) + +type clientFacade interface { + Client() *Client + SetClient(*Client) + ClientLock() *sync.Mutex + WaitGroup() *sync.WaitGroup //for wait group control, etcd client listener & etcd client container + GetDone() chan struct{} //for etcd client control + RestartCallBack() bool + common.Node +} + +func HandleClientRestart(r clientFacade) { + + var ( + err error + failTimes int + ) + + defer r.WaitGroup().Done() +LOOP: + for { + select { + case <-r.GetDone(): + logger.Warnf("(ETCDV3ProviderRegistry)reconnectETCDV3 goroutine exit now...") + break LOOP + // re-register all services + case <-r.Client().Done(): + r.ClientLock().Lock() + clientName := RegistryETCDV3Client + timeout, _ := time.ParseDuration(r.GetUrl().GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT)) + endpoint := r.GetUrl().Location + r.Client().Close() + r.SetClient(nil) + r.ClientLock().Unlock() + + // try to connect to etcd, + failTimes = 0 + for { + select { + case <-r.GetDone(): + logger.Warnf("(ETCDV3ProviderRegistry)reconnectETCDRegistry goroutine exit now...") + break LOOP + case <-getty.GetTimeWheel().After(timeSecondDuration(failTimes * ConnDelay)): // avoid connect frequent + } + err = ValidateClient( + r, + WithName(clientName), + WithEndpoints(endpoint), + WithTimeout(timeout), + ) + logger.Infof("ETCDV3ProviderRegistry.validateETCDV3Client(etcd Addr{%s}) = error{%#v}", + endpoint, perrors.WithStack(err)) + if err == nil { + if r.RestartCallBack() { + break + } + } + failTimes++ + if MaxFailTimes <= failTimes { + failTimes = MaxFailTimes + } + } + } + } +} diff --git a/remoting/etcdv3/listener.go b/remoting/etcdv3/listener.go new file mode 100644 index 0000000000000000000000000000000000000000..59273af554a63e5fc907ba5a30bb1e18bb22c0f5 --- /dev/null +++ b/remoting/etcdv3/listener.go @@ -0,0 +1,217 @@ +package etcdv3 + +import ( + "sync" + "time" +) + +import ( + "github.com/coreos/etcd/clientv3" + "github.com/coreos/etcd/mvcc/mvccpb" + perrors "github.com/pkg/errors" +) + +import ( + "github.com/apache/dubbo-go/common/logger" + "github.com/apache/dubbo-go/remoting" +) + +type EventListener struct { + client *Client + keyMapLock sync.Mutex + keyMap map[string]struct{} + wg sync.WaitGroup +} + +func NewEventListener(client *Client) *EventListener { + return &EventListener{ + client: client, + keyMap: make(map[string]struct{}), + } +} + +// Listen on a spec key +// this method will return true when spec key deleted, +// this method will return false when deep layer connection lose +func (l *EventListener) ListenServiceNodeEvent(key string, listener ...remoting.DataListener) bool { + l.wg.Add(1) + defer l.wg.Done() + for { + wc, err := l.client.Watch(key) + if err != nil { + logger.Warnf("WatchExist{key:%s} = error{%v}", key, err) + return false + } + + select { + + // client stopped + case <-l.client.Done(): + logger.Warnf("etcd client stopped") + return false + + // client ctx stop + case <-l.client.ctx.Done(): + logger.Warnf("etcd client ctx cancel") + return false + + // handle etcd events + case e, ok := <-wc: + if !ok { + logger.Warnf("etcd watch-chan closed") + return false + } + + if e.Err() != nil { + logger.Errorf("etcd watch ERR {err: %s}", e.Err()) + continue + } + for _, event := range e.Events { + if l.handleEvents(event, listener...) { + // if event is delete + return true + } + } + } + } + + return false +} + +// return true mean the event type is DELETE +// return false mean the event type is CREATE || UPDATE +func (l *EventListener) handleEvents(event *clientv3.Event, listeners ...remoting.DataListener) bool { + + logger.Infof("got a etcd event {type: %s, key: %s}", event.Type, event.Kv.Key) + + switch event.Type { + // the etcdv3 event just include PUT && DELETE + case mvccpb.PUT: + for _, listener := range listeners { + switch event.IsCreate() { + case true: + logger.Infof("etcd get event (key{%s}) = event{EventNodeDataCreated}", event.Kv.Key) + listener.DataChange(remoting.Event{ + Path: string(event.Kv.Key), + Action: remoting.EventTypeAdd, + Content: string(event.Kv.Value), + }) + case false: + logger.Infof("etcd get event (key{%s}) = event{EventNodeDataChanged}", event.Kv.Key) + listener.DataChange(remoting.Event{ + Path: string(event.Kv.Key), + Action: remoting.EvnetTypeUpdate, + Content: string(event.Kv.Value), + }) + } + } + return false + case mvccpb.DELETE: + logger.Warnf("etcd get event (key{%s}) = event{EventNodeDeleted}", event.Kv.Key) + return true + + default: + return false + } + + panic("unreachable") +} + +// Listen on a set of key with spec prefix +func (l *EventListener) ListenServiceNodeEventWithPrefix(prefix string, listener ...remoting.DataListener) { + + l.wg.Add(1) + defer l.wg.Done() + for { + wc, err := l.client.WatchWithPrefix(prefix) + if err != nil { + logger.Warnf("listenDirEvent(key{%s}) = error{%v}", prefix, err) + } + + select { + + // client stopped + case <-l.client.Done(): + logger.Warnf("etcd client stopped") + return + + // client ctx stop + case <-l.client.ctx.Done(): + logger.Warnf("etcd client ctx cancel") + return + + // etcd event stream + case e, ok := <-wc: + + if !ok { + logger.Warnf("etcd watch-chan closed") + return + } + + if e.Err() != nil { + logger.Errorf("etcd watch ERR {err: %s}", e.Err()) + continue + } + for _, event := range e.Events { + l.handleEvents(event, listener...) + } + } + } +} + +func timeSecondDuration(sec int) time.Duration { + return time.Duration(sec) * time.Second +} + +// this func is invoked by etcdv3 ConsumerRegistry::Registe/ etcdv3 ConsumerRegistry::get/etcdv3 ConsumerRegistry::getListener +// registry.go:Listen -> listenServiceEvent -> listenDirEvent -> ListenServiceNodeEvent +// | +// --------> ListenServiceNodeEvent +func (l *EventListener) ListenServiceEvent(key string, listener remoting.DataListener) { + + l.keyMapLock.Lock() + _, ok := l.keyMap[key] + l.keyMapLock.Unlock() + if ok { + logger.Warnf("etcdv3 key %s has already been listened.", key) + return + } + + l.keyMapLock.Lock() + l.keyMap[key] = struct{}{} + l.keyMapLock.Unlock() + + keyList, valueList, err := l.client.getChildren(key) + if err != nil { + logger.Errorf("Get new node path {%v} 's content error,message is {%v}", key, perrors.WithMessage(err, "get children")) + } + + logger.Infof("get key children list %s, keys %v values %v", key, keyList, valueList) + + for i, k := range keyList { + logger.Infof("got children list key -> %s", k) + listener.DataChange(remoting.Event{ + Path: k, + Action: remoting.EventTypeAdd, + Content: valueList[i], + }) + } + + logger.Infof("listen dubbo provider key{%s} event and wait to get all provider etcdv3 nodes", key) + go func(key string, listener remoting.DataListener) { + l.ListenServiceNodeEventWithPrefix(key, listener) + logger.Warnf("listenDirEvent(key{%s}) goroutine exit now", key) + }(key, listener) + + logger.Infof("listen dubbo service key{%s}", key) + go func(key string) { + if l.ListenServiceNodeEvent(key) { + listener.DataChange(remoting.Event{Path: key, Action: remoting.EventTypeDel}) + } + logger.Warnf("listenSelf(etcd key{%s}) goroutine exit now", key) + }(key) +} + +func (l *EventListener) Close() { + l.wg.Wait() +} diff --git a/remoting/etcdv3/listener_test.go b/remoting/etcdv3/listener_test.go new file mode 100644 index 0000000000000000000000000000000000000000..33904a21345ec0ac7ee1adbb239a0a7a44852387 --- /dev/null +++ b/remoting/etcdv3/listener_test.go @@ -0,0 +1,87 @@ +package etcdv3 + +import ( + "time" +) + +import ( + "github.com/stretchr/testify/assert" +) + +import ( + "github.com/apache/dubbo-go/remoting" +) + +var changedData = ` + dubbo.consumer.request_timeout=3s + dubbo.consumer.connect_timeout=5s + dubbo.application.organization=ikurento.com + dubbo.application.name=BDTService + dubbo.application.module=dubbogo user-info server + dubbo.application.version=0.0.1 + dubbo.application.owner=ZX + dubbo.application.environment=dev + dubbo.registries.hangzhouzk.protocol=zookeeper + dubbo.registries.hangzhouzk.timeout=3s + dubbo.registries.hangzhouzk.address=127.0.0.1:2181 + dubbo.registries.shanghaizk.protocol=zookeeper + dubbo.registries.shanghaizk.timeout=3s + dubbo.registries.shanghaizk.address=127.0.0.1:2182 + dubbo.service.com.ikurento.user.UserProvider.protocol=dubbo + dubbo.service.com.ikurento.user.UserProvider.interface=com.ikurento.user.UserProvider + dubbo.service.com.ikurento.user.UserProvider.loadbalance=random + dubbo.service.com.ikurento.user.UserProvider.warmup=100 + dubbo.service.com.ikurento.user.UserProvider.cluster=failover +` + +func (suite *ClientTestSuite) TestListener() { + + var tests = []struct { + input struct { + k string + v string + } + }{ + {input: struct { + k string + v string + }{k: "/dubbo", v: changedData}}, + } + + c := suite.client + t := suite.T() + + listener := NewEventListener(c) + dataListener := &mockDataListener{client: c, changedData: changedData, rc: make(chan remoting.Event)} + listener.ListenServiceEvent("/dubbo", dataListener) + + // NOTICE: direct listen will lose create msg + time.Sleep(time.Second) + for _, tc := range tests { + + k := tc.input.k + v := tc.input.v + if err := c.Create(k, v); err != nil { + t.Fatal(err) + } + + } + msg := <-dataListener.rc + assert.Equal(t, changedData, msg.Content) +} + +type mockDataListener struct { + eventList []remoting.Event + client *Client + changedData string + + rc chan remoting.Event +} + +func (m *mockDataListener) DataChange(eventType remoting.Event) bool { + m.eventList = append(m.eventList, eventType) + if eventType.Content == m.changedData { + m.rc <- eventType + } + return true +} diff --git a/remoting/listener.go b/remoting/listener.go index 866c8503bb1c112db4182e31052199d49a25c7fd..b94ba26980b50db99e766fcc8febb07d6b554274 100644 --- a/remoting/listener.go +++ b/remoting/listener.go @@ -52,6 +52,7 @@ const ( var serviceEventTypeStrings = [...]string{ "add", "delete", + "update", } func (t EventType) String() string { diff --git a/remoting/zookeeper/client.go b/remoting/zookeeper/client.go index d1d5f9900dbd67bbd061b411eaf2e40ffa0e7561..008848ea61ba2deb1a70aba5c29da097c3c48da9 100644 --- a/remoting/zookeeper/client.go +++ b/remoting/zookeeper/client.go @@ -125,7 +125,8 @@ func ValidateZookeeperClient(container zkClientFacade, opts ...Option) error { url.GetParam(constant.REGISTRY_TIMEOUT_KEY, constant.DEFAULT_REG_TIMEOUT), err.Error()) return perrors.WithMessagef(err, "newZookeeperClient(address:%+v)", url.Location) } - newClient, err := newZookeeperClient(opions.zkName, []string{url.Location}, timeout) + zkAddresses := strings.Split(url.Location, ",") + newClient, err := newZookeeperClient(opions.zkName, zkAddresses, timeout) if err != nil { logger.Warnf("newZookeeperClient(name{%s}, zk addresss{%v}, timeout{%d}) = error{%v}", opions.zkName, url.Location, timeout.String(), err) @@ -298,29 +299,26 @@ func (z *ZookeeperClient) UnregisterEvent(zkPath string, event *chan struct{}) { if zkPath == "" { return } - z.Lock() - for { - a, ok := z.eventRegistry[zkPath] - if !ok { - break - } - for i, e := range a { - if e == event { - arr := a - a = append(arr[:i], arr[i+1:]...) - logger.Debugf("zkClient{%s} unregister event{path:%s, event:%p}", z.name, zkPath, event) - } - } - logger.Debugf("after zkClient{%s} unregister event{path:%s, event:%p}, array length %d", - z.name, zkPath, event, len(a)) - if len(a) == 0 { - delete(z.eventRegistry, zkPath) - } else { - z.eventRegistry[zkPath] = a + defer z.Unlock() + infoList, ok := z.eventRegistry[zkPath] + if !ok { + return + } + for i, e := range infoList { + if e == event { + arr := infoList + infoList = append(arr[:i], arr[i+1:]...) + logger.Infof("zkClient{%s} unregister event{path:%s, event:%p}", z.name, zkPath, event) } } - z.Unlock() + logger.Debugf("after zkClient{%s} unregister event{path:%s, event:%p}, array length %d", + z.name, zkPath, event, len(infoList)) + if len(infoList) == 0 { + delete(z.eventRegistry, zkPath) + } else { + z.eventRegistry[zkPath] = infoList + } } func (z *ZookeeperClient) Done() <-chan struct{} { diff --git a/remoting/zookeeper/facade.go b/remoting/zookeeper/facade.go index 4fd800f87732288527d9387580fe70d0a9cae9d2..cdc7ead61226906a629fdb99b6b966ada5ee5253 100644 --- a/remoting/zookeeper/facade.go +++ b/remoting/zookeeper/facade.go @@ -19,9 +19,9 @@ package zookeeper import ( "sync" - "time" ) import ( + "github.com/dubbogo/getty" perrors "github.com/pkg/errors" ) @@ -63,14 +63,14 @@ LOOP: r.SetZkClient(nil) r.ZkClientLock().Unlock() - // 接zk,直至成功 + // Connect zk until success. failTimes = 0 for { select { case <-r.GetDone(): logger.Warnf("(ZkProviderRegistry)reconnectZkRegistry goroutine exit now...") break LOOP - case <-time.After(time.Duration(1e9 * failTimes * ConnDelay)): // 防止疯狂重连zk + case <-getty.GetTimeWheel().After(timeSecondDuration(failTimes * ConnDelay)): // Prevent crazy reconnection zk. } err = ValidateZookeeperClient(r, WithZkName(zkName)) logger.Infof("ZkProviderRegistry.validateZookeeperClient(zkAddr{%s}) = error{%#v}", diff --git a/remoting/zookeeper/listener.go b/remoting/zookeeper/listener.go index 78c83ba3b249aae1e3f1059d64d718d0546b0d81..30347d494c14b989c43c2f3f4ea276b35d99f71b 100644 --- a/remoting/zookeeper/listener.go +++ b/remoting/zookeeper/listener.go @@ -24,6 +24,7 @@ import ( ) import ( + "github.com/dubbogo/getty" perrors "github.com/pkg/errors" "github.com/samuel/go-zookeeper/zk" ) @@ -129,14 +130,14 @@ func (l *ZkEventListener) handleZkNodeEvent(zkPath string, children []string, li continue } // listen l service node - go func(node, childNode string) { + go func(node string) { logger.Infof("delete zkNode{%s}", node) if l.ListenServiceNodeEvent(node, listener) { - logger.Infof("delete content{%s}", childNode) + logger.Infof("delete content{%s}", node) listener.DataChange(remoting.Event{Path: zkPath, Action: remoting.EventTypeDel}) } logger.Warnf("listenSelf(zk path{%s}) goroutine exit now", zkPath) - }(newNode, n) + }(newNode) } // old node was deleted @@ -188,7 +189,7 @@ func (l *ZkEventListener) listenDirEvent(zkPath string, listener remoting.DataLi } l.client.RegisterEvent(zkPath, &event) select { - case <-time.After(timeSecondDuration(failTimes * ConnDelay)): + case <-getty.GetTimeWheel().After(timeSecondDuration(failTimes * ConnDelay)): l.client.UnregisterEvent(zkPath, &event) continue case <-l.client.Done(): @@ -207,6 +208,20 @@ func (l *ZkEventListener) listenDirEvent(zkPath string, listener remoting.DataLi // listen l service node dubboPath := path.Join(zkPath, c) + + //Save the path to avoid listen repeatly + l.pathMapLock.Lock() + _, ok := l.pathMap[dubboPath] + l.pathMapLock.Unlock() + if ok { + logger.Warnf("@zkPath %s has already been listened.", zkPath) + continue + } + + l.pathMapLock.Lock() + l.pathMap[dubboPath] = struct{}{} + l.pathMapLock.Unlock() + content, _, err := l.client.Conn.Get(dubboPath) if err != nil { logger.Errorf("Get new node path {%v} 's content error,message is {%v}", dubboPath, perrors.WithStack(err)) diff --git a/remoting/zookeeper/listener_test.go b/remoting/zookeeper/listener_test.go index c2fedb911b7560a13c5b98d865cb97575a7719df..a90fbad05ae787f36d38607b0a73374d874e6994 100644 --- a/remoting/zookeeper/listener_test.go +++ b/remoting/zookeeper/listener_test.go @@ -118,6 +118,7 @@ func (m *mockDataListener) DataChange(eventType remoting.Event) bool { if eventType.Content == m.changedData { m.wait.Done() m.client.Close() + } return true } diff --git a/remoting/zookeeper/zookeeper-4unitest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar b/remoting/zookeeper/zookeeper-4unitest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar deleted file mode 100644 index 839531b8b8762a9c19e334a5cbf79314cb16f945..0000000000000000000000000000000000000000 Binary files a/remoting/zookeeper/zookeeper-4unitest/contrib/fatjar/zookeeper-3.4.9-fatjar.jar and /dev/null differ